Merge "board: storage: enable eMMC DDR capability for non-CDP platforms" into msm-3.4
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
index a33d833..d8784db 100644
--- a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
+++ b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
@@ -40,6 +40,7 @@
 - qcom,saw2-spm-cmd-ret: The Retention command sequence
 - qcom,saw2-spm-cmd-spc: The Standalone PC command sequence
 - qcom,saw2-spm-cmd-pc: The Power Collapse command sequence
+- qcom,saw2-spm-cmd-gdhs: L2 GDHS command sequence
 
 Example:
 	qcom,spm@f9089000 {
@@ -56,11 +57,11 @@
 		qcom,saw2-avs-dly= <0>;
 		qcom,saw2-spm-dly= <0x20000400>;
 		qcom,saw2-spm-ctl = <0x1>;
-		qcom,spm-cmd-wfi = [03 0b 0f];
-		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
 				a0 b0 03 68 70 3b 92 a0 b0
 				82 2b 50 10 30 02 22 30 0f];
-		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+		qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
 				a0 b0 82 10 30 02 22 30 0f];
 	};
 
diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt
new file mode 100644
index 0000000..8b17ba9
--- /dev/null
+++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt
@@ -0,0 +1,10 @@
+* QSEECOM (Qualcomm Secure Execution Environment Communicator)
+
+Required properties:
+- compatible : Should be "qcom,qseecom"
+
+Example:
+
+	qcom,qseecom@fe806000 {
+		compatible = "qcom,qseecom";
+	};
diff --git a/Documentation/tzcom.txt b/Documentation/tzcom.txt
deleted file mode 100644
index 7472dee..0000000
--- a/Documentation/tzcom.txt
+++ /dev/null
@@ -1,181 +0,0 @@
-Introduction
-============
-
-The tzcom (TrustZone Communicator) device driver provides IOCTLs for userspace
-to communicate with TrustZone Operating Environment (TZBSP) using Secure
-Channel Manager (SCM) interface. It also provides a way for TZBSP to utilize
-services in HLOS.
-
-Hardware description
-====================
-
-The hardware interaction is specified in Secure Channel Manager for TZBSP design
-document. This driver exercises the SCM interface (scm_call).
-
-Software description
-====================
-
-This driver is a character device driver and following operations are registered:
-- tzcom_open()
-- tzcom_release()
-- tzcom_ioctl()
-
-
-This driver provides following IOCTL methods:
-  TZCOM_IOCTL_REGISTER_SERVICE_REQ - to register HLOS service
-  TZCOM_IOCTL_UNREGISTER_SERVICE_REQ - to unregister HLOS service
-  TZCOM_IOCTL_SEND_CMD_REQ - send a command to a service
-  TZCOM_IOCTL_READ_NEXT_CMD_REQ - wait for a cmd from TZBSP to use HLOS service
-  TZCOM_IOCTL_CONTINUE_CMD_REQ - continue the last incomplete cmd on TZBSP
-
-TZCOM_IOCTL_REGISTER_SERVICE_REQ sequence diagram:
-
-    +--------------+  +---------------+
-    |   USERSPACE  |  |    TZCOM      |
-    +------+-------+  +-------+-------+
-           | REGISTER_SERVICE |
-           |----------------->|   ___
-           |                  |,-'   ``.
-           |                  + verify &`.
-           |                  |  add     |
-           |                  | service  |
-           |                  | to a list|
-           |   registered     |<-.._,,,,/
-           |<-----------------|
-           |                  |
-
-TZCOM_IOCTL_READ_NEXT_CMD_REQ, TZCOM_IOCTL_SEND_CMD_REQ and
-TZCOM_IOCTL_CONTINUE_CMD_REQ sequence:
-
-     +--------------+  +---------------+  +-------------+  +----------------+
-     |   USERSPACE  |  |    TZCOM      |  |     SCM     |  |     TZBSP      |
-     +---+--+-------+  +-------+-------+  +------+------+  +-------+--------+
-         |  |  READ_NEXT_CMD   |                 |                 |
-         +--|----------------->|                 |                 |
-         |  |                  |.--------.       |                 |
-         |  |                  || BLOCKED|       |                 |
-         |  |                  |`--------'       |                 |
-         |  |                  |                 |                 |
-         |  |                  |                 |                 |
-         |  |    SEND_CMD      |                 |                 |
-         |  +----------------->|                 |                 |
-         |  |                  |    scm_call     |                 |
-         |  |                  +---------------->|    SEND_CMD     |
-         |  |                  |                 +---------------->|
-         |  |                  |                 |  cmd incomplete |
-         |  |                  | scm_call returns|<----------------+
-         |  |                  |<----------------+                 |
-         |  |                  |                 |                 |
-         |  |                  |,-'''-.          |                 |
-         |  |                  + READ  `.        |                 |
-         |  |                  | NEXT   |        |                 |
-         |  |                  |  CMD   /        |                 |
-         |  | READ_NEXT_CMD ret|<.____,'         |                 |
-         |<-|------------------+                 |                 |
-  ,---.  |  |                  |                 |                 |
- /     \ |  |                  |                 |                 |
-/perform\|  |                  |                 |                 |
- received)  |                  |                 |                 |
-\command/|  |                  |                 |                 |
- \     / |  |                  |                 |                 |
-  `---'  |  |                  |                 |                 |
-         |  |                  |                 |                 |
-         |  | CONTINUE_CMD     |                 |                 |
-         +--|----------------->|                 |                 |
-         |  | returns          | _,...           |                 |
-         |  |  immediately     |'     `.         |                 |
-         |  |                  | fill in`.       |                 |
-         |  |                  | incomplete      |                 |
-         |  |                  | cmd     ;       |                 |
-            |                  |<-...---'        |                 |
-            |                  |   scm_call      |                 |
-            |                  +---------------->|   SEND_CMD      |
-            |                  |                 +---------------->|
-            |                  |                 |  cmd complete   |
-            |                  | scm_call returns|<----------------+
-            |SEND_CMD return   |<----------------+                 |
-            |<-----------------+                 |                 |
-            |                  |                 |                 |
-
-
-
-There are three shared buffers between TZCOM driver and TZBSP.
-1) For command and response buffers for SEND_CMD requests
-2) For commands originated from TZBSP and their corresponding responses
-3) For debug service
-
-When calling IOCTL_SEND_CMD_REQ from userspace, command request and response
-buffers are initialized and provided in the IOCTL arguments. Where request and
-response buffers will be passed as an arguments to the smc_call method.
-
-The requests are synchronous. The driver will put the process to sleep,
-waiting for the completion of the requests using wait_for_completion().
-
-This driver uses kmalloc for shared buffer pools which get initialized at driver
-initialization. There are three buffers each 20 KB. If any of the buffers fail
-to initialize then driver will fail to load. Assumption is the allocated
-memory for buffers is contiguous.
-
-
-Design
-======
-
-The goal of this driver is to provide a communication API for the userspace
-application to execute services in TrustZone as well as TrustZone operating
-environment to access services in HLOS.
-
-Currently TZ->HLOS communication happens from a blocking call to READ_NEXT_CMD
-that is initiated from the userspace and on receiving a command request from TZ
-service, command is placed on a queue to unblock READ_NEXT_CMD call. This could
-have been solved by using a callback, but the practice of invoking callbacks in
-userspace from kernel is discouraged.
-
-Power Management
-================
-
-n/a
-
-SMP/multi-core
-==============
-
-TZCOM allows multiple services being registered from HLOS and multiple processes
-or threads can call IOCTL_READ_NEXT_MSG. These services will block until new
-data arrives on the shared buffer (buffer #2 as mentioned in Software
-Description). This is achieved using wait queues.
-
-Security
-========
-
-Please refer to Security Channel Manager design document.
-
-Performance
-===========
-
-Every scm_call is a context switch between non-trusted and trusted operating
-environment. There are no performance related matrix for scm_call available as
-of now.
-
-Interface
-=========
-
-This driver will have a /dev/tzcom node and following IOCTL calls can be made.
-
-Userspace API (ioctl calls):
-  TZCOM_IOCTL_REGISTER_SERVICE_REQ - to register HLOS service
-  TZCOM_IOCTL_UNREGISTER_SERVICE_REQ - to unregister HLOS service
-  TZCOM_IOCTL_SEND_CMD_REQ - send a command to a service
-  TZCOM_IOCTL_READ_NEXT_CMD_REQ - wait for a cmd from TZBSP to use HLOS service
-  TZCOM_IOCTL_CONTINUE_CMD_REQ - continue the last incomplete cmd on TZBSP
-
-
-Dependencies
-============
-
-This driver interacts with Trustzone operating environment, thus depends on
-the TZBSP supported architecture.
-
-
-To do
-=====
-
-TBD
diff --git a/arch/arm/boot/dts/msm9625.dts b/arch/arm/boot/dts/msm9625.dts
index b7b8be2..6c007fb 100644
--- a/arch/arm/boot/dts/msm9625.dts
+++ b/arch/arm/boot/dts/msm9625.dts
@@ -41,6 +41,15 @@
 		clock-frequency = <5000000>;
 	};
 
+	qcom,sps@f9980000 {
+		compatible = "qcom,msm_sps";
+		reg = <0xf9984000 0x15000>,
+		      <0xf9999000 0xb000>,
+		      <0xfe800000 0x4800>;
+		interrupts = <0 94 0>;
+		qcom,device-type = <2>;
+	};
+
 	serial@f991f000 {
 		compatible = "qcom,msm-lsuart-v14";
 		reg = <0xf991f000 0x1000>;
diff --git a/arch/arm/boot/dts/msmcopper-regulator.dtsi b/arch/arm/boot/dts/msmcopper-regulator.dtsi
index 0d0c587..a926aa3 100644
--- a/arch/arm/boot/dts/msmcopper-regulator.dtsi
+++ b/arch/arm/boot/dts/msmcopper-regulator.dtsi
@@ -155,7 +155,7 @@
 			};
 
 			pm8941_l13: regulator@4c00 {
-				regulator-min-microvolt = <2950000>;
+				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <2950000>;
 				qcom,enable-time = <200>;
 				qcom,pull-down-enable = <1>;
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 5b5e646..5c0384f 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -296,6 +296,53 @@
 		qcom,firmware-name = "adsp";
 	};
 
+        qcom,msm-pcm {
+                compatible = "qcom,msm-pcm-dsp";
+        };
+
+        qcom,msm-pcm-routing {
+                compatible = "qcom,msm-pcm-routing";
+        };
+
+        qcom,msm-pcm-lpa {
+                compatible = "qcom,msm-pcm-lpa";
+        };
+
+        qcom,msm-voip-dsp {
+                compatible = "qcom,msm-voip-dsp";
+        };
+
+        qcom,msm-stub-codec {
+                compatible = "qcom,msm-stub-codec";
+        };
+
+        qcom,msm-dai-fe {
+                compatible = "qcom,msm-dai-fe";
+        };
+
+        qcom,msm-dai-q6 {
+                compatible = "qcom,msm-dai-q6";
+                qcom,msm-cpudai-auxpcm-clk = "pcm_clk";
+                qcom,msm-cpudai-auxpcm-mode = <0>;
+                qcom,msm-cpudai-auxpcm-sync = <1>;
+                qcom,msm-cpudai-auxpcm-frame = <5>;
+                qcom,msm-cpudai-auxpcm-quant = <2>;
+                qcom,msm-cpudai-auxpcm-slot = <1>;
+                qcom,msm-cpudai-auxpcm-data = <0>;
+                qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>;
+
+                qcom,msm-dai-q6-rx {
+                        qcom,msm-dai-q6-id = <4106>;
+                };
+                qcom,msm-dai-q6-tx {
+                        qcom,msm-dai-q6-id = <4107>;
+                };
+        };
+
+        qcom,msm-pcm-hostless {
+                compatible = "qcom,msm-pcm-hostless";
+        };
+
 	qcom,mss@fc880000 {
 		compatible = "qcom,pil-q6v5-mss";
 		reg = <0xfc880000 0x100>,
@@ -341,4 +388,8 @@
                compatible = "qcom,msm-rng";
                reg = <0xf9bff000 0x200>;
         };
+
+	qcom,qseecom@fe806000 {
+		compatible = "qcom,qseecom";
+	};
 };
diff --git a/arch/arm/boot/dts/msmcopper_pm.dtsi b/arch/arm/boot/dts/msmcopper_pm.dtsi
index 0da3200..79cb95c 100644
--- a/arch/arm/boot/dts/msmcopper_pm.dtsi
+++ b/arch/arm/boot/dts/msmcopper_pm.dtsi
@@ -27,11 +27,11 @@
 		qcom,saw2-avs-dly= <0>;
 		qcom,saw2-spm-dly= <0x20000400>;
 		qcom,saw2-spm-ctl = <0x1>;
-		qcom,spm-cmd-wfi = [03 0b 0f];
-		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
 				a0 b0 03 68 70 3b 92 a0 b0
 				82 2b 50 10 30 02 22 30 0f];
-		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+		qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
 				a0 b0 82 10 30 02 22 30 0f];
 	};
 
@@ -49,11 +49,11 @@
 		qcom,saw2-avs-dly= <0>;
 		qcom,saw2-spm-dly= <0x20000400>;
 		qcom,saw2-spm-ctl = <0x1>;
-		qcom,spm-cmd-wfi = [03 0b 0f];
-		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
 				a0 b0 03 68 70 3b 92 a0 b0
 				82 2b 50 10 30 02 22 30 0f];
-		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+		qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
 				a0 b0 82 10 30 02 22 30 0f];
 	};
 
@@ -71,11 +71,11 @@
 		qcom,saw2-avs-dly= <0>;
 		qcom,saw2-spm-dly= <0x20000400>;
 		qcom,saw2-spm-ctl = <0x1>;
-		qcom,spm-cmd-wfi = [03 0b 0f];
-		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
 				a0 b0 03 68 70 3b 92 a0 b0
 				82 2b 50 10 30 02 22 30 0f];
-		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+		qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
 				a0 b0 82 10 30 02 22 30 0f];
 	};
 
@@ -93,11 +93,11 @@
 		qcom,saw2-avs-dly= <0>;
 		qcom,saw2-spm-dly= <0x20000400>;
 		qcom,saw2-spm-ctl = <0x1>;
-		qcom,spm-cmd-wfi = [03 0b 0f];
-		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
 				a0 b0 03 68 70 3b 92 a0 b0
 				82 2b 50 10 30 02 22 30 0f];
-		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+		qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
 				a0 b0 82 10 30 02 22 30 0f];
 	};
 
@@ -123,12 +123,12 @@
 		qcom,vctl-timeout-us = <50>;
 		qcom,vctl-port = <0x0>; /* TODO: */
 		qcom,phase-port = <0x1>; /* TODO: */
-		qcom,spm-cmd-ret = [0b 00 20 03 22 00 0f];
-		qcom,spm-cmd-spc = [00 20 32 60 70 80 42 03
-				78 80 44 22 50 3b 60 02 32
-				50 0f];
-		qcom,spm-cmd-pc = [00 10 32 60 70 80 b0 11 42
-				07 01 b0 78 80 12 44 a0 50
+		qcom,saw2-spm-cmd-ret = [0b 00 20 03 22 00 0f];
+		qcom,saw2-spm-cmd-gdhs =  [00 20 32 60 70 80 0b 42 07
+				      78 80 44 22 50 3b 60 02 32
+				      50 0f];
+		qcom,saw2-spm-cmd-pc = [00 10 32 60 70 80 b0 11 0b
+				42 07 01 b0 78 80 12 44 a0 50
 				3b 60 02 32 a0 50 0f];
 	};
 
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 54a8392..174a799 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -248,28 +248,17 @@
 	u32 enabled;
 	unsigned long pending[32];
 	void __iomem *base = gic_data_dist_base(gic);
-#ifdef CONFIG_ARCH_MSM8625
-	unsigned long flags;
-#endif
 
 	if (!msm_show_resume_irq_mask)
 		return;
 
-#ifdef CONFIG_ARCH_MSM8625
-	raw_spin_lock_irqsave(&irq_controller_lock, flags);
-#else
 	raw_spin_lock(&irq_controller_lock);
-#endif
 	for (i = 0; i * 32 < gic->max_irq; i++) {
 		enabled = readl_relaxed(base + GIC_DIST_ENABLE_CLEAR + i * 4);
 		pending[i] = readl_relaxed(base + GIC_DIST_PENDING_SET + i * 4);
 		pending[i] &= enabled;
 	}
-#ifdef CONFIG_ARCH_MSM8625
-	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
-#else
-	raw_spin_lock(&irq_controller_lock);
-#endif
+	raw_spin_unlock(&irq_controller_lock);
 
 	for (i = find_first_bit(pending, gic->max_irq);
 	     i < gic->max_irq;
@@ -283,22 +272,14 @@
 {
 	unsigned int i;
 	void __iomem *base = gic_data_dist_base(gic);
-#ifdef CONFIG_ARCH_MSM8625
-	unsigned long flags;
-#endif
+
 	gic_show_resume_irq(gic);
 	for (i = 0; i * 32 < gic->max_irq; i++) {
-#ifdef CONFIG_ARCH_MSM8625
-		raw_spin_lock_irqsave(&irq_controller_lock, flags);
-#endif
 		/* disable all of them */
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4);
 		/* enable the enabled set */
 		writel_relaxed(gic->enabled_irqs[i],
 			base + GIC_DIST_ENABLE_SET + i * 4);
-#ifdef CONFIG_ARCH_MSM8625
-		raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
-#endif
 	}
 	mb();
 }
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 18f6d7f..4ba55de 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -32,6 +32,8 @@
 CONFIG_MSM_SMD_PKG3=y
 # CONFIG_MSM_SMD_DEBUG is not set
 CONFIG_MSM_ONCRPCROUTER=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 # CONFIG_MSM_ONCRPCROUTER_DEBUG is not set
 # CONFIG_MSM_HW3D is not set
 # CONFIG_QSD_AUDIO is not set
@@ -86,6 +88,7 @@
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
+CONFIG_MTD_UBI=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=8
 CONFIG_BLK_DEV_RAM_SIZE=16384
@@ -159,6 +162,7 @@
 CONFIG_TMPFS=y
 CONFIG_YAFFS_FS=y
 CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_UBIFS_FS=m
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_NLS_CODEPAGE_437=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index 4707556..ad1b6a6 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -32,6 +32,8 @@
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG3=y
 CONFIG_MSM_ONCRPCROUTER=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 # CONFIG_MSM_HW3D is not set
 # CONFIG_QSD_AUDIO is not set
 # CONFIG_SURF_FFA_GPIO_KEYPAD is not set
@@ -85,6 +87,7 @@
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
+CONFIG_MTD_UBI=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=8
 CONFIG_BLK_DEV_RAM_SIZE=16384
@@ -158,6 +161,7 @@
 CONFIG_TMPFS=y
 CONFIG_YAFFS_FS=y
 CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_UBIFS_FS=m
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_NLS_CODEPAGE_437=y
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 49fae4a..f6764d4 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -10,7 +10,6 @@
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
-# CONFIG_FAIR_GROUP_SCHED is not set
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
@@ -75,15 +74,26 @@
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
+CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=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
+# CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
@@ -98,9 +108,13 @@
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_KS8851=m
 # CONFIG_MSM_RMNET is not set
+CONFIG_DUMMY=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_INPUT_JOYSTICK=y
@@ -174,6 +188,7 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_NLS_CODEPAGE_437=y
@@ -198,6 +213,7 @@
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_DES=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 136dc46..7de7fee 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -261,6 +261,7 @@
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_VIDEOBUF2_MSM_MEM=y
 CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_MSM_KGSL=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 98661be..fe30dc8 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -416,7 +416,6 @@
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
 CONFIG_MSM_SSBI=y
-CONFIG_MSM_IOMMU=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index ec7c036..45339ee 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -418,7 +418,6 @@
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
 CONFIG_MSM_SSBI=y
-CONFIG_MSM_IOMMU=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 47d6ea8..362b4b2 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -90,6 +90,7 @@
 CONFIG_MSM_DLOAD_MODE=y
 CONFIG_MSM_QDSS=y
 CONFIG_MSM_SLEEP_STATS=y
+CONFIG_MSM_EBI_ERP=y
 CONFIG_MSM_CACHE_ERP=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
 CONFIG_MSM_DCVS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index a0636f9..8f4937a 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -91,6 +91,7 @@
 CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
+CONFIG_MSM_EBI_ERP=y
 CONFIG_MSM_CACHE_ERP=y
 CONFIG_MSM_L1_ERR_PANIC=y
 CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 1e45f66..bb3554b 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -85,6 +85,9 @@
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_AUTHENC=y
 CONFIG_CRYPTO_CBC=y
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index 2fecc60..a40f81e 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -25,7 +25,9 @@
 	ARM_PERF_PMU_ID_CA7,
 	ARM_PERF_PMU_ID_SCORPION,
 	ARM_PERF_PMU_ID_SCORPIONMP,
+	ARM_PERF_PMU_ID_SCORPIONMP_L2,
 	ARM_PERF_PMU_ID_KRAIT,
+	ARM_PERF_PMU_ID_KRAIT_L2,
 	ARM_NUM_PMU_IDS,
 };
 
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 1e54b58..37cbfcb 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -21,7 +21,7 @@
  */
 enum arm_pmu_type {
 	ARM_PMU_DEVICE_CPU	= 0,
-	ARM_PMU_DEVICE_L2	= 1,
+	ARM_PMU_DEVICE_L2CC	= 1,
 	ARM_NUM_PMU_DEVICES,
 };
 
@@ -129,11 +129,13 @@
 	u64		max_period;
 	struct platform_device	*plat_device;
 	struct pmu_hw_events	*(*get_hw_events)(void);
+	int	(*test_set_event_constraints)(struct perf_event *event);
+	int	(*clear_event_constraints)(struct perf_event *event);
 };
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
 
-int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+int armpmu_register(struct arm_pmu *armpmu, char *name, int type);
 
 u64 armpmu_event_update(struct perf_event *event,
 			struct hw_perf_event *hwc,
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 88cf368..87bb7d3 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -374,8 +374,10 @@
 {
 	int err;
 
-	if (!local_timer_is_architected())
+	if (timer_base)
 		arch_specific_timer = &arch_timer_ops_mem;
+	else if (!local_timer_is_architected())
+		return -ENXIO;
 
 	err = arch_timer_available();
 	if (err)
@@ -490,10 +492,12 @@
 		return -ENODEV;
 	}
 
-	timer_base = of_iomap(np, 0);
-	if (!timer_base) {
-		pr_err("arch_timer: cant map timer base\n");
-		return -ENOMEM;
+	if (of_get_address(np, 0, NULL, NULL)) {
+		timer_base = of_iomap(np, 0);
+		if (!timer_base) {
+			pr_err("arch_timer: cant map timer base\n");
+			return -ENOMEM;
+		}
 	}
 
 	if (of_get_property(np, "irq-is-not-percpu", NULL))
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index af6e7e6..e37b28b 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -28,6 +28,8 @@
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
+#include <linux/cpu_pm.h>
+
 /*
  * ARMv6 supports a maximum of 3 events, starting from index 0. If we add
  * another platform that supports more, we need to increase this to be the
@@ -271,6 +273,10 @@
 	hw_events->events[idx] = NULL;
 	clear_bit(idx, hw_events->used_mask);
 
+	/* Clear event constraints. */
+	if (armpmu->clear_event_constraints)
+		armpmu->clear_event_constraints(event);
+
 	perf_event_update_userpage(event);
 }
 
@@ -284,6 +290,17 @@
 	int err = 0;
 
 	perf_pmu_disable(event->pmu);
+	/*
+	 * Tests if event is constrained. If not sets it so that next
+	 * collision can be detected.
+	 */
+	if (armpmu->test_set_event_constraints)
+		if (armpmu->test_set_event_constraints(event) < 0) {
+			pr_err("Event: %llx failed constraint check.\n",
+					event->attr.config);
+			event->state = PERF_EVENT_STATE_OFF;
+			goto out;
+		}
 
 	/* If we don't have a space for the counter then finish early. */
 	idx = armpmu->get_event_idx(hw_events, hwc);
@@ -383,10 +400,7 @@
 {
 	int i, irq, irqs;
 	struct platform_device *pmu_device = armpmu->plat_device;
-#if 0
-	struct arm_pmu_platdata *plat =
-		dev_get_platdata(&pmu_device->dev);
-#endif
+
 	irqs = min(pmu_device->num_resources, num_possible_cpus());
 
 	for (i = 0; i < irqs; ++i) {
@@ -394,13 +408,6 @@
 			continue;
 		irq = platform_get_irq(pmu_device, i);
 		armpmu->free_pmu_irq(irq);
-#if 0
-		if (irq >= 0) {
-			if (plat && plat->disable_irq)
-				plat->disable_irq(irq);
-			free_irq(irq, armpmu);
-		}
-#endif
 	}
 
 	release_pmu(armpmu->type);
@@ -462,19 +469,6 @@
                         return err;
                 }
 
-#if 0
-		err = request_irq(irq, handle_irq,
-				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "arm-pmu", armpmu);
-		if (err) {
-			pr_err("unable to request IRQ%d for ARM PMU counters\n",
-				irq);
-			armpmu_release_hardware(armpmu);
-			return err;
-		} else if (plat && plat->enable_irq)
-			plat->enable_irq(irq);
-#endif
-
 		cpumask_set_cpu(i, &armpmu->active_irqs);
 	}
 
@@ -538,6 +532,7 @@
 		return -EPERM;
 	}
 
+
 	/*
 	 * Store the event encoding into the config_base field.
 	 */
@@ -616,7 +611,7 @@
 	armpmu->stop();
 }
 
-static void __init armpmu_init(struct arm_pmu *armpmu)
+static void armpmu_init(struct arm_pmu *armpmu)
 {
 	atomic_set(&armpmu->active_events, 0);
 	mutex_init(&armpmu->reserve_mutex);
@@ -633,7 +628,7 @@
 	};
 }
 
-int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
 {
 	armpmu_init(armpmu);
 	return perf_pmu_register(&armpmu->pmu, name, type);
@@ -644,6 +639,7 @@
 #include "perf_event_v6.c"
 #include "perf_event_v7.c"
 #include "perf_event_msm_krait.c"
+#include "perf_event_msm.c"
 
 /*
  * Ensure the PMU has sane values out of reset.
@@ -734,10 +730,76 @@
 	return NOTIFY_OK;
 }
 
+static void armpmu_update_counters(void)
+{
+	struct pmu_hw_events *hw_events;
+	int idx;
+
+	if (!cpu_pmu)
+		return;
+
+	hw_events = cpu_pmu->get_hw_events();
+
+	for (idx = 0; idx <= cpu_pmu->num_events; ++idx) {
+		struct perf_event *event = hw_events->events[idx];
+
+		if (!event)
+			continue;
+
+		armpmu_read(event);
+	}
+}
+
+static int cpu_has_active_perf(void)
+{
+	struct pmu_hw_events *hw_events;
+	int enabled;
+
+	if (!cpu_pmu)
+		return 0;
+
+	hw_events = cpu_pmu->get_hw_events();
+	enabled = bitmap_weight(hw_events->used_mask, cpu_pmu->num_events);
+
+	if (enabled)
+		/*Even one event's existence is good enough.*/
+		return 1;
+
+	return 0;
+}
+
 static struct notifier_block __cpuinitdata pmu_cpu_notifier = {
 	.notifier_call = pmu_cpu_notify,
 };
 
+/*TODO: Unify with pending patch from ARM */
+static int perf_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
+		void *v)
+{
+	switch (cmd) {
+	case CPU_PM_ENTER:
+		if (cpu_has_active_perf()) {
+			armpmu_update_counters();
+			perf_pmu_disable(&cpu_pmu->pmu);
+		}
+		break;
+
+	case CPU_PM_ENTER_FAILED:
+	case CPU_PM_EXIT:
+		if (cpu_has_active_perf() && cpu_pmu->reset) {
+			cpu_pmu->reset(NULL);
+			perf_pmu_enable(&cpu_pmu->pmu);
+		}
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block perf_cpu_pm_notifier_block = {
+	.notifier_call = perf_cpu_pm_notifier,
+};
+
 /*
  * CPU PMU identification and registration.
  */
@@ -790,11 +852,11 @@
 	} else if (0x51 == implementor) {
 		switch (part_number) {
 		case 0x00F0:    /* 8x50 & 7x30*/
-//			cpu_pmu = armv7_scorpion_pmu_init();
+			cpu_pmu = armv7_scorpion_pmu_init();
 			break;
 		case 0x02D0:    /* 8x60 */
 //			fabricmon_pmu_init();
-//			cpu_pmu = armv7_scorpionmp_pmu_init();
+			cpu_pmu = armv7_scorpionmp_pmu_init();
 //			scorpionmp_l2_pmu_init();
 			break;
 		case 0x0490:    /* 8960 sim */
@@ -814,6 +876,7 @@
 		cpu_pmu_init(cpu_pmu);
 		register_cpu_notifier(&pmu_cpu_notifier);
 		armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
+		cpu_pm_register_notifier(&perf_cpu_pm_notifier_block);
 	} else {
 		pr_info("no hardware support available\n");
 	}
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index 0ca5164..46fa8fe 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -12,7 +12,7 @@
  */
 
 #include <linux/cpumask.h>
-
+#include <asm/cp15.h>
 #include <asm/vfp.h>
 #include <asm/system.h>
 #include "../vfp/vfpinstr.h"
@@ -143,12 +143,16 @@
 		 * combined.
 		 */
 		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DCACHE_REFILL,
 		},
 		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DCACHE_REFILL,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
@@ -236,6 +240,13 @@
 	},
 };
 
+static int msm_scorpion_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_scorpion_perf_map,
+			&armv7_scorpion_perf_cache_map, 0xfffff);
+}
+
+
 struct scorpion_evt {
 	/*
 	 * The scorpion_evt_type field corresponds to the actual Scorpion
@@ -483,9 +494,9 @@
 	u32 v_orig_val;
 	u32 f_orig_val;
 
-	/* CPACR Enable CP10 access */
+	/* CPACR Enable CP10 and CP11 access */
 	v_orig_val = get_copro_access();
-	venum_new_val = v_orig_val | CPACC_SVC(10);
+	venum_new_val = v_orig_val | CPACC_SVC(10) | CPACC_SVC(11);
 	set_copro_access(venum_new_val);
 	/* Store orig venum val */
 	__get_cpu_var(venum_orig_val) = v_orig_val;
@@ -551,17 +562,13 @@
 
 static void scorpion_clear_pmuregs(void)
 {
-	unsigned long flags;
-
 	scorpion_write_lpm0(0);
 	scorpion_write_lpm1(0);
 	scorpion_write_lpm2(0);
 	scorpion_write_l2lpm(0);
-	raw_spin_lock_irqsave(&pmu_lock, flags);
 	scorpion_pre_vlpm();
 	scorpion_write_vlpm(0);
 	scorpion_post_vlpm();
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
 }
 
 static void scorpion_clearpmu(u32 grp, u32 val, u32 evt_code)
@@ -585,9 +592,11 @@
 	u32 gr;
 	unsigned long event;
 	struct scorpion_evt evtinfo;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+
 
 	/* Disable counter and interrupt */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 
 	/* Disable counter */
 	armv7_pmnc_disable_counter(idx);
@@ -596,7 +605,7 @@
 	 * Clear lpm code (if destined for PMNx counters)
 	 * We don't need to set the event if it's a cycle count
 	 */
-	if (idx != ARMV7_CYCLE_COUNTER) {
+	if (idx != ARMV7_IDX_CYCLE_COUNTER) {
 		val = hwc->config_base;
 		val &= SCORPION_EVTYPE_EVENT;
 
@@ -613,10 +622,11 @@
 	armv7_pmnc_disable_intens(idx);
 
 scorpion_dis_out:
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void scorpion_pmu_enable_event(struct hw_perf_event *hwc, int idx)
+static void scorpion_pmu_enable_event(struct hw_perf_event *hwc,
+		int idx, int cpu)
 {
 	unsigned long flags;
 	u32 val = 0;
@@ -624,12 +634,13 @@
 	unsigned long event;
 	struct scorpion_evt evtinfo;
 	unsigned long long prev_count = local64_read(&hwc->prev_count);
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	/*
 	 * Enable counter and interrupt, and set the counter to count
 	 * the event that we're interested in.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 
 	/* Disable counter */
 	armv7_pmnc_disable_counter(idx);
@@ -638,7 +649,7 @@
 	 * Set event (if destined for PMNx counters)
 	 * We don't need to set the event if it's a cycle count
 	 */
-	if (idx != ARMV7_CYCLE_COUNTER) {
+	if (idx != ARMV7_IDX_CYCLE_COUNTER) {
 		val = hwc->config_base;
 		val &= SCORPION_EVTYPE_EVENT;
 
@@ -673,59 +684,12 @@
 	armv7_pmnc_enable_counter(idx);
 
 scorpion_out:
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void enable_irq_callback(void *info)
-{
-	int irq = *(unsigned int *)info;
-
-	enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
-}
-
-static void disable_irq_callback(void *info)
-{
-	int irq = *(unsigned int *)info;
-
-	disable_percpu_irq(irq);
-}
-
-static int
-msm_request_irq(int irq, irq_handler_t *handle_irq)
-{
-	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
-msm_free_irq(int irq)
-{
-	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);
-	}
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void scorpion_pmu_reset(void *info)
 {
-	u32 idx, nb_cnt = armpmu->num_events;
+	u32 idx, nb_cnt = cpu_pmu->num_events;
 
 	/* Stop all counters and their interrupts */
 	for (idx = 1; idx < nb_cnt; ++idx) {
@@ -751,7 +715,7 @@
 	.disable		= scorpion_pmu_disable_event,
 	.read_counter		= armv7pmu_read_counter,
 	.write_counter		= armv7pmu_write_counter,
-	.raw_event_mask		= 0xFFFFF,
+	.map_event		= msm_scorpion_map_event,
 	.get_event_idx		= armv7pmu_get_event_idx,
 	.start			= armv7pmu_start,
 	.stop			= armv7pmu_stop,
@@ -759,33 +723,29 @@
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init armv7_scorpion_pmu_init(void)
+static struct arm_pmu *__init armv7_scorpion_pmu_init(void)
 {
 	scorpion_pmu.id		= ARM_PERF_PMU_ID_SCORPION;
 	scorpion_pmu.name	= "ARMv7 Scorpion";
-	scorpion_pmu.cache_map	= &armv7_scorpion_perf_cache_map;
-	scorpion_pmu.event_map	= &armv7_scorpion_perf_map;
 	scorpion_pmu.num_events	= armv7_read_num_pmnc_events();
 	scorpion_clear_pmuregs();
 	return &scorpion_pmu;
 }
 
-static const struct arm_pmu *__init armv7_scorpionmp_pmu_init(void)
+static struct arm_pmu *__init armv7_scorpionmp_pmu_init(void)
 {
 	scorpion_pmu.id		= ARM_PERF_PMU_ID_SCORPIONMP;
 	scorpion_pmu.name	= "ARMv7 Scorpion-MP";
-	scorpion_pmu.cache_map	= &armv7_scorpion_perf_cache_map;
-	scorpion_pmu.event_map	= &armv7_scorpion_perf_map;
 	scorpion_pmu.num_events	= armv7_read_num_pmnc_events();
 	scorpion_clear_pmuregs();
 	return &scorpion_pmu;
 }
 #else
-static const struct arm_pmu *__init armv7_scorpion_pmu_init(void)
+static struct arm_pmu *__init armv7_scorpion_pmu_init(void)
 {
 	return NULL;
 }
-static const struct arm_pmu *__init armv7_scorpionmp_pmu_init(void)
+static struct arm_pmu *__init armv7_scorpionmp_pmu_init(void)
 {
 	return NULL;
 }
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 8dbd047..1b115b4 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -58,6 +58,17 @@
 static u32 krait_ver, evt_index;
 static u32 krait_max_l1_reg;
 
+
+/*
+ * Every 4 bytes represents a prefix.
+ * Every nibble represents a register.
+ * Every bit represents a group within a register.
+ *
+ * This supports up to 4 groups per register, upto 8
+ * registers per prefix and upto 2 prefixes.
+ */
+static DEFINE_PER_CPU(u64, pmu_bitmap);
+
 static const unsigned armv7_krait_perf_map[PERF_COUNT_HW_MAX] = {
 	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
@@ -556,6 +567,58 @@
         }
 }
 
+/*
+ * We check for column exclusion constraints here.
+ * Two events cant have same reg and same group.
+ */
+static int msm_test_set_ev_constraint(struct perf_event *event)
+{
+	u32 krait_evt_type = event->attr.config & KRAIT_EVENT_MASK;
+	u8 prefix = (krait_evt_type & 0xF0000) >> 16;
+	u8 reg = (krait_evt_type & 0x0F000) >> 12;
+	u8 group = krait_evt_type & 0x0000F;
+	u64 cpu_pmu_bitmap = __get_cpu_var(pmu_bitmap);
+	u64 bitmap_t;
+
+	/* Return if non MSM event. */
+	if (!prefix)
+		return 0;
+
+	bitmap_t = 1 << (((prefix - 1) * 32) + (reg * 4) + group);
+
+	/* Set it if not already set. */
+	if (!(cpu_pmu_bitmap & bitmap_t)) {
+		cpu_pmu_bitmap |= bitmap_t;
+		__get_cpu_var(pmu_bitmap) = cpu_pmu_bitmap;
+		return 1;
+	}
+	/* Bit is already set. Constraint failed. */
+	return -EPERM;
+}
+
+static int msm_clear_ev_constraint(struct perf_event *event)
+{
+	u32 krait_evt_type = event->attr.config & KRAIT_EVENT_MASK;
+	u8 prefix = (krait_evt_type & 0xF0000) >> 16;
+	u8 reg = (krait_evt_type & 0x0F000) >> 12;
+	u8 group = krait_evt_type & 0x0000F;
+	u64 cpu_pmu_bitmap = __get_cpu_var(pmu_bitmap);
+	u64 bitmap_t;
+
+	/* Return if non MSM event. */
+	if (!prefix)
+		return 0;
+
+	bitmap_t = 1 << (((prefix - 1) * 32) + (reg * 4) + group);
+
+	/* Clear constraint bit. */
+	cpu_pmu_bitmap &= ~(bitmap_t);
+
+	__get_cpu_var(pmu_bitmap) = cpu_pmu_bitmap;
+
+	return 1;
+}
+
 static struct arm_pmu krait_pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
 	.request_pmu_irq	= msm_request_irq,
@@ -568,6 +631,8 @@
 	.start			= armv7pmu_start,
 	.stop			= armv7pmu_stop,
 	.reset			= krait_pmu_reset,
+	.test_set_event_constraints	= msm_test_set_ev_constraint,
+	.clear_event_constraints	= msm_clear_ev_constraint,
 	.max_period		= (1LLU << 32) - 1,
 };
 
diff --git a/arch/arm/kernel/perf_event_msm_krait_l2.c b/arch/arm/kernel/perf_event_msm_krait_l2.c
deleted file mode 100644
index baa05ac..0000000
--- a/arch/arm/kernel/perf_event_msm_krait_l2.c
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * 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.
- */
-#ifdef CONFIG_ARCH_MSM_KRAIT
-
-#include <linux/irq.h>
-
-#include <mach/msm-krait-l2-accessors.h>
-
-#define MAX_L2_PERIOD	((1ULL << 32) - 1)
-#define MAX_KRAIT_L2_CTRS 5
-
-#define L2PMCCNTR 0x409
-#define L2PMCCNTCR 0x408
-#define L2PMCCNTSR 0x40A
-#define L2CYCLE_CTR_BIT 31
-#define L2CYCLE_CTR_EVENT_IDX 4
-#define L2CYCLE_CTR_RAW_CODE 0xfe
-
-#define L2PMOVSR	0x406
-
-#define L2PMCR	0x400
-#define L2PMCR_RESET_ALL	0x6
-#define L2PMCR_GLOBAL_ENABLE	0x1
-#define L2PMCR_GLOBAL_DISABLE	0x0
-
-#define L2PMCNTENSET	0x403
-#define L2PMCNTENCLR	0x402
-
-#define L2PMINTENSET	0x405
-#define L2PMINTENCLR	0x404
-
-#define IA_L2PMXEVCNTCR_BASE	0x420
-#define IA_L2PMXEVTYPER_BASE	0x424
-#define IA_L2PMRESX_BASE	0x410
-#define IA_L2PMXEVFILTER_BASE	0x423
-#define IA_L2PMXEVCNTR_BASE	0x421
-
-/* event format is -e rsRCCG See get_event_desc() */
-
-#define EVENT_REG_MASK		0xf000
-#define EVENT_GROUPSEL_MASK	0x000f
-#define	EVENT_GROUPCODE_MASK	0x0ff0
-#define EVENT_REG_SHIFT		12
-#define EVENT_GROUPCODE_SHIFT	4
-
-#define	RESRX_VALUE_EN	0x80000000
-
-static struct platform_device *l2_pmu_device;
-
-struct hw_krait_l2_pmu {
-	struct perf_event *events[MAX_KRAIT_L2_CTRS];
-	unsigned long active_mask[BITS_TO_LONGS(MAX_KRAIT_L2_CTRS)];
-	raw_spinlock_t lock;
-};
-
-struct hw_krait_l2_pmu hw_krait_l2_pmu;
-
-struct event_desc {
-	int event_groupsel;
-	int event_reg;
-	int event_group_code;
-};
-
-void get_event_desc(u64 config, struct event_desc *evdesc)
-{
-	/* L2PMEVCNTRX */
-	evdesc->event_reg = (config & EVENT_REG_MASK) >> EVENT_REG_SHIFT;
-	/* Group code (row ) */
-	evdesc->event_group_code =
-	    (config & EVENT_GROUPCODE_MASK) >> EVENT_GROUPCODE_SHIFT;
-	/* Group sel (col) */
-	evdesc->event_groupsel = (config & EVENT_GROUPSEL_MASK);
-
-	pr_debug("%s: reg: %x, group_code: %x, groupsel: %x\n", __func__,
-		 evdesc->event_reg, evdesc->event_group_code,
-		 evdesc->event_groupsel);
-}
-
-static void set_evcntcr(int ctr)
-{
-	u32 evtcr_reg = (ctr * 16) + IA_L2PMXEVCNTCR_BASE;
-
-	set_l2_indirect_reg(evtcr_reg, 0x0);
-}
-
-static void set_evtyper(int event_groupsel, int event_reg, int ctr)
-{
-	u32 evtype_reg = (ctr * 16) + IA_L2PMXEVTYPER_BASE;
-	u32 evtype_val = event_groupsel + (4 * event_reg);
-
-	set_l2_indirect_reg(evtype_reg, evtype_val);
-}
-
-static void set_evres(int event_groupsel, int event_reg, int event_group_code)
-{
-	u32 group_reg = event_reg + IA_L2PMRESX_BASE;
-	u32 group_val =
-		RESRX_VALUE_EN | (event_group_code << (8 * event_groupsel));
-	u32 resr_val;
-	u32 group_byte = 0xff;
-	u32 group_mask = ~(group_byte << (8 * event_groupsel));
-
-	resr_val = get_l2_indirect_reg(group_reg);
-	resr_val &= group_mask;
-	resr_val |= group_val;
-
-	set_l2_indirect_reg(group_reg, resr_val);
-}
-
-static void set_evfilter_task_mode(int ctr)
-{
-	u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
-	u32 filter_val = 0x000f0030 | 1 << smp_processor_id();
-
-	set_l2_indirect_reg(filter_reg, filter_val);
-}
-
-static void set_evfilter_sys_mode(int ctr)
-{
-	u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
-	u32 filter_val = 0x000f003f;
-
-	set_l2_indirect_reg(filter_reg, filter_val);
-}
-
-static void enable_intenset(u32 idx)
-{
-	if (idx == L2CYCLE_CTR_EVENT_IDX)
-		set_l2_indirect_reg(L2PMINTENSET, 1 << L2CYCLE_CTR_BIT);
-	else
-		set_l2_indirect_reg(L2PMINTENSET, 1 << idx);
-}
-
-static void disable_intenclr(u32 idx)
-{
-	if (idx == L2CYCLE_CTR_EVENT_IDX)
-		set_l2_indirect_reg(L2PMINTENCLR, 1 << L2CYCLE_CTR_BIT);
-	else
-		set_l2_indirect_reg(L2PMINTENCLR, 1 << idx);
-}
-
-static void enable_counter(u32 idx)
-{
-	if (idx == L2CYCLE_CTR_EVENT_IDX)
-		set_l2_indirect_reg(L2PMCNTENSET, 1 << L2CYCLE_CTR_BIT);
-	else
-		set_l2_indirect_reg(L2PMCNTENSET, 1 << idx);
-}
-
-static void disable_counter(u32 idx)
-{
-	if (idx == L2CYCLE_CTR_EVENT_IDX)
-		set_l2_indirect_reg(L2PMCNTENCLR, 1 << L2CYCLE_CTR_BIT);
-	else
-		set_l2_indirect_reg(L2PMCNTENCLR, 1 << idx);
-}
-
-static u64 read_counter(u32 idx)
-{
-	u32 val;
-	u32 counter_reg = (idx * 16) + IA_L2PMXEVCNTR_BASE;
-
-	if (idx == L2CYCLE_CTR_EVENT_IDX)
-		val = get_l2_indirect_reg(L2PMCCNTR);
-	else
-		val = get_l2_indirect_reg(counter_reg);
-
-	return val;
-}
-
-static void write_counter(u32 idx, u32 val)
-{
-	u32 counter_reg = (idx * 16) + IA_L2PMXEVCNTR_BASE;
-
-	if (idx == L2CYCLE_CTR_EVENT_IDX)
-		set_l2_indirect_reg(L2PMCCNTR, val);
-	else
-		set_l2_indirect_reg(counter_reg, val);
-}
-
-static int
-pmu_event_set_period(struct perf_event *event,
-		     struct hw_perf_event *hwc, int idx)
-{
-	s64 left = local64_read(&hwc->period_left);
-	s64 period = hwc->sample_period;
-	int ret = 0;
-
-	if (unlikely(left <= -period)) {
-		left = period;
-		local64_set(&hwc->period_left, left);
-		hwc->last_period = period;
-		ret = 1;
-	}
-
-	if (unlikely(left <= 0)) {
-		left += period;
-		local64_set(&hwc->period_left, left);
-		hwc->last_period = period;
-		ret = 1;
-	}
-
-	if (left > (s64) MAX_L2_PERIOD)
-		left = MAX_L2_PERIOD;
-
-	local64_set(&hwc->prev_count, (u64)-left);
-
-	write_counter(idx, (u64) (-left) & 0xffffffff);
-
-	perf_event_update_userpage(event);
-
-	return ret;
-}
-
-static u64
-pmu_event_update(struct perf_event *event, struct hw_perf_event *hwc, int idx,
-		 int overflow)
-{
-	u64 prev_raw_count, new_raw_count;
-	u64 delta;
-
-again:
-	prev_raw_count = local64_read(&hwc->prev_count);
-	new_raw_count = read_counter(idx);
-
-	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-			    new_raw_count) != prev_raw_count)
-		goto again;
-
-	new_raw_count &= MAX_L2_PERIOD;
-	prev_raw_count &= MAX_L2_PERIOD;
-
-	if (overflow)
-		delta = MAX_L2_PERIOD - prev_raw_count + new_raw_count;
-	else
-		delta = new_raw_count - prev_raw_count;
-
-	local64_add(delta, &event->count);
-	local64_sub(delta, &hwc->period_left);
-
-	pr_debug("%s: new: %lld, prev: %lld, event: %ld count: %lld\n",
-		 __func__, new_raw_count, prev_raw_count,
-		 hwc->config_base, local64_read(&event->count));
-
-	return new_raw_count;
-}
-
-static void krait_l2_read(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	pmu_event_update(event, hwc, hwc->idx, 0);
-}
-
-static void krait_l2_stop_counter(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-
-	if (!(hwc->state & PERF_HES_STOPPED)) {
-		disable_intenclr(idx);
-		disable_counter(idx);
-
-		pmu_event_update(event, hwc, idx, 0);
-		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
-	}
-
-	pr_debug("%s: event: %ld ctr: %d stopped\n", __func__, hwc->config_base,
-		 idx);
-}
-
-static void krait_l2_start_counter(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-	struct event_desc evdesc;
-
-	if (flags & PERF_EF_RELOAD)
-		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
-
-	hwc->state = 0;
-
-	pmu_event_set_period(event, hwc, idx);
-
-	if (hwc->config_base == L2CYCLE_CTR_RAW_CODE)
-		goto out;
-
-	set_evcntcr(idx);
-
-	memset(&evdesc, 0, sizeof(evdesc));
-
-	get_event_desc(hwc->config_base, &evdesc);
-
-	set_evtyper(evdesc.event_groupsel, evdesc.event_reg, idx);
-
-	set_evres(evdesc.event_groupsel, evdesc.event_reg,
-		  evdesc.event_group_code);
-
-	if (event->cpu < 0)
-		set_evfilter_task_mode(idx);
-	else
-		set_evfilter_sys_mode(idx);
-
-out:
-	enable_intenset(idx);
-	enable_counter(idx);
-
-	pr_debug
-	    ("%s: ctr: %d group: %ld group_code: %lld started from cpu:%d\n",
-	     __func__, idx, hwc->config_base, hwc->config, smp_processor_id());
-}
-
-static void krait_l2_del_event(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-	unsigned long iflags;
-
-	raw_spin_lock_irqsave(&hw_krait_l2_pmu.lock, iflags);
-
-	clear_bit(idx, (long unsigned int *)(&hw_krait_l2_pmu.active_mask));
-
-	krait_l2_stop_counter(event, PERF_EF_UPDATE);
-	hw_krait_l2_pmu.events[idx] = NULL;
-	hwc->idx = -1;
-
-	raw_spin_unlock_irqrestore(&hw_krait_l2_pmu.lock, iflags);
-
-	pr_debug("%s: event: %ld deleted\n", __func__, hwc->config_base);
-
-	perf_event_update_userpage(event);
-}
-
-static int krait_l2_add_event(struct perf_event *event, int flags)
-{
-	int ctr = 0;
-	struct hw_perf_event *hwc = &event->hw;
-	unsigned long iflags;
-	int err = 0;
-
-	perf_pmu_disable(event->pmu);
-
-	raw_spin_lock_irqsave(&hw_krait_l2_pmu.lock, iflags);
-
-	/* Cycle counter has a resrvd index */
-	if (hwc->config_base == L2CYCLE_CTR_RAW_CODE) {
-		if (hw_krait_l2_pmu.events[L2CYCLE_CTR_EVENT_IDX]) {
-			pr_err("%s: Stale cycle ctr event ptr !\n", __func__);
-			err = -EINVAL;
-			goto out;
-		}
-		hwc->idx = L2CYCLE_CTR_EVENT_IDX;
-		hw_krait_l2_pmu.events[L2CYCLE_CTR_EVENT_IDX] = event;
-		set_bit(L2CYCLE_CTR_EVENT_IDX,
-			(long unsigned int *)&hw_krait_l2_pmu.active_mask);
-		goto skip_ctr_loop;
-	}
-
-	for (ctr = 0; ctr < MAX_KRAIT_L2_CTRS - 1; ctr++) {
-		if (!hw_krait_l2_pmu.events[ctr]) {
-			hwc->idx = ctr;
-			hw_krait_l2_pmu.events[ctr] = event;
-			set_bit(ctr,
-				(long unsigned int *)
-				&hw_krait_l2_pmu.active_mask);
-			break;
-		}
-	}
-
-	if (hwc->idx < 0) {
-		err = -ENOSPC;
-		pr_err("%s: No space for event: %llx!!\n", __func__,
-		       event->attr.config);
-		goto out;
-	}
-
-skip_ctr_loop:
-
-	disable_counter(hwc->idx);
-
-	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
-
-	if (flags & PERF_EF_START)
-		krait_l2_start_counter(event, PERF_EF_RELOAD);
-
-	perf_event_update_userpage(event);
-
-	pr_debug("%s: event: %ld, ctr: %d added from cpu:%d\n",
-		 __func__, hwc->config_base, hwc->idx, smp_processor_id());
-out:
-	raw_spin_unlock_irqrestore(&hw_krait_l2_pmu.lock, iflags);
-
-	/* Resume the PMU even if this event could not be added */
-	perf_pmu_enable(event->pmu);
-
-	return err;
-}
-
-static void krait_l2_pmu_enable(struct pmu *pmu)
-{
-	isb();
-	set_l2_indirect_reg(L2PMCR, L2PMCR_GLOBAL_ENABLE);
-}
-
-static void krait_l2_pmu_disable(struct pmu *pmu)
-{
-	set_l2_indirect_reg(L2PMCR, L2PMCR_GLOBAL_DISABLE);
-	isb();
-}
-
-u32 get_reset_pmovsr(void)
-{
-	int val;
-
-	val = get_l2_indirect_reg(L2PMOVSR);
-	/* reset it */
-	val &= 0xffffffff;
-	set_l2_indirect_reg(L2PMOVSR, val);
-
-	return val;
-}
-
-static irqreturn_t krait_l2_handle_irq(int irq_num, void *dev)
-{
-	unsigned long pmovsr;
-	struct perf_sample_data data;
-	struct pt_regs *regs;
-	struct perf_event *event;
-	struct hw_perf_event *hwc;
-	int bitp;
-	int idx = 0;
-
-	pmovsr = get_reset_pmovsr();
-
-	if (!(pmovsr & 0xffffffff))
-		return IRQ_NONE;
-
-	regs = get_irq_regs();
-
-	perf_sample_data_init(&data, 0);
-
-	raw_spin_lock(&hw_krait_l2_pmu.lock);
-
-	while (pmovsr) {
-		bitp = __ffs(pmovsr);
-
-		if (bitp == L2CYCLE_CTR_BIT)
-			idx = L2CYCLE_CTR_EVENT_IDX;
-		else
-			idx = bitp;
-
-		event = hw_krait_l2_pmu.events[idx];
-
-		if (!event)
-			goto next;
-
-		if (!test_bit(idx, hw_krait_l2_pmu.active_mask))
-			goto next;
-
-		hwc = &event->hw;
-		pmu_event_update(event, hwc, idx, 1);
-		data.period = event->hw.last_period;
-
-		if (!pmu_event_set_period(event, hwc, idx))
-			goto next;
-
-		if (perf_event_overflow(event, 0, &data, regs))
-			disable_counter(hwc->idx);
-next:
-		pmovsr &= (pmovsr - 1);
-	}
-
-	raw_spin_unlock(&hw_krait_l2_pmu.lock);
-
-	irq_work_run();
-
-	return IRQ_HANDLED;
-}
-
-static atomic_t active_l2_events = ATOMIC_INIT(0);
-static DEFINE_MUTEX(krait_pmu_reserve_mutex);
-
-static int pmu_reserve_hardware(void)
-{
-	int i, err = -ENODEV, irq;
-
-	l2_pmu_device = reserve_pmu(ARM_PMU_DEVICE_L2);
-
-	if (IS_ERR(l2_pmu_device)) {
-		pr_warning("unable to reserve pmu\n");
-		return PTR_ERR(l2_pmu_device);
-	}
-
-	if (l2_pmu_device->num_resources < 1) {
-		pr_err("no irqs for PMUs defined\n");
-		return -ENODEV;
-	}
-
-	if (strncmp(l2_pmu_device->name, "l2-arm-pmu", 6)) {
-		pr_err("Incorrect pdev reserved !\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < l2_pmu_device->num_resources; ++i) {
-		irq = platform_get_irq(l2_pmu_device, i);
-		if (irq < 0)
-			continue;
-
-		err = request_irq(irq, krait_l2_handle_irq,
-				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "krait-l2-pmu", NULL);
-		if (err) {
-			pr_warning("unable to request IRQ%d for Krait L2 perf "
-				   "counters\n", irq);
-			break;
-		}
-
-		irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
-	}
-
-	if (err) {
-		for (i = i - 1; i >= 0; --i) {
-			irq = platform_get_irq(l2_pmu_device, i);
-			if (irq >= 0)
-				free_irq(irq, NULL);
-		}
-		release_pmu(l2_pmu_device);
-		l2_pmu_device = NULL;
-	}
-
-	return err;
-}
-
-static void pmu_release_hardware(void)
-{
-	int i, irq;
-
-	for (i = l2_pmu_device->num_resources - 1; i >= 0; --i) {
-		irq = platform_get_irq(l2_pmu_device, i);
-		if (irq >= 0)
-			free_irq(irq, NULL);
-	}
-
-	krait_l2_pmu_disable(NULL);
-
-	release_pmu(l2_pmu_device);
-	l2_pmu_device = NULL;
-}
-
-static void pmu_perf_event_destroy(struct perf_event *event)
-{
-	if (atomic_dec_and_mutex_lock
-	    (&active_l2_events, &krait_pmu_reserve_mutex)) {
-		pmu_release_hardware();
-		mutex_unlock(&krait_pmu_reserve_mutex);
-	}
-}
-
-static int krait_l2_event_init(struct perf_event *event)
-{
-	int err = 0;
-	struct hw_perf_event *hwc = &event->hw;
-	int status = 0;
-
-	switch (event->attr.type) {
-	case PERF_TYPE_SHARED:
-		break;
-
-	default:
-		return -ENOENT;
-	}
-
-	hwc->idx = -1;
-
-	event->destroy = pmu_perf_event_destroy;
-
-	if (!atomic_inc_not_zero(&active_l2_events)) {
-		/* 0 active events */
-		mutex_lock(&krait_pmu_reserve_mutex);
-		err = pmu_reserve_hardware();
-		mutex_unlock(&krait_pmu_reserve_mutex);
-		if (!err)
-			atomic_inc(&active_l2_events);
-		else
-			return err;
-	}
-
-	hwc->config = 0;
-	hwc->event_base = 0;
-
-	/* Check if we came via perf default syms */
-	if (event->attr.config == PERF_COUNT_HW_L2_CYCLES)
-		hwc->config_base = L2CYCLE_CTR_RAW_CODE;
-	else
-		hwc->config_base = event->attr.config;
-
-	/* Only one CPU can control the cycle counter */
-	if (hwc->config_base == L2CYCLE_CTR_RAW_CODE) {
-		/* Check if its already running */
-		status = get_l2_indirect_reg(L2PMCCNTSR);
-		if (status == 0x2) {
-			err = -ENOSPC;
-			goto out;
-		}
-	}
-
-	if (!hwc->sample_period) {
-		hwc->sample_period = MAX_L2_PERIOD;
-		hwc->last_period = hwc->sample_period;
-		local64_set(&hwc->period_left, hwc->sample_period);
-	}
-
-	pr_debug("%s: event: %lld init'd\n", __func__, event->attr.config);
-
-out:
-	if (err < 0)
-		pmu_perf_event_destroy(event);
-
-	return err;
-}
-
-static struct pmu krait_l2_pmu = {
-	.pmu_enable = krait_l2_pmu_enable,
-	.pmu_disable = krait_l2_pmu_disable,
-	.event_init = krait_l2_event_init,
-	.add = krait_l2_add_event,
-	.del = krait_l2_del_event,
-	.start = krait_l2_start_counter,
-	.stop = krait_l2_stop_counter,
-	.read = krait_l2_read,
-};
-
-static const struct arm_pmu *__init krait_l2_pmu_init(void)
-{
-	/* Register our own PMU here */
-	perf_pmu_register(&krait_l2_pmu, "Krait L2", PERF_TYPE_SHARED);
-
-	memset(&hw_krait_l2_pmu, 0, sizeof(hw_krait_l2_pmu));
-
-	/* Reset all ctrs */
-	set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
-
-	/* 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;
-}
-#else
-
-static const struct arm_pmu *__init krait_l2_pmu_init(void)
-{
-	return NULL;
-}
-#endif
diff --git a/arch/arm/kernel/perf_event_msm_l2.c b/arch/arm/kernel/perf_event_msm_l2.c
deleted file mode 100644
index 26753d8..0000000
--- a/arch/arm/kernel/perf_event_msm_l2.c
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * 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.
- */
-#ifdef CONFIG_ARCH_MSM8X60
-
-#include <linux/irq.h>
-
-#define MAX_BB_L2_PERIOD	((1ULL << 32) - 1)
-#define MAX_BB_L2_CTRS 5
-#define BB_L2CYCLE_CTR_BIT 31
-#define BB_L2CYCLE_CTR_EVENT_IDX 4
-#define BB_L2CYCLE_CTR_RAW_CODE 0xfe
-#define SCORPIONL2_PMNC_E       (1 << 0)	/* Enable all counters */
-#define SCORPION_L2_EVT_PREFIX 3
-#define SCORPION_MAX_L2_REG 4
-
-/*
- * Lock to protect r/m/w sequences to the L2 PMU.
- */
-DEFINE_RAW_SPINLOCK(bb_l2_pmu_lock);
-
-static struct platform_device *bb_l2_pmu_device;
-
-struct hw_bb_l2_pmu {
-	struct perf_event *events[MAX_BB_L2_CTRS];
-	unsigned long active_mask[BITS_TO_LONGS(MAX_BB_L2_CTRS)];
-	raw_spinlock_t lock;
-};
-
-struct hw_bb_l2_pmu hw_bb_l2_pmu;
-
-struct bb_l2_scorp_evt {
-	u32 evt_type;
-	u32 val;
-	u8 grp;
-	u32 evt_type_act;
-};
-
-enum scorpion_perf_types {
-	SCORPIONL2_TOTAL_BANK_REQ = 0x90,
-	SCORPIONL2_DSIDE_READ = 0x91,
-	SCORPIONL2_DSIDE_WRITE = 0x92,
-	SCORPIONL2_ISIDE_READ = 0x93,
-	SCORPIONL2_L2CACHE_ISIDE_READ = 0x94,
-	SCORPIONL2_L2CACHE_BANK_REQ = 0x95,
-	SCORPIONL2_L2CACHE_DSIDE_READ = 0x96,
-	SCORPIONL2_L2CACHE_DSIDE_WRITE = 0x97,
-	SCORPIONL2_L2NOCACHE_DSIDE_WRITE = 0x98,
-	SCORPIONL2_L2NOCACHE_ISIDE_READ = 0x99,
-	SCORPIONL2_L2NOCACHE_TOTAL_REQ = 0x9a,
-	SCORPIONL2_L2NOCACHE_DSIDE_READ = 0x9b,
-	SCORPIONL2_DSIDE_READ_NOL1 = 0x9c,
-	SCORPIONL2_L2CACHE_WRITETHROUGH = 0x9d,
-	SCORPIONL2_BARRIERS = 0x9e,
-	SCORPIONL2_HARDWARE_TABLE_WALKS = 0x9f,
-	SCORPIONL2_MVA_POC = 0xa0,
-	SCORPIONL2_L2CACHE_HW_TABLE_WALKS = 0xa1,
-	SCORPIONL2_SETWAY_CACHE_OPS = 0xa2,
-	SCORPIONL2_DSIDE_WRITE_HITS = 0xa3,
-	SCORPIONL2_ISIDE_READ_HITS = 0xa4,
-	SCORPIONL2_CACHE_DSIDE_READ_NOL1 = 0xa5,
-	SCORPIONL2_TOTAL_CACHE_HITS = 0xa6,
-	SCORPIONL2_CACHE_MATCH_MISS = 0xa7,
-	SCORPIONL2_DREAD_HIT_L1_DATA = 0xa8,
-	SCORPIONL2_L2LINE_LOCKED = 0xa9,
-	SCORPIONL2_HW_TABLE_WALK_HIT = 0xaa,
-	SCORPIONL2_CACHE_MVA_POC = 0xab,
-	SCORPIONL2_L2ALLOC_DWRITE_MISS = 0xac,
-	SCORPIONL2_CORRECTED_TAG_ARRAY = 0xad,
-	SCORPIONL2_CORRECTED_DATA_ARRAY = 0xae,
-	SCORPIONL2_CORRECTED_REPLACEMENT_ARRAY = 0xaf,
-	SCORPIONL2_PMBUS_MPAAF = 0xb0,
-	SCORPIONL2_PMBUS_MPWDAF = 0xb1,
-	SCORPIONL2_PMBUS_MPBRT = 0xb2,
-	SCORPIONL2_CPU0_GRANT = 0xb3,
-	SCORPIONL2_CPU1_GRANT = 0xb4,
-	SCORPIONL2_CPU0_NOGRANT = 0xb5,
-	SCORPIONL2_CPU1_NOGRANT = 0xb6,
-	SCORPIONL2_CPU0_LOSING_ARB = 0xb7,
-	SCORPIONL2_CPU1_LOSING_ARB = 0xb8,
-	SCORPIONL2_SLAVEPORT_NOGRANT = 0xb9,
-	SCORPIONL2_SLAVEPORT_BPQ_FULL = 0xba,
-	SCORPIONL2_SLAVEPORT_LOSING_ARB = 0xbb,
-	SCORPIONL2_SLAVEPORT_GRANT = 0xbc,
-	SCORPIONL2_SLAVEPORT_GRANTLOCK = 0xbd,
-	SCORPIONL2_L2EM_STREX_PASS = 0xbe,
-	SCORPIONL2_L2EM_STREX_FAIL = 0xbf,
-	SCORPIONL2_LDREX_RESERVE_L2EM = 0xc0,
-	SCORPIONL2_SLAVEPORT_LDREX = 0xc1,
-	SCORPIONL2_CPU0_L2EM_CLEARED = 0xc2,
-	SCORPIONL2_CPU1_L2EM_CLEARED = 0xc3,
-	SCORPIONL2_SLAVEPORT_L2EM_CLEARED = 0xc4,
-	SCORPIONL2_CPU0_CLAMPED = 0xc5,
-	SCORPIONL2_CPU1_CLAMPED = 0xc6,
-	SCORPIONL2_CPU0_WAIT = 0xc7,
-	SCORPIONL2_CPU1_WAIT = 0xc8,
-	SCORPIONL2_CPU0_NONAMBAS_WAIT = 0xc9,
-	SCORPIONL2_CPU1_NONAMBAS_WAIT = 0xca,
-	SCORPIONL2_CPU0_DSB_WAIT = 0xcb,
-	SCORPIONL2_CPU1_DSB_WAIT = 0xcc,
-	SCORPIONL2_AXI_READ = 0xcd,
-	SCORPIONL2_AXI_WRITE = 0xce,
-
-	SCORPIONL2_1BEAT_WRITE = 0xcf,
-	SCORPIONL2_2BEAT_WRITE = 0xd0,
-	SCORPIONL2_4BEAT_WRITE = 0xd1,
-	SCORPIONL2_8BEAT_WRITE = 0xd2,
-	SCORPIONL2_12BEAT_WRITE = 0xd3,
-	SCORPIONL2_16BEAT_WRITE = 0xd4,
-	SCORPIONL2_1BEAT_DSIDE_READ = 0xd5,
-	SCORPIONL2_2BEAT_DSIDE_READ = 0xd6,
-	SCORPIONL2_4BEAT_DSIDE_READ = 0xd7,
-	SCORPIONL2_8BEAT_DSIDE_READ = 0xd8,
-	SCORPIONL2_CSYS_READ_1BEAT = 0xd9,
-	SCORPIONL2_CSYS_READ_2BEAT = 0xda,
-	SCORPIONL2_CSYS_READ_4BEAT = 0xdb,
-	SCORPIONL2_CSYS_READ_8BEAT = 0xdc,
-	SCORPIONL2_4BEAT_IFETCH_READ = 0xdd,
-	SCORPIONL2_8BEAT_IFETCH_READ = 0xde,
-	SCORPIONL2_CSYS_WRITE_1BEAT = 0xdf,
-	SCORPIONL2_CSYS_WRITE_2BEAT = 0xe0,
-	SCORPIONL2_AXI_READ_DATA_BEAT = 0xe1,
-	SCORPIONL2_AXI_WRITE_EVT1 = 0xe2,
-	SCORPIONL2_AXI_WRITE_EVT2 = 0xe3,
-	SCORPIONL2_LDREX_REQ = 0xe4,
-	SCORPIONL2_STREX_PASS = 0xe5,
-	SCORPIONL2_STREX_FAIL = 0xe6,
-	SCORPIONL2_CPREAD = 0xe7,
-	SCORPIONL2_CPWRITE = 0xe8,
-	SCORPIONL2_BARRIER_REQ = 0xe9,
-	SCORPIONL2_AXI_READ_SLVPORT = 0xea,
-	SCORPIONL2_AXI_WRITE_SLVPORT = 0xeb,
-	SCORPIONL2_AXI_READ_SLVPORT_DATABEAT = 0xec,
-	SCORPIONL2_AXI_WRITE_SLVPORT_DATABEAT = 0xed,
-	SCORPIONL2_SNOOPKILL_PREFILTER = 0xee,
-	SCORPIONL2_SNOOPKILL_FILTEROUT = 0xef,
-	SCORPIONL2_SNOOPED_IC = 0xf0,
-	SCORPIONL2_SNOOPED_BP = 0xf1,
-	SCORPIONL2_SNOOPED_BARRIERS = 0xf2,
-	SCORPIONL2_SNOOPED_TLB = 0xf3,
-	BB_L2_MAX_EVT,
-};
-
-static const struct bb_l2_scorp_evt sc_evt[] = {
-	{SCORPIONL2_TOTAL_BANK_REQ, 0x80000001, 0, 0x00},
-	{SCORPIONL2_DSIDE_READ, 0x80000100, 0, 0x01},
-	{SCORPIONL2_DSIDE_WRITE, 0x80010000, 0, 0x02},
-	{SCORPIONL2_ISIDE_READ, 0x81000000, 0, 0x03},
-	{SCORPIONL2_L2CACHE_ISIDE_READ, 0x80000002, 0, 0x00},
-	{SCORPIONL2_L2CACHE_BANK_REQ, 0x80000200, 0, 0x01},
-	{SCORPIONL2_L2CACHE_DSIDE_READ, 0x80020000, 0, 0x02},
-	{SCORPIONL2_L2CACHE_DSIDE_WRITE, 0x82000000, 0, 0x03},
-	{SCORPIONL2_L2NOCACHE_DSIDE_WRITE, 0x80000003, 0, 0x00},
-	{SCORPIONL2_L2NOCACHE_ISIDE_READ, 0x80000300, 0, 0x01},
-	{SCORPIONL2_L2NOCACHE_TOTAL_REQ, 0x80030000, 0, 0x02},
-	{SCORPIONL2_L2NOCACHE_DSIDE_READ, 0x83000000, 0, 0x03},
-	{SCORPIONL2_DSIDE_READ_NOL1, 0x80000004, 0, 0x00},
-	{SCORPIONL2_L2CACHE_WRITETHROUGH, 0x80000400, 0, 0x01},
-	{SCORPIONL2_BARRIERS, 0x84000000, 0, 0x03},
-	{SCORPIONL2_HARDWARE_TABLE_WALKS, 0x80000005, 0, 0x00},
-	{SCORPIONL2_MVA_POC, 0x80000500, 0, 0x01},
-	{SCORPIONL2_L2CACHE_HW_TABLE_WALKS, 0x80050000, 0, 0x02},
-	{SCORPIONL2_SETWAY_CACHE_OPS, 0x85000000, 0, 0x03},
-	{SCORPIONL2_DSIDE_WRITE_HITS, 0x80000006, 0, 0x00},
-	{SCORPIONL2_ISIDE_READ_HITS, 0x80000600, 0, 0x01},
-	{SCORPIONL2_CACHE_DSIDE_READ_NOL1, 0x80060000, 0, 0x02},
-	{SCORPIONL2_TOTAL_CACHE_HITS, 0x86000000, 0, 0x03},
-	{SCORPIONL2_CACHE_MATCH_MISS, 0x80000007, 0, 0x00},
-	{SCORPIONL2_DREAD_HIT_L1_DATA, 0x87000000, 0, 0x03},
-	{SCORPIONL2_L2LINE_LOCKED, 0x80000008, 0, 0x00},
-	{SCORPIONL2_HW_TABLE_WALK_HIT, 0x80000800, 0, 0x01},
-	{SCORPIONL2_CACHE_MVA_POC, 0x80080000, 0, 0x02},
-	{SCORPIONL2_L2ALLOC_DWRITE_MISS, 0x88000000, 0, 0x03},
-	{SCORPIONL2_CORRECTED_TAG_ARRAY, 0x80001A00, 0, 0x01},
-	{SCORPIONL2_CORRECTED_DATA_ARRAY, 0x801A0000, 0, 0x02},
-	{SCORPIONL2_CORRECTED_REPLACEMENT_ARRAY, 0x9A000000, 0, 0x03},
-	{SCORPIONL2_PMBUS_MPAAF, 0x80001C00, 0, 0x01},
-	{SCORPIONL2_PMBUS_MPWDAF, 0x801C0000, 0, 0x02},
-	{SCORPIONL2_PMBUS_MPBRT, 0x9C000000, 0, 0x03},
-
-	{SCORPIONL2_CPU0_GRANT, 0x80000001, 1, 0x04},
-	{SCORPIONL2_CPU1_GRANT, 0x80000100, 1, 0x05},
-	{SCORPIONL2_CPU0_NOGRANT, 0x80020000, 1, 0x06},
-	{SCORPIONL2_CPU1_NOGRANT, 0x82000000, 1, 0x07},
-	{SCORPIONL2_CPU0_LOSING_ARB, 0x80040000, 1, 0x06},
-	{SCORPIONL2_CPU1_LOSING_ARB, 0x84000000, 1, 0x07},
-	{SCORPIONL2_SLAVEPORT_NOGRANT, 0x80000007, 1, 0x04},
-	{SCORPIONL2_SLAVEPORT_BPQ_FULL, 0x80000700, 1, 0x05},
-	{SCORPIONL2_SLAVEPORT_LOSING_ARB, 0x80070000, 1, 0x06},
-	{SCORPIONL2_SLAVEPORT_GRANT, 0x87000000, 1, 0x07},
-	{SCORPIONL2_SLAVEPORT_GRANTLOCK, 0x80000008, 1, 0x04},
-	{SCORPIONL2_L2EM_STREX_PASS, 0x80000009, 1, 0x04},
-	{SCORPIONL2_L2EM_STREX_FAIL, 0x80000900, 1, 0x05},
-	{SCORPIONL2_LDREX_RESERVE_L2EM, 0x80090000, 1, 0x06},
-	{SCORPIONL2_SLAVEPORT_LDREX, 0x89000000, 1, 0x07},
-	{SCORPIONL2_CPU0_L2EM_CLEARED, 0x800A0000, 1, 0x06},
-	{SCORPIONL2_CPU1_L2EM_CLEARED, 0x8A000000, 1, 0x07},
-	{SCORPIONL2_SLAVEPORT_L2EM_CLEARED, 0x80000B00, 1, 0x05},
-	{SCORPIONL2_CPU0_CLAMPED, 0x8000000E, 1, 0x04},
-	{SCORPIONL2_CPU1_CLAMPED, 0x80000E00, 1, 0x05},
-	{SCORPIONL2_CPU0_WAIT, 0x800F0000, 1, 0x06},
-	{SCORPIONL2_CPU1_WAIT, 0x8F000000, 1, 0x07},
-	{SCORPIONL2_CPU0_NONAMBAS_WAIT, 0x80000010, 1, 0x04},
-	{SCORPIONL2_CPU1_NONAMBAS_WAIT, 0x80001000, 1, 0x05},
-	{SCORPIONL2_CPU0_DSB_WAIT, 0x80000014, 1, 0x04},
-	{SCORPIONL2_CPU1_DSB_WAIT, 0x80001400, 1, 0x05},
-
-	{SCORPIONL2_AXI_READ, 0x80000001, 2, 0x08},
-	{SCORPIONL2_AXI_WRITE, 0x80000100, 2, 0x09},
-	{SCORPIONL2_1BEAT_WRITE, 0x80010000, 2, 0x0a},
-	{SCORPIONL2_2BEAT_WRITE, 0x80010000, 2, 0x0b},
-	{SCORPIONL2_4BEAT_WRITE, 0x80000002, 2, 0x08},
-	{SCORPIONL2_8BEAT_WRITE, 0x80000200, 2, 0x09},
-	{SCORPIONL2_12BEAT_WRITE, 0x80020000, 2, 0x0a},
-	{SCORPIONL2_16BEAT_WRITE, 0x82000000, 2, 0x0b},
-	{SCORPIONL2_1BEAT_DSIDE_READ, 0x80000003, 2, 0x08},
-	{SCORPIONL2_2BEAT_DSIDE_READ, 0x80000300, 2, 0x09},
-	{SCORPIONL2_4BEAT_DSIDE_READ, 0x80030000, 2, 0x0a},
-	{SCORPIONL2_8BEAT_DSIDE_READ, 0x83000000, 2, 0x0b},
-	{SCORPIONL2_CSYS_READ_1BEAT, 0x80000004, 2, 0x08},
-	{SCORPIONL2_CSYS_READ_2BEAT, 0x80000400, 2, 0x09},
-	{SCORPIONL2_CSYS_READ_4BEAT, 0x80040000, 2, 0x0a},
-	{SCORPIONL2_CSYS_READ_8BEAT, 0x84000000, 2, 0x0b},
-	{SCORPIONL2_4BEAT_IFETCH_READ, 0x80000005, 2, 0x08},
-	{SCORPIONL2_8BEAT_IFETCH_READ, 0x80000500, 2, 0x09},
-	{SCORPIONL2_CSYS_WRITE_1BEAT, 0x80050000, 2, 0x0a},
-	{SCORPIONL2_CSYS_WRITE_2BEAT, 0x85000000, 2, 0x0b},
-	{SCORPIONL2_AXI_READ_DATA_BEAT, 0x80000600, 2, 0x09},
-	{SCORPIONL2_AXI_WRITE_EVT1, 0x80060000, 2, 0x0a},
-	{SCORPIONL2_AXI_WRITE_EVT2, 0x86000000, 2, 0x0b},
-	{SCORPIONL2_LDREX_REQ, 0x80000007, 2, 0x08},
-	{SCORPIONL2_STREX_PASS, 0x80000700, 2, 0x09},
-	{SCORPIONL2_STREX_FAIL, 0x80070000, 2, 0x0a},
-	{SCORPIONL2_CPREAD, 0x80000008, 2, 0x08},
-	{SCORPIONL2_CPWRITE, 0x80000800, 2, 0x09},
-	{SCORPIONL2_BARRIER_REQ, 0x88000000, 2, 0x0b},
-
-	{SCORPIONL2_AXI_READ_SLVPORT, 0x80000001, 3, 0x0c},
-	{SCORPIONL2_AXI_WRITE_SLVPORT, 0x80000100, 3, 0x0d},
-	{SCORPIONL2_AXI_READ_SLVPORT_DATABEAT, 0x80010000, 3, 0x0e},
-	{SCORPIONL2_AXI_WRITE_SLVPORT_DATABEAT, 0x81000000, 3, 0x0f},
-
-	{SCORPIONL2_SNOOPKILL_PREFILTER, 0x80000001, 4, 0x10},
-	{SCORPIONL2_SNOOPKILL_FILTEROUT, 0x80000100, 4, 0x11},
-	{SCORPIONL2_SNOOPED_IC, 0x80000002, 4, 0x10},
-	{SCORPIONL2_SNOOPED_BP, 0x80000200, 4, 0x11},
-	{SCORPIONL2_SNOOPED_BARRIERS, 0x80020000, 4, 0x12},
-	{SCORPIONL2_SNOOPED_TLB, 0x82000000, 4, 0x13},
-};
-
-static u32 bb_l2_read_l2pm0(void)
-{
-	u32 val;
-	asm volatile ("mrc p15, 3, %0, c15, c7, 0" : "=r" (val));
-	return val;
-}
-
-static void bb_l2_write_l2pm0(u32 val)
-{
-	asm volatile ("mcr p15, 3, %0, c15, c7, 0" : : "r" (val));
-}
-
-static u32 bb_l2_read_l2pm1(void)
-{
-	u32 val;
-	asm volatile ("mrc p15, 3, %0, c15, c7, 1" : "=r" (val));
-	return val;
-}
-
-static void bb_l2_write_l2pm1(u32 val)
-{
-	asm volatile ("mcr p15, 3, %0, c15, c7, 1" : : "r" (val));
-}
-
-static u32 bb_l2_read_l2pm2(void)
-{
-	u32 val;
-	asm volatile ("mrc p15, 3, %0, c15, c7, 2" : "=r" (val));
-	return val;
-}
-
-static void bb_l2_write_l2pm2(u32 val)
-{
-	asm volatile ("mcr p15, 3, %0, c15, c7, 2" : : "r" (val));
-}
-
-static u32 bb_l2_read_l2pm3(void)
-{
-	u32 val;
-	asm volatile ("mrc p15, 3, %0, c15, c7, 3" : "=r" (val));
-	return val;
-}
-
-static void bb_l2_write_l2pm3(u32 val)
-{
-	asm volatile ("mcr p15, 3, %0, c15, c7, 3" : : "r" (val));
-}
-
-static u32 bb_l2_read_l2pm4(void)
-{
-	u32 val;
-	asm volatile ("mrc p15, 3, %0, c15, c7, 4" : "=r" (val));
-	return val;
-}
-
-static void bb_l2_write_l2pm4(u32 val)
-{
-	asm volatile ("mcr p15, 3, %0, c15, c7, 4" : : "r" (val));
-}
-
-struct bb_scorpion_access_funcs {
-	u32(*read) (void);
-	void (*write) (u32);
-	void (*pre) (void);
-	void (*post) (void);
-};
-
-struct bb_scorpion_access_funcs bb_l2_func[] = {
-	{bb_l2_read_l2pm0, bb_l2_write_l2pm0, NULL, NULL},
-	{bb_l2_read_l2pm1, bb_l2_write_l2pm1, NULL, NULL},
-	{bb_l2_read_l2pm2, bb_l2_write_l2pm2, NULL, NULL},
-	{bb_l2_read_l2pm3, bb_l2_write_l2pm3, NULL, NULL},
-	{bb_l2_read_l2pm4, bb_l2_write_l2pm4, NULL, NULL},
-};
-
-#define COLMN0MASK 0x000000ff
-#define COLMN1MASK 0x0000ff00
-#define COLMN2MASK 0x00ff0000
-
-static u32 bb_l2_get_columnmask(u32 setval)
-{
-	if (setval & COLMN0MASK)
-		return 0xffffff00;
-	else if (setval & COLMN1MASK)
-		return 0xffff00ff;
-	else if (setval & COLMN2MASK)
-		return 0xff00ffff;
-	else
-		return 0x80ffffff;
-}
-
-static void bb_l2_evt_setup(u32 gr, u32 setval)
-{
-	u32 val;
-	if (bb_l2_func[gr].pre)
-		bb_l2_func[gr].pre();
-	val = bb_l2_get_columnmask(setval) & bb_l2_func[gr].read();
-	val = val | setval;
-	bb_l2_func[gr].write(val);
-	if (bb_l2_func[gr].post)
-		bb_l2_func[gr].post();
-}
-
-#define BB_L2_EVT_START_IDX 0x90
-#define BB_L2_INV_EVTYPE 0
-
-static unsigned int get_bb_l2_evtinfo(unsigned int evt_type,
-				      struct bb_l2_scorp_evt *evtinfo)
-{
-	u32 idx;
-	u8 prefix;
-	u8 reg;
-	u8 code;
-	u8 group;
-
-	prefix = (evt_type & 0xF0000) >> 16;
-	if (prefix == SCORPION_L2_EVT_PREFIX) {
-		reg   = (evt_type & 0x0F000) >> 12;
-		code  = (evt_type & 0x00FF0) >> 4;
-		group =  evt_type & 0x0000F;
-
-		if ((group > 3) || (reg > SCORPION_MAX_L2_REG))
-			return BB_L2_INV_EVTYPE;
-
-		evtinfo->val = 0x80000000 | (code << (group * 8));
-		evtinfo->grp = reg;
-		evtinfo->evt_type_act = group | (reg << 2);
-		return evtinfo->evt_type_act;
-	}
-
-	if (evt_type < BB_L2_EVT_START_IDX || evt_type >= BB_L2_MAX_EVT)
-		return BB_L2_INV_EVTYPE;
-	idx = evt_type - BB_L2_EVT_START_IDX;
-	if (sc_evt[idx].evt_type == evt_type) {
-		evtinfo->val = sc_evt[idx].val;
-		evtinfo->grp = sc_evt[idx].grp;
-		evtinfo->evt_type_act = sc_evt[idx].evt_type_act;
-		return sc_evt[idx].evt_type_act;
-	}
-	return BB_L2_INV_EVTYPE;
-}
-
-static inline void bb_l2_pmnc_write(unsigned long val)
-{
-	val &= 0xff;
-	asm volatile ("mcr p15, 3, %0, c15, c4, 0" : : "r" (val));
-}
-
-static inline unsigned long bb_l2_pmnc_read(void)
-{
-	u32 val;
-	asm volatile ("mrc p15, 3, %0, c15, c4, 0" : "=r" (val));
-	return val;
-}
-
-static void bb_l2_set_evcntcr(void)
-{
-	u32 val = 0x0;
-	asm volatile ("mcr p15, 3, %0, c15, c6, 4" : : "r" (val));
-}
-
-static inline void bb_l2_set_evtyper(int ctr, int val)
-{
-	/* select ctr */
-	asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (ctr));
-
-	/* write into EVTYPER */
-	asm volatile ("mcr p15, 3, %0, c15, c6, 7" : : "r" (val));
-}
-
-static void bb_l2_set_evfilter_task_mode(void)
-{
-	u32 filter_val = 0x000f0030 | 1 << smp_processor_id();
-
-	asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
-}
-
-static void bb_l2_set_evfilter_sys_mode(void)
-{
-	u32 filter_val = 0x000f003f;
-
-	asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
-}
-
-static void bb_l2_enable_intenset(u32 idx)
-{
-	if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
-		asm volatile ("mcr p15, 3, %0, c15, c5, 1" : : "r"
-			      (1 << BB_L2CYCLE_CTR_BIT));
-	} else {
-		asm volatile ("mcr p15, 3, %0, c15, c5, 1" : : "r" (1 << idx));
-	}
-}
-
-static void bb_l2_disable_intenclr(u32 idx)
-{
-	if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
-		asm volatile ("mcr p15, 3, %0, c15, c5, 0" : : "r"
-			      (1 << BB_L2CYCLE_CTR_BIT));
-	} else {
-		asm volatile ("mcr p15, 3, %0, c15, c5, 0" : : "r" (1 << idx));
-	}
-}
-
-static void bb_l2_enable_counter(u32 idx)
-{
-	if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
-		asm volatile ("mcr p15, 3, %0, c15, c4, 3" : : "r"
-			      (1 << BB_L2CYCLE_CTR_BIT));
-	} else {
-		asm volatile ("mcr p15, 3, %0, c15, c4, 3" : : "r" (1 << idx));
-	}
-}
-
-static void bb_l2_disable_counter(u32 idx)
-{
-	if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
-		asm volatile ("mcr p15, 3, %0, c15, c4, 2" : : "r"
-			      (1 << BB_L2CYCLE_CTR_BIT));
-
-	} else {
-		asm volatile ("mcr p15, 3, %0, c15, c4, 2" : : "r" (1 << idx));
-	}
-}
-
-static u64 bb_l2_read_counter(u32 idx)
-{
-	u32 val;
-	unsigned long flags;
-
-	if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
-		asm volatile ("mrc p15, 3, %0, c15, c4, 5" : "=r" (val));
-	} else {
-		raw_spin_lock_irqsave(&bb_l2_pmu_lock, flags);
-		asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (idx));
-
-		/* read val from counter */
-		asm volatile ("mrc p15, 3, %0, c15, c6, 5" : "=r" (val));
-		raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, flags);
-	}
-
-	return val;
-}
-
-static void bb_l2_write_counter(u32 idx, u32 val)
-{
-	unsigned long flags;
-
-	if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
-		asm volatile ("mcr p15, 3, %0, c15, c4, 5" : : "r" (val));
-	} else {
-		raw_spin_lock_irqsave(&bb_l2_pmu_lock, flags);
-		/* select counter */
-		asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (idx));
-
-		/* write val into counter */
-		asm volatile ("mcr p15, 3, %0, c15, c6, 5" : : "r" (val));
-		raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, flags);
-	}
-}
-
-static int
-bb_pmu_event_set_period(struct perf_event *event,
-			struct hw_perf_event *hwc, int idx)
-{
-	s64 left = local64_read(&hwc->period_left);
-	s64 period = hwc->sample_period;
-	int ret = 0;
-
-	if (unlikely(left <= -period)) {
-		left = period;
-		local64_set(&hwc->period_left, left);
-		hwc->last_period = period;
-		ret = 1;
-	}
-
-	if (unlikely(left <= 0)) {
-		left += period;
-		local64_set(&hwc->period_left, left);
-		hwc->last_period = period;
-		ret = 1;
-	}
-
-	if (left > (s64) MAX_BB_L2_PERIOD)
-		left = MAX_BB_L2_PERIOD;
-
-	local64_set(&hwc->prev_count, (u64)-left);
-
-	bb_l2_write_counter(idx, (u64) (-left) & 0xffffffff);
-
-	perf_event_update_userpage(event);
-
-	return ret;
-}
-
-static u64
-bb_pmu_event_update(struct perf_event *event, struct hw_perf_event *hwc,
-		    int idx, int overflow)
-{
-	u64 prev_raw_count, new_raw_count;
-	u64 delta;
-
-again:
-	prev_raw_count = local64_read(&hwc->prev_count);
-	new_raw_count = bb_l2_read_counter(idx);
-
-	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-			    new_raw_count) != prev_raw_count)
-		goto again;
-
-	new_raw_count &= MAX_BB_L2_PERIOD;
-	prev_raw_count &= MAX_BB_L2_PERIOD;
-
-	if (overflow) {
-		delta = MAX_BB_L2_PERIOD - prev_raw_count + new_raw_count;
-		pr_err("%s: delta: %lld\n", __func__, delta);
-	} else
-		delta = new_raw_count - prev_raw_count;
-
-	local64_add(delta, &event->count);
-	local64_sub(delta, &hwc->period_left);
-
-	pr_debug("%s: new: %lld, prev: %lld, event: %ld count: %lld\n",
-		 __func__, new_raw_count, prev_raw_count,
-		 hwc->config_base, local64_read(&event->count));
-
-	return new_raw_count;
-}
-
-static void bb_l2_read(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	bb_pmu_event_update(event, hwc, hwc->idx, 0);
-}
-
-static void bb_l2_stop_counter(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-
-	if (!(hwc->state & PERF_HES_STOPPED)) {
-		bb_l2_disable_intenclr(idx);
-		bb_l2_disable_counter(idx);
-
-		bb_pmu_event_update(event, hwc, idx, 0);
-		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
-	}
-
-	pr_debug("%s: event: %ld ctr: %d stopped\n", __func__, hwc->config_base,
-		 idx);
-}
-
-static void bb_l2_start_counter(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-	struct bb_l2_scorp_evt evtinfo;
-	int evtype = hwc->config_base;
-	int ev_typer;
-	unsigned long iflags;
-	int cpu_id = smp_processor_id();
-
-	if (flags & PERF_EF_RELOAD)
-		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
-
-	hwc->state = 0;
-
-	bb_pmu_event_set_period(event, hwc, idx);
-
-	if (hwc->config_base == BB_L2CYCLE_CTR_RAW_CODE)
-		goto out;
-
-	memset(&evtinfo, 0, sizeof(evtinfo));
-
-	ev_typer = get_bb_l2_evtinfo(evtype, &evtinfo);
-
-	raw_spin_lock_irqsave(&bb_l2_pmu_lock, iflags);
-
-	bb_l2_set_evtyper(idx, ev_typer);
-
-	bb_l2_set_evcntcr();
-
-	if (event->cpu < 0)
-		bb_l2_set_evfilter_task_mode();
-	else
-		bb_l2_set_evfilter_sys_mode();
-
-	bb_l2_evt_setup(evtinfo.grp, evtinfo.val);
-
-	raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, iflags);
-
-out:
-
-	bb_l2_enable_intenset(idx);
-
-	bb_l2_enable_counter(idx);
-
-	pr_debug("%s: idx: %d, event: %d, val: %x, cpu: %d\n",
-		 __func__, idx, evtype, evtinfo.val, cpu_id);
-}
-
-static void bb_l2_del_event(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-	unsigned long iflags;
-
-	raw_spin_lock_irqsave(&hw_bb_l2_pmu.lock, iflags);
-
-	clear_bit(idx, (long unsigned int *)(&hw_bb_l2_pmu.active_mask));
-
-	bb_l2_stop_counter(event, PERF_EF_UPDATE);
-	hw_bb_l2_pmu.events[idx] = NULL;
-	hwc->idx = -1;
-
-	raw_spin_unlock_irqrestore(&hw_bb_l2_pmu.lock, iflags);
-
-	pr_debug("%s: event: %ld deleted\n", __func__, hwc->config_base);
-
-	perf_event_update_userpage(event);
-}
-
-static int bb_l2_add_event(struct perf_event *event, int flags)
-{
-	int ctr = 0;
-	struct hw_perf_event *hwc = &event->hw;
-	unsigned long iflags;
-	int err = 0;
-
-	perf_pmu_disable(event->pmu);
-
-	raw_spin_lock_irqsave(&hw_bb_l2_pmu.lock, iflags);
-
-	/* Cycle counter has a resrvd index */
-	if (hwc->config_base == BB_L2CYCLE_CTR_RAW_CODE) {
-		if (hw_bb_l2_pmu.events[BB_L2CYCLE_CTR_EVENT_IDX]) {
-			pr_err("%s: Stale cycle ctr event ptr !\n", __func__);
-			err = -EINVAL;
-			goto out;
-		}
-		hwc->idx = BB_L2CYCLE_CTR_EVENT_IDX;
-		hw_bb_l2_pmu.events[BB_L2CYCLE_CTR_EVENT_IDX] = event;
-		set_bit(BB_L2CYCLE_CTR_EVENT_IDX,
-			(long unsigned int *)&hw_bb_l2_pmu.active_mask);
-		goto skip_ctr_loop;
-	}
-
-	for (ctr = 0; ctr < MAX_BB_L2_CTRS - 1; ctr++) {
-		if (!hw_bb_l2_pmu.events[ctr]) {
-			hwc->idx = ctr;
-			hw_bb_l2_pmu.events[ctr] = event;
-			set_bit(ctr, (long unsigned int *)
-				&hw_bb_l2_pmu.active_mask);
-			break;
-		}
-	}
-
-	if (hwc->idx < 0) {
-		err = -ENOSPC;
-		pr_err("%s: No space for event: %llx!!\n", __func__,
-		       event->attr.config);
-		goto out;
-	}
-
-skip_ctr_loop:
-
-	bb_l2_disable_counter(hwc->idx);
-
-	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
-
-	if (flags & PERF_EF_START)
-		bb_l2_start_counter(event, PERF_EF_RELOAD);
-
-	perf_event_update_userpage(event);
-
-	pr_debug("%s: event: %ld, ctr: %d added from cpu:%d\n",
-		 __func__, hwc->config_base, hwc->idx, smp_processor_id());
-out:
-	raw_spin_unlock_irqrestore(&hw_bb_l2_pmu.lock, iflags);
-
-	/* Resume the PMU even if this event could not be added */
-	perf_pmu_enable(event->pmu);
-
-	return err;
-}
-
-static void bb_l2_pmu_enable(struct pmu *pmu)
-{
-	unsigned long flags;
-	isb();
-	raw_spin_lock_irqsave(&bb_l2_pmu_lock, flags);
-	/* Enable all counters */
-	bb_l2_pmnc_write(bb_l2_pmnc_read() | SCORPIONL2_PMNC_E);
-	raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, flags);
-}
-
-static void bb_l2_pmu_disable(struct pmu *pmu)
-{
-	unsigned long flags;
-	raw_spin_lock_irqsave(&bb_l2_pmu_lock, flags);
-	/* Disable all counters */
-	bb_l2_pmnc_write(bb_l2_pmnc_read() & ~SCORPIONL2_PMNC_E);
-	raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, flags);
-	isb();
-}
-
-static inline u32 bb_l2_get_reset_pmovsr(void)
-{
-	u32 val;
-
-	/* Read */
-	asm volatile ("mrc p15, 3, %0, c15, c4, 1" : "=r" (val));
-
-	/* Write to clear flags */
-	val &= 0xffffffff;
-	asm volatile ("mcr p15, 3, %0, c15, c4, 1" : : "r" (val));
-
-	return val;
-}
-
-static irqreturn_t bb_l2_handle_irq(int irq_num, void *dev)
-{
-	unsigned long pmovsr;
-	struct perf_sample_data data;
-	struct pt_regs *regs;
-	struct perf_event *event;
-	struct hw_perf_event *hwc;
-	int bitp;
-	int idx = 0;
-
-	pmovsr = bb_l2_get_reset_pmovsr();
-
-	if (!(pmovsr & 0xffffffff))
-		return IRQ_NONE;
-
-	regs = get_irq_regs();
-
-	perf_sample_data_init(&data, 0);
-
-	raw_spin_lock(&hw_bb_l2_pmu.lock);
-
-	while (pmovsr) {
-		bitp = __ffs(pmovsr);
-
-		if (bitp == BB_L2CYCLE_CTR_BIT)
-			idx = BB_L2CYCLE_CTR_EVENT_IDX;
-		else
-			idx = bitp;
-
-		event = hw_bb_l2_pmu.events[idx];
-
-		if (!event)
-			goto next;
-
-		if (!test_bit(idx, hw_bb_l2_pmu.active_mask))
-			goto next;
-
-		hwc = &event->hw;
-		bb_pmu_event_update(event, hwc, idx, 1);
-		data.period = event->hw.last_period;
-
-		if (!bb_pmu_event_set_period(event, hwc, idx))
-			goto next;
-
-		if (perf_event_overflow(event, 0, &data, regs))
-			bb_l2_disable_counter(hwc->idx);
-next:
-		pmovsr &= (pmovsr - 1);
-	}
-
-	raw_spin_unlock(&hw_bb_l2_pmu.lock);
-
-	irq_work_run();
-
-	return IRQ_HANDLED;
-}
-
-static atomic_t active_bb_l2_events = ATOMIC_INIT(0);
-static DEFINE_MUTEX(bb_pmu_reserve_mutex);
-
-static int bb_pmu_reserve_hardware(void)
-{
-	int i, err = -ENODEV, irq;
-
-	bb_l2_pmu_device = reserve_pmu(ARM_PMU_DEVICE_L2);
-
-	if (IS_ERR(bb_l2_pmu_device)) {
-		pr_warning("unable to reserve pmu\n");
-		return PTR_ERR(bb_l2_pmu_device);
-	}
-
-	if (bb_l2_pmu_device->num_resources < 1) {
-		pr_err("no irqs for PMUs defined\n");
-		return -ENODEV;
-	}
-
-	if (strncmp(bb_l2_pmu_device->name, "l2-arm-pmu", 6)) {
-		pr_err("Incorrect pdev reserved !\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < bb_l2_pmu_device->num_resources; ++i) {
-		irq = platform_get_irq(bb_l2_pmu_device, i);
-		if (irq < 0)
-			continue;
-
-		err = request_irq(irq, bb_l2_handle_irq,
-				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "bb-l2-pmu", NULL);
-		if (err) {
-			pr_warning("unable to request IRQ%d for Krait L2 perf "
-				   "counters\n", irq);
-			break;
-		}
-
-		irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
-	}
-
-	if (err) {
-		for (i = i - 1; i >= 0; --i) {
-			irq = platform_get_irq(bb_l2_pmu_device, i);
-			if (irq >= 0)
-				free_irq(irq, NULL);
-		}
-		release_pmu(bb_l2_pmu_device);
-		bb_l2_pmu_device = NULL;
-	}
-
-	return err;
-}
-
-static void bb_pmu_release_hardware(void)
-{
-	int i, irq;
-
-	for (i = bb_l2_pmu_device->num_resources - 1; i >= 0; --i) {
-		irq = platform_get_irq(bb_l2_pmu_device, i);
-		if (irq >= 0)
-			free_irq(irq, NULL);
-	}
-
-	bb_l2_pmu_disable(NULL);
-
-	release_pmu(bb_l2_pmu_device);
-	bb_l2_pmu_device = NULL;
-}
-
-static void bb_pmu_perf_event_destroy(struct perf_event *event)
-{
-	if (atomic_dec_and_mutex_lock
-	    (&active_bb_l2_events, &bb_pmu_reserve_mutex)) {
-		bb_pmu_release_hardware();
-		mutex_unlock(&bb_pmu_reserve_mutex);
-	}
-}
-
-static int bb_l2_event_init(struct perf_event *event)
-{
-	int err = 0;
-	struct hw_perf_event *hwc = &event->hw;
-	int status = 0;
-
-	switch (event->attr.type) {
-	case PERF_TYPE_SHARED:
-		break;
-
-	default:
-		return -ENOENT;
-	}
-
-	hwc->idx = -1;
-
-	event->destroy = bb_pmu_perf_event_destroy;
-
-	if (!atomic_inc_not_zero(&active_bb_l2_events)) {
-		/* 0 active events */
-		mutex_lock(&bb_pmu_reserve_mutex);
-		err = bb_pmu_reserve_hardware();
-		mutex_unlock(&bb_pmu_reserve_mutex);
-		if (!err)
-			atomic_inc(&active_bb_l2_events);
-		else
-			return err;
-	}
-
-	hwc->config = 0;
-	hwc->event_base = 0;
-
-	/* Check if we came via perf default syms */
-	if (event->attr.config == PERF_COUNT_HW_L2_CYCLES)
-		hwc->config_base = BB_L2CYCLE_CTR_RAW_CODE;
-	else
-		hwc->config_base = event->attr.config;
-
-	/* Only one CPU can control the cycle counter */
-	if (hwc->config_base == BB_L2CYCLE_CTR_RAW_CODE) {
-		/* Check if its already running */
-		asm volatile ("mrc p15, 3, %0, c15, c4, 6" : "=r" (status));
-		if (status == 0x2) {
-			err = -ENOSPC;
-			goto out;
-		}
-	}
-
-	if (!hwc->sample_period) {
-		hwc->sample_period = MAX_BB_L2_PERIOD;
-		hwc->last_period = hwc->sample_period;
-		local64_set(&hwc->period_left, hwc->sample_period);
-	}
-
-	pr_debug("%s: event: %lld init'd\n", __func__, event->attr.config);
-
-out:
-	if (err < 0)
-		bb_pmu_perf_event_destroy(event);
-
-	return err;
-}
-
-static struct pmu bb_l2_pmu = {
-	.pmu_enable = bb_l2_pmu_enable,
-	.pmu_disable = bb_l2_pmu_disable,
-	.event_init = bb_l2_event_init,
-	.add = bb_l2_add_event,
-	.del = bb_l2_del_event,
-	.start = bb_l2_start_counter,
-	.stop = bb_l2_stop_counter,
-	.read = bb_l2_read,
-};
-
-static const struct arm_pmu *__init scorpionmp_l2_pmu_init(void)
-{
-	/* Register our own PMU here */
-	perf_pmu_register(&bb_l2_pmu, "BB L2", PERF_TYPE_SHARED);
-
-	memset(&hw_bb_l2_pmu, 0, sizeof(hw_bb_l2_pmu));
-
-	/* 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;
-}
-#else
-
-static const struct arm_pmu *__init scorpionmp_l2_pmu_init(void)
-{
-	return NULL;
-}
-
-#endif
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 08b65db..304520b 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -242,6 +242,9 @@
 	select SPARSE_IRQ
 	select MSM_RPM_SMD
 	select REGULATOR
+	select MSM_QDSP6_APR
+	select MSM_QDSP6V2_CODECS
+	select MSM_AUDIO_QDSP6V2 if SND_SOC
 
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
@@ -2173,6 +2176,15 @@
 	  used by audio driver to configure QDSP6's
 	  ASM, ADM and AFE.
 
+config MSM_QDSP6V2_CODECS
+	bool "Audio QDSP6V2 APR support"
+	depends on MSM_SMD
+	help
+	  Enable Audio codecs with APR IPC protocol support between
+	  application processor and QDSP6 for B-family. APR is
+	  used by audio driver to configure QDSP6's
+	  ASM, ADM and AFE.
+
 config MSM_AUDIO_QDSP6
         bool "QDSP6 HW Audio support"
         select SND_SOC_MSM_QDSP6_INTF
@@ -2181,6 +2193,16 @@
           Enable HW audio support in QDSP6.
           QDSP6 can support HW encoder & decoder and audio processing
 
+config MSM_AUDIO_QDSP6V2
+        bool "QDSP6V2 HW Audio support"
+        select SND_SOC_MSM_QDSP6V2_INTF
+        help
+          Enable HW audio support in QDSP6V2.
+          QDSP6V2 can support HW encoder & decoder and
+          audio processing. It will enable support for
+          AAC, AMRNB, AMRWB, EVRC, MP3, QCELP among
+          others.
+
 config MSM_ULTRASOUND
 	bool "MSM ultrasound support"
 	depends on MSM_AUDIO_QDSP6
@@ -2257,6 +2279,16 @@
 	  separately. This will guarantee that the last acesses for each cpu
 	  will be logged but there will be fewer entries per cpu
 
+config MSM_EBI_ERP
+	bool "External Bus Interface (EBI) error reporting"
+	help
+	  Say 'Y' here to enable reporting of external bus interface errors to
+	  the kernel log. Information such as the offending address and
+	  transaction type will be logged. This may be useful for debugging
+	  seemingly broken memory accesses.
+
+	  For production builds, you should probably say 'N' here.
+
 config MSM_CACHE_ERP
 	bool "Cache / CPU error reporting"
 	depends on ARCH_MSM_KRAIT
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 5cc9471..1896059 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -25,7 +25,8 @@
 obj-y += acpuclock.o
 obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o clock-pll.o
 obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
-obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o
+obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
+obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
 obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o
 
 ifndef CONFIG_MSM_SMP
@@ -155,6 +156,7 @@
 obj-$(CONFIG_MSM_QDSP6) += qdsp6/
 obj-$(CONFIG_MSM8X60_AUDIO) += qdsp6v2/
 obj-$(CONFIG_MSM_AUDIO_QDSP6) += qdsp6v2/
+obj-$(CONFIG_MSM_AUDIO_QDSP6V2) += qdsp6v2/
 obj-$(CONFIG_MSM_HW3D) += hw3d.o
 obj-$(CONFIG_PM) += pm-boot.o
 obj-$(CONFIG_MSM_PM8X60) += pm-8x60.o pm-data.o
@@ -331,6 +333,7 @@
 obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
 endif
 obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o
 
 obj-$(CONFIG_ARCH_MSM7X27) += gpiomux-7x27.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
@@ -364,6 +367,7 @@
 obj-$(CONFIG_ARCH_MSM8960) += mdm2.o mdm_common.o
 obj-$(CONFIG_MSM_RTB) += msm_rtb.o
 obj-$(CONFIG_MSM_CACHE_ERP) += cache_erp.o
+obj-$(CONFIG_MSM_EBI_ERP) += ebi_erp.o
 obj-$(CONFIG_MSM_CACHE_DUMP) += msm_cache_dump.o
 
 obj-$(CONFIG_MSM_HSIC_SYSMON) += hsic_sysmon.o
diff --git a/arch/arm/mach-msm/acpuclock-7627.c b/arch/arm/mach-msm/acpuclock-7627.c
index 7c2c556..f9ff226 100644
--- a/arch/arm/mach-msm/acpuclock-7627.c
+++ b/arch/arm/mach-msm/acpuclock-7627.c
@@ -18,6 +18,7 @@
 
 #include <linux/version.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -27,6 +28,8 @@
 #include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/sort.h>
+#include <linux/platform_device.h>
+
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
@@ -402,7 +405,7 @@
 #ifdef CONFIG_CPU_FREQ_MSM
 static struct cpufreq_frequency_table freq_table[NR_CPUS][20];
 
-static void __init cpufreq_table_init(void)
+static void __devinit cpufreq_table_init(void)
 {
 	int cpu;
 	for_each_possible_cpu(cpu) {
@@ -693,7 +696,7 @@
 	return rc;
 }
 
-static void __init acpuclk_hw_init(void)
+static void __devinit acpuclk_hw_init(void)
 {
 	struct clkctl_acpu_speed *speed;
 	uint32_t div, sel, reg_clksel;
@@ -775,7 +778,7 @@
  * Clock driver initialization
  *---------------------------------------------------------------------------*/
 #define MHZ 1000000
-static void __init select_freq_plan(void)
+static void __devinit select_freq_plan(void)
 {
 	unsigned long pll_mhz[ACPU_PLL_END];
 	struct pll_freq_tbl_map *t;
@@ -835,7 +838,7 @@
  * Hardware requires the CPU to be dropped to less than MAX_WAIT_FOR_IRQ_KHZ
  * before entering a wait for irq low-power mode. Find a suitable rate.
  */
-static unsigned long __init find_wait_for_irq_khz(void)
+static unsigned long __devinit find_wait_for_irq_khz(void)
 {
 	unsigned long found_khz = 0;
 	int i;
@@ -847,7 +850,7 @@
 	return found_khz;
 }
 
-static void __init lpj_init(void)
+static void __devinit lpj_init(void)
 {
 	int i = 0, cpu;
 	const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
@@ -868,7 +871,7 @@
 	}
 }
 
-static void __init precompute_stepping(void)
+static void __devinit precompute_stepping(void)
 {
 	int i, step_idx;
 
@@ -909,7 +912,7 @@
 	}
 }
 
-static void __init print_acpu_freq_tbl(void)
+static void __devinit print_acpu_freq_tbl(void)
 {
 	struct clkctl_acpu_speed *t;
 	short down_idx[ACPU_PLL_END];
@@ -947,15 +950,17 @@
 	.switch_time_us = 50,
 };
 
-static int __init acpuclk_7627_init(struct acpuclk_soc_data *soc_data)
+static int __devinit acpuclk_7627_probe(struct platform_device *pdev)
 {
+	const struct acpuclk_pdata *pdata = pdev->dev.platform_data;
+
 	pr_info("%s()\n", __func__);
 
 	drv_state.ebi1_clk = clk_get(NULL, "ebi1_acpu_clk");
 	BUG_ON(IS_ERR(drv_state.ebi1_clk));
 
 	mutex_init(&drv_state.lock);
-	drv_state.max_speed_delta_khz = soc_data->max_speed_delta_khz;
+	drv_state.max_speed_delta_khz = pdata->max_speed_delta_khz;
 	select_freq_plan();
 	acpuclk_7627_data.wait_for_irq_khz = find_wait_for_irq_khz();
 	precompute_stepping();
@@ -970,23 +975,16 @@
 	return 0;
 }
 
-struct acpuclk_soc_data acpuclk_7x27_soc_data __initdata = {
-	.max_speed_delta_khz = 400000,
-	.init = acpuclk_7627_init,
+static struct platform_driver acpuclk_7627_driver = {
+	.probe = acpuclk_7627_probe,
+	.driver = {
+		.name = "acpuclk-7627",
+		.owner = THIS_MODULE,
+	},
 };
 
-struct acpuclk_soc_data acpuclk_7x27a_soc_data __initdata = {
-	.max_speed_delta_khz = 400000,
-	.init = acpuclk_7627_init,
-};
-
-struct acpuclk_soc_data acpuclk_7x27aa_soc_data __initdata = {
-	.max_speed_delta_khz = 504000,
-	.init = acpuclk_7627_init,
-};
-
-struct acpuclk_soc_data acpuclk_8625_soc_data __initdata = {
-	/* TODO: Need to update speed delta from H/w Team */
-	.max_speed_delta_khz = 604800,
-	.init = acpuclk_7627_init,
-};
+static int __init acpuclk_7627_init(void)
+{
+	return platform_driver_register(&acpuclk_7627_driver);
+}
+postcore_initcall(acpuclk_7627_init);
diff --git a/arch/arm/mach-msm/acpuclock-7x30.c b/arch/arm/mach-msm/acpuclock-7x30.c
index 29b0065..b49613e 100644
--- a/arch/arm/mach-msm/acpuclock-7x30.c
+++ b/arch/arm/mach-msm/acpuclock-7x30.c
@@ -16,6 +16,7 @@
 
 #include <linux/version.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -25,6 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/sort.h>
+#include <linux/platform_device.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 #include <asm/mach-types.h>
@@ -315,7 +317,7 @@
  * Clock driver initialization
  *---------------------------------------------------------------------------*/
 
-static void __init acpuclk_hw_init(void)
+static void __devinit acpuclk_hw_init(void)
 {
 	struct clkctl_acpu_speed *s;
 	uint32_t div, sel, src_num;
@@ -393,7 +395,7 @@
 }
 
 /* Initalize the lpj field in the acpu_freq_tbl. */
-static void __init lpj_init(void)
+static void __devinit lpj_init(void)
 {
 	int i;
 	const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
@@ -431,7 +433,7 @@
  * Truncate the frequency table at the current PLL2 rate and determine the
  * backup PLL to use when scaling PLL2.
  */
-void __init pll2_fixup(void)
+void __devinit pll2_fixup(void)
 {
 	struct clkctl_acpu_speed *speed = acpu_freq_tbl;
 	u8 pll2_l = readl_relaxed(PLL2_L_VAL_ADDR) & 0xFF;
@@ -453,7 +455,7 @@
 #define RPM_BYPASS_MASK	(1 << 3)
 #define PMIC_MODE_MASK	(1 << 4)
 
-static void __init populate_plls(void)
+static void __devinit populate_plls(void)
 {
 	acpuclk_sources[PLL_1] = clk_get_sys("acpu", "pll1_clk");
 	BUG_ON(IS_ERR(acpuclk_sources[PLL_1]));
@@ -479,7 +481,7 @@
 	.switch_time_us = 50,
 };
 
-static int __init acpuclk_7x30_init(struct acpuclk_soc_data *soc_data)
+static int __devinit acpuclk_7x30_probe(struct platform_device *pdev)
 {
 	pr_info("%s()\n", __func__);
 
@@ -494,6 +496,16 @@
 	return 0;
 }
 
-struct acpuclk_soc_data acpuclk_7x30_soc_data __initdata = {
-	.init = acpuclk_7x30_init,
+static struct platform_driver acpuclk_7x30_driver = {
+	.probe = acpuclk_7x30_probe,
+	.driver = {
+		.name = "acpuclk-7x30",
+		.owner = THIS_MODULE,
+	},
 };
+
+static int __init acpuclk_7x30_init(void)
+{
+	return platform_driver_register(&acpuclk_7x30_driver);
+}
+postcore_initcall(acpuclk_7x30_init);
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index a58eb6e..d29fee6 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -13,6 +13,7 @@
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/delay.h>
@@ -22,6 +23,7 @@
 #include <linux/cpufreq.h>
 #include <linux/cpu.h>
 #include <linux/regulator/consumer.h>
+#include <linux/platform_device.h>
 
 #include <asm/mach-types.h>
 #include <asm/cpu.h>
@@ -660,7 +662,7 @@
 	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1175000 },
 	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1187500 },
 	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1187500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1212500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1200000 },
 	{ 0, { 0 } }
 };
 
@@ -687,7 +689,7 @@
 	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1125000 },
 	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1137500 },
 	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1137500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1175000 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1150000 },
 	{ 0, { 0 } }
 };
 
@@ -715,27 +717,80 @@
 };
 
 /* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl_8930[] = {
-	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   925000 },
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   925000 },
-	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   937500 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   962500 },
-	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   987500 },
+static struct acpu_level acpu_freq_tbl_8930_slow[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
+	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   975000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   975000 },
+	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),  1000000 },
 	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),  1000000 },
 	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),  1025000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),  1037500 },
-	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1062500 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1087500 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),  1025000 },
+	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1075000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1075000 },
 	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1100000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1125000 },
-	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(16), 1137500 },
-	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1162500 },
-	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1187500 },
-	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1200000 },
-	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1225000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1100000 },
+	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(11), 1125000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1125000 },
+	{ 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(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 },
 	{ 0, { 0 } }
 };
 
+static struct acpu_level acpu_freq_tbl_8930_nom[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   925000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   925000 },
+	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   950000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   950000 },
+	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   975000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   975000 },
+	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),  1000000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),  1000000 },
+	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1050000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1050000 },
+	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1075000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1075000 },
+	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(11), 1100000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1100000 },
+	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1150000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1150000 },
+	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1175000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1175000 },
+	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1200000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1200000 },
+	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1212500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_8930_fast[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
+	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   900000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   900000 },
+	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   925000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   925000 },
+	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),   950000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),   950000 },
+	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1000000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1000000 },
+	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
+	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(11), 1050000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1050000 },
+	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1100000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1100000 },
+	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1125000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1125000 },
+	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1150000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1150000 },
+	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1162500 },
+	{ 0, { 0 } }
+};
 /* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
 #undef L2
 #define L2(x) (&l2_freq_tbl_8627[(x)])
@@ -793,6 +848,12 @@
 	[PVS_FASTER] = acpu_freq_tbl_8064_fast,
 };
 
+static struct acpu_level *acpu_freq_tbl_8930_pvs[NUM_PVS] __initdata = {
+	[PVS_SLOW] = acpu_freq_tbl_8930_slow,
+	[PVS_NOM] = acpu_freq_tbl_8930_nom,
+	[PVS_FAST] = acpu_freq_tbl_8930_fast,
+};
+
 static unsigned long acpuclk_8960_get_rate(int cpu)
 {
 	return scalable[cpu].current_speed->khz;
@@ -1560,8 +1621,10 @@
 		l2_freq_tbl = l2_freq_tbl_8627;
 		l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8627);
 	} else if (cpu_is_msm8930()) {
+		enum pvs pvs_id = get_pvs();
+
 		scalable = scalable_8930;
-		acpu_freq_tbl = acpu_freq_tbl_8930;
+		acpu_freq_tbl = acpu_freq_tbl_8930_pvs[pvs_id];
 		l2_freq_tbl = l2_freq_tbl_8930;
 		l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8930);
 	} else {
@@ -1588,7 +1651,7 @@
 	.wait_for_irq_khz = STBY_KHZ,
 };
 
-static int __init acpuclk_8960_init(struct acpuclk_soc_data *soc_data)
+static int __init acpuclk_8960_probe(struct platform_device *pdev)
 {
 	struct acpu_level *max_acpu_level = select_freq_plan();
 
@@ -1606,14 +1669,15 @@
 	return 0;
 }
 
-struct acpuclk_soc_data acpuclk_8960_soc_data __initdata = {
-	.init = acpuclk_8960_init,
+static struct platform_driver acpuclk_8960_driver = {
+	.driver = {
+		.name = "acpuclk-8960",
+		.owner = THIS_MODULE,
+	},
 };
 
-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,
-};
+static int __init acpuclk_8960_init(void)
+{
+	return platform_driver_probe(&acpuclk_8960_driver, acpuclk_8960_probe);
+}
+device_initcall(acpuclk_8960_init);
diff --git a/arch/arm/mach-msm/acpuclock-8x50.c b/arch/arm/mach-msm/acpuclock-8x50.c
index cde5a14..996f883 100644
--- a/arch/arm/mach-msm/acpuclock-8x50.c
+++ b/arch/arm/mach-msm/acpuclock-8x50.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
@@ -12,6 +12,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/delay.h>
@@ -20,6 +21,7 @@
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/mfd/tps65023.h>
+#include <linux/platform_device.h>
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
@@ -130,7 +132,7 @@
 #ifdef CONFIG_CPU_FREQ_MSM
 static struct cpufreq_frequency_table freq_table[20];
 
-static void __init cpufreq_table_init(void)
+static void __devinit cpufreq_table_init(void)
 {
 	unsigned int i;
 	unsigned int freq_cnt = 0;
@@ -504,7 +506,7 @@
 	return rc;
 }
 
-static void __init acpuclk_hw_init(void)
+static void __devinit acpuclk_hw_init(void)
 {
 	struct clkctl_acpu_speed *speed;
 	uint32_t div, sel, regval;
@@ -582,7 +584,7 @@
 
 #define PLL0_M_VAL_ADDR		(MSM_CLK_CTL_BASE + 0x308)
 
-static void __init acpu_freq_tbl_fixup(void)
+static void __devinit acpu_freq_tbl_fixup(void)
 {
 	void __iomem *ct_csr_base;
 	uint32_t tcsr_spare2, pll0_m_val;
@@ -645,7 +647,7 @@
 }
 
 /* Initalize the lpj field in the acpu_freq_tbl. */
-static void __init lpj_init(void)
+static void __devinit lpj_init(void)
 {
 	int i;
 	const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
@@ -657,7 +659,7 @@
 }
 
 #ifdef CONFIG_MSM_CPU_AVS
-static int __init acpu_avs_init(int (*set_vdd) (int), int khz)
+static int __devinit acpu_avs_init(int (*set_vdd) (int), int khz)
 {
 	int i;
 	int freq_count = 0;
@@ -704,7 +706,7 @@
 	.switch_time_us = 20,
 };
 
-static int __init acpuclk_8x50_init(struct acpuclk_soc_data *soc_data)
+static int __devinit acpuclk_8x50_probe(struct platform_device *pdev)
 {
 	mutex_init(&drv_state.lock);
 	drv_state.acpu_set_vdd = qsd8x50_tps65023_set_dcdc1;
@@ -736,6 +738,16 @@
 	return 0;
 }
 
-struct acpuclk_soc_data acpuclk_8x50_soc_data __initdata = {
-	.init = acpuclk_8x50_init,
+static struct platform_driver acpuclk_8x50_driver = {
+	.probe = acpuclk_8x50_probe,
+	.driver = {
+		.name = "acpuclk-8x50",
+		.owner = THIS_MODULE,
+	},
 };
+
+static int __init acpuclk_8x50_init(void)
+{
+	return platform_driver_register(&acpuclk_8x50_driver);
+}
+postcore_initcall(acpuclk_8x50_init);
diff --git a/arch/arm/mach-msm/acpuclock-8x60.c b/arch/arm/mach-msm/acpuclock-8x60.c
index 48efa18..ef34b3c 100644
--- a/arch/arm/mach-msm/acpuclock-8x60.c
+++ b/arch/arm/mach-msm/acpuclock-8x60.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/delay.h>
@@ -20,6 +21,7 @@
 #include <linux/cpufreq.h>
 #include <linux/cpu.h>
 #include <linux/regulator/consumer.h>
+#include <linux/platform_device.h>
 
 #include <asm/cpu.h>
 
@@ -734,7 +736,7 @@
 	}
 
 	/* AVS needs SAW_VCTL to be intitialized correctly, before enable,
-	 * and is not initialized at acpuclk_init().
+	 * and is not initialized during probe.
 	 */
 	if (reason == SETRATE_CPUFREQ)
 		AVS_DISABLE(cpu);
@@ -1062,7 +1064,7 @@
 	.wait_for_irq_khz = MAX_AXI,
 };
 
-static int __init acpuclk_8x60_init(struct acpuclk_soc_data *soc_data)
+static int __init acpuclk_8x60_probe(struct platform_device *pdev)
 {
 	struct clkctl_acpu_speed *max_freq;
 	int cpu;
@@ -1091,6 +1093,15 @@
 	return 0;
 }
 
-struct acpuclk_soc_data acpuclk_8x60_soc_data __initdata = {
-	.init = acpuclk_8x60_init,
+static struct platform_driver acpuclk_8x60_driver = {
+	.driver = {
+		.name = "acpuclk-8x60",
+		.owner = THIS_MODULE,
+	},
 };
+
+static int __init acpuclk_8x60_init(void)
+{
+	return platform_driver_probe(&acpuclk_8x60_driver, acpuclk_8x60_probe);
+}
+device_initcall(acpuclk_8x60_init);
diff --git a/arch/arm/mach-msm/acpuclock-9615.c b/arch/arm/mach-msm/acpuclock-9615.c
index 8882f41..db7bab3 100644
--- a/arch/arm/mach-msm/acpuclock-9615.c
+++ b/arch/arm/mach-msm/acpuclock-9615.c
@@ -14,6 +14,7 @@
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/delay.h>
@@ -22,6 +23,7 @@
 #include <linux/errno.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
+#include <linux/platform_device.h>
 
 #include <asm/cpu.h>
 
@@ -39,7 +41,6 @@
 #define REG_CLKDIV_1	(MSM_APCS_GLB_BASE + 0x14)
 #define REG_CLKOUTSEL	(MSM_APCS_GLB_BASE + 0x18)
 
-#define MAX_VDD_CPU	1150000
 #define MAX_VDD_MEM	1150000
 
 enum clk_src {
@@ -111,12 +112,12 @@
 static uint32_t bus_perf_client;
 
 static struct clkctl_acpu_speed acpu_freq_tbl[] = {
-	{ 0,  19200, SRC_CXO,  0, 0,  950000, 1050000, 0 },
-	{ 1, 138000, SRC_PLL0, 6, 1,  950000, 1050000, 2 },
-	{ 1, 276000, SRC_PLL0, 6, 0, 1050000, 1050000, 2 },
-	{ 1, 384000, SRC_PLL8, 3, 0, 1150000, 1150000, 4 },
+	{ 0,  19200, SRC_CXO,  0, 0, RPM_VREG_CORNER_LOW,     1050000, 0 },
+	{ 1, 138000, SRC_PLL0, 6, 1, RPM_VREG_CORNER_LOW,     1050000, 2 },
+	{ 1, 276000, SRC_PLL0, 6, 0, RPM_VREG_CORNER_NOMINAL, 1050000, 2 },
+	{ 1, 384000, SRC_PLL8, 3, 0, RPM_VREG_CORNER_HIGH,    1150000, 4 },
 	/* The row below may be changed at runtime depending on hw rev. */
-	{ 1, 440000, SRC_PLL9, 2, 0, 1150000, 1150000, 4 },
+	{ 1, 440000, SRC_PLL9, 2, 0, RPM_VREG_CORNER_HIGH,    1150000, 4 },
 	{ 0 }
 };
 
@@ -171,8 +172,8 @@
 		return rc;
 	}
 
-	rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_S1, RPM_VREG_VOTER1,
-				  vdd_cpu, MAX_VDD_CPU, 0);
+	rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_VDD_DIG_CORNER,
+			RPM_VREG_VOTER1, vdd_cpu, RPM_VREG_CORNER_HIGH, 0);
 	if (rc)
 		pr_err("vdd_cpu increase failed (%d)\n", rc);
 
@@ -185,8 +186,9 @@
 	int ret;
 
 	/* Update CPU voltage. */
-	ret = rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_S1, RPM_VREG_VOTER1,
-				  vdd_cpu, MAX_VDD_CPU, 0);
+	ret = rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_VDD_DIG_CORNER,
+		RPM_VREG_VOTER1, vdd_cpu, RPM_VREG_CORNER_HIGH, 0);
+
 	if (ret) {
 		pr_err("vdd_cpu decrease failed (%d)\n", ret);
 		return;
@@ -306,7 +308,7 @@
 	.wait_for_irq_khz = 19200,
 };
 
-static int __init acpuclk_9615_init(struct acpuclk_soc_data *soc_data)
+static int __init acpuclk_9615_probe(struct platform_device *pdev)
 {
 	unsigned long max_cpu_khz = 0;
 	int i;
@@ -351,6 +353,15 @@
 	return 0;
 }
 
-struct acpuclk_soc_data acpuclk_9615_soc_data __initdata = {
-	.init = acpuclk_9615_init,
+static struct platform_driver acpuclk_9615_driver = {
+	.driver = {
+		.name = "acpuclk-9615",
+		.owner = THIS_MODULE,
+	},
 };
+
+static int __init acpuclk_9615_init(void)
+{
+	return platform_driver_probe(&acpuclk_9615_driver, acpuclk_9615_probe);
+}
+device_initcall(acpuclk_9615_init);
diff --git a/arch/arm/mach-msm/acpuclock-fsm9xxx.c b/arch/arm/mach-msm/acpuclock-fsm9xxx.c
index 3cdc58d..af1c0eb 100644
--- a/arch/arm/mach-msm/acpuclock-fsm9xxx.c
+++ b/arch/arm/mach-msm/acpuclock-fsm9xxx.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
@@ -11,8 +11,10 @@
  *
  */
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 #include <mach/board.h>
 
 #include "acpuclock.h"
@@ -40,13 +42,22 @@
 	.get_rate = acpuclk_9xxx_get_rate,
 };
 
-static int __init acpuclk_9xxx_init(struct acpuclk_soc_data *soc_data)
+static int __init acpuclk_9xxx_probe(struct platform_device *pdev)
 {
 	acpuclk_register(&acpuclk_9xxx_data);
 	pr_info("ACPU running at %lu KHz\n", acpuclk_get_rate(0));
 	return 0;
 }
 
-struct acpuclk_soc_data acpuclk_9xxx_soc_data __initdata = {
-	.init = acpuclk_9xxx_init,
+static struct platform_driver acpuclk_9xxx_driver = {
+	.driver = {
+		.name = "acpuclk-9xxx",
+		.owner = THIS_MODULE,
+	},
 };
+
+static int __init acpuclk_9xxx_init(void)
+{
+	return platform_driver_probe(&acpuclk_9xxx_driver, acpuclk_9xxx_probe);
+}
+device_initcall(acpuclk_9xxx_init);
diff --git a/arch/arm/mach-msm/acpuclock.c b/arch/arm/mach-msm/acpuclock.c
index 91071c4..be056e6 100644
--- a/arch/arm/mach-msm/acpuclock.c
+++ b/arch/arm/mach-msm/acpuclock.c
@@ -53,24 +53,7 @@
 	return rate;
 }
 
-void __init acpuclk_register(struct acpuclk_data *data)
+void __devinit acpuclk_register(struct acpuclk_data *data)
 {
 	acpuclk_data = data;
 }
-
-int __init acpuclk_init(struct acpuclk_soc_data *soc_data)
-{
-	int rc;
-
-	if (!soc_data->init)
-		return -EINVAL;
-
-	rc = soc_data->init(soc_data);
-	if (rc)
-		return rc;
-
-	if (!acpuclk_data)
-		return -ENODEV;
-
-	return 0;
-}
diff --git a/arch/arm/mach-msm/acpuclock.h b/arch/arm/mach-msm/acpuclock.h
index c5f0ee3..e73a2af 100644
--- a/arch/arm/mach-msm/acpuclock.h
+++ b/arch/arm/mach-msm/acpuclock.h
@@ -31,12 +31,11 @@
 };
 
 /**
- * struct acpuclk_soc_data - SoC data for acpuclk_init()
+ * struct acpuclk_pdata - Platform data for acpuclk
  */
-struct acpuclk_soc_data {
+struct acpuclk_pdata {
 	unsigned long max_speed_delta_khz;
 	unsigned int max_axi_khz;
-	int (*init)(struct acpuclk_soc_data *);
 };
 
 /**
@@ -91,25 +90,4 @@
  */
 void acpuclk_register(struct acpuclk_data *data);
 
-/**
- * acpuclk_init() - acpuclock driver initialization function
- *
- * Return 0 for success.
- */
-int acpuclk_init(struct acpuclk_soc_data *);
-
-/* SoC-specific acpuclock initialization functions. */
-extern struct acpuclk_soc_data acpuclk_7x27_soc_data;
-extern struct acpuclk_soc_data acpuclk_7x27a_soc_data;
-extern struct acpuclk_soc_data acpuclk_7x27aa_soc_data;
-extern struct acpuclk_soc_data acpuclk_7x30_soc_data;
-extern struct acpuclk_soc_data acpuclk_8x50_soc_data;
-extern struct acpuclk_soc_data acpuclk_8x60_soc_data;
-extern struct acpuclk_soc_data acpuclk_8960_soc_data;
-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;
-extern struct acpuclk_soc_data acpuclk_8625_soc_data;
-
 #endif
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 2d1f787..c37491d 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -334,17 +334,11 @@
 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,
 	},
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 7368f6e..101a26d 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -293,12 +293,16 @@
 static int hdmi_enable_5v(int on);
 static int hdmi_core_power(int on, int show);
 static int hdmi_cec_power(int on);
+static int hdmi_gpio_config(int on);
+static int hdmi_panel_power(int on);
 
 static struct msm_hdmi_platform_data hdmi_msm_data = {
 	.irq = HDMI_IRQ,
 	.enable_5v = hdmi_enable_5v,
 	.core_power = hdmi_core_power,
 	.cec_power = hdmi_cec_power,
+	.panel_power = hdmi_panel_power,
+	.gpio_config = hdmi_gpio_config,
 };
 
 static struct platform_device hdmi_msm_device = {
@@ -716,8 +720,22 @@
 
 static struct lcdc_platform_data dtv_pdata = {
 	.bus_scale_table = &dtv_bus_scale_pdata,
+	.lcdc_power_save = hdmi_panel_power,
 };
 
+static int hdmi_panel_power(int on)
+{
+	int rc;
+
+	pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
+	rc = hdmi_core_power(on, 1);
+	if (rc)
+		rc = hdmi_cec_power(on);
+
+	pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
+	return rc;
+}
+
 static int hdmi_enable_5v(int on)
 {
 	/* TBD: PM8921 regulator instead of 8901 */
@@ -765,7 +783,6 @@
 	static struct regulator *reg_8921_lvs7, *reg_8921_s4, *reg_ext_3p3v;
 	static int prev_on;
 	int rc;
-	int pmic_gpio14 = PM8921_GPIO_PM_TO_SYS(14);
 
 	if (on == prev_on)
 		return 0;
@@ -822,20 +839,61 @@
 		rc = regulator_enable(reg_ext_3p3v);
 		if (rc) {
 			pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
-			return -ENODEV;
+			return rc;
 		}
 		rc = regulator_enable(reg_8921_lvs7);
 		if (rc) {
 			pr_err("'%s' regulator enable failed, rc=%d\n",
 				"hdmi_vdda", rc);
-			return rc;
+			goto error1;
 		}
 		rc = regulator_enable(reg_8921_s4);
 		if (rc) {
 			pr_err("'%s' regulator enable failed, rc=%d\n",
 				"hdmi_lvl_tsl", rc);
-			return rc;
+			goto error2;
 		}
+		pr_debug("%s(on): success\n", __func__);
+	} else {
+		rc = regulator_disable(reg_ext_3p3v);
+		if (rc) {
+			pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+		rc = regulator_disable(reg_8921_lvs7);
+		if (rc) {
+			pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+		rc = regulator_disable(reg_8921_s4);
+		if (rc) {
+			pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+		pr_debug("%s(off): success\n", __func__);
+	}
+
+	prev_on = on;
+
+	return 0;
+
+error2:
+	regulator_disable(reg_8921_lvs7);
+error1:
+	regulator_disable(reg_ext_3p3v);
+	return rc;
+}
+
+static int hdmi_gpio_config(int on)
+{
+	int rc = 0;
+	static int prev_on;
+	int pmic_gpio14 = PM8921_GPIO_PM_TO_SYS(14);
+
+	if (on == prev_on)
+		return 0;
+
+	if (on) {
 		rc = gpio_request(HDMI_DDC_CLK_GPIO, "HDMI_DDC_CLK");
 		if (rc) {
 			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
@@ -873,27 +931,10 @@
 			gpio_set_value_cansleep(pmic_gpio14, 1);
 			gpio_free(pmic_gpio14);
 		}
-
-		rc = regulator_disable(reg_ext_3p3v);
-		if (rc) {
-			pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
-			return -ENODEV;
-		}
-		rc = regulator_disable(reg_8921_lvs7);
-		if (rc) {
-			pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
-			return -ENODEV;
-		}
-		rc = regulator_disable(reg_8921_s4);
-		if (rc) {
-			pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
-			return -ENODEV;
-		}
 		pr_debug("%s(off): success\n", __func__);
 	}
 
 	prev_on = on;
-
 	return 0;
 
 error4:
@@ -903,8 +944,6 @@
 error2:
 	gpio_free(HDMI_DDC_CLK_GPIO);
 error1:
-	regulator_disable(reg_8921_lvs7);
-	regulator_disable(reg_8921_s4);
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 2009584..fc886ed 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -236,11 +236,16 @@
 	14, 10, 6, 4, 1
 };
 
+/*
+ * Note: There is a bug in LPG module that results in incorrect
+ * behavior of pattern when LUT index 0 is used. So effectively
+ * there are 63 usable LUT entries.
+ */
 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,
+	.start_idx = 1,
 };
 
 static struct pm8xxx_led_config pm8921_led_configs[] = {
@@ -359,6 +364,7 @@
 static struct pm8xxx_ccadc_platform_data
 apq8064_pm8xxx_ccadc_pdata = {
 	.r_sense		= 10,
+	.calib_delay_ms		= 600000,
 };
 
 static struct pm8921_bms_platform_data
@@ -367,7 +373,6 @@
 	.r_sense		= 10,
 	.i_test			= 2500,
 	.v_failure		= 3000,
-	.calib_delay_ms		= 600000,
 	.max_voltage_uv		= MAX_VOLTAGE_MV * 1000,
 };
 
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index f7d5403..622b213 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -560,7 +560,7 @@
 	RPM_SMPS(S2, 0, 1, 0, 1300000, 1300000, NULL,      0, 1p60, NONE, NONE),
 	RPM_SMPS(S3, 0, 1, 1,  500000, 1150000, NULL, 100000, 4p80, NONE, NONE),
 	RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL, 100000, 1p60, AUTO, AUTO),
-	RPM_SMPS(S7, 0, 1, 0, 1300000, 1300000, NULL, 100000, 3p20, NONE, NONE),
+	RPM_SMPS(S7, 0, 0, 0, 1300000, 1300000, NULL, 100000, 3p20, NONE, NONE),
 	RPM_SMPS(S8, 0, 1, 0, 2200000, 2200000, NULL,      0, 1p60, NONE, NONE),
 
 	/*	ID a_on pd ss min_uV   max_uV   supply    sys_uA init_ip */
@@ -586,7 +586,7 @@
 	RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL,          0,     0),
 	RPM_LDO(L24, 0, 1, 1,  750000, 1150000, "8921_s1", 10000, 10000),
 	RPM_LDO(L25, 1, 1, 0, 1250000, 1250000, "8921_s1", 10000, 10000),
-	RPM_LDO(L27, 0, 1, 0, 1100000, 1100000, "8921_s7",     0,     0),
+	RPM_LDO(L27, 0, 0, 0, 1100000, 1100000, "8921_s7",     0,     0),
 	RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7",     0,     0),
 	RPM_LDO(L29, 0, 1, 0, 2000000, 2000000, NULL,          0,     0),
 
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 5f1a57d..1d231ef 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -74,7 +74,6 @@
 
 #include "msm_watchdog.h"
 #include "board-8064.h"
-#include "acpuclock.h"
 #include "spm.h"
 #include <mach/mpm.h>
 #include "rpm_resources.h"
@@ -2110,6 +2109,7 @@
 };
 
 static struct platform_device *common_devices[] __initdata = {
+	&msm8960_device_acpuclk,
 	&apq8064_device_dmov,
 	&apq8064_device_qup_spi_gsbi5,
 	&apq8064_device_ext_5v_vreg,
@@ -2210,6 +2210,8 @@
 	&apq8064_cpu_idle_device,
 	&apq8064_msm_gov_device,
 	&apq8064_device_cache_erp,
+	&msm8960_device_ebi1_ch0_erp,
+	&msm8960_device_ebi1_ch1_erp,
 	&epm_adc_device,
 	&apq8064_qdss_device,
 	&msm_etb_device,
@@ -2909,7 +2911,6 @@
 		ARRAY_SIZE(apq8064_slim_devices));
 	apq8064_init_dsps();
 	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);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index e7f0e68..6ee315c 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -342,17 +342,11 @@
 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,
 	},
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index e18e40d..8a837d6 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -516,12 +516,16 @@
 static int hdmi_enable_5v(int on);
 static int hdmi_core_power(int on, int show);
 static int hdmi_cec_power(int on);
+static int hdmi_gpio_config(int on);
+static int hdmi_panel_power(int on);
 
 static struct msm_hdmi_platform_data hdmi_msm_data = {
 	.irq = HDMI_IRQ,
 	.enable_5v = hdmi_enable_5v,
 	.core_power = hdmi_core_power,
 	.cec_power = hdmi_cec_power,
+	.panel_power = hdmi_panel_power,
+	.gpio_config = hdmi_gpio_config,
 };
 
 static struct platform_device hdmi_msm_device = {
@@ -594,7 +598,21 @@
 
 static struct lcdc_platform_data dtv_pdata = {
 	.bus_scale_table = &dtv_bus_scale_pdata,
+	.lcdc_power_save = hdmi_panel_power,
 };
+
+static int hdmi_panel_power(int on)
+{
+	int rc;
+
+	pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
+	rc = hdmi_core_power(on, 1);
+	if (rc)
+		rc = hdmi_cec_power(on);
+
+	pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
+	return rc;
+}
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@@ -674,30 +692,8 @@
 				"hdmi_avdd", rc);
 			return rc;
 		}
-		rc = gpio_request(100, "HDMI_DDC_CLK");
-		if (rc) {
-			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
-				"HDMI_DDC_CLK", 100, rc);
-			goto error1;
-		}
-		rc = gpio_request(101, "HDMI_DDC_DATA");
-		if (rc) {
-			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
-				"HDMI_DDC_DATA", 101, rc);
-			goto error2;
-		}
-		rc = gpio_request(102, "HDMI_HPD");
-		if (rc) {
-			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
-				"HDMI_HPD", 102, rc);
-			goto error3;
-		}
 		pr_debug("%s(on): success\n", __func__);
 	} else {
-		gpio_free(100);
-		gpio_free(101);
-		gpio_free(102);
-
 		rc = regulator_disable(reg_8038_l23);
 		if (rc) {
 			pr_err("disable reg_8038_l23 failed, rc=%d\n", rc);
@@ -714,13 +710,50 @@
 	prev_on = on;
 
 	return 0;
+}
 
-error3:
-	gpio_free(101);
+static int hdmi_gpio_config(int on)
+{
+	int rc = 0;
+	static int prev_on;
+
+	if (on == prev_on)
+		return 0;
+
+	if (on) {
+		rc = gpio_request(100, "HDMI_DDC_CLK");
+		if (rc) {
+			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+				"HDMI_DDC_CLK", 100, rc);
+			return rc;
+		}
+		rc = gpio_request(101, "HDMI_DDC_DATA");
+		if (rc) {
+			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+				"HDMI_DDC_DATA", 101, rc);
+			goto error1;
+		}
+		rc = gpio_request(102, "HDMI_HPD");
+		if (rc) {
+			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+				"HDMI_HPD", 102, rc);
+			goto error2;
+		}
+		pr_debug("%s(on): success\n", __func__);
+	} else {
+		gpio_free(100);
+		gpio_free(101);
+		gpio_free(102);
+		pr_debug("%s(off): success\n", __func__);
+	}
+
+	prev_on = on;
+	return 0;
+
 error2:
-	gpio_free(100);
+	gpio_free(101);
 error1:
-	regulator_disable(reg_8038_l23);
+	gpio_free(100);
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index cf7a829..e6a13b1 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -274,11 +274,16 @@
 		14, 10, 6, 4, 1
 };
 
+/*
+ * Note: There is a bug in LPG module that results in incorrect
+ * behavior of pattern when LUT index 0 is used. So effectively
+ * there are 63 usable LUT entries.
+ */
 static struct pm8xxx_pwm_duty_cycles pm8038_led0_pwm_duty_cycles = {
 	.duty_pcts = (int *)&pm8038_led0_pwm_duty_pcts,
 	.num_duty_pcts = ARRAY_SIZE(pm8038_led0_pwm_duty_pcts),
 	.duty_ms = PM8XXX_LED_PWM_DUTY_MS,
-	.start_idx = 0,
+	.start_idx = 1,
 };
 
 static struct pm8xxx_led_config pm8038_led_configs[] = {
@@ -323,6 +328,7 @@
 
 static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
 	.r_sense		= 10,
+	.calib_delay_ms		= 600000,
 };
 
 static struct pm8xxx_misc_platform_data pm8xxx_misc_pdata = {
@@ -338,7 +344,6 @@
 	.r_sense		= 10,
 	.i_test			= 2500,
 	.v_failure		= 3000,
-	.calib_delay_ms		= 600000,
 	.max_voltage_uv		= MAX_VOLTAGE_MV * 1000,
 };
 
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index cb8903c..5bee8a2 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -485,7 +485,7 @@
 	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(L20,	 1, 1, 0, 1250000, 1250000, "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),
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 338cb84..e075630 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -86,7 +86,6 @@
 #include <mach/cpuidle.h>
 #include "rpm_resources.h"
 #include <mach/mpm.h>
-#include "acpuclock.h"
 #include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
@@ -786,13 +785,13 @@
 	{
 		.name = "VDDD_CDC_D",
 		.min_uV = 1200000,
-		.max_uV = 1200000,
+		.max_uV = 1250000,
 		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
 	},
 	{
 		.name = "CDC_VDDA_A_1P2V",
 		.min_uV = 1200000,
-		.max_uV = 1200000,
+		.max_uV = 1250000,
 		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
 	},
 	},
@@ -850,13 +849,13 @@
 	{
 		.name = "VDDD_CDC_D",
 		.min_uV = 1200000,
-		.max_uV = 1200000,
+		.max_uV = 1250000,
 		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
 	},
 	{
 		.name = "CDC_VDDA_A_1P2V",
 		.min_uV = 1200000,
-		.max_uV = 1200000,
+		.max_uV = 1250000,
 		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
 	},
 	},
@@ -1018,6 +1017,55 @@
 #define QCE_SHARE_CE_RESOURCE	1
 #define QCE_CE_SHARED		0
 
+/* Begin Bus scaling definitions */
+static struct msm_bus_vectors crypto_hw_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT1,
+		.dst = MSM_BUS_SLAVE_GSBI1_UART,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+static struct msm_bus_vectors crypto_hw_active_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 70000000UL,
+		.ib = 70000000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT1,
+		.dst = MSM_BUS_SLAVE_GSBI1_UART,
+		.ab = 2480000000UL,
+		.ib = 2480000000UL,
+	},
+};
+
+static struct msm_bus_paths crypto_hw_bus_scale_usecases[] = {
+	{
+		ARRAY_SIZE(crypto_hw_init_vectors),
+		crypto_hw_init_vectors,
+	},
+	{
+		ARRAY_SIZE(crypto_hw_active_vectors),
+		crypto_hw_active_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata crypto_hw_bus_scale_pdata = {
+		crypto_hw_bus_scale_usecases,
+		ARRAY_SIZE(crypto_hw_bus_scale_usecases),
+		.name = "cryptohw",
+};
+/* End Bus Scaling Definitions*/
+
 static struct resource qcrypto_resources[] = {
 	[0] = {
 		.start = QCE_0_BASE,
@@ -1080,6 +1128,7 @@
 	.shared_ce_resource = QCE_SHARE_CE_RESOURCE,
 	.hw_key_support = QCE_HW_KEY_SUPPORT,
 	.sha_hmac = QCE_SHA_HMAC_SUPPORT,
+	.bus_scale_table = &crypto_hw_bus_scale_pdata,
 };
 
 static struct platform_device qcrypto_device = {
@@ -1102,6 +1151,7 @@
 	.shared_ce_resource = QCE_SHARE_CE_RESOURCE,
 	.hw_key_support = QCE_HW_KEY_SUPPORT,
 	.sha_hmac = QCE_SHA_HMAC_SUPPORT,
+	.bus_scale_table = &crypto_hw_bus_scale_pdata,
 };
 
 static struct platform_device qcedev_device = {
@@ -1984,6 +2034,7 @@
 };
 
 static struct platform_device *common_devices[] __initdata = {
+	&msm8960_device_acpuclk,
 	&msm8960_device_dmov,
 	&msm_device_smd,
 	&msm8960_device_uart_gsbi5,
@@ -2382,7 +2433,6 @@
 	msm8930_init_cam();
 #endif
 	msm8930_init_mmc();
-	acpuclk_init(&acpuclk_8930_soc_data);
 	mxt_init_vkeys_8930();
 	register_i2c_devices();
 	msm8930_init_fb();
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 9c25b78..b6c03a4 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -399,25 +399,16 @@
 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,
 	},
 	{
 		.csid_core = 2,
-		.is_csiphy = 1,
-		.is_csid   = 1,
-		.is_ispif  = 1,
 		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 	},
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index a9b2a59..c1017a9 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -717,12 +717,16 @@
 static int hdmi_enable_5v(int on);
 static int hdmi_core_power(int on, int show);
 static int hdmi_cec_power(int on);
+static int hdmi_gpio_config(int on);
+static int hdmi_panel_power(int on);
 
 static struct msm_hdmi_platform_data hdmi_msm_data = {
 	.irq = HDMI_IRQ,
 	.enable_5v = hdmi_enable_5v,
 	.core_power = hdmi_core_power,
 	.cec_power = hdmi_cec_power,
+	.panel_power = hdmi_panel_power,
+	.gpio_config = hdmi_gpio_config,
 };
 
 static struct platform_device hdmi_msm_device = {
@@ -784,7 +788,21 @@
 
 static struct lcdc_platform_data dtv_pdata = {
 	.bus_scale_table = &dtv_bus_scale_pdata,
+	.lcdc_power_save = hdmi_panel_power,
 };
+
+static int hdmi_panel_power(int on)
+{
+	int rc;
+
+	pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
+	rc = hdmi_core_power(on, 1);
+	if (rc)
+		rc = hdmi_cec_power(on);
+
+	pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
+	return rc;
+}
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@@ -885,30 +903,8 @@
 				"hdmi_vcc", rc);
 			return rc;
 		}
-		rc = gpio_request(100, "HDMI_DDC_CLK");
-		if (rc) {
-			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
-				"HDMI_DDC_CLK", 100, rc);
-			goto error1;
-		}
-		rc = gpio_request(101, "HDMI_DDC_DATA");
-		if (rc) {
-			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
-				"HDMI_DDC_DATA", 101, rc);
-			goto error2;
-		}
-		rc = gpio_request(102, "HDMI_HPD");
-		if (rc) {
-			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
-				"HDMI_HPD", 102, rc);
-			goto error3;
-		}
 		pr_debug("%s(on): success\n", __func__);
 	} else {
-		gpio_free(100);
-		gpio_free(101);
-		gpio_free(102);
-
 		rc = regulator_disable(reg_8921_l23);
 		if (rc) {
 			pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
@@ -930,14 +926,50 @@
 	prev_on = on;
 
 	return 0;
+}
 
-error3:
-	gpio_free(101);
+static int hdmi_gpio_config(int on)
+{
+	int rc = 0;
+	static int prev_on;
+
+	if (on == prev_on)
+		return 0;
+
+	if (on) {
+		rc = gpio_request(100, "HDMI_DDC_CLK");
+		if (rc) {
+			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+				"HDMI_DDC_CLK", 100, rc);
+			return rc;
+		}
+		rc = gpio_request(101, "HDMI_DDC_DATA");
+		if (rc) {
+			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+				"HDMI_DDC_DATA", 101, rc);
+			goto error1;
+		}
+		rc = gpio_request(102, "HDMI_HPD");
+		if (rc) {
+			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+				"HDMI_HPD", 102, rc);
+			goto error2;
+		}
+		pr_debug("%s(on): success\n", __func__);
+	} else {
+		gpio_free(100);
+		gpio_free(101);
+		gpio_free(102);
+		pr_debug("%s(off): success\n", __func__);
+	}
+
+	prev_on = on;
+	return 0;
+
 error2:
-	gpio_free(100);
+	gpio_free(101);
 error1:
-	regulator_disable(reg_8921_l23);
-	regulator_disable(reg_8921_s4);
+	gpio_free(100);
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index ea1ab58..19564e9 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -442,9 +442,8 @@
 	.r_sense		= 10,
 	.i_test			= 2500,
 	.v_failure		= 3000,
-	.calib_delay_ms		= 600000,
 	.max_voltage_uv		= MAX_VOLTAGE_MV * 1000,
-	.rconn_mohm		= 30,
+	.rconn_mohm		= 18,
 };
 
 #define	PM8921_LC_LED_MAX_CURRENT	4	/* I = 4mA */
@@ -529,11 +528,16 @@
 		14, 10, 6, 4, 1
 };
 
+/*
+ * Note: There is a bug in LPG module that results in incorrect
+ * behavior of pattern when LUT index 0 is used. So effectively
+ * there are 63 usable LUT entries.
+ */
 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,
+	.start_idx = 1,
 };
 
 static struct pm8xxx_led_config pm8921_led_configs[] = {
@@ -562,6 +566,7 @@
 
 static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
 	.r_sense		= 10,
+	.calib_delay_ms		= 600000,
 };
 
 /**
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 9c096b7..22ef940 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -97,7 +97,6 @@
 #include <mach/cpuidle.h>
 #include "rpm_resources.h"
 #include <mach/mpm.h>
-#include "acpuclock.h"
 #include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
@@ -2508,6 +2507,7 @@
 #endif
 
 static struct platform_device *common_devices[] __initdata = {
+	&msm8960_device_acpuclk,
 	&msm8960_device_dmov,
 	&msm_device_smd,
 	&msm_device_uart_dm6,
@@ -2587,6 +2587,8 @@
 	&msm8960_cpu_idle_device,
 	&msm8960_msm_gov_device,
 	&msm8960_device_cache_erp,
+	&msm8960_device_ebi1_ch0_erp,
+	&msm8960_device_ebi1_ch1_erp,
 	&msm8960_cache_dump_device,
 	&msm8960_iommu_domain_device,
 	&msm_tsens_device,
@@ -3058,7 +3060,6 @@
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm8960_pm8921_gpio_mpp_init();
 	platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
-	acpuclk_init(&acpuclk_8960_soc_data);
 
 	msm8960_device_qup_spi_gsbi1.dev.platform_data =
 				&msm8960_qup_spi_gsbi1_pdata;
@@ -3171,7 +3172,6 @@
 	msm8960_init_cam();
 #endif
 	msm8960_init_mmc();
-	acpuclk_init(&acpuclk_8960_soc_data);
 	if (machine_is_msm8960_liquid())
 		mxt_init_hw_liquid();
 	register_i2c_devices();
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index 1122ed9..2561def 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -69,9 +69,6 @@
 };
 VREG_CONSUMERS(S1) = {
 	REGULATOR_SUPPLY("8018_s1",		NULL),
-	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_otg"),
-	REGULATOR_SUPPLY("HSIC_VDDCX",		"msm_hsic_peripheral"),
-	REGULATOR_SUPPLY("HSIC_VDDCX",		"msm_hsic_host"),
 };
 VREG_CONSUMERS(S2) = {
 	REGULATOR_SUPPLY("8018_s2",		NULL),
@@ -117,6 +114,11 @@
 	REGULATOR_SUPPLY("ext_2p95v",		NULL),
 	REGULATOR_SUPPLY("sdc_vdd",		"msm_sdcc.1"),
 };
+VREG_CONSUMERS(VDD_DIG_CORNER) = {
+	REGULATOR_SUPPLY("hsusb_vdd_dig",	"msm_otg"),
+	REGULATOR_SUPPLY("hsic_vdd_dig",	"msm_hsic_peripheral"),
+	REGULATOR_SUPPLY("hsic_vdd_dig",	"msm_hsic_host"),
+};
 
 #define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
 			 _apply_uV, _pull_down, _always_on, _supply_regulator, \
@@ -262,6 +264,16 @@
 		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
 		 _supply_regulator, 0)
 
+#define RPM_CORNER(_id, _always_on, _sleep_selectable, _min_uV, _max_uV, \
+		_supply_regulator) \
+	RPM_INIT(_id, _min_uV, _max_uV, 0, REGULATOR_CHANGE_VOLTAGE \
+		 | REGULATOR_CHANGE_STATUS, 0, _max_uV, 0, 0, 0, \
+		 RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_9615_NONE, \
+		 RPM_VREG_FORCE_MODE_9615_NONE, \
+		 RPM_VREG_FORCE_MODE_9615_NONE, RPM_VREG_POWER_MODE_9615_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) \
 	{ \
@@ -331,6 +343,10 @@
 
 	/*	ID    a_on pd ss		    supply */
 	RPM_VS(LVS1,    0, 1, 0,		    "8018_s3"),
+
+	/*	   ID            a_on ss min_corner  max_corner  supply */
+	RPM_CORNER(VDD_DIG_CORNER, 0, 1, RPM_VREG_CORNER_NONE,
+		RPM_VREG_CORNER_HIGH, NULL),
 };
 
 int msm_pm8018_regulator_pdata_len __devinitdata =
@@ -342,5 +358,5 @@
 	.num_regulators		= ARRAY_SIZE(msm_rpm_regulator_init_data),
 	.version		= RPM_VREG_VERSION_9615,
 	.vreg_id_vdd_mem	= RPM_VREG_ID_PM8018_L9,
-	.vreg_id_vdd_dig	= RPM_VREG_ID_PM8018_S1,
+	.vreg_id_vdd_dig	= RPM_VREG_ID_PM8018_VDD_DIG_CORNER,
 };
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index dc376b5..1089d61 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -50,7 +50,6 @@
 #include "devices.h"
 #include "board-9615.h"
 #include "pm.h"
-#include "acpuclock.h"
 #include "pm-boot.h"
 #include <mach/gpiomux.h>
 
@@ -850,6 +849,7 @@
 };
 
 static struct platform_device *common_devices[] = {
+	&msm9615_device_acpuclk,
 	&msm9615_device_dmov,
 	&msm_device_smd,
 #ifdef CONFIG_LTC4088_CHARGER
@@ -979,7 +979,6 @@
 	msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm9615_pm8xxx_gpio_mpp_init();
-	acpuclk_init(&acpuclk_9615_soc_data);
 
 	/* Ensure ar6000pm device is registered before MMC/SDC */
 	msm9615_init_ar6000pm();
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index f83b403..4dda0b7 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -46,6 +46,7 @@
 #include "clock.h"
 #include "devices.h"
 #include "spm.h"
+#include "modem_notifier.h"
 
 #define MSM_KERNEL_EBI1_MEM_SIZE	0x280000
 #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
@@ -457,6 +458,7 @@
  */
 void __init msm_copper_add_drivers(void)
 {
+	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
 	rpm_regulator_smd_driver_init();
@@ -507,6 +509,8 @@
 			"pil_pronto", NULL),
 	OF_DEV_AUXDATA("qcom,msm-rng", 0xF9BFF000, \
 			"msm_rng", NULL),
+	OF_DEV_AUXDATA("qcom,qseecom", 0xFE806000, \
+			"qseecom", NULL),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index 6ad3cef..b071353 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -38,7 +38,6 @@
 #include <mach/socinfo.h>
 #include "devices.h"
 #include "timer.h"
-#include "acpuclock.h"
 #include "pm.h"
 #include "spm.h"
 #include <linux/regulator/consumer.h>
@@ -804,11 +803,17 @@
 	},
 };
 
+static struct platform_device fsm9xxx_device_acpuclk = {
+	.name		= "acpuclk-9xxx",
+	.id		= -1,
+};
+
 /*
  * Devices
  */
 
 static struct platform_device *devices[] __initdata = {
+	&fsm9xxx_device_acpuclk,
 	&msm_device_smd,
 	&msm_device_dmov,
 	&msm_device_nand,
@@ -873,8 +878,6 @@
 
 static void __init fsm9xxx_init(void)
 {
-	acpuclk_init(&acpuclk_9xxx_soc_data);
-
 	regulator_has_full_constraints();
 
 #if defined(CONFIG_I2C_SSBI) || defined(CONFIG_MSM_SSBI)
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 2873fc0..38bdeca 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -125,14 +125,12 @@
 struct msm_camera_device_platform_data msm_camera_device_data_csi1[] = {
 	{
 		.csid_core = 1,
-		.is_csic = 1,
 		.ioclk = {
 			.vfe_clk_rate = 192000000,
 		},
 	},
 	{
 		.csid_core = 1,
-		.is_csic = 1,
 		.ioclk = {
 			.vfe_clk_rate = 266667000,
 		},
@@ -142,14 +140,12 @@
 struct msm_camera_device_platform_data msm_camera_device_data_csi0[] = {
 	{
 		.csid_core = 0,
-		.is_csic = 1,
 		.ioclk = {
 			.vfe_clk_rate = 192000000,
 		},
 	},
 	{
 		.csid_core = 0,
-		.is_csic = 1,
 		.ioclk = {
 			.vfe_clk_rate = 266667000,
 		},
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index c2b7b9d..3da68ad 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -497,12 +497,10 @@
 	} else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
 		if (!strncmp(name, "lcdc_truly_hvga_ips3p2335_pt", 28))
 			ret = 0;
-	} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
+	} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
+			machine_is_msm8625_evt()) {
 		if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
 			ret = 0;
-	} else if (machine_is_msm8625_evt()) {
-		if (!strncmp(name, "mipi_video_nt35510_wvga", 23))
-			ret = 0;
 	}
 
 #if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
@@ -579,90 +577,98 @@
 };
 #endif
 
-static int evb_backlight_control(int level)
+static int evb_backlight_control(int level, int mode)
 {
 
 	int i = 0;
-	int remainder;
+	int remainder, ret = 0;
+
 	/* device address byte = 0x72 */
-	gpio_set_value(96, 0);
-	udelay(67);
-	gpio_set_value(96, 1);
-	udelay(33);
-	gpio_set_value(96, 0);
-	udelay(33);
-	gpio_set_value(96, 1);
-	udelay(67);
-	gpio_set_value(96, 0);
-	udelay(33);
-	gpio_set_value(96, 1);
-	udelay(67);
-	gpio_set_value(96, 0);
-	udelay(33);
-	gpio_set_value(96, 1);
-	udelay(67);
-	gpio_set_value(96, 0);
-	udelay(67);
-	gpio_set_value(96, 1);
-	udelay(33);
-	gpio_set_value(96, 0);
-	udelay(67);
-	gpio_set_value(96, 1);
-	udelay(33);
-	gpio_set_value(96, 0);
-	udelay(33);
-	gpio_set_value(96, 1);
-	udelay(67);
-	gpio_set_value(96, 0);
-	udelay(67);
-	gpio_set_value(96, 1);
-	udelay(33);
+	if (!mode) {
+		gpio_set_value(96, 0);
+		udelay(67);
+		gpio_set_value(96, 1);
+		udelay(33);
+		gpio_set_value(96, 0);
+		udelay(33);
+		gpio_set_value(96, 1);
+		udelay(67);
+		gpio_set_value(96, 0);
+		udelay(33);
+		gpio_set_value(96, 1);
+		udelay(67);
+		gpio_set_value(96, 0);
+		udelay(33);
+		gpio_set_value(96, 1);
+		udelay(67);
+		gpio_set_value(96, 0);
+		udelay(67);
+		gpio_set_value(96, 1);
+		udelay(33);
+		gpio_set_value(96, 0);
+		udelay(67);
+		gpio_set_value(96, 1);
+		udelay(33);
+		gpio_set_value(96, 0);
+		udelay(33);
+		gpio_set_value(96, 1);
+		udelay(67);
+		gpio_set_value(96, 0);
+		udelay(67);
+		gpio_set_value(96, 1);
+		udelay(33);
 
-	/* t-EOS and t-start */
-	gpio_set_value(96, 0);
-	ndelay(4200);
-	gpio_set_value(96, 1);
-	ndelay(9000);
+		/* t-EOS and t-start */
+		gpio_set_value(96, 0);
+		ndelay(4200);
+		gpio_set_value(96, 1);
+		ndelay(9000);
 
-	/* data byte */
-	/* RFA = 0 */
-	gpio_set_value(96, 0);
-	udelay(67);
-	gpio_set_value(96, 1);
-	udelay(33);
+		/* data byte */
+		/* RFA = 0 */
+		gpio_set_value(96, 0);
+		udelay(67);
+		gpio_set_value(96, 1);
+		udelay(33);
 
-	/* Address bits */
-	gpio_set_value(96, 0);
-	udelay(67);
-	gpio_set_value(96, 1);
-	udelay(33);
-	gpio_set_value(96, 0);
-	udelay(67);
-	gpio_set_value(96, 1);
-	udelay(33);
+		/* Address bits */
+		gpio_set_value(96, 0);
+		udelay(67);
+		gpio_set_value(96, 1);
+		udelay(33);
+		gpio_set_value(96, 0);
+		udelay(67);
+		gpio_set_value(96, 1);
+		udelay(33);
 
-	/* Data bits */
-	for (i = 0; i < 5; i++) {
-		remainder = (level) & (16);
-		if (remainder) {
-			gpio_set_value(96, 0);
-			udelay(33);
-			gpio_set_value(96, 1);
-			udelay(67);
-		} else {
-			gpio_set_value(96, 0);
-			udelay(67);
-			gpio_set_value(96, 1);
-			udelay(33);
+		/* Data bits */
+		for (i = 0; i < 5; i++) {
+			remainder = (level) & (16);
+			if (remainder) {
+				gpio_set_value(96, 0);
+				udelay(33);
+				gpio_set_value(96, 1);
+				udelay(67);
+			} else {
+				gpio_set_value(96, 0);
+				udelay(67);
+				gpio_set_value(96, 1);
+				udelay(33);
+			}
+			level = level << 1;
 		}
-		level = level << 1;
+
+		/* t-EOS */
+		gpio_set_value(96, 0);
+		ndelay(12000);
+		gpio_set_value(96, 1);
+	} else {
+		ret = pmapp_disp_backlight_set_brightness(level);
+		 if (ret)
+			pr_err("%s: can't set lcd backlight!\n", __func__);
 	}
 
-	/* t-EOS */
-	gpio_set_value(96, 0);
-	ndelay(12000);
-	gpio_set_value(96, 1);
-	return 0;
+	return ret;
 }
 
 static int mipi_NT35510_rotate_panel(void)
@@ -687,7 +693,7 @@
 };
 
 static struct msm_panel_common_pdata mipi_NT35510_pdata = {
-	.pmic_backlight = evb_backlight_control,
+	.backlight    = evb_backlight_control,
 	.rotate_panel = mipi_NT35510_rotate_panel,
 };
 
@@ -700,7 +706,7 @@
 };
 
 static struct msm_panel_common_pdata mipi_NT35516_pdata = {
-	.pmic_backlight = evb_backlight_control,
+	.backlight = evb_backlight_control,
 };
 
 static struct platform_device mipi_dsi_NT35516_panel_device = {
@@ -1143,6 +1149,7 @@
 	static struct regulator *gpio_reg_2p85v, *gpio_reg_1p8v;
 
 	if (!qrd3_dsi_gpio_initialized) {
+		pmapp_disp_backlight_init();
 		rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
 			"qrd3_gpio_bkl_en");
 		if (rc < 0)
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index 07b7ab0..0949c5f 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -327,13 +327,16 @@
 		}
 		gpio_set_value(gpio_wlan_sys_rest_en, 0);
 	} else {
-		gpio_request(gpio_wlan_sys_rest_en, "WLAN_DEEP_SLEEP_N");
-		rc = setup_wlan_gpio(on);
-		if (rc) {
-			pr_err("%s: wlan_set_gpio = %d\n", __func__, rc);
-			goto set_gpio_fail;
+		rc = gpio_request(gpio_wlan_sys_rest_en, "WLAN_DEEP_SLEEP_N");
+		if (!rc) {
+			rc = setup_wlan_gpio(on);
+			if (rc) {
+				pr_err("%s: setup_wlan_gpio = %d\n",
+					__func__, rc);
+				goto set_gpio_fail;
+			}
+			gpio_free(gpio_wlan_sys_rest_en);
 		}
-		gpio_free(gpio_wlan_sys_rest_en);
 	}
 
 	/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index d42458f..a7fed3e 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -65,7 +65,6 @@
 #include "board-msm7627-regulator.h"
 #include "devices.h"
 #include "clock.h"
-#include "acpuclock.h"
 #include "msm-keypad-devices.h"
 #include "pm.h"
 #include "pm-boot.h"
@@ -1775,7 +1774,7 @@
 		}
 	}
 #endif
-	acpuclk_init(&acpuclk_7x27_soc_data);
+	platform_device_register(&msm7x27_device_acpuclk);
 
 	usb_mpp_init();
 
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 1c32b5e..dc473e6 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -162,7 +162,7 @@
 #define MSM_PMEM_MDP_SIZE       0x2300000
 #define MSM7x25A_MSM_PMEM_MDP_SIZE       0x1500000
 
-#define MSM_PMEM_ADSP_SIZE      0x1100000
+#define MSM_PMEM_ADSP_SIZE      0x1200000
 #define MSM7x25A_MSM_PMEM_ADSP_SIZE      0xB91000
 
 #endif
@@ -650,7 +650,12 @@
 	u32 low_voltage	 = msm_psy_batt_data.voltage_min_design;
 	u32 high_voltage = msm_psy_batt_data.voltage_max_design;
 
-	return (current_voltage - low_voltage) * 100
+	if (current_voltage <= low_voltage)
+		return 0;
+	else if (current_voltage >= high_voltage)
+		return 100;
+	else
+		return (current_voltage - low_voltage) * 100
 			/ (high_voltage - low_voltage);
 }
 
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 7ac0c9a..2834f24 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -105,7 +105,7 @@
  */
 #define MSM_V4L2_VIDEO_OVERLAY_BUF_SIZE 2764800
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL
 #define MSM_FB_EXT_BUF_SIZE (1280 * 720 * 2 * 1) /* 2 bpp x 1 page */
 #else
 #define MSM_FB_EXT_BUF_SIZE    0
@@ -880,7 +880,6 @@
 static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
 	{
 		.csid_core = 0,
-		.is_csic = 1,
 		.is_vpe    = 1,
 		.ioclk = {
 			.vfe_clk_rate =	153600000,
@@ -6957,7 +6956,7 @@
 	msm7x30_init_uart2();
 #endif
 	msm_spm_init(&msm_spm_data, 1);
-	acpuclk_init(&acpuclk_7x30_soc_data);
+	platform_device_register(&msm7x30_device_acpuclk);
 	if (machine_is_msm7x30_surf() || machine_is_msm7x30_fluid())
 		msm7x30_cfg_smsc911x();
 
diff --git a/arch/arm/mach-msm/board-msm8x60-camera.c b/arch/arm/mach-msm/board-msm8x60-camera.c
index 32d5530..cd95630 100644
--- a/arch/arm/mach-msm/board-msm8x60-camera.c
+++ b/arch/arm/mach-msm/board-msm8x60-camera.c
@@ -361,7 +361,6 @@
 static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
 	{
 		.csid_core = 0,
-		.is_csic = 1,
 		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 		.ioclk = {
@@ -370,7 +369,6 @@
 	},
 	{
 		.csid_core = 1,
-		.is_csic = 1,
 		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 		.ioclk = {
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 3488fb3..098ad6e 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -100,7 +100,6 @@
 #include "peripheral-loader.h"
 #include <linux/platform_data/qcom_crypto_device.h>
 #include "rpm_resources.h"
-#include "acpuclock.h"
 #include "pm-boot.h"
 #include "board-storage-common-a.h"
 
@@ -2604,7 +2603,7 @@
 #define MSM_FB_EXT_BUF_SIZE  \
 		(roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
 #else
-#define MSM_FB_EXT_BUFT_SIZE	0
+#define MSM_FB_EXT_BUF_SIZE	0
 #endif
 
 /* Note: must be multiple of 4096 */
@@ -3083,13 +3082,17 @@
 
 static int hdmi_enable_5v(int on);
 static int hdmi_core_power(int on, int show);
+static int hdmi_gpio_config(int on);
 static int hdmi_cec_power(int on);
+static int hdmi_panel_power(int on);
 
 static struct msm_hdmi_platform_data hdmi_msm_data = {
 	.irq = HDMI_IRQ,
 	.enable_5v = hdmi_enable_5v,
 	.core_power = hdmi_core_power,
 	.cec_power = hdmi_cec_power,
+	.panel_power = hdmi_panel_power,
+	.gpio_config = hdmi_gpio_config,
 };
 
 static struct platform_device hdmi_msm_device = {
@@ -5131,6 +5134,7 @@
 };
 
 static struct platform_device *surf_devices[] __initdata = {
+	&msm8x60_device_acpuclk,
 	&msm_device_smd,
 	&msm_device_uart_dm12,
 	&msm_pil_q6v3,
@@ -9006,6 +9010,29 @@
 				"8058_l16", rc);
 			return rc;
 		}
+		pr_debug("%s(on): success\n", __func__);
+	} else {
+		rc = regulator_disable(reg_8058_l16);
+		if (rc)
+			pr_warning("'%s' regulator disable failed, rc=%d\n",
+				"8058_l16", rc);
+		pr_debug("%s(off): success\n", __func__);
+	}
+
+	prev_on = on;
+
+	return 0;
+}
+
+static int hdmi_gpio_config(int on)
+{
+	int rc = 0;
+	static int prev_on;
+
+	if (on == prev_on)
+		return 0;
+
+	if (on) {
 		rc = gpio_request(170, "HDMI_DDC_CLK");
 		if (rc) {
 			pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
@@ -9024,20 +9051,15 @@
 				"HDMI_HPD", 172, rc);
 			goto error3;
 		}
-		pr_info("%s(on): success\n", __func__);
+		pr_debug("%s(on): success\n", __func__);
 	} else {
 		gpio_free(170);
 		gpio_free(171);
 		gpio_free(172);
-		rc = regulator_disable(reg_8058_l16);
-		if (rc)
-			pr_warning("'%s' regulator disable failed, rc=%d\n",
-				"8058_l16", rc);
-		pr_info("%s(off): success\n", __func__);
+		pr_debug("%s(off): success\n", __func__);
 	}
 
 	prev_on = on;
-
 	return 0;
 
 error3:
@@ -9045,7 +9067,6 @@
 error2:
 	gpio_free(170);
 error1:
-	regulator_disable(reg_8058_l16);
 	return rc;
 }
 
@@ -9094,6 +9115,18 @@
 	return rc;
 }
 
+static int hdmi_panel_power(int on)
+{
+	int rc;
+
+	pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
+	rc = hdmi_core_power(on, 1);
+	if (rc)
+		rc = hdmi_cec_power(on);
+
+	pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
+	return rc;
+}
 #undef _GET_REGULATOR
 
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
@@ -9516,6 +9549,7 @@
 
 static struct lcdc_platform_data dtv_pdata = {
 	.bus_scale_table = &dtv_bus_scale_pdata,
+	.lcdc_power_save = hdmi_panel_power,
 };
 
 static struct msm_bus_paths dtv_hdmi_prim_bus_scale_usecases[] = {
@@ -10305,9 +10339,6 @@
 	 */
 	msm8x60_init_buses();
 	platform_add_devices(early_devices, ARRAY_SIZE(early_devices));
-	/* CPU frequency control is not supported on simulated targets. */
-	if (!machine_is_msm8x60_rumi3() && !machine_is_msm8x60_sim())
-		acpuclk_init(&acpuclk_8x60_soc_data);
 
 	/*
 	 * Enable EBI2 only for boards which make use of it. Leave
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index c8f8b10..9c80c8b 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -130,7 +130,7 @@
 
 #ifdef CONFIG_ARCH_MSM7X27A
 #define MSM_PMEM_MDP_SIZE       0x2300000
-#define MSM_PMEM_ADSP_SIZE      0x1100000
+#define MSM_PMEM_ADSP_SIZE      0x1200000
 #endif
 
 static struct android_usb_platform_data android_usb_pdata = {
@@ -596,7 +596,12 @@
 	u32 low_voltage	 = msm_psy_batt_data.voltage_min_design;
 	u32 high_voltage = msm_psy_batt_data.voltage_max_design;
 
-	return (current_voltage - low_voltage) * 100
+	if (current_voltage <= low_voltage)
+		return 0;
+	else if (current_voltage >= high_voltage)
+		return 100;
+	else
+		return (current_voltage - low_voltage) * 100
 			/ (high_voltage - low_voltage);
 }
 
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 6a39316..4df4266 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -2409,7 +2409,7 @@
 {
 	msm_clock_init(&qds8x50_clock_init_data);
 	qsd8x50_cfg_smc91x();
-	acpuclk_init(&acpuclk_8x50_soc_data);
+	platform_device_register(&msm8x50_device_acpuclk);
 
 	msm_hsusb_pdata.swfi_latency =
 		msm_pm_data
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index aca2a3b..5867eef 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4602,7 +4602,6 @@
 static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_qseecom_clk, &dfab_clk.c, 0);
-static DEFINE_CLK_VOTER(dfab_tzcom_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c, 0);
 
@@ -5309,7 +5308,6 @@
 	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
 	CLK_LOOKUP("bus_clk",		dfab_qseecom_clk.c,	"qseecom"),
-	CLK_LOOKUP("bus_clk",		dfab_tzcom_clk.c,	"tzcom"),
 
 	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"),
@@ -5654,7 +5652,6 @@
 	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
 	CLK_LOOKUP("bus_clk",		dfab_qseecom_clk.c,	"qseecom"),
-	CLK_LOOKUP("bus_clk",		dfab_tzcom_clk.c,	"tzcom"),
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
 	CLK_LOOKUP("mem_clk",		ebi1_acpu_a_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 834deb6..a2e0bc9 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -187,15 +187,15 @@
 
 static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
 {
-	static const int vdd_uv[] = {
-		[VDD_DIG_NONE]    =       0,
-		[VDD_DIG_LOW]     =  945000,
-		[VDD_DIG_NOMINAL] = 1050000,
-		[VDD_DIG_HIGH]    = 1150000
+	static const int vdd_corner[] = {
+		[VDD_DIG_NONE]    = RPM_VREG_CORNER_NONE,
+		[VDD_DIG_LOW]     = RPM_VREG_CORNER_LOW,
+		[VDD_DIG_NOMINAL] = RPM_VREG_CORNER_NOMINAL,
+		[VDD_DIG_HIGH]    = RPM_VREG_CORNER_HIGH,
 	};
 
-	return rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_S1, RPM_VREG_VOTER3,
-				    vdd_uv[level], vdd_uv[VDD_DIG_HIGH], 1);
+	return rpm_vreg_set_voltage(RPM_VREG_ID_PM8018_VDD_DIG_CORNER,
+		RPM_VREG_VOTER3, vdd_corner[level], RPM_VREG_CORNER_HIGH, 1);
 }
 
 static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig);
diff --git a/arch/arm/mach-msm/clock-copper.c b/arch/arm/mach-msm/clock-copper.c
index 72424f2..5727c34 100644
--- a/arch/arm/mach-msm/clock-copper.c
+++ b/arch/arm/mach-msm/clock-copper.c
@@ -3716,7 +3716,8 @@
 static struct branch_clk mmss_mmssnoc_axi_clk = {
 	.cbcr_reg = MMSS_MMSSNOC_AXI_CBCR,
 	.parent = &axi_clk_src.c,
-	.has_sibling = 1,
+	/* The bus driver needs set_rate to go through to the parent */
+	.has_sibling = 0,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "mmss_mmssnoc_axi_clk",
@@ -3998,7 +3999,6 @@
 
 static struct branch_clk audio_core_lpaif_codec_spkr_ebit_clk = {
 	.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR,
-	.parent = &audio_core_lpaif_codec_spkr_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
@@ -4012,7 +4012,7 @@
 	.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR,
 	.parent = &audio_core_lpaif_codec_spkr_clk_src.c,
 	.has_sibling = 1,
-	.max_div = 16,
+	.max_div = 15,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
 		.dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
@@ -4035,7 +4035,6 @@
 
 static struct branch_clk audio_core_lpaif_pri_ebit_clk = {
 	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_EBIT_CBCR,
-	.parent = &audio_core_lpaif_pri_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
@@ -4049,7 +4048,7 @@
 	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_IBIT_CBCR,
 	.parent = &audio_core_lpaif_pri_clk_src.c,
 	.has_sibling = 1,
-	.max_div = 16,
+	.max_div = 15,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
 		.dbg_name = "audio_core_lpaif_pri_ibit_clk",
@@ -4072,7 +4071,6 @@
 
 static struct branch_clk audio_core_lpaif_sec_ebit_clk = {
 	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_EBIT_CBCR,
-	.parent = &audio_core_lpaif_sec_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
@@ -4086,7 +4084,7 @@
 	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_IBIT_CBCR,
 	.parent = &audio_core_lpaif_sec_clk_src.c,
 	.has_sibling = 1,
-	.max_div = 16,
+	.max_div = 15,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
 		.dbg_name = "audio_core_lpaif_sec_ibit_clk",
@@ -4109,7 +4107,6 @@
 
 static struct branch_clk audio_core_lpaif_ter_ebit_clk = {
 	.cbcr_reg = AUDIO_CORE_LPAIF_TER_EBIT_CBCR,
-	.parent = &audio_core_lpaif_ter_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
@@ -4123,7 +4120,7 @@
 	.cbcr_reg = AUDIO_CORE_LPAIF_TER_IBIT_CBCR,
 	.parent = &audio_core_lpaif_ter_clk_src.c,
 	.has_sibling = 1,
-	.max_div = 16,
+	.max_div = 15,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
 		.dbg_name = "audio_core_lpaif_ter_ibit_clk",
@@ -4146,7 +4143,6 @@
 
 static struct branch_clk audio_core_lpaif_quad_ebit_clk = {
 	.cbcr_reg = AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR,
-	.parent = &audio_core_lpaif_quad_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
@@ -4160,7 +4156,7 @@
 	.cbcr_reg = AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR,
 	.parent = &audio_core_lpaif_quad_clk_src.c,
 	.has_sibling = 1,
-	.max_div = 16,
+	.max_div = 15,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
 		.dbg_name = "audio_core_lpaif_quad_ibit_clk",
@@ -4171,7 +4167,6 @@
 
 static struct branch_clk audio_core_lpaif_pcm0_ebit_clk = {
 	.cbcr_reg = AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR,
-	.parent = &audio_core_lpaif_pcm0_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
@@ -4185,7 +4180,6 @@
 	.cbcr_reg = AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR,
 	.parent = &audio_core_lpaif_pcm0_clk_src.c,
 	.has_sibling = 1,
-	.max_div = 16,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
 		.dbg_name = "audio_core_lpaif_pcm0_ibit_clk",
@@ -4210,7 +4204,6 @@
 	.cbcr_reg = AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR,
 	.parent = &audio_core_lpaif_pcm1_clk_src.c,
 	.has_sibling = 1,
-	.max_div = 16,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
 		.dbg_name = "audio_core_lpaif_pcm1_ibit_clk",
@@ -4819,6 +4812,7 @@
 	CLK_DUMMY("dfab_clk",  DFAB_CLK,    "msm_sps", OFF),
 	CLK_DUMMY("mem_clk",       NULL,    "msm_sps", OFF),
 	CLK_DUMMY("bus_clk",       NULL,        "scm", OFF),
+	CLK_DUMMY("bus_clk",       NULL,    "qseecom", OFF),
 
 	CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
 	CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
@@ -4844,8 +4838,8 @@
 	CLK_LOOKUP("ocmem_a_clk", ocmemgx_msmbus_a_clk.c, "msm_bus"),
 	CLK_LOOKUP("bus_clk",	ocmemnoc_clk.c,		"msm_ocmem_noc"),
 	CLK_LOOKUP("bus_a_clk",	ocmemnoc_clk.c,		"msm_ocmem_noc"),
-	CLK_LOOKUP("bus_clk",	axi_clk_src.c,		"msm_mmss_noc"),
-	CLK_LOOKUP("bus_a_clk",	axi_clk_src.c,		"msm_mmss_noc"),
+	CLK_LOOKUP("bus_clk",	mmss_mmssnoc_axi_clk.c,	"msm_mmss_noc"),
+	CLK_LOOKUP("bus_a_clk",	mmss_mmssnoc_axi_clk.c,	"msm_mmss_noc"),
 };
 
 static struct pll_config_regs gpll0_regs __initdata = {
diff --git a/arch/arm/mach-msm/clock-dss-8960.c b/arch/arm/mach-msm/clock-dss-8960.c
index 8331899..7f3646f 100644
--- a/arch/arm/mach-msm/clock-dss-8960.c
+++ b/arch/arm/mach-msm/clock-dss-8960.c
@@ -97,6 +97,7 @@
 {
 	unsigned int val;
 	u32 ahb_en_reg, ahb_enabled;
+	unsigned int timeout_count;
 
 	ahb_en_reg = readl_relaxed(AHB_EN_REG);
 	ahb_enabled = ahb_en_reg & BIT(4);
@@ -110,6 +111,12 @@
 	writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
 	writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
 	writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
+	/* Wait for a short time before de-asserting
+	 * to allow the hardware to complete its job.
+	 * This much of delay should be fine for hardware
+	 * to assert and de-assert.
+	 */
+	udelay(10);
 	/* De-assert PLL S/W reset */
 	writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
 
@@ -118,6 +125,11 @@
 	/* Assert PHY S/W reset */
 	writel_relaxed(val, HDMI_PHY_REG_12);
 	val &= ~BIT(5);
+	/* Wait for a short time before de-asserting
+	   to allow the hardware to complete its job.
+	   This much of delay should be fine for hardware
+	   to assert and de-assert. */
+	udelay(10);
 	/* De-assert PHY S/W reset */
 	writel_relaxed(val, HDMI_PHY_REG_12);
 	writel_relaxed(0x3f, HDMI_PHY_REG_2);
@@ -135,8 +147,32 @@
 	writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
 	writel_relaxed(0x80, HDMI_PHY_REG_2);
 
-	while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)))
-		cpu_relax();
+	timeout_count = 1000;
+	while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)) &&
+			timeout_count) {
+		if (--timeout_count == 0) {
+			/*
+			 * PLL has still not locked.
+			 * Do a software reset and try again
+			 * Assert PLL S/W reset first
+			 */
+			writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
+
+			/* Wait for a short time before de-asserting
+			 * to allow the hardware to complete its job.
+			 * This much of delay should be fine for hardware
+			 * to assert and de-assert.
+			 */
+			udelay(10);
+			writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
+			timeout_count = 1000;
+
+			pr_err("%s: PLL not locked after %d iterations\n",
+				__func__, timeout_count);
+			pr_err("%s: Asserting PLL S/W reset & trying again\n",
+				__func__);
+		}
+	}
 
 	if (!ahb_enabled)
 		writel_relaxed(ahb_en_reg & ~BIT(4), AHB_EN_REG);
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 467d5d1..9fe9591 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -408,6 +408,19 @@
 	return -EPERM;
 }
 
+static long branch_clk_round_rate(struct clk *c, unsigned long rate)
+{
+	struct branch_clk *branch = to_branch_clk(c);
+
+	if (branch->max_div)
+		return rate <= (branch->max_div) ? rate : -EPERM;
+
+	if (!branch->has_sibling)
+		return clk_round_rate(branch->parent, rate);
+
+	return -EPERM;
+}
+
 static unsigned long branch_clk_get_rate(struct clk *c)
 {
 	struct branch_clk *branch = to_branch_clk(c);
@@ -580,6 +593,7 @@
 	.set_rate = branch_clk_set_rate,
 	.get_rate = branch_clk_get_rate,
 	.list_rate = branch_clk_list_rate,
+	.round_rate = branch_clk_round_rate,
 	.reset = branch_clk_reset,
 	.get_parent = branch_clk_get_parent,
 	.handoff = branch_clk_handoff,
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index e0707fc..ab57cf8 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -237,7 +237,7 @@
 	if (r->rpmrs_data->get_rate_fn)
 		return r->rpmrs_data->get_rate_fn(r);
 	else
-		return 0;
+		return clk->rate;
 }
 
 static int rpm_clk_is_enabled(struct clk *clk)
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 63534a4..0fa1e2d 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -19,6 +19,7 @@
 
 #include <linux/earlysuspend.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/workqueue.h>
 #include <linux/completion.h>
@@ -27,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/suspend.h>
 #include <mach/socinfo.h>
+#include <mach/cpufreq.h>
 
 #include "acpuclock.h"
 
@@ -50,10 +52,33 @@
 
 static DEFINE_PER_CPU(struct cpufreq_suspend_t, cpufreq_suspend);
 
+struct cpu_freq {
+	uint32_t max;
+	uint32_t min;
+	uint32_t allowed_max;
+	uint32_t allowed_min;
+	uint32_t limits_init;
+};
+
+static DEFINE_PER_CPU(struct cpu_freq, cpu_freq_info);
+
 static int set_cpu_freq(struct cpufreq_policy *policy, unsigned int new_freq)
 {
 	int ret = 0;
 	struct cpufreq_freqs freqs;
+	struct cpu_freq *limit = &per_cpu(cpu_freq_info, policy->cpu);
+
+	if (limit->limits_init) {
+		if (new_freq > limit->allowed_max) {
+			new_freq = limit->allowed_max;
+			pr_debug("max: limiting freq to %d\n", new_freq);
+		}
+
+		if (new_freq < limit->allowed_min) {
+			new_freq = limit->allowed_min;
+			pr_debug("min: limiting freq to %d\n", new_freq);
+		}
+	}
 
 	freqs.old = policy->cur;
 	freqs.new = new_freq;
@@ -158,6 +183,72 @@
 	return 0;
 }
 
+static unsigned int msm_cpufreq_get_freq(unsigned int cpu)
+{
+	return acpuclk_get_rate(cpu);
+}
+
+static inline int msm_cpufreq_limits_init(void)
+{
+	int cpu = 0;
+	int i = 0;
+	struct cpufreq_frequency_table *table = NULL;
+	uint32_t min = (uint32_t) -1;
+	uint32_t max = 0;
+	struct cpu_freq *limit = NULL;
+
+	for_each_possible_cpu(cpu) {
+		limit = &per_cpu(cpu_freq_info, cpu);
+		table = cpufreq_frequency_get_table(cpu);
+		if (table == NULL) {
+			pr_err("%s: error reading cpufreq table for cpu %d\n",
+					__func__, cpu);
+			continue;
+		}
+		for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+			if (table[i].frequency > max)
+				max = table[i].frequency;
+			if (table[i].frequency < min)
+				min = table[i].frequency;
+		}
+		limit->allowed_min = min;
+		limit->allowed_max = max;
+		limit->min = min;
+		limit->max = max;
+		limit->limits_init = 1;
+	}
+
+	return 0;
+}
+
+int msm_cpufreq_set_freq_limits(uint32_t cpu, uint32_t min, uint32_t max)
+{
+	struct cpu_freq *limit = &per_cpu(cpu_freq_info, cpu);
+
+	if (!limit->limits_init)
+		msm_cpufreq_limits_init();
+
+	if ((min != MSM_CPUFREQ_NO_LIMIT) &&
+		min >= limit->min && min <= limit->max)
+		limit->allowed_min = min;
+	else
+		limit->allowed_min = limit->min;
+
+
+	if ((max != MSM_CPUFREQ_NO_LIMIT) &&
+		max <= limit->max && max >= limit->min)
+		limit->allowed_max = max;
+	else
+		limit->allowed_max = limit->max;
+
+	pr_debug("%s: Limiting cpu %d min = %d, max = %d\n",
+			__func__, cpu,
+			limit->allowed_min, limit->allowed_max);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_cpufreq_set_freq_limits);
+
 static int __cpuinit msm_cpufreq_init(struct cpufreq_policy *policy)
 {
 	int cur_freq;
@@ -274,6 +365,7 @@
 	.init		= msm_cpufreq_init,
 	.verify		= msm_cpufreq_verify,
 	.target		= msm_cpufreq_target,
+	.get		= msm_cpufreq_get_freq,
 	.name		= "msm",
 	.attr		= msm_freq_attr,
 };
@@ -300,4 +392,3 @@
 }
 
 late_initcall(msm_cpufreq_register);
-
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index b9617f3..66ce30e 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -1061,6 +1061,59 @@
 	},
 };
 
+static struct msm_bus_vectors vidc_venc_1080p_turbo_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 222298112,
+		.ib  = 3522000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 330301440,
+		.ib  = 3522000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 2500000,
+		.ib  = 700000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 2500000,
+		.ib  = 10000000,
+	},
+};
+static struct msm_bus_vectors vidc_vdec_1080p_turbo_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 222298112,
+		.ib  = 3522000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 330301440,
+		.ib  = 3522000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 2500000,
+		.ib  = 700000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 2500000,
+		.ib  = 10000000,
+	},
+};
+
 static struct msm_bus_paths vidc_bus_client_config[] = {
 	{
 		ARRAY_SIZE(vidc_init_vectors),
@@ -1090,6 +1143,14 @@
 		ARRAY_SIZE(vidc_vdec_1080p_vectors),
 		vidc_vdec_1080p_vectors,
 	},
+	{
+		ARRAY_SIZE(vidc_venc_1080p_turbo_vectors),
+		vidc_venc_1080p_turbo_vectors,
+	},
+	{
+		ARRAY_SIZE(vidc_vdec_1080p_turbo_vectors),
+		vidc_vdec_1080p_turbo_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata vidc_bus_client_data = {
@@ -2316,13 +2377,21 @@
 	},
 };
 
-
 static struct msm_bus_vectors vcap_480_vectors[]  = {
 	{
 		.src = MSM_BUS_MASTER_VIDEO_CAP,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 1280 * 720 * 3 * 60,
-		.ib = 1280 * 720 * 3 * 60 * 1.5,
+		.ab = 480 * 720 * 3 * 60,
+		.ib = 480 * 720 * 3 * 60 * 1.5,
+	},
+};
+
+static struct msm_bus_vectors vcap_576_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_CAP,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 576 * 720 * 3 * 60,
+		.ib = 576 * 720 * 3 * 60 * 1.5,
 	},
 };
 
@@ -2354,6 +2423,10 @@
 		vcap_480_vectors,
 	},
 	{
+		ARRAY_SIZE(vcap_576_vectors),
+		vcap_576_vectors,
+	},
+	{
 		ARRAY_SIZE(vcap_720_vectors),
 		vcap_720_vectors,
 	},
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index db55d14..550a283 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -202,6 +202,11 @@
 	},
 };
 
+struct platform_device msm8960_device_acpuclk = {
+	.name		= "acpuclk-8960",
+	.id		= -1,
+};
+
 #define SHARED_IMEM_TZ_BASE 0x2a03f720
 static struct resource tzlog_resources[] = {
 	{
@@ -3488,6 +3493,44 @@
 
 #endif
 
+static struct resource msm_ebi1_ch0_erp_resources[] = {
+	{
+		.start = HSDDRX_EBI1CH0_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = 0x00A40000,
+		.end   = 0x00A40000 + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8960_device_ebi1_ch0_erp = {
+	.name		= "msm_ebi_erp",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(msm_ebi1_ch0_erp_resources),
+	.resource	= msm_ebi1_ch0_erp_resources,
+};
+
+static struct resource msm_ebi1_ch1_erp_resources[] = {
+	{
+		.start = HSDDRX_EBI1CH1_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = 0x00D40000,
+		.end   = 0x00D40000 + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8960_device_ebi1_ch1_erp = {
+	.name		= "msm_ebi_erp",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(msm_ebi1_ch1_erp_resources),
+	.resource	= msm_ebi1_ch1_erp_resources,
+};
+
 static int msm8960_LPM_latency = 1000; /* >100 usec for WFI */
 
 struct platform_device msm8960_cpu_idle_device = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 4677a1c..06d8653 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -107,6 +107,11 @@
 	},
 };
 
+struct platform_device msm9615_device_acpuclk = {
+	.name           = "acpuclk-9615",
+	.id             = -1,
+};
+
 #define MSM_USB_BAM_BASE     0x12502000
 #define MSM_USB_BAM_SIZE     SZ_16K
 #define MSM_HSIC_BAM_BASE    0x12542000
@@ -1035,6 +1040,7 @@
 		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),
+		MSM_RPM_MAP(9615, VOLTAGE_CORNER, VOLTAGE_CORNER, 1),
 	},
 	.target_status = {
 		MSM_RPM_STATUS_ID_MAP(9615, VERSION_MAJOR),
@@ -1100,6 +1106,7 @@
 		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),
+		MSM_RPM_STATUS_ID_MAP(9615, VOLTAGE_CORNER),
 	},
 	.target_ctrl_id = {
 		MSM_RPM_CTRL_MAP(9615, VERSION_MAJOR),
@@ -1280,17 +1287,17 @@
 		[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,
+		[MSM_RPMRS_VDD_DIG_RET_LOW]     = 0,
+		[MSM_RPMRS_VDD_DIG_RET_HIGH]    = 0,
+		[MSM_RPMRS_VDD_DIG_ACTIVE]      = 1,
+		[MSM_RPMRS_VDD_DIG_MAX]         = 3,
 	},
 	.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_DIG_0]        = MSM_RPM_ID_VOLTAGE_CORNER,
+		[MSM_RPMRS_ID_VDD_DIG_1]        = MSM_RPM_ID_LAST,
 		[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,
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index ffd10fa..4619cca 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -27,6 +27,7 @@
 
 #include "devices.h"
 #include "footswitch.h"
+#include "acpuclock.h"
 
 #include <asm/mach/flash.h>
 
@@ -431,6 +432,16 @@
 	msm_pm_set_irq_extns(&msm7x27_pm_irq_calls);
 }
 
+static struct acpuclk_pdata msm7x27_acpuclk_pdata = {
+	.max_speed_delta_khz = 400000,
+};
+
+struct platform_device msm7x27_device_acpuclk = {
+	.name		= "acpuclk-7627",
+	.id		= -1,
+	.dev.platform_data = &msm7x27_acpuclk_pdata,
+};
+
 #define MSM_SDC1_BASE         0xA0400000
 #define MSM_SDC2_BASE         0xA0500000
 #define MSM_SDC3_BASE         0xA0600000
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index adc9169..b3454cd 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -211,6 +211,37 @@
 	},
 };
 
+static struct acpuclk_pdata msm7x27a_acpuclk_pdata = {
+	.max_speed_delta_khz = 400000,
+};
+
+struct platform_device msm7x27a_device_acpuclk = {
+	.name		= "acpuclk-7627",
+	.id		= -1,
+	.dev.platform_data = &msm7x27a_acpuclk_pdata,
+};
+
+static struct acpuclk_pdata msm7x27aa_acpuclk_pdata = {
+	.max_speed_delta_khz = 504000,
+};
+
+struct platform_device msm7x27aa_device_acpuclk = {
+	.name		= "acpuclk-7627",
+	.id		= -1,
+	.dev.platform_data = &msm7x27aa_acpuclk_pdata,
+};
+
+static struct acpuclk_pdata msm8625_acpuclk_pdata = {
+	/* TODO: Need to update speed delta from H/w Team */
+	.max_speed_delta_khz = 604800,
+};
+
+struct platform_device msm8625_device_acpuclk = {
+	.name		= "acpuclk-7627",
+	.id		= -1,
+	.dev.platform_data = &msm8625_acpuclk_pdata,
+};
+
 struct platform_device msm_device_smd = {
 	.name	= "msm_smd",
 	.id	= -1,
@@ -1623,16 +1654,15 @@
 
 	msm_clock_init(&msm7x27a_clock_init_data);
 	if (cpu_is_msm7x27aa() || cpu_is_msm7x25ab())
-		acpuclk_init(&acpuclk_7x27aa_soc_data);
+		platform_device_register(&msm7x27aa_device_acpuclk);
 	else if (cpu_is_msm8625()) {
 		if (msm8625_cpu_id() == MSM8625)
-			acpuclk_init(&acpuclk_7x27aa_soc_data);
+			platform_device_register(&msm7x27aa_device_acpuclk);
 		else if (msm8625_cpu_id() == MSM8625A)
-			acpuclk_init(&acpuclk_8625_soc_data);
-	 } else {
-		acpuclk_init(&acpuclk_7x27a_soc_data);
-	 }
-
+			platform_device_register(&msm8625_device_acpuclk);
+	} else {
+		platform_device_register(&msm7x27a_device_acpuclk);
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index de70429..ff747e2 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -42,6 +42,11 @@
 #include "pm.h"
 #include "irq.h"
 
+struct platform_device msm7x30_device_acpuclk = {
+	.name		= "acpuclk-7x30",
+	.id		= -1,
+};
+
 /* EBI THERMAL DRIVER */
 static struct resource msm_ebi0_thermal_resources[] = {
 	{
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 37844c1..d8bf054 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -163,6 +163,11 @@
 	},
 };
 
+struct platform_device msm8x60_device_acpuclk = {
+	.name		= "acpuclk-8x60",
+	.id		= -1,
+};
+
 #ifdef CONFIG_MSM_DSPS
 #define GSBI12_DEV (&msm_dsps_device.dev)
 #else
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index ee8a2cf..2ecc852 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -34,6 +34,11 @@
 #include <mach/rpc_hsusb.h>
 #include "pm.h"
 
+struct platform_device msm8x50_device_acpuclk = {
+	.name		= "acpuclk-8x50",
+	.id		= -1,
+};
+
 static struct resource resources_uart1[] = {
 	{
 		.start	= INT_UART1,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 2b2fcc7..ea47727 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -77,6 +77,8 @@
 extern struct platform_device msm8960_device_vfe;
 extern struct platform_device msm8960_device_vpe;
 extern struct platform_device msm8960_device_cache_erp;
+extern struct platform_device msm8960_device_ebi1_ch0_erp;
+extern struct platform_device msm8960_device_ebi1_ch1_erp;
 
 extern struct platform_device apq8064_device_uart_gsbi1;
 extern struct platform_device apq8064_device_uart_gsbi3;
@@ -410,3 +412,13 @@
 extern struct platform_device mdm_sglte_device;
 
 extern struct platform_device apq_device_tz_log;
+
+extern struct platform_device msm7x27_device_acpuclk;
+extern struct platform_device msm7x27a_device_acpuclk;
+extern struct platform_device msm7x27aa_device_acpuclk;
+extern struct platform_device msm7x30_device_acpuclk;
+extern struct platform_device msm8625_device_acpuclk;
+extern struct platform_device msm8x50_device_acpuclk;
+extern struct platform_device msm8x60_device_acpuclk;
+extern struct platform_device msm8960_device_acpuclk;
+extern struct platform_device msm9615_device_acpuclk;
diff --git a/arch/arm/mach-msm/ebi_erp.c b/arch/arm/mach-msm/ebi_erp.c
new file mode 100644
index 0000000..cd9119d
--- /dev/null
+++ b/arch/arm/mach-msm/ebi_erp.c
@@ -0,0 +1,194 @@
+/* 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/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/cpu.h>
+
+#define MODULE_NAME "msm_ebi_erp"
+
+#define EBI_ERR_ADDR		0x100
+#define SLV_ERR_APACKET_0	0x108
+#define SLV_ERR_APACKET_1	0x10C
+#define SLV_ERR_CNTL		0x114
+
+#define CNTL_ERR_OCCURRED	BIT(4)
+#define CNTL_CLEAR_ERR		BIT(8)
+#define CNTL_IRQ_EN		BIT(12)
+
+#define AMID_MASK		0xFFFF
+#define ERR_AWRITE		BIT(0)
+#define ERR_AOOOWR		BIT(1)
+#define ERR_AOOORD		BIT(2)
+#define ERR_APTORNS		BIT(3)
+#define ERR_ALOCK_SHIFT		6
+#define ERR_ALOCK_MASK		0x3
+#define ERR_ATYPE_SHIFT		8
+#define ERR_ATYPE_MASK		0xF
+#define ERR_ABURST		BIT(12)
+#define ERR_ASIZE_SHIFT		13
+#define ERR_ASIZE_MASK		0x7
+#define ERR_ATID_SHIFT		16
+#define ERR_ATID_MASK		0xFF
+#define ERR_ALEN_SHIFT		24
+#define ERR_ALEN_MASK		0xF
+
+#define ERR_CODE_DECODE_ERROR	BIT(0)
+#define ERR_CODE_MPU_ERROR	BIT(1)
+
+struct msm_ebi_erp_data {
+	void __iomem *base;
+	struct device *dev;
+};
+
+static const char *err_lock_types[4] = {
+	"normal",
+	"exclusive",
+	"locked",
+	"barrier",
+};
+
+static const char *err_sizes[8] = {
+	"byte",
+	"half word",
+	"word",
+	"double word",
+	"reserved_4",
+	"reserved_5",
+	"reserved_6",
+	"reserved_7",
+};
+
+static irqreturn_t msm_ebi_irq(int irq, void *dev_id)
+{
+	struct msm_ebi_erp_data *drvdata = dev_id;
+	void __iomem *base = drvdata->base;
+	unsigned int err_addr, err_apacket0, err_apacket1, err_cntl;
+
+	err_addr = readl_relaxed(base + EBI_ERR_ADDR);
+	err_apacket0 = readl_relaxed(base + SLV_ERR_APACKET_0);
+	err_apacket1 = readl_relaxed(base + SLV_ERR_APACKET_1);
+	err_cntl = readl_relaxed(base + SLV_ERR_CNTL);
+
+	if (!(err_cntl & CNTL_ERR_OCCURRED))
+		return IRQ_NONE;
+
+	pr_alert("EBI error detected!\n");
+	pr_alert("\tDevice   = %s\n", dev_name(drvdata->dev));
+	pr_alert("\tERR_ADDR = 0x%08x\n", err_addr);
+	pr_alert("\tAPACKET0 = 0x%08x\n", err_apacket0);
+	pr_alert("\tAPACKET1 = 0x%08x\n", err_apacket1);
+	pr_alert("\tERR_CNTL = 0x%08x\n", err_cntl);
+
+	pr_alert("\tAMID     = 0x%08x\n", err_apacket0 & AMID_MASK);
+	pr_alert("\tType     = %s, %s, %s\n",
+		err_apacket1 & ERR_AWRITE ? "write" : "read",
+		err_sizes[(err_apacket1 >> ERR_ASIZE_SHIFT) & ERR_ASIZE_MASK],
+		err_apacket1 & ERR_APTORNS ? "non-secure" : "secure");
+
+	pr_alert("\tALOCK    = %s\n",
+	    err_lock_types[(err_apacket1 >> ERR_ALOCK_SHIFT) & ERR_ALOCK_MASK]);
+
+	pr_alert("\tABURST   = %s\n", err_apacket1 & ERR_ABURST ?
+						"increment" : "wrap");
+
+	pr_alert("\tCODE     = %s %s\n", err_cntl & ERR_CODE_DECODE_ERROR ?
+						"decode error" : "",
+					 err_cntl & ERR_CODE_MPU_ERROR ?
+						"mpu error" : "");
+	err_cntl |= CNTL_CLEAR_ERR;
+	writel_relaxed(err_cntl, base + SLV_ERR_CNTL);
+	mb();	/* Ensure interrupt is cleared before returning */
+	return IRQ_HANDLED;
+}
+
+static int __devinit msm_ebi_erp_probe(struct platform_device *pdev)
+{
+	struct resource *r;
+	struct msm_ebi_erp_data *drvdata;
+	int ret, irq;
+	unsigned int err_cntl;
+
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -EINVAL;
+
+	drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (!drvdata->base)
+		return -ENOMEM;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_irq(&pdev->dev, irq, msm_ebi_irq, IRQF_TRIGGER_HIGH,
+			       dev_name(&pdev->dev), drvdata);
+	if (ret)
+		return ret;
+
+	/* Enable the interrupt */
+	err_cntl = readl_relaxed(drvdata->base + SLV_ERR_CNTL);
+	err_cntl |= CNTL_IRQ_EN;
+	writel_relaxed(err_cntl, drvdata->base + SLV_ERR_CNTL);
+	mb();	/* Ensure interrupt is enabled before returning */
+	return 0;
+}
+
+static int msm_ebi_erp_remove(struct platform_device *pdev)
+{
+	struct msm_ebi_erp_data *drvdata = platform_get_drvdata(pdev);
+	unsigned int err_cntl;
+
+	/* Disable the interrupt */
+	err_cntl = readl_relaxed(drvdata->base + SLV_ERR_CNTL);
+	err_cntl &= ~CNTL_IRQ_EN;
+	writel_relaxed(err_cntl, drvdata->base + SLV_ERR_CNTL);
+	mb();	/* Ensure interrupt is disabled before returning */
+	return 0;
+}
+
+static struct platform_driver msm_ebi_erp_driver = {
+	.probe = msm_ebi_erp_probe,
+	.remove = __devexit_p(msm_ebi_erp_remove),
+	.driver = {
+		.name = MODULE_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_ebi_erp_init(void)
+{
+	return platform_driver_register(&msm_ebi_erp_driver);
+}
+
+static void __exit msm_ebi_erp_exit(void)
+{
+	platform_driver_unregister(&msm_ebi_erp_driver);
+}
+
+
+module_init(msm_ebi_erp_init);
+module_exit(msm_ebi_erp_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM cache error reporting driver");
diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S
index 50d2060..e5ad312 100644
--- a/arch/arm/mach-msm/headsmp.S
+++ b/arch/arm/mach-msm/headsmp.S
@@ -27,10 +27,6 @@
 	sub	r4, r4, r5		@ determine virtual/phys offsets
 	add	r6, r6, r4		@ apply
 pen:
-	wfe
-	dsb				@ ensure subsequent access is
-					@ after event
-
 	ldr	r7, [r6]		@ pen_rel has cpu to remove from reset
 	cmp	r7, r0			@ are we lucky?
 	bne	pen
diff --git a/arch/arm/mach-msm/hsic_sysmon.c b/arch/arm/mach-msm/hsic_sysmon.c
index 2dedbac..07a9dbb 100644
--- a/arch/arm/mach-msm/hsic_sysmon.c
+++ b/arch/arm/mach-msm/hsic_sysmon.c
@@ -139,14 +139,13 @@
 	}
 
 	if (!hs->ifc) {
-		dev_err(&hs->udev->dev, "can't %s, device disconnected\n",
-				opstr);
+		pr_err("can't %s, device disconnected", opstr);
 		return -ENODEV;
 	}
 
 	ret = usb_autopm_get_interface(hs->ifc);
 	if (ret < 0) {
-		dev_err(&hs->udev->dev, "can't %s, autopm_get failed:%d\n",
+		dev_err(&hs->ifc->dev, "can't %s, autopm_get failed:%d\n",
 			opstr, ret);
 		return ret;
 	}
@@ -159,7 +158,7 @@
 	atomic_dec(&hs->dbg_pending[op]);
 
 	if (ret)
-		dev_err(&hs->udev->dev,
+		dev_err(&hs->ifc->dev,
 			"can't %s, usb_bulk_msg failed, err:%d\n", opstr, ret);
 	else
 		atomic_add(*actual_len, &hs->dbg_bytecnt[op]);
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index bae5cbc..be254f6 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -61,10 +61,6 @@
 	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;
 };
@@ -389,6 +385,7 @@
 	int (*backlight_level)(int level, int max, int min);
 	int (*pmic_backlight)(int level);
 	int (*rotate_panel)(void);
+	int (*backlight) (int level, int mode);
 	int (*panel_num)(void);
 	void (*panel_config_gpio)(int);
 	int (*vga_switch)(int select_vga);
@@ -485,6 +482,8 @@
 	int (*enable_5v)(int on);
 	int (*core_power)(int on, int show);
 	int (*cec_power)(int on);
+	int (*panel_power)(int on);
+	int (*gpio_config)(int on);
 	int (*init_irq)(void);
 	bool (*check_hdcp_hw_support)(void);
 };
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 87e7de1..d8543f3 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -114,52 +114,6 @@
 	STEREO_RAW_SNAP_STARTED,
 };
 
-enum msm_ispif_intftype {
-	PIX0,
-	RDI0,
-	PIX1,
-	RDI1,
-	PIX2,
-	RDI2,
-};
-
-enum msm_ispif_vc {
-	VC0,
-	VC1,
-	VC2,
-	VC3,
-};
-
-enum msm_ispif_cid {
-	CID0,
-	CID1,
-	CID2,
-	CID3,
-	CID4,
-	CID5,
-	CID6,
-	CID7,
-	CID8,
-	CID9,
-	CID10,
-	CID11,
-	CID12,
-	CID13,
-	CID14,
-	CID15,
-};
-
-struct msm_ispif_params {
-	uint8_t intftype;
-	uint16_t cid_mask;
-	uint8_t csid;
-};
-
-struct msm_ispif_params_list {
-	uint32_t len;
-	struct msm_ispif_params params[3];
-};
-
 struct msm_vpe_phy_info {
 	uint32_t sbuf_phy;
 	uint32_t planar0_off;
@@ -172,12 +126,6 @@
 	uint32_t frame_id;
 };
 
-struct msm_camera_csid_vc_cfg {
-	uint8_t cid;
-	uint8_t dt;
-	uint8_t decode_format;
-};
-
 struct msm_camera_csid_lut_params {
 	uint8_t num_cid;
 	struct msm_camera_csid_vc_cfg *vc_cfg;
@@ -209,18 +157,6 @@
 #define VFE31_OUTPUT_MODE_P_ALL_CHNLS (0x1 << 5)
 #endif
 
-#define CSI_EMBED_DATA 0x12
-#define CSI_RESERVED_DATA_0 0x13
-#define CSI_YUV422_8  0x1E
-#define CSI_RAW8    0x2A
-#define CSI_RAW10   0x2B
-#define CSI_RAW12   0x2C
-
-#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;
 	uint32_t planar0_off;
diff --git a/arch/arm/mach-msm/include/mach/cpufreq.h b/arch/arm/mach-msm/include/mach/cpufreq.h
new file mode 100644
index 0000000..8c2be11
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/cpufreq.h
@@ -0,0 +1,42 @@
+/* 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_MACH_CPUFREQ_H
+#define __ARCH_ARM_MACH_MSM_MACH_CPUFREQ_H
+
+#define MSM_CPUFREQ_NO_LIMIT 0xFFFFFFFF
+
+#ifdef CONFIG_CPU_FREQ_MSM
+
+/**
+ * msm_cpufreq_set_freq_limit() - Set max/min freq limits on cpu
+ *
+ * @cpu: The cpu core for which the limits apply
+ * @max: The max frequency allowed
+ * @min: The min frequency allowed
+ *
+ * If the @max or @min is set to MSM_CPUFREQ_NO_LIMIT, the limit
+ * will default to the CPUFreq limit.
+ *
+ * returns 0 on success, errno on failure
+ */
+extern int msm_cpufreq_set_freq_limits(
+		uint32_t cpu, uint32_t min, uint32_t max);
+#else
+static inline int msm_cpufreq_set_freq_limits(
+		uint32_t cpu, uint32_t min, uint32_t max)
+{
+	return -ENOSYS;
+}
+#endif
+
+#endif /* __ARCH_ARM_MACH_MSM_MACH_CPUFREQ_H */
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h
index 956d44e..0c556b5 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h
@@ -39,6 +39,8 @@
 	const struct msm_bus_board_algorithm *board_algo;
 	int hw_sel;
 	void *hw_data;
+	uint32_t qos_freq;
+	bool virt;
 };
 
 enum msm_bus_bw_tier_type {
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 57e794f..2455e93 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -36,7 +36,16 @@
 int hdmi_audio_packet_enable(bool on);
 void hdmi_msm_audio_sample_rate_reset(int rate);
 int hdmi_msm_audio_get_sample_rate(void);
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
 int hdmi_msm_audio_info_setup(bool enabled, u32 num_of_channels,
 	u32 channel_allocation, u32 level_shift, bool down_mix);
-
+#else
+static inline int hdmi_msm_audio_info_setup(bool enabled,
+	u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+	bool down_mix)
+{
+	return 0;
+}
+#endif
 #endif /* __MSM_HDMI_AUDIO_H*/
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index fbb8502..e19f39d 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -95,7 +95,7 @@
 #define SMSM_WLAN_TX_RINGS_EMPTY 0x00000200
 #define SMSM_WLAN_TX_ENABLE	0x00000400
 
-#define SMSM_ERR_SRV_READY         0x00008000
+#define SMSM_SUBSYS2AP_STATUS         0x00008000
 
 #ifdef CONFIG_MSM_SMD
 void *smem_alloc(unsigned id, unsigned size);
diff --git a/arch/arm/mach-msm/include/mach/ocmem.h b/arch/arm/mach-msm/include/mach/ocmem.h
index bf7c338..b0475ed 100644
--- a/arch/arm/mach-msm/include/mach/ocmem.h
+++ b/arch/arm/mach-msm/include/mach/ocmem.h
@@ -41,7 +41,7 @@
 };
 
 struct ocmem_map_list {
-	int num_chunks;
+	unsigned num_chunks;
 	struct ocmem_chunk chunks[OCMEM_MAX_CHUNKS];
 };
 
@@ -84,9 +84,14 @@
 
 int ocmem_notifier_unregister(void *notif_hndl, struct notifier_block *nb);
 
+/* Obtain the maximum quota for the client */
+unsigned long get_max_quota(int client_id);
+
 /* Allocation APIs */
 struct ocmem_buf *ocmem_allocate(int client_id, unsigned long size);
 
+struct ocmem_buf *ocmem_allocate_nowait(int client_id, unsigned long size);
+
 struct ocmem_buf *ocmem_allocate_nb(int client_id, unsigned long size);
 
 struct ocmem_buf *ocmem_allocate_range(int client_id, unsigned long min,
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index dd3a318..dd976ea 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -24,6 +24,9 @@
 #define OCMEM_PHYS_BASE 0xFEC00000
 #define OCMEM_PHYS_SIZE 0x180000
 
+#define TO_OCMEM 0x1
+#define TO_DDR 0x2
+
 struct ocmem_zone;
 
 struct ocmem_zone_ops {
@@ -45,6 +48,19 @@
 	struct ocmem_zone_ops *z_ops;
 };
 
+enum op_code {
+	SCHED_NOP = 0x0,
+	SCHED_ALLOCATE,
+	SCHED_FREE,
+	SCHED_GROW,
+	SCHED_SHRINK,
+	SCHED_MAP,
+	SCHED_UNMAP,
+	SCHED_EVICT,
+	SCHED_RESTORE,
+	SCHED_DUMP,
+};
+
 struct ocmem_req {
 	struct rw_semaphore rw_sem;
 	/* Chain in sched queue */
@@ -60,6 +76,8 @@
 	/* reverse pointers */
 	struct ocmem_zone *zone;
 	struct ocmem_buf *buffer;
+	struct ocmem_map_list *mlist;
+	enum op_code op;
 	unsigned long state;
 	/* Request assignments */
 	unsigned long req_start;
@@ -73,7 +91,41 @@
 	struct ocmem_req *req;
 };
 
+static inline struct ocmem_buf *handle_to_buffer(struct ocmem_handle *handle)
+{
+	if (handle)
+		return &handle->buffer;
+	else
+		return NULL;
+}
+
+static inline struct ocmem_handle *buffer_to_handle(struct ocmem_buf *buffer)
+{
+	if (buffer)
+		return container_of(buffer, struct ocmem_handle, buffer);
+	else
+		return NULL;
+}
+
+static inline struct ocmem_req *handle_to_req(struct ocmem_handle *handle)
+{
+	if (handle)
+		return handle->req;
+	else
+		return NULL;
+}
+
+static inline struct ocmem_handle *req_to_handle(struct ocmem_req *req)
+{
+	if (req && req->buffer)
+		return container_of(req->buffer, struct ocmem_handle, buffer);
+	else
+		return NULL;
+}
+
 struct ocmem_zone *get_zone(unsigned);
+unsigned long offset_to_phys(unsigned long);
+unsigned long phys_to_offset(unsigned long);
 unsigned long allocate_head(struct ocmem_zone *, unsigned long);
 int free_head(struct ocmem_zone *, unsigned long, unsigned long);
 unsigned long allocate_tail(struct ocmem_zone *, unsigned long);
@@ -82,4 +134,12 @@
 int ocmem_notifier_init(void);
 int check_notifier(int);
 int dispatch_notification(int, enum ocmem_notif_type, struct ocmem_buf *);
+
+int ocmem_sched_init(void);
+int process_allocate(int, struct ocmem_handle *, unsigned long, unsigned long,
+			unsigned long, bool, bool);
+int process_free(int, struct ocmem_handle *);
+int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *,
+			int direction);
+unsigned long process_quota(int);
 #endif
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 a55dee6..65cf647 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
@@ -14,8 +14,11 @@
 #define _AUDIO_ACDB_H
 
 #include <linux/msm_audio_acdb.h>
+#ifdef CONFIG_ARCH_MSMCOPPER
+#include <sound/q6adm-v2.h>
+#else
 #include <sound/q6adm.h>
-
+#endif
 enum {
 	RX_CAL,
 	TX_CAL,
diff --git a/arch/arm/mach-msm/include/mach/rpm-9615.h b/arch/arm/mach-msm/include/mach/rpm-9615.h
index 6ae7bae..4ca5eea 100644
--- a/arch/arm/mach-msm/include/mach/rpm-9615.h
+++ b/arch/arm/mach-msm/include/mach/rpm-9615.h
@@ -72,8 +72,9 @@
 	MSM_RPM_9615_SEL_CXO_BUFFERS				= 81,
 	MSM_RPM_9615_SEL_USB_OTG_SWITCH				= 82,
 	MSM_RPM_9615_SEL_HDMI_SWITCH				= 83,
+	MSM_RPM_9615_SEL_VOLTAGE_CORNER				= 87,
 
-	MSM_RPM_9615_SEL_LAST = MSM_RPM_9615_SEL_HDMI_SWITCH,
+	MSM_RPM_9615_SEL_LAST = MSM_RPM_9615_SEL_VOLTAGE_CORNER,
 };
 
 /* RPM resource (4 byte) word ID enum */
@@ -162,8 +163,9 @@
 	MSM_RPM_9615_ID_CXO_BUFFERS				= 105,
 	MSM_RPM_9615_ID_USB_OTG_SWITCH				= 106,
 	MSM_RPM_9615_ID_HDMI_SWITCH				= 107,
+	MSM_RPM_9615_ID_VOLTAGE_CORNER				= 109,
 
-	MSM_RPM_9615_ID_LAST = MSM_RPM_9615_ID_HDMI_SWITCH,
+	MSM_RPM_9615_ID_LAST = MSM_RPM_9615_ID_VOLTAGE_CORNER,
 };
 
 /* RPM status ID enum */
@@ -231,8 +233,9 @@
 	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_9615_STATUS_ID_VOLTAGE_CORNER			= 64,
 
-	MSM_RPM_9615_STATUS_ID_LAST = MSM_RPM_9615_STATUS_ID_HDMI_SWITCH,
+	MSM_RPM_9615_STATUS_ID_LAST = MSM_RPM_9615_STATUS_ID_VOLTAGE_CORNER,
 };
 
 #endif /* __ARCH_ARM_MACH_MSM_RPM_9615_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-9615.h b/arch/arm/mach-msm/include/mach/rpm-regulator-9615.h
index f5fa8ca..6a7fae5 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-9615.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-9615.h
@@ -107,7 +107,8 @@
 	RPM_VREG_ID_PM8018_S4,
 	RPM_VREG_ID_PM8018_S5,
 	RPM_VREG_ID_PM8018_LVS1,
-	RPM_VREG_ID_PM8018_MAX_REAL = RPM_VREG_ID_PM8018_LVS1,
+	RPM_VREG_ID_PM8018_VDD_DIG_CORNER,
+	RPM_VREG_ID_PM8018_MAX_REAL = RPM_VREG_ID_PM8018_VDD_DIG_CORNER,
 
 	/* The following are IDs for regulator devices to enable pin control. */
 	RPM_VREG_ID_PM8018_L2_PC,
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index c15e8b1..c0bff63 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -472,19 +472,19 @@
 	return port_ptr;
 }
 
+/*
+ * Should be called with local_ports_lock locked
+ */
 static struct msm_ipc_port *msm_ipc_router_lookup_local_port(uint32_t port_id)
 {
 	int key = (port_id & (LP_HASH_SIZE - 1));
 	struct msm_ipc_port *port_ptr;
 
-	mutex_lock(&local_ports_lock);
 	list_for_each_entry(port_ptr, &local_ports[key], list) {
 		if (port_ptr->this_port.port_id == port_id) {
-			mutex_unlock(&local_ports_lock);
 			return port_ptr;
 		}
 	}
-	mutex_unlock(&local_ports_lock);
 	return NULL;
 }
 
@@ -1432,16 +1432,19 @@
 	resume_tx_node_id = hdr->dst_node_id;
 	resume_tx_port_id = hdr->dst_port_id;
 
+	rport_ptr = msm_ipc_router_lookup_remote_port(hdr->src_node_id,
+						      hdr->src_port_id);
+
+	mutex_lock(&local_ports_lock);
 	port_ptr = msm_ipc_router_lookup_local_port(hdr->dst_port_id);
 	if (!port_ptr) {
 		pr_err("%s: No local port id %08x\n", __func__,
 			hdr->dst_port_id);
+		mutex_unlock(&local_ports_lock);
 		release_pkt(pkt);
 		goto process_done;
 	}
 
-	rport_ptr = msm_ipc_router_lookup_remote_port(hdr->src_node_id,
-						      hdr->src_port_id);
 	if (!rport_ptr) {
 		rport_ptr = msm_ipc_router_create_remote_port(
 							hdr->src_node_id,
@@ -1449,6 +1452,7 @@
 		if (!rport_ptr) {
 			pr_err("%s: Remote port %08x:%08x creation failed\n",
 				__func__, hdr->src_node_id, hdr->src_port_id);
+			mutex_unlock(&local_ports_lock);
 			goto process_done;
 		}
 	}
@@ -1459,7 +1463,9 @@
 		list_add_tail(&pkt->list, &port_ptr->port_rx_q);
 		wake_up(&port_ptr->port_rx_wait_q);
 		mutex_unlock(&port_ptr->port_rx_q_lock);
+		mutex_unlock(&local_ports_lock);
 	} else {
+		mutex_lock(&port_ptr->port_rx_q_lock);
 		src_addr = kmalloc(sizeof(struct msm_ipc_port_addr),
 				   GFP_KERNEL);
 		if (src_addr) {
@@ -1467,8 +1473,10 @@
 			src_addr->port_id = hdr->src_port_id;
 		}
 		skb_pull(head_skb, IPC_ROUTER_HDR_SIZE);
+		mutex_unlock(&local_ports_lock);
 		port_ptr->notify(MSM_IPC_ROUTER_READ_CB, pkt->pkt_fragment_q,
 				 src_addr, port_ptr->priv);
+		mutex_unlock(&port_ptr->port_rx_q_lock);
 		pkt->pkt_fragment_q = NULL;
 		src_addr = NULL;
 		release_pkt(pkt);
@@ -1628,9 +1636,11 @@
 	hdr->dst_port_id = port_id;
 	pkt->length += IPC_ROUTER_HDR_SIZE;
 
+	mutex_lock(&local_ports_lock);
 	port_ptr = msm_ipc_router_lookup_local_port(port_id);
 	if (!port_ptr) {
 		pr_err("%s: Local port %d not present\n", __func__, port_id);
+		mutex_unlock(&local_ports_lock);
 		release_pkt(pkt);
 		return -ENODEV;
 	}
@@ -1640,6 +1650,7 @@
 	list_add_tail(&pkt->list, &port_ptr->port_rx_q);
 	wake_up(&port_ptr->port_rx_wait_q);
 	mutex_unlock(&port_ptr->port_rx_q_lock);
+	mutex_unlock(&local_ports_lock);
 
 	return pkt->length;
 }
@@ -1932,6 +1943,10 @@
 		return -EINVAL;
 
 	if (port_ptr->type == SERVER_PORT || port_ptr->type == CLIENT_PORT) {
+		mutex_lock(&local_ports_lock);
+		list_del(&port_ptr->list);
+		mutex_unlock(&local_ports_lock);
+
 		if (port_ptr->type == SERVER_PORT) {
 			msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_SERVER;
 			msg.srv.service = port_ptr->port_name.service;
@@ -1950,6 +1965,10 @@
 		}
 		broadcast_ctl_msg(&msg);
 		broadcast_ctl_msg_locally(&msg);
+	} else if (port_ptr->type == CONTROL_PORT) {
+		mutex_lock(&control_ports_lock);
+		list_del(&port_ptr->list);
+		mutex_unlock(&control_ports_lock);
 	}
 
 	mutex_lock(&port_ptr->port_rx_q_lock);
@@ -1969,17 +1988,6 @@
 			msm_ipc_router_destroy_server(server,
 				port_ptr->this_port.node_id,
 				port_ptr->this_port.port_id);
-		mutex_lock(&local_ports_lock);
-		list_del(&port_ptr->list);
-		mutex_unlock(&local_ports_lock);
-	} else if (port_ptr->type == CLIENT_PORT) {
-		mutex_lock(&local_ports_lock);
-		list_del(&port_ptr->list);
-		mutex_unlock(&local_ports_lock);
-	} else if (port_ptr->type == CONTROL_PORT) {
-		mutex_lock(&control_ports_lock);
-		list_del(&port_ptr->list);
-		mutex_unlock(&control_ports_lock);
 	}
 
 	wake_lock_destroy(&port_ptr->port_rx_wake_lock);
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index ffff782..74bf25d 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -45,6 +45,7 @@
 #define MDM_MODEM_DELTA	100
 #define MDM_BOOT_TIMEOUT	60000L
 #define MDM_RDUMP_TIMEOUT	60000L
+#define MDM2AP_STATUS_TIMEOUT_MS 60000L
 
 static int mdm_debug_on;
 static struct workqueue_struct *mdm_queue;
@@ -90,6 +91,22 @@
 
 static DECLARE_WORK(sfr_reason_work, mdm_restart_reason_fn);
 
+static void mdm2ap_status_check(struct work_struct *work)
+{
+	/*
+	 * If the mdm modem did not pull the MDM2AP_STATUS gpio
+	 * high then call subsystem_restart.
+	 */
+	if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) {
+		pr_err("%s: MDM2AP_STATUS gpio did not go high\n",
+			   __func__);
+		mdm_drv->mdm_ready = 0;
+		subsystem_restart(EXTERNAL_MODEM);
+	}
+}
+
+static DECLARE_DELAYED_WORK(mdm2ap_status_check_work, mdm2ap_status_check);
+
 long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
 				unsigned long arg)
 {
@@ -131,6 +148,14 @@
 			complete(&mdm_boot);
 		else
 			first_boot = 0;
+
+		/* Start a timer to check that the mdm2ap_status gpio
+		 * goes high.
+		 */
+
+		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+			schedule_delayed_work(&mdm2ap_status_check_work,
+				msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS));
 		break;
 	case RAM_DUMP_DONE:
 		pr_debug("%s: mdm done collecting RAM dumps\n", __func__);
@@ -256,6 +281,7 @@
 		mdm_drv->mdm_ready = 0;
 		subsystem_restart(EXTERNAL_MODEM);
 	} else if (value == 1) {
+		cancel_delayed_work(&mdm2ap_status_check_work);
 		pr_info("%s: status = 1: mdm is now ready\n", __func__);
 		queue_work(mdm_queue, &mdm_status_work);
 	}
diff --git a/arch/arm/mach-msm/modem_notifier.c b/arch/arm/mach-msm/modem_notifier.c
index d92098b..2f4f6af 100644
--- a/arch/arm/mach-msm/modem_notifier.c
+++ b/arch/arm/mach-msm/modem_notifier.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -193,8 +193,15 @@
 }
 #endif
 
-static int __init init_modem_notifier_list(void)
+int __init msm_init_modem_notifier_list(void)
 {
+	static bool registered;
+
+	if (registered)
+		return 0;
+
+	registered = true;
+
 	srcu_init_notifier_head(&modem_notifier_list);
 	modem_notifier_debugfs_init();
 #if defined(DEBUG)
@@ -210,4 +217,4 @@
 
 	return 0;
 }
-module_init(init_modem_notifier_list);
+module_init(msm_init_modem_notifier_list);
diff --git a/arch/arm/mach-msm/modem_notifier.h b/arch/arm/mach-msm/modem_notifier.h
index 1bd2d6d..e39c163 100644
--- a/arch/arm/mach-msm/modem_notifier.h
+++ b/arch/arm/mach-msm/modem_notifier.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -30,5 +30,6 @@
 extern void modem_queue_start_reset_notify(void);
 extern void modem_queue_end_reset_notify(void);
 extern void modem_queue_smsm_init_notify(void);
+extern int __init msm_init_modem_notifier_list(void);
 
 #endif /* _MODEM_NOTIFIER_H */
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index 061998c..766856c 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -1,7 +1,8 @@
 #
 # Makefile for msm-bus driver specific files
 #
-obj-y += msm_bus_core.o msm_bus_fabric.o msm_bus_config.o msm_bus_arb.o msm_bus_rpm.o
+obj-y += msm_bus_core.o msm_bus_fabric.o msm_bus_config.o msm_bus_arb.o
+obj-y += msm_bus_rpm.o msm_bus_bimc.o msm_bus_noc.o
 obj-$(CONFIG_ARCH_MSM8X60) += msm_bus_board_8660.o
 obj-$(CONFIG_ARCH_MSM8960) += msm_bus_board_8960.o
 obj-$(CONFIG_ARCH_MSM9615) += msm_bus_board_9615.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
new file mode 100644
index 0000000..823f14d
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
@@ -0,0 +1,1990 @@
+/* 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) "AXI: BIMC: %s(): " fmt, __func__
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <mach/msm_bus_board.h>
+#include "msm_bus_core.h"
+#include "msm_bus_bimc.h"
+
+enum msm_bus_bimc_slave_block {
+	SLAVE_BLOCK_RESERVED = 0,
+	SLAVE_BLOCK_SLAVE_WAY,
+	SLAVE_BLOCK_XPU,
+	SLAVE_BLOCK_ARBITER,
+	SLAVE_BLOCK_SCMO,
+};
+
+
+/* Misc module */
+
+#define MISC_REG_BASE(b)		((b) + 0x00000000)
+
+#define MISC_HW_VERSION_ADDR(b)	(MISC_REG_BASE(b) + 0x0000000)
+enum bimc_misc_hw_version {
+	MISC_HW_VERSION_RMSK		= 0xffffff,
+	MISC_HW_VERSION_MAJOR_BMSK	= 0xff0000,
+	MISC_HW_VERSION_MAJOR_SHFT	= 0x10,
+	MISC_HW_VERSION_MINOR_BMSK	= 0xff00,
+	MISC_HW_VERSION_MINOR_SHFT	= 0x8,
+	MISC_HW_VERSION_STEP_BMSK	= 0xff,
+	MISC_HW_VERSION_STEP_SHFT	= 0x0,
+};
+
+#define MISC_CORE_INFO_ADDR(b)	(MISC_REG_BASE(b) + 0x00000004)
+enum bimc_misc_core_info {
+	MISC_CORE_INFO_RMSK		= 0xffffffff,
+	MISC_CORE_INFO_CORE_INFO_BMSK	= 0xffffffff,
+	MISC_CORE_INFO_CORE_INFO_SHFT	= 0x0,
+};
+
+#define MISC_HW_INFO_ADDR(b)	(MISC_REG_BASE(b) + 0x00000008)
+enum bimc_misc_hw_info {
+	MISC_HW_INFO_RMSK		= 0xffffffff,
+	MISC_HW_INFO_HW_MAJOR_BMSK	= 0xff000000,
+	MISC_HW_INFO_HW_MAJOR_SHFT	= 0x18,
+	MISC_HW_INFO_HW_BRANCH_BMSK	= 0xff0000,
+	MISC_HW_INFO_HW_BRANCH_SHFT	= 0x10,
+	MISC_HW_INFO_HW_MINOR_BMSK	= 0xff00,
+	MISC_HW_INFO_HW_MINOR_SHFT	= 0x8,
+	MISC_HW_INFO_HW_ECO_BMSK	= 0xff,
+	MISC_HW_INFO_HW_ECO_SHFT	= 0x0,
+};
+
+#define MISC_CORE_CLK_SEL_ADDR(b) \
+	(MISC_REG_BASE(b) + 0x00000020)
+enum bimc_misc_core_clk_sel {
+	MISC_CORE_CLK_SEL_RMSK				= 0x3,
+	MISC_CORE_CLK_SEL_CLK_2X_MODE_BMSK		= 0x2,
+	MISC_CORE_CLK_SEL_CLK_2X_MODE_SHFT		= 0x1,
+	MISC_CORE_CLK_SEL_CLK_2X_MODE_CTRL_EN_BMSK	= 0x1,
+	MISC_CORE_CLK_SEL_CLK_2X_MODE_CTRL_EN_SHFT	= 0x0,
+};
+
+#define MISC_CLK_PERIOD_ADDR(b) \
+	(MISC_REG_BASE(b) + 0x00000024)
+enum bimc_misc_bimc_clk_preiod {
+	MISC_CLK_PERIOD_RMSK			= 0xff,
+	MISC_CLK_PERIOD_CORE_CLK_PERIOD_BMSK	= 0xff,
+	MISC_CLK_PERIOD_CORE_CLK_PERIOD_SHFT	= 0x0,
+};
+
+#define MISC_SCMOn_LOCAL_CGC_THRESH_ADDR(b, n) \
+		(MISC_REG_BASE(b) + 0x00000100 + 0x4 * (n))
+enum bimc_misc_scm0n_local_cgc_thresh {
+	MISC_SCMOn_LOCAL_CGC_THRESH_RMSK		= 0x800000ff,
+	MISC_SCMOn_LOCAL_CGC_THRESH_MAXn		= 1,
+	MISC_SCMOn_LOCAL_CGC_THRESH_EN_BMSK		= 0x80000000,
+	MISC_SCMOn_LOCAL_CGC_THRESH_EN_SHFT		= 0x1f,
+	MISC_SCMOn_LOCAL_CGC_THRESH_THRESH_VAL_BMSK	= 0xff,
+	MISC_SCMOn_LOCAL_CGC_THRESH_THRESH_VAL_SHFT	= 0x0,
+};
+
+#define MISC_DPEn_LOCAL_CGC_THRESH_ADDR(b, n) \
+		(MISC_REG_BASE(b) + 0x00000140 + 0x4 * (n))
+enum bimc_misc_dpen_local_cgc_thresh {
+	MISC_DPEn_LOCAL_CGC_THRESH_RMSK			= 0x800000ff,
+	MISC_DPEn_LOCAL_CGC_THRESH_MAXn			= 1,
+	MISC_DPEn_LOCAL_CGC_THRESH_EN_BMSK		= 0x80000000,
+	MISC_DPEn_LOCAL_CGC_THRESH_EN_SHFT		= 0x1f,
+	MISC_DPEn_LOCAL_CGC_THRESH_THRESH_VAL_BMSK	= 0xff,
+	MISC_DPEn_LOCAL_CGC_THRESH_THRESH_VAL_SHFT	= 0x0,
+};
+
+#define MISC_MPORT_LOCAL_CGC_THRESH_ADDR(b) \
+	(MISC_REG_BASE(b) + 0x00000180)
+enum bimc_misc_mport_local_cgc_thresh {
+	MISC_MPORT_LOCAL_CGC_THRESH_RMSK		= 0x800000ff,
+	MISC_MPORT_LOCAL_CGC_THRESH_EN_BMSK		= 0x80000000,
+	MISC_MPORT_LOCAL_CGC_THRESH_EN_SHFT		= 0x1f,
+	MISC_MPORT_LOCAL_CGC_THRESH_THRESH_VAL_BMSK	= 0xff,
+	MISC_MPORT_LOCAL_CGC_THRESH_THRESH_VAL_SHFT	= 0x0,
+};
+
+#define MISC_SWAY_LOCAL_CGC_THRESH_ADDR(b) \
+	(MISC_REG_BASE(b) + 0x000001c0)
+enum bimc_misc_sway_local_cgc_thresh {
+	MISC_SWAY_LOCAL_CGC_THRESH_RMSK			= 0x800000ff,
+	MISC_SWAY_LOCAL_CGC_THRESH_EN_BMSK		= 0x80000000,
+	MISC_SWAY_LOCAL_CGC_THRESH_EN_SHFT		= 0x1f,
+	MISC_SWAY_LOCAL_CGC_THRESH_THRESH_VAL_BMSK	= 0xff,
+	MISC_SWAY_LOCAL_CGC_THRESH_THRESH_VAL_SHFT	= 0x0,
+};
+
+#define MISC_SCMOn_CGC_THRESH_ADDR(b, n) \
+	(MISC_REG_BASE(b) + 0x00000200 + 0x4 * (n))
+enum bimc_misc_scmon_cgc_thresh {
+	MISC_SCMOn_CGC_THRESH_RMSK		= 0x800000ff,
+	MISC_SCMOn_CGC_THRESH_MAXn		= 1,
+	MISC_SCMOn_CGC_THRESH_EN_BMSK		= 0x80000000,
+	MISC_SCMOn_CGC_THRESH_EN_SHFT		= 0x1f,
+	MISC_SCMOn_CGC_THRESH_THRESH_VAL_BMSK	= 0xff,
+	MISC_SCMOn_CGC_THRESH_THRESH_VAL_SHFT	= 0x0,
+};
+
+#define MISC_SCMOn_DYN_CLK_CTRL_ADDR(b, n) \
+	 (MISC_REG_BASE(b) + 0x00000240 + 0x4 * (n))
+enum bimc_misc_scmon_dyn_clk_ctrl {
+	MISC_SCMOn_DYN_CLK_CTRL_RMSK		= 0x3,
+	MISC_SCMOn_DYN_CLK_CTRL_MAXn		= 1,
+	MISC_SCMOn_DYN_CLK_CTRL_CGC_EN_BMSK	= 0x2,
+	MISC_SCMOn_DYN_CLK_CTRL_CGC_EN_SHFT	= 0x1,
+	MISC_SCMOn_DYN_CLK_CTRL_CLK_EN_BMSK	= 0x1,
+	MISC_SCMOn_DYN_CLK_CTRL_CLK_EN_SHFT	= 0x0,
+};
+
+#define MISC_DPEn_CGC_THRESH_ADDR(b, n) \
+	(MISC_REG_BASE(b) + 0x00000280 + 0x4 * (n))
+enum bimc_misc_dpen_cgc_thresh {
+	MISC_DPEn_CGC_THRESH_RMSK		= 0x800000ff,
+	MISC_DPEn_CGC_THRESH_MAXn		= 1,
+	MISC_DPEn_CGC_THRESH_EN_BMSK		= 0x80000000,
+	MISC_DPEn_CGC_THRESH_EN_SHFT		= 0x1f,
+	MISC_DPEn_CGC_THRESH_THRESH_VAL_BMSK	= 0xff,
+	MISC_DPEn_CGC_THRESH_THRESH_VAL_SHFT	= 0x0,
+};
+
+#define MISC_DPEn_DYN_CLK_CTRL_ADDR(b, n) \
+	(MISC_REG_BASE(b) + 0x000002c0 + 0x4 * (n))
+enum bimc_misc_dpen_dyn_clk_ctrl {
+	MISC_DPEn_DYN_CLK_CTRL_RMSK		= 0x3,
+	MISC_DPEn_DYN_CLK_CTRL_MAXn		= 1,
+	MISC_DPEn_DYN_CLK_CTRL_CGC_EN_BMSK	= 0x2,
+	MISC_DPEn_DYN_CLK_CTRL_CGC_EN_SHFT	= 0x1,
+	MISC_DPEn_DYN_CLK_CTRL_CLK_EN_BMSK	= 0x1,
+	MISC_DPEn_DYN_CLK_CTRL_CLK_EN_SHFT	= 0x0,
+};
+
+/* BIMC Global registers */
+
+#define GLOBAL_1_REG_BASE(b)		((b) + 0x00001000)
+
+#define GLOBAL_1_COMPONENT_INFO_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x00000000)
+enum bimc_global_1_component_info {
+	GLOBAL_1_COMPONENT_INFO_RMSK		= 0xffff,
+	GLOBAL_1_COMPONENT_INFO_SUB_TYPE_BMSK	= 0xff00,
+	GLOBAL_1_COMPONENT_INFO_SUB_TYPE_SHFT	= 0x8,
+	GLOBAL_1_COMPONENT_INFO_TYPE_BMSK	= 0xff,
+	GLOBAL_1_COMPONENT_INFO_TYPE_SHFT	= 0x0,
+};
+
+#define VERSION_INFO_ADDR(b) \
+	(GLOBAL1_REG_BASE(b) + 0x00000010)
+enum bimc_version_info {
+	VERSION_INFO_RMSK		= 0xffff,
+	VERSION_INFO_MAJOR_BMSK		= 0xf0000000,
+	VERSION_INFO_MAJOR_SHFT		= 0x1c,
+	VERSION_INFO_BRANCH_BMSK	= 0xfff0000,
+	VERSION_INFO_BRANCH_SHFT	= 0x10,
+	VERSION_INFO_MINOR_BMSK		= 0xff00,
+	VERSION_INFO_MINOR_SHFT		= 0x8,
+	VERSION_INFO_ECO_BMSK		= 0xff,
+	VERSION_INFO_ECO_SHFT		= 0x0,
+};
+
+#define HW_VERSION_ADDR(b) \
+	(GLOBAL1_REG_BASE(b) + 0x00000014)
+enum bimc_hw_version {
+	HW_VERSION_RMSK			= 0xffffffff,
+	HW_VERSION_MAJOR_BMSK		= 0xf0000000,
+	HW_VERSION_MAJOR_SHFT		= 0x1c,
+	HW_VERSION_MINOR_BMSK		= 0xfff0000,
+	HW_VERSION_MINOR_SHFT		= 0x10,
+	HW_VERSION_STEP_BMSK		= 0xffff,
+	HW_VERSION_STEP_SHFT		= 0x0,
+};
+
+#define BRIC_CONFIG_INFO_0_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x00000020)
+enum bimc_bric_config_info_0 {
+	BRIC_CONFIG_INFO_0_RMSK			= 0xffffffff,
+	BRIC_CONFIG_INFO_0_ADDR_WIDTH_BMSK	= 0xff000000,
+	BRIC_CONFIG_INFO_0_ADDR_WIDTH_SHFT	= 0x18,
+	BRIC_CONFIG_INFO_0_BUSID_BMSK		= 0xff0000,
+	BRIC_CONFIG_INFO_0_BUSID_SHFT		= 0x10,
+	BRIC_CONFIG_INFO_0_NUM_SWAYS_BMSK	= 0xff00,
+	BRIC_CONFIG_INFO_0_NUM_SWAYS_SHFT	= 0x8,
+	BRIC_CONFIG_INFO_0_NUM_MPORTS_BMSK	= 0xff,
+	BRIC_CONFIG_INFO_0_NUM_MPORTS_SHFT	= 0x0,
+};
+
+#define BRIC_CONFIG_INFO_1_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x00000030)
+enum bimc_bric_config_info_1 {
+	BRIC_CONFIG_INFO_1_RMSK			= 0xffffffff,
+	BRIC_CONFIG_INFO_1_DATA_WIDTH_BMSK	= 0xffff0000,
+	BRIC_CONFIG_INFO_1_DATA_WIDTH_SHFT	= 0x10,
+	BRIC_CONFIG_INFO_1_TID_WIDTH_BMSK	= 0xff00,
+	BRIC_CONFIG_INFO_1_TID_WIDTH_SHFT	= 0x8,
+	BRIC_CONFIG_INFO_1_MID_WIDTH_BMSK	= 0xff,
+	BRIC_CONFIG_INFO_1_MID_WIDTH_SHFT	= 0x0,
+};
+
+#define MP_INT_STATUS_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x00000100)
+enum bimc_mp_int_status {
+	MP_INT_STATUS_RMSK		= 0x7f,
+	MP_INT_STATUS_MASTERPORT_BMSK	= 0x7f,
+	MP_INT_STATUS_MASTERPORT_SHFT	= 0x0,
+};
+
+#define MP_INT_CLR_ADDR(b) \
+	(GLOBAL1_REG_BASE(b) + 0x00000108)
+enum bimc_mp_int_clr {
+	MP_INT_CLR_RMSK			= 0x7f,
+	MP_INT_CLR_MASTERPORT_BMSK	= 0x7f,
+	MP_INT_CLR_MASTERPORT_SHFT	= 0x0,
+};
+
+#define MP_INT_EN_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x0000010c)
+enum bimc_mp_int_en {
+	MP_INT_EN_RMSK			= 0x7f,
+	MP_INT_EN_MASTERPORT_BMSK	= 0x7f,
+	MP_INT_EN_MASTERPORT_SHFT	= 0x0,
+};
+
+#define SW_INT_STATUS_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x00000110)
+enum bimc_sw_int_status {
+	SW_INT_STATUS_RMSK		= 0x1f,
+	SW_INT_STATUS_MASTERPORT_BMSK	= 0x1f,
+	SW_INT_STATUS_MASTERPORT_SHFT	= 0x0,
+};
+
+#define SW_INT_CLR_ADDR(b) \
+	(GLOBAL1_REG_BASE(b) + 0x00000118)
+enum bimc_sw_int_clr {
+	SW_INT_CLR_RMSK			= 0x1f,
+	SW_INT_CLR_MASTERPORT_BMSK	= 0x1f,
+	SW_INT_CLR_MASTERPORT_SHFT	= 0x0,
+};
+
+#define SW_INT_EN_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x0000011c)
+enum bimc_sw_int_en {
+	SW_INT_EN_RMSK			= 0x1f,
+	SW_INT_EN_MASTERPORT_BMSK	= 0x1f,
+	SW_INT_EN_MASTERPORT_SHFT	= 0x0,
+};
+
+#define REF_TIMER_CONFIG_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x00000200)
+enum bimc_ref_timer_config {
+	REF_TIMER_CONFIG_RMSK		= 0xffff,
+	REF_TIMER_CONFIG_MASTERPORT_BMSK	= 0xffff,
+	REF_TIMER_CONFIG_MASTERPORT_SHFT	= 0x0,
+};
+
+#define DEBUG_SEL_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x00000210)
+enum bimc_debug_sel {
+	DEBUG_SEL_RMSK			= 0xffffffff,
+	DEBUG_SEL_COMPONENT_BMSK	= 0xff000000,
+	DEBUG_SEL_COMPONENT_SHFT	= 0x18,
+	DEBUG_SEL_INSTANCE_BMSK		= 0xff0000,
+	DEBUG_SEL_INSTANCE_SHFT		= 0x10,
+	DEBUG_SEL_SEL_BMSK		= 0xffff,
+	DEBUG_SEL_SEL_SHFT		= 0x0,
+};
+
+/* BIMC Global 2 */
+
+#define GLOBAL2_REG_BASE(b)		((b) + 0x00002000)
+
+#define GLOBAL2_COMPONENT_INFO_ADDR(b) \
+		(GLOBAL2_REG_BASE(b) + 0x00000000)
+enum bimc_global2_component_info {
+	GLOBAL2_COMPONENT_INFO_RMSK		= 0xffff,
+	GLOBAL2_COMPONENT_INFO_SUB_TYPE_BMSK	= 0xff00,
+	GLOBAL2_COMPONENT_INFO_SUB_TYPE_SHFT	= 0x8,
+	GLOBAL2_COMPONENT_INFO_TYPE_BMSK	= 0xff,
+	GLOBAL2_COMPONENT_INFO_TYPE_SHFT	= 0x0,
+};
+
+#define DEFAULT_SEGMENT_CONFIG_ADDR(b) \
+		(GLOBAL1_REG_BASE(b) + 0x000001f0)
+enum bimc_default_segment_config {
+	DEFAULT_SEGMENT_CONFIG_RMSK		= 0xf00f,
+	DEFAULT_SEGMENT_CONFIG_REDIRECT_BMSK	= 0xf0000,
+	DEFAULT_SEGMENT_CONFIG_REDIRECT_SHFT	= 0x10,
+	DEFAULT_SEGMENT_CONFIG_DEFAULT_BMSK	= 0xf,
+	DEFAULT_SEGMENT_CONFIG_DEFAULT_SHFT	= 0x0,
+};
+
+#define SEGMENTn_ADDR_BASEm_LOWER_ADDR(b, n, m) \
+	(GLOBAL2_REG_BASE(b) + 0x00000200 + 0x80 * (n) + 0x10 * (m))
+enum bimc_segmentn_addr_basem_lower {
+	SEGMENTn_ADDR_BASEm_LOWER_RMSK		= 0xfff0040f,
+	SEGMENTn_ADDR_BASEm_LOWER_MAXn		= 4,
+	SEGMENTn_ADDR_BASEm_LOWER_BASE_31_20_BMSK	= 0xfff00000,
+	SEGMENTn_ADDR_BASEm_LOWER_BASE_31_20_SHFT	= 0x14,
+	SEGMENTn_ADDR_BASEm_LOWER_BASE_10_BMSK	= 0x400,
+	SEGMENTn_ADDR_BASEm_LOWER_BASE_10_SHFT	= 0xa,
+	SEGMENTn_ADDR_BASEm_LOWER_EN_BMSK	= 0x1,
+	SEGMENTn_ADDR_BASEm_LOWER_EN_SHFT	= 0x0,
+};
+
+#define SEGMENTn_ADDR_BASEm_UPPER_ADDR(b, n, m) \
+	(GLOBAL2_REG_BASE(b) + 0x00000204 + 0x80 * (n) + 0x10 * (m))
+enum bimc_segmentn_addr_basem_upper {
+	SEGMENTn_ADDR_BASEm_UPPER_RMSK		= 0xf,
+	SEGMENTn_ADDR_BASEm_UPPER_MAXn		= 4,
+};
+
+#define SEGMENTn_ADDR_MASKm_LOWER_ADDR(b, n, m) \
+	(GLOBAL2_REG_BASE(b) + 0x00000208 + 0x80 * (n) + 0x10 * (m))
+enum bimc_segmentn_addr_maskm_lower {
+	SEGMENTn_ADDR_MASKm_LOWER_RMSK		= 0xfff00400,
+	SEGMENTn_ADDR_MASKm_LOWER_MAXn		= 4,
+	SEGMENTn_ADDR_MASKm_LOWER_MASK_31_20_BMSK	= 0xfff00000,
+	SEGMENTn_ADDR_MASKm_LOWER_MASK_31_20_SHFT	= 0x14,
+	SEGMENTn_ADDR_MASKm_LOWER_MASK_10_BMSK	= 0x400,
+	SEGMENTn_ADDR_MASKm_LOWER_MASK_10_SHFT	= 0xa,
+};
+
+#define SEGMENTn_ADDR_MASKm_UPPER_ADDR(b, n, m) \
+	(GLOBAL2_REG_BASE(b) + 0x0000020c + 0x80 * (n) + 0x10 * (m))
+enum bimc_segmentn_addr_maskm_upper {
+	SEGMENTn_ADDR_MASKm_UPPER_RMSK		= 0xf,
+	SEGMENTn_ADDR_MASKm_UPPER_MAXn		= 4,
+};
+
+/* M_Generic */
+
+#define M_REG_BASE(b)		((b) + 0x00008000)
+
+#define M_COMPONENT_INFO_ADDR(b, n) \
+		(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000000)
+enum bimc_m_component_info {
+	M_COMPONENT_INFO_RMSK		= 0xffffff,
+	M_COMPONENT_INFO_INSTANCE_BMSK	= 0xff0000,
+	M_COMPONENT_INFO_INSTANCE_SHFT	= 0x10,
+	M_COMPONENT_INFO_SUB_TYPE_BMSK	= 0xff00,
+	M_COMPONENT_INFO_SUB_TYPE_SHFT	= 0x8,
+	M_COMPONENT_INFO_TYPE_BMSK	= 0xff,
+	M_COMPONENT_INFO_TYPE_SHFT	= 0x0,
+};
+
+#define M_CONFIG_INFO_0_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000020)
+enum bimc_m_config_info_0 {
+	M_CONFIG_INFO_0_RMSK			= 0xff00ffff,
+	M_CONFIG_INFO_0_SYNC_MODE_BMSK		= 0xff000000,
+	M_CONFIG_INFO_0_SYNC_MODE_SHFT		= 0x18,
+	M_CONFIG_INFO_0_CONNECTION_TYPE_BMSK	= 0xff00,
+	M_CONFIG_INFO_0_CONNECTION_TYPE_SHFT	= 0x8,
+	M_CONFIG_INFO_0_FUNC_BMSK		= 0xff,
+	M_CONFIG_INFO_0_FUNC_SHFT		= 0x0,
+};
+
+#define M_CONFIG_INFO_1_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000030)
+enum bimc_m_config_info_1 {
+	M_CONFIG_INFO_1_RMSK			= 0xffffffff,
+	M_CONFIG_INFO_1_SWAY_CONNECTIVITY_BMSK	= 0xffffffff,
+	M_CONFIG_INFO_1_SWAY_CONNECTIVITY_SHFT	= 0x0,
+};
+
+#define M_CONFIG_INFO_2_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000040)
+enum bimc_m_config_info_2 {
+	M_CONFIG_INFO_2_RMSK			= 0xffffffff,
+	M_CONFIG_INFO_2_M_DATA_WIDTH_BMSK	= 0xffff0000,
+	M_CONFIG_INFO_2_M_DATA_WIDTH_SHFT	= 0x10,
+	M_CONFIG_INFO_2_M_TID_WIDTH_BMSK	= 0xff00,
+	M_CONFIG_INFO_2_M_TID_WIDTH_SHFT	= 0x8,
+	M_CONFIG_INFO_2_M_MID_WIDTH_BMSK	= 0xff,
+	M_CONFIG_INFO_2_M_MID_WIDTH_SHFT	= 0x0,
+};
+
+#define M_CONFIG_INFO_3_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000050)
+enum bimc_m_config_info_3 {
+	M_CONFIG_INFO_3_RMSK			= 0xffffffff,
+	M_CONFIG_INFO_3_RCH_DEPTH_BMSK		= 0xff000000,
+	M_CONFIG_INFO_3_RCH_DEPTH_SHFT		= 0x18,
+	M_CONFIG_INFO_3_BCH_DEPTH_BMSK		= 0xff0000,
+	M_CONFIG_INFO_3_BCH_DEPTH_SHFT		= 0x10,
+	M_CONFIG_INFO_3_WCH_DEPTH_BMSK		= 0xff00,
+	M_CONFIG_INFO_3_WCH_DEPTH_SHFT		= 0x8,
+	M_CONFIG_INFO_3_ACH_DEPTH_BMSK		= 0xff,
+	M_CONFIG_INFO_3_ACH_DEPTH_SHFT		= 0x0,
+};
+
+#define M_CONFIG_INFO_4_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000060)
+enum bimc_m_config_info_4 {
+	M_CONFIG_INFO_4_RMSK			= 0xffff,
+	M_CONFIG_INFO_4_REORDER_BUF_DEPTH_BMSK	= 0xff00,
+	M_CONFIG_INFO_4_REORDER_BUF_DEPTH_SHFT	= 0x8,
+	M_CONFIG_INFO_4_REORDER_TABLE_DEPTH_BMSK	= 0xff,
+	M_CONFIG_INFO_4_REORDER_TABLE_DEPTH_SHFT	= 0x0,
+};
+
+#define M_CONFIG_INFO_5_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000070)
+enum bimc_m_config_info_5 {
+	M_CONFIG_INFO_5_RMSK			= 0x111,
+	M_CONFIG_INFO_5_MP2ARB_PIPELINE_EN_BMSK	= 0x100,
+	M_CONFIG_INFO_5_MP2ARB_PIPELINE_EN_SHFT	= 0x8,
+	M_CONFIG_INFO_5_MPBUF_PIPELINE_EN_BMSK	= 0x10,
+	M_CONFIG_INFO_5_MPBUF_PIPELINE_EN_SHFT	= 0x4,
+	M_CONFIG_INFO_5_M2MP_PIPELINE_EN_BMSK	= 0x1,
+	M_CONFIG_INFO_5_M2MP_PIPELINE_EN_SHFT	= 0x0,
+};
+
+#define M_INT_STATUS_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000100)
+enum bimc_m_int_status {
+	M_INT_STATUS_RMSK			= 0x3,
+};
+
+#define M_INT_CLR_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000108)
+enum bimc_m_int_clr {
+	M_INT_CLR_RMSK			= 0x3,
+};
+
+#define M_INT_EN_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x0000010c)
+enum bimc_m_int_en {
+	M_INT_EN_RMSK			= 0x3,
+};
+
+#define M_CLK_CTRL_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000200)
+enum bimc_m_clk_ctrl {
+	M_CLK_CTRL_RMSK				= 0x3,
+	M_CLK_CTRL_MAS_CLK_GATING_EN_BMSK	= 0x2,
+	M_CLK_CTRL_MAS_CLK_GATING_EN_SHFT	= 0x1,
+	M_CLK_CTRL_CORE_CLK_GATING_EN_BMSK	= 0x1,
+	M_CLK_CTRL_CORE_CLK_GATING_EN_SHFT	= 0x0,
+};
+
+#define M_MODE_ADDR(b, n) \
+		(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000210)
+enum bimc_m_mode {
+	M_MODE_RMSK				= 0xf0000001,
+	M_MODE_WR_GATHER_BEATS_BMSK		= 0xf0000000,
+	M_MODE_WR_GATHER_BEATS_SHFT		= 0x1c,
+	M_MODE_ORDERING_MODEL_BMSK		= 0x1,
+	M_MODE_ORDERING_MODEL_SHFT		= 0x0,
+};
+
+#define M_PRIOLVL_OVERRIDE_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000220)
+enum bimc_m_priolvl_override {
+	M_PRIOLVL_OVERRIDE_RMSK			= 0x301,
+	M_PRIOLVL_OVERRIDE_BMSK			= 0x300,
+	M_PRIOLVL_OVERRIDE_SHFT			= 0x8,
+	M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_BMSK	= 0x1,
+	M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_SHFT	= 0x0,
+};
+
+#define M_RD_CMD_OVERRIDE_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000230)
+enum bimc_m_read_command_override {
+	M_RD_CMD_OVERRIDE_RMSK			= 0x37f3f,
+	M_RD_CMD_OVERRIDE_AREQPRIO_BMSK		= 0x300000,
+	M_RD_CMD_OVERRIDE_AREQPRIO_SHFT		= 0x18,
+	M_RD_CMD_OVERRIDE_AMEMTYPE_BMSK		= 0x70000,
+	M_RD_CMD_OVERRIDE_AMEMTYPE_SHFT		= 0x10,
+	M_RD_CMD_OVERRIDE_ATRANSIENT_BMSK		= 0x1000,
+	M_RD_CMD_OVERRIDE_ATRANSIENT_SHFT		= 0xc,
+	M_RD_CMD_OVERRIDE_ASHARED_BMSK		= 0x800,
+	M_RD_CMD_OVERRIDE_ASHARED_SHFT		= 0xb,
+	M_RD_CMD_OVERRIDE_AREDIRECT_BMSK		= 0x400,
+	M_RD_CMD_OVERRIDE_AREDIRECT_SHFT		= 0xa,
+	M_RD_CMD_OVERRIDE_AOOO_BMSK			= 0x200,
+	M_RD_CMD_OVERRIDE_AOOO_SHFT			= 0x9,
+	M_RD_CMD_OVERRIDE_AINNERSHARED_BMSK		= 0x100,
+	M_RD_CMD_OVERRIDE_AINNERSHARED_SHFT		= 0x8,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK	= 0x40,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT	= 0x6,
+	M_RD_CMD_OVERRIDE_OVERRIDE_ATRANSIENT_BMSK	= 0x20,
+	M_RD_CMD_OVERRIDE_OVERRIDE_ATRANSIENT_SHFT	= 0x5,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_BMSK	= 0x10,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_SHFT	= 0x4,
+	M_RD_CMD_OVERRIDE_OVERRIDE_ASHARED_BMSK	= 0x8,
+	M_RD_CMD_OVERRIDE_OVERRIDE_ASHARED_SHFT	= 0x3,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AREDIRECT_BMSK	= 0x4,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AREDIRECT_SHFT	= 0x2,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AOOO_BMSK		= 0x2,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AOOO_SHFT		= 0x1,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AINNERSHARED_BMSK	= 0x1,
+	M_RD_CMD_OVERRIDE_OVERRIDE_AINNERSHARED_SHFT	= 0x0,
+};
+
+#define M_WR_CMD_OVERRIDE_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000240)
+enum bimc_m_write_command_override {
+	M_WR_CMD_OVERRIDE_RMSK			= 0x37f3f,
+	M_WR_CMD_OVERRIDE_AREQPRIO_BMSK		= 0x30000,
+	M_WR_CMD_OVERRIDE_AREQPRIO_SHFT		= 0x10,
+	M_WR_CMD_OVERRIDE_AMEMTYPE_BMSK		= 0x7000,
+	M_WR_CMD_OVERRIDE_AMEMTYPE_SHFT		= 0xc,
+	M_WR_CMD_OVERRIDE_ASHARED_BMSK		= 0x800,
+	M_WR_CMD_OVERRIDE_ASHARED_SHFT		= 0xb,
+	M_WR_CMD_OVERRIDE_AREDIRECT_BMSK		= 0x400,
+	M_WR_CMD_OVERRIDE_AREDIRECT_SHFT		= 0xa,
+	M_WR_CMD_OVERRIDE_AOOO_BMSK			= 0x200,
+	M_WR_CMD_OVERRIDE_AOOO_SHFT			= 0x9,
+	M_WR_CMD_OVERRIDE_AINNERSHARED_BMSK		= 0x100,
+	M_WR_CMD_OVERRIDE_AINNERSHARED_SHFT		= 0x8,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK	= 0x20,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT	= 0x5,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_BMSK	= 0x10,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_SHFT	= 0x4,
+	M_WR_CMD_OVERRIDE_OVERRIDE_ASHARED_BMSK	= 0x8,
+	M_WR_CMD_OVERRIDE_OVERRIDE_ASHARED_SHFT	= 0x3,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AREDIRECT_BMSK	= 0x4,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AREDIRECT_SHFT	= 0x2,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AOOO_BMSK	= 0x2,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AOOO_SHFT	= 0x1,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AINNERSHARED_BMSK	= 0x1,
+	M_WR_CMD_OVERRIDE_OVERRIDE_AINNERSHARED_SHFT	= 0x0,
+};
+
+#define M_BKE_EN_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000300)
+enum bimc_m_bke_en {
+	M_BKE_EN_RMSK			= 0x1,
+	M_BKE_EN_EN_BMSK		= 0x1,
+	M_BKE_EN_EN_SHFT		= 0x0,
+};
+
+/* Grant Period registers */
+#define M_BKE_GP_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000304)
+enum bimc_m_bke_grant_period {
+	M_BKE_GP_RMSK		= 0x3ff,
+	M_BKE_GP_GP_BMSK	= 0x3ff,
+	M_BKE_GP_GP_SHFT	= 0x0,
+};
+
+/* Grant count registers */
+#define M_BKE_GC_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000308)
+enum bimc_m_bke_grant_count {
+	M_BKE_GC_RMSK			= 0xffff,
+	M_BKE_GC_GC_BMSK		= 0xffff,
+	M_BKE_GC_GC_SHFT		= 0x0,
+};
+
+/* Threshold High Registers */
+#define M_BKE_THH_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000320)
+enum bimc_m_bke_thresh_high {
+	M_BKE_THH_RMSK		= 0xffff,
+	M_BKE_THH_THRESH_BMSK	= 0xffff,
+	M_BKE_THH_THRESH_SHFT	= 0x0,
+};
+
+/* Threshold Medium Registers */
+#define M_BKE_THM_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000324)
+enum bimc_m_bke_thresh_medium {
+	M_BKE_THM_RMSK		= 0xffff,
+	M_BKE_THM_THRESH_BMSK	= 0xffff,
+	M_BKE_THM_THRESH_SHFT	= 0x0,
+};
+
+/* Threshold Low Registers */
+#define M_BKE_THL_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000328)
+enum bimc_m_bke_thresh_low {
+	M_BKE_THL_RMSK			= 0xffff,
+	M_BKE_THL_THRESH_BMSK		= 0xffff,
+	M_BKE_THL_THRESH_SHFT		= 0x0,
+};
+
+#define M_BKE_HEALTH_0_CONFIG_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000340)
+enum bimc_m_bke_health_0 {
+	M_BKE_HEALTH_0_CONFIG_RMSK			= 0x80000303,
+	M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_BMSK		= 0x80000000,
+	M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_SHFT		= 0x1f,
+	M_BKE_HEALTH_0_CONFIG_AREQPRIO_BMSK		= 0x300,
+	M_BKE_HEALTH_0_CONFIG_AREQPRIO_SHFT		= 0x8,
+	M_BKE_HEALTH_0_CONFIG_PRIOLVL_BMSK		= 0x3,
+	M_BKE_HEALTH_0_CONFIG_PRIOLVL_SHFT		= 0x0,
+};
+
+#define M_BKE_HEALTH_1_CONFIG_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000344)
+enum bimc_m_bke_health_1 {
+	M_BKE_HEALTH_1_CONFIG_RMSK			= 0x80000303,
+	M_BKE_HEALTH_1_CONFIG_LIMIT_CMDS_BMSK		= 0x80000000,
+	M_BKE_HEALTH_1_CONFIG_LIMIT_CMDS_SHFT		= 0x1f,
+	M_BKE_HEALTH_1_CONFIG_AREQPRIO_BMSK		= 0x300,
+	M_BKE_HEALTH_1_CONFIG_AREQPRIO_SHFT		= 0x8,
+	M_BKE_HEALTH_1_CONFIG_PRIOLVL_BMSK		= 0x3,
+	M_BKE_HEALTH_1_CONFIG_PRIOLVL_SHFT		= 0x0,
+};
+
+#define M_BKE_HEALTH_2_CONFIG_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000348)
+enum bimc_m_bke_health_2 {
+	M_BKE_HEALTH_2_CONFIG_RMSK			= 0x80000303,
+	M_BKE_HEALTH_2_CONFIG_LIMIT_CMDS_BMSK		= 0x80000000,
+	M_BKE_HEALTH_2_CONFIG_LIMIT_CMDS_SHFT		= 0x1f,
+	M_BKE_HEALTH_2_CONFIG_AREQPRIO_BMSK		= 0x300,
+	M_BKE_HEALTH_2_CONFIG_AREQPRIO_SHFT		= 0x8,
+	M_BKE_HEALTH_2_CONFIG_PRIOLVL_BMSK		= 0x3,
+	M_BKE_HEALTH_2_CONFIG_PRIOLVL_SHFT		= 0x0,
+};
+
+#define M_BKE_HEALTH_3_CONFIG_ADDR(b, n) \
+	(M_REG_BASE(b) + (0x4000 * (n)) + 0x0000034c)
+enum bimc_m_bke_health_3 {
+	M_BKE_HEALTH_3_CONFIG_RMSK			= 0x303,
+	M_BKE_HEALTH_3_CONFIG_AREQPRIO_BMSK	= 0x300,
+	M_BKE_HEALTH_3_CONFIG_AREQPRIO_SHFT	= 0x8,
+	M_BKE_HEALTH_3_CONFIG_PRIOLVL_BMSK		= 0x3,
+	M_BKE_HEALTH_3_CONFIG_PRIOLVL_SHFT		= 0x0,
+};
+
+#define M_BUF_STATUS_ADDR(b, n) \
+		(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000400)
+enum bimc_m_buf_status {
+	M_BUF_STATUS_RMSK			= 0xf03f030,
+	M_BUF_STATUS_RCH_DATA_WR_FULL_BMSK	= 0x8000000,
+	M_BUF_STATUS_RCH_DATA_WR_FULL_SHFT	= 0x1b,
+	M_BUF_STATUS_RCH_DATA_WR_EMPTY_BMSK	= 0x4000000,
+	M_BUF_STATUS_RCH_DATA_WR_EMPTY_SHFT	= 0x1a,
+	M_BUF_STATUS_RCH_CTRL_WR_FULL_BMSK	= 0x2000000,
+	M_BUF_STATUS_RCH_CTRL_WR_FULL_SHFT	= 0x19,
+	M_BUF_STATUS_RCH_CTRL_WR_EMPTY_BMSK	= 0x1000000,
+	M_BUF_STATUS_RCH_CTRL_WR_EMPTY_SHFT	= 0x18,
+	M_BUF_STATUS_BCH_WR_FULL_BMSK		= 0x20000,
+	M_BUF_STATUS_BCH_WR_FULL_SHFT		= 0x11,
+	M_BUF_STATUS_BCH_WR_EMPTY_BMSK		= 0x10000,
+	M_BUF_STATUS_BCH_WR_EMPTY_SHFT		= 0x10,
+	M_BUF_STATUS_WCH_DATA_RD_FULL_BMSK	= 0x8000,
+	M_BUF_STATUS_WCH_DATA_RD_FULL_SHFT	= 0xf,
+	M_BUF_STATUS_WCH_DATA_RD_EMPTY_BMSK	= 0x4000,
+	M_BUF_STATUS_WCH_DATA_RD_EMPTY_SHFT	= 0xe,
+	M_BUF_STATUS_WCH_CTRL_RD_FULL_BMSK	= 0x2000,
+	M_BUF_STATUS_WCH_CTRL_RD_FULL_SHFT	= 0xd,
+	M_BUF_STATUS_WCH_CTRL_RD_EMPTY_BMSK	= 0x1000,
+	M_BUF_STATUS_WCH_CTRL_RD_EMPTY_SHFT	= 0xc,
+	M_BUF_STATUS_ACH_RD_FULL_BMSK		= 0x20,
+	M_BUF_STATUS_ACH_RD_FULL_SHFT		= 0x5,
+	M_BUF_STATUS_ACH_RD_EMPTY_BMSK		= 0x10,
+	M_BUF_STATUS_ACH_RD_EMPTY_SHFT		= 0x4,
+};
+/*BIMC Generic */
+
+#define S_REG_BASE(b)	((b) + 0x00048000)
+
+#define S_COMPONENT_INFO_ADDR(b, n) \
+	(S_REG_BASE(b) + (0x8000 * (n)) + 0x00000000)
+enum bimc_s_component_info {
+	S_COMPONENT_INFO_RMSK			= 0xffffff,
+	S_COMPONENT_INFO_INSTANCE_BMSK		= 0xff0000,
+	S_COMPONENT_INFO_INSTANCE_SHFT		= 0x10,
+	S_COMPONENT_INFO_SUB_TYPE_BMSK		= 0xff00,
+	S_COMPONENT_INFO_SUB_TYPE_SHFT		= 0x8,
+	S_COMPONENT_INFO_TYPE_BMSK		= 0xff,
+	S_COMPONENT_INFO_TYPE_SHFT		= 0x0,
+};
+
+#define S_HW_INFO_ADDR(b, n) \
+	(S_REG_BASE(b) + (0x80000 * (n)) + 0x00000010)
+enum bimc_s_hw_info {
+	S_HW_INFO_RMSK				= 0xffffffff,
+	S_HW_INFO_MAJOR_BMSK			= 0xff000000,
+	S_HW_INFO_MAJOR_SHFT			= 0x18,
+	S_HW_INFO_BRANCH_BMSK			= 0xff0000,
+	S_HW_INFO_BRANCH_SHFT			= 0x10,
+	S_HW_INFO_MINOR_BMSK			= 0xff00,
+	S_HW_INFO_MINOR_SHFT			= 0x8,
+	S_HW_INFO_ECO_BMSK			= 0xff,
+	S_HW_INFO_ECO_SHFT			= 0x0,
+};
+
+
+/* S_SCMO_GENERIC */
+
+#define S_SCMO_REG_BASE(b)	((b) + 0x00048000)
+
+#define S_SCMO_CONFIG_INFO_0_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000020)
+enum bimc_s_scmo_config_info_0 {
+	S_SCMO_CONFIG_INFO_0_RMSK		= 0xffffffff,
+	S_SCMO_CONFIG_INFO_0_DATA_WIDTH_BMSK	= 0xffff0000,
+	S_SCMO_CONFIG_INFO_0_DATA_WIDTH_SHFT	= 0x10,
+	S_SCMO_CONFIG_INFO_0_TID_WIDTH_BMSK	= 0xff00,
+	S_SCMO_CONFIG_INFO_0_TID_WIDTH_SHFT	= 0x8,
+	S_SCMO_CONFIG_INFO_0_MID_WIDTH_BMSK	= 0xff,
+	S_SCMO_CONFIG_INFO_0_MID_WIDTH_SHFT	= 0x0,
+};
+
+#define S_SCMO_CONFIG_INFO_1_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000030)
+enum bimc_s_scmo_config_info_1 {
+	S_SCMO_CONFIG_INFO_1_RMSK			= 0xffffffff,
+	S_SCMO_CONFIG_INFO_1_MPORT_CONNECTIVITY_BMSK	= 0xffffffff,
+	S_SCMO_CONFIG_INFO_1_MPORT_CONNECTIVITY_SHFT	= 0x0,
+};
+
+#define S_SCMO_CONFIG_INFO_2_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000040)
+enum bimc_s_scmo_config_info_2 {
+	S_SCMO_CONFIG_INFO_2_RMSK			= 0xff00ff,
+	S_SCMO_CONFIG_INFO_2_NUM_GLOBAL_MONS_BMSK	= 0xff0000,
+	S_SCMO_CONFIG_INFO_2_NUM_GLOBAL_MONS_SHFT	= 0x10,
+	S_SCMO_CONFIG_INFO_2_VMID_WIDTH_BMSK	= 0xff,
+	S_SCMO_CONFIG_INFO_2_VMID_WIDTH_SHFT	= 0x0,
+};
+
+#define S_SCMO_CONFIG_INFO_3_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000050)
+enum bimc_s_scmo_config_info_3 {
+	S_SCMO_CONFIG_INFO_3_RMSK			= 0xffffffff,
+	S_SCMO_CONFIG_INFO_3_RCH0_CTRL_DEPTH_BMSK	= 0xff000000,
+	S_SCMO_CONFIG_INFO_3_RCH0_CTRL_DEPTH_SHFT	= 0x18,
+	S_SCMO_CONFIG_INFO_3_RCH0_DEPTH_BMSK		= 0xff0000,
+	S_SCMO_CONFIG_INFO_3_RCH0_DEPTH_SHFT		= 0x10,
+	S_SCMO_CONFIG_INFO_3_BCH_DEPTH_BMSK		= 0xff00,
+	S_SCMO_CONFIG_INFO_3_BCH_DEPTH_SHFT		= 0x8,
+	S_SCMO_CONFIG_INFO_3_WCH_DEPTH_BMSK		= 0xff,
+	S_SCMO_CONFIG_INFO_3_WCH_DEPTH_SHFT		= 0x0,
+};
+
+#define S_SCMO_CONFIG_INFO_4_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000060)
+enum bimc_s_scmo_config_info_4 {
+	S_SCMO_CONFIG_INFO_4_RMSK			= 0xffff,
+	S_SCMO_CONFIG_INFO_4_RCH1_CTRL_DEPTH_BMSK	= 0xff00,
+	S_SCMO_CONFIG_INFO_4_RCH1_CTRL_DEPTH_SHFT	= 0x8,
+	S_SCMO_CONFIG_INFO_4_RCH1_DEPTH_BMSK		= 0xff,
+	S_SCMO_CONFIG_INFO_4_RCH1_DEPTH_SHFT		= 0x0,
+};
+
+#define S_SCMO_CONFIG_INFO_5_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000070)
+enum bimc_s_scmo_config_info_5 {
+	S_SCMO_CONFIG_INFO_5_RMSK			= 0xffff,
+	S_SCMO_CONFIG_INFO_5_DPE_CQ_DEPTH_BMSK		= 0xff00,
+	S_SCMO_CONFIG_INFO_5_DPE_CQ_DEPTH_SHFT		= 0x8,
+	S_SCMO_CONFIG_INFO_5_DDR_BUS_WIDTH_BMSK		= 0xff,
+	S_SCMO_CONFIG_INFO_5_DDR_BUS_WIDTH_SHFT		= 0x0,
+};
+
+#define S_SCMO_CONFIG_INFO_6_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000080)
+enum bimc_s_scmo_config_info_6 {
+	S_SCMO_CONFIG_INFO_6_RMSK			= 0x1111,
+	S_SCMO_CONFIG_INFO_6_WBUFC_PIPE_BMSK		= 0x1000,
+	S_SCMO_CONFIG_INFO_6_WBUFC_PIPE_SHFT		= 0xc,
+	S_SCMO_CONFIG_INFO_6_RDOPT_PIPE_BMSK		= 0x100,
+	S_SCMO_CONFIG_INFO_6_RDOPT_PIPE_SHFT		= 0x8,
+	S_SCMO_CONFIG_INFO_6_ACHAN_INTF_PIPE_BMSK	= 0x10,
+	S_SCMO_CONFIG_INFO_6_ACHAN_INTF_PIPE_SHFT	= 0x4,
+	S_SCMO_CONFIG_INFO_6_ADDR_DECODE_HT_BMSK	= 0x1,
+	S_SCMO_CONFIG_INFO_6_ADDR_DECODE_HT_SHFT	= 0x0,
+};
+
+#define S_SCMO_INT_STATUS_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000100)
+enum bimc_s_scmo_int_status {
+	S_SCMO_INT_STATUS_RMSK			= 0x1,
+	S_SCMO_INT_STATUS_ERR_OCCURED_BMSK	= 0x1,
+	S_SCMO_INT_STATUS_ERR_OCCURED_SHFT	= 0x0,
+};
+
+#define S_SCMO_INT_CLR_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000108)
+enum bimc_s_scmo_int_clr {
+	S_SCMO_INT_CLR_RMSK		= 0x1,
+	S_SCMO_INT_CLR_IRQ_CLR_BMSK	= 0x1,
+	S_SCMO_INT_CLR_IRQ_CLR_SHFT	= 0x0,
+};
+
+#define S_SCMO_INT_EN_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x0000010c)
+enum bimc_s_scmo_int_en {
+	S_SCMO_INT_EN_RMSK		= 0x1,
+	S_SCMO_INT_EN_IRQ_EN_BMSK	= 0x1,
+	S_SCMO_INT_EN_IRQ_EN_SHFT	= 0x0,
+};
+
+#define S_SCMO_ESYN_ADDR_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000120)
+enum bimc_s_scmo_esyn_addr {
+	S_SCMO_ESYN_ADDR_RMSK				= 0xffffffff,
+	S_SCMO_ESYN_ADDR_ESYN_ADDR_ERR_ADDR_BMSK	= 0xffffffff,
+	S_SCMO_ESYN_ADDR_ESYN_ADDR_ERR_ADDR_SHFT	= 0x0,
+};
+
+#define S_SCMO_ESYN_APACKET_0_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000128)
+enum bimc_s_scmo_esyn_apacket_0 {
+	S_SCMO_ESYN_APACKET_0_RMSK			= 0xff1fffff,
+	S_SCMO_ESYN_APACKET_0_ERR_ATID_BMSK		= 0xff000000,
+	S_SCMO_ESYN_APACKET_0_ERR_ATID_SHFT		= 0x18,
+	S_SCMO_ESYN_APACKET_0_ERR_AVMID_BMSK		= 0x1f0000,
+	S_SCMO_ESYN_APACKET_0_ERR_AVMID_SHFT		= 0x10,
+	S_SCMO_ESYN_APACKET_0_ERR_AMID_BMSK		= 0xffff,
+	S_SCMO_ESYN_APACKET_0_ERR_AMID_SHFT		= 0x0,
+};
+
+#define S_SCMO_ESYN_APACKET_1_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x0000012c)
+enum bimc_s_scmo_esyn_apacket_1 {
+	S_SCMO_ESYN_APACKET_1_RMSK			= 0x10ff117,
+	S_SCMO_ESYN_APACKET_1_ERR_CODE_BMSK		= 0x1000000,
+	S_SCMO_ESYN_APACKET_1_ERR_CODE_SHFT		= 0x18,
+	S_SCMO_ESYN_APACKET_1_ERR_ALEN_BMSK		= 0xf0000,
+	S_SCMO_ESYN_APACKET_1_ERR_ALEN_SHFT		= 0x10,
+	S_SCMO_ESYN_APACKET_1_ERR_ASIZE_BMSK		= 0xe000,
+	S_SCMO_ESYN_APACKET_1_ERR_ASIZE_SHFT		= 0xd,
+	S_SCMO_ESYN_APACKET_1_ERR_ABURST_BMSK		= 0x1000,
+	S_SCMO_ESYN_APACKET_1_ERR_ABURST_SHFT		= 0xc,
+	S_SCMO_ESYN_APACKET_1_ERR_AEXCLUSIVE_BMSK	= 0x100,
+	S_SCMO_ESYN_APACKET_1_ERR_AEXCLUSIVE_SHFT	= 0x8,
+	S_SCMO_ESYN_APACKET_1_ERR_APRONTS_BMSK		= 0x10,
+	S_SCMO_ESYN_APACKET_1_ERR_APRONTS_SHFT		= 0x4,
+	S_SCMO_ESYN_APACKET_1_ERR_AOOORD_BMSK		= 0x4,
+	S_SCMO_ESYN_APACKET_1_ERR_AOOORD_SHFT		= 0x2,
+	S_SCMO_ESYN_APACKET_1_ERR_AOOOWR_BMSK		= 0x2,
+	S_SCMO_ESYN_APACKET_1_ERR_AOOOWR_SHFT		= 0x1,
+	S_SCMO_ESYN_APACKET_1_ERR_AWRITE_BMSK		= 0x1,
+	S_SCMO_ESYN_APACKET_1_ERR_AWRITE_SHFT		= 0x0,
+};
+
+#define S_SCMO_CLK_CTRL_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000200)
+enum bimc_s_scmo_clk_ctrl {
+	S_SCMO_CLK_CTRL_RMSK				= 0xffff1111,
+	S_SCMO_CLK_CTRL_PEN_CMD_CG_EN_BMSK		= 0x10000,
+	S_SCMO_CLK_CTRL_PEN_CMD_CG_EN_SHFT		= 0x10,
+	S_SCMO_CLK_CTRL_RCH_CG_EN_BMSK			= 0x1000,
+	S_SCMO_CLK_CTRL_RCH_CG_EN_SHFT			= 0xc,
+	S_SCMO_CLK_CTRL_FLUSH_CG_EN_BMSK		= 0x100,
+	S_SCMO_CLK_CTRL_FLUSH_CG_EN_SHFT		= 0x8,
+	S_SCMO_CLK_CTRL_WCH_CG_EN_BMSK			= 0x10,
+	S_SCMO_CLK_CTRL_WCH_CG_EN_SHFT			= 0x4,
+	S_SCMO_CLK_CTRL_ACH_CG_EN_BMSK			= 0x1,
+	S_SCMO_CLK_CTRL_ACH_CG_EN_SHFT			= 0x0,
+};
+
+#define S_SCMO_SLV_INTERLEAVE_CFG_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000400)
+enum bimc_s_scmo_slv_interleave_cfg {
+	S_SCMO_SLV_INTERLEAVE_CFG_RMSK			= 0xff,
+	S_SCMO_SLV_INTERLEAVE_CFG_INTERLEAVE_CS1_BMSK	= 0x10,
+	S_SCMO_SLV_INTERLEAVE_CFG_INTERLEAVE_CS1_SHFT	= 0x4,
+	S_SCMO_SLV_INTERLEAVE_CFG_INTERLEAVE_CS0_BMSK	= 0x1,
+	S_SCMO_SLV_INTERLEAVE_CFG_INTERLEAVE_CS0_SHFT	= 0x0,
+};
+
+#define S_SCMO_ADDR_BASE_CSn_ADDR(b, n, o)	\
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000410 + 0x4 * (o))
+enum bimc_s_scmo_addr_base_csn {
+	S_SCMO_ADDR_BASE_CSn_RMSK			= 0xffff,
+	S_SCMO_ADDR_BASE_CSn_MAXn			= 1,
+	S_SCMO_ADDR_BASE_CSn_ADDR_BASE_BMSK		= 0xfc,
+	S_SCMO_ADDR_BASE_CSn_ADDR_BASE_SHFT		= 0x2,
+};
+
+#define S_SCMO_ADDR_MAP_CSn_ADDR(b, n, o) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000420 + 0x4 * (o))
+enum bimc_s_scmo_addr_map_csn {
+	S_SCMO_ADDR_MAP_CSn_RMSK		= 0xffff,
+	S_SCMO_ADDR_MAP_CSn_MAXn		= 1,
+	S_SCMO_ADDR_MAP_CSn_RANK_EN_BMSK	= 0x8000,
+	S_SCMO_ADDR_MAP_CSn_RANK_EN_SHFT	= 0xf,
+	S_SCMO_ADDR_MAP_CSn_ADDR_MODE_BMSK	= 0x1000,
+	S_SCMO_ADDR_MAP_CSn_ADDR_MODE_SHFT	= 0xc,
+	S_SCMO_ADDR_MAP_CSn_BANK_SIZE_BMSK	= 0x100,
+	S_SCMO_ADDR_MAP_CSn_BANK_SIZE_SHFT	= 0x8,
+	S_SCMO_ADDR_MAP_CSn_ROW_SIZE_BMSK	= 0x30,
+	S_SCMO_ADDR_MAP_CSn_ROW_SIZE_SHFT	= 0x4,
+	S_SCMO_ADDR_MAP_CSn_COL_SIZE_BMSK	= 0x3,
+	S_SCMO_ADDR_MAP_CSn_COL_SIZE_SHFT	= 0x0,
+};
+
+#define S_SCMO_ADDR_MASK_CSn_ADDR(b, n, o) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000430 + 0x4 * (0))
+enum bimc_s_scmo_addr_mask_csn {
+	S_SCMO_ADDR_MASK_CSn_RMSK		= 0xffff,
+	S_SCMO_ADDR_MASK_CSn_MAXn		= 1,
+	S_SCMO_ADDR_MASK_CSn_ADDR_MASK_BMSK	= 0xfc,
+	S_SCMO_ADDR_MASK_CSn_ADDR_MASK_SHFT	= 0x2,
+};
+
+#define S_SCMO_SLV_STATUS_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000450)
+enum bimc_s_scmo_slv_status {
+	S_SCMO_SLV_STATUS_RMSK				= 0xff3,
+	S_SCMO_SLV_STATUS_GLOBAL_MONS_IN_USE_BMSK	= 0xff0,
+	S_SCMO_SLV_STATUS_GLOBAL_MONS_IN_USE_SHFT	= 0x4,
+	S_SCMO_SLV_STATUS_SLAVE_IDLE_BMSK		= 0x3,
+	S_SCMO_SLV_STATUS_SLAVE_IDLE_SHFT		= 0x0,
+};
+
+#define S_SCMO_CMD_BUF_CFG_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000500)
+enum bimc_s_scmo_cmd_buf_cfg {
+	S_SCMO_CMD_BUF_CFG_RMSK				= 0xf1f,
+	S_SCMO_CMD_BUF_CFG_CMD_ORDERING_BMSK		= 0x300,
+	S_SCMO_CMD_BUF_CFG_CMD_ORDERING_SHFT		= 0x8,
+	S_SCMO_CMD_BUF_CFG_HP_CMD_AREQPRIO_MAP_BMSK	= 0x10,
+	S_SCMO_CMD_BUF_CFG_HP_CMD_AREQPRIO_MAP_SHFT	= 0x4,
+	S_SCMO_CMD_BUF_CFG_HP_CMD_Q_DEPTH_BMSK		= 0x7,
+	S_SCMO_CMD_BUF_CFG_HP_CMD_Q_DEPTH_SHFT		= 0x0,
+};
+
+#define S_SCM_CMD_BUF_STATUS_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000520)
+enum bimc_s_scm_cmd_buf_status {
+	S_SCMO_CMD_BUF_STATUS_RMSK				= 0x77,
+	S_SCMO_CMD_BUF_STATUS_HP_CMD_BUF_ENTRIES_IN_USE_BMSK	= 0x70,
+	S_SCMO_CMD_BUF_STATUS_HP_CMD_BUF_ENTRIES_IN_USE_SHFT	= 0x4,
+	S_SCMO_CMD_BUF_STATUS_LP_CMD_BUF_ENTRIES_IN_USE_BMSK	= 0x7,
+	S_SCMO_CMD_BUF_STATUS_LP_CMD_BUF_ENTRIES_IN_USE_SHFT	= 0x0,
+};
+
+#define S_SCMO_RCH_SEL_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000540)
+enum bimc_s_scmo_rch_sel {
+	S_SCMO_RCH_SEL_RMSK			= 0xffffffff,
+	S_SCMO_CMD_BUF_STATUS_RCH_PORTS_BMSK	= 0xffffffff,
+	S_SCMO_CMD_BUF_STATUS_RCH_PORTS_SHFT	= 0x0,
+};
+
+#define S_SCMO_RCH_BKPR_CFG_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000544)
+enum bimc_s_scmo_rch_bkpr_cfg {
+	S_SCMO_RCH_BKPR_CFG_RMSK			= 0xffffffff,
+	S_SCMO_RCH_BKPR_CFG_RCH1_FIFO_BKPR_HI_TH_BMSK	= 0x3f000000,
+	S_SCMO_RCH_BKPR_CFG_RCH1_FIFO_BKPR_HI_TH_SHFT	= 0x18,
+	S_SCMO_RCH_BKPR_CFG_RCH1_FIFO_BKPR_LO_TH_BMSK	= 0x3f0000,
+	S_SCMO_RCH_BKPR_CFG_RCH1_FIFO_BKPR_LO_TH_SHFT	= 0x10,
+	S_SCMO_RCH_BKPR_CFG_RCH0_FIFO_BKPR_HI_TH_BMSK	= 0x3f00,
+	S_SCMO_RCH_BKPR_CFG_RCH0_FIFO_BKPR_HI_TH_SHFT	= 0x8,
+	S_SCMO_RCH_BKPR_CFG_RCH0_FIFO_BKPR_LO_TH_BMSK	= 0x3f,
+	S_SCMO_RCH_BKPR_CFG_RCH0_FIFO_BKPR_LO_TH_SHFT	= 0x0,
+};
+
+#define S_SCMO_RCH_STATUS_ADDR(b, n) \
+		(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000560)
+enum bimc_s_scmo_rch_status {
+	S_SCMO_RCH_STATUS_RMSK				= 0x33333,
+	S_SCMO_RCH_STATUS_PRQ_FIFO_FULL_BMSK		= 0x20000,
+	S_SCMO_RCH_STATUS_PRQ_FIFO_FULL_SHFT		= 0x11,
+	S_SCMO_RCH_STATUS_PRQ_FIFO_EMPTY_BMSK		= 0x10000,
+	S_SCMO_RCH_STATUS_PRQ_FIFO_EMPTY_SHFT		= 0x10,
+	S_SCMO_RCH_STATUS_RCH1_QUAL_FIFO_FULL_BMSK	= 0x2000,
+	S_SCMO_RCH_STATUS_RCH1_QUAL_FIFO_FULL_SHFT	= 0xd,
+	S_SCMO_RCH_STATUS_RCH1_QUAL_FIFO_EMPTY_BMSK	= 0x1000,
+	S_SCMO_RCH_STATUS_RCH1_QUAL_FIFO_EMPTY_SHFT	= 0xc,
+	S_SCMO_RCH_STATUS_RCH1_DATA_FIFO_FULL_BMSK	= 0x200,
+	S_SCMO_RCH_STATUS_RCH1_DATA_FIFO_FULL_SHFT	= 0x9,
+	S_SCMO_RCH_STATUS_RCH1_DATA_FIFO_EMPTY_BMSK	= 0x100,
+	S_SCMO_RCH_STATUS_RCH1_DATA_FIFO_EMPTY_SHFT	= 0x8,
+	S_SCMO_RCH_STATUS_RCH0_QUAL_FIFO_FULL_BMSK	= 0x20,
+	S_SCMO_RCH_STATUS_RCH0_QUAL_FIFO_FULL_SHFT	= 0x5,
+	S_SCMO_RCH_STATUS_RCH0_QUAL_FIFO_EMPTY_BMSK	= 0x10,
+	S_SCMO_RCH_STATUS_RCH0_QUAL_FIFO_EMPTY_SHFT	= 0x4,
+	S_SCMO_RCH_STATUS_RCH0_DATA_FIFO_FULL_BMSK	= 0x2,
+	S_SCMO_RCH_STATUS_RCH0_DATA_FIFO_FULL_SHFT	= 0x1,
+	S_SCMO_RCH_STATUS_RCH0_DATA_FIFO_EMPTY_BMSK	= 0x1,
+	S_SCMO_RCH_STATUS_RCH0_DATA_FIFO_EMPTY_SHFT	= 0x0,
+};
+
+#define S_SCMO_WCH_BUF_CFG_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000580)
+enum bimc_s_scmo_wch_buf_cfg {
+	S_SCMO_WCH_BUF_CFG_RMSK				= 0xff,
+	S_SCMO_WCH_BUF_CFG_WRITE_BLOCK_READ_BMSK	= 0x10,
+	S_SCMO_WCH_BUF_CFG_WRITE_BLOCK_READ_SHFT	= 0x4,
+	S_SCMO_WCH_BUF_CFG_COALESCE_EN_BMSK		= 0x1,
+	S_SCMO_WCH_BUF_CFG_COALESCE_EN_SHFT		= 0x0,
+};
+
+#define S_SCMO_WCH_STATUS_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x000005a0)
+enum bimc_s_scmo_wch_status {
+	S_SCMO_WCH_STATUS_RMSK				= 0x333,
+	S_SCMO_WCH_STATUS_BRESP_FIFO_FULL_BMSK		= 0x200,
+	S_SCMO_WCH_STATUS_BRESP_FIFO_FULL_SHFT		= 0x9,
+	S_SCMO_WCH_STATUS_BRESP_FIFO_EMPTY_BMSK		= 0x100,
+	S_SCMO_WCH_STATUS_BRESP_FIFO_EMPTY_SHFT		= 0x8,
+	S_SCMO_WCH_STATUS_WDATA_FIFO_FULL_BMSK		= 0x20,
+	S_SCMO_WCH_STATUS_WDATA_FIFO_FULL_SHFT		= 0x5,
+	S_SCMO_WCH_STATUS_WDATA_FIFO_EMPTY_BMSK		= 0x10,
+	S_SCMO_WCH_STATUS_WDATA_FIFO_EMPTY_SHFT		= 0x4,
+	S_SCMO_WCH_STATUS_WBUF_FULL_BMSK		= 0x2,
+	S_SCMO_WCH_STATUS_WBUF_FULL_SHFT		= 0x1,
+	S_SCMO_WCH_STATUS_WBUF_EMPTY_BMSK		= 0x1,
+	S_SCMO_WCH_STATUS_WBUF_EMPTY_SHFT		= 0x0,
+};
+
+#define S_SCMO_FLUSH_CFG_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x000005c0)
+enum bimc_s_scmo_flush_cfg {
+	S_SCMO_FLUSH_CFG_RMSK				= 0xffffffff,
+	S_SCMO_FLUSH_CFG_FLUSH_IN_ORDER_BMSK		= 0x10000000,
+	S_SCMO_FLUSH_CFG_FLUSH_IN_ORDER_SHFT		= 0x1c,
+	S_SCMO_FLUSH_CFG_FLUSH_IDLE_DELAY_BMSK		= 0x3ff0000,
+	S_SCMO_FLUSH_CFG_FLUSH_IDLE_DELAY_SHFT		= 0x10,
+	S_SCMO_FLUSH_CFG_FLUSH_UPPER_LIMIT_BMSK		= 0xf00,
+	S_SCMO_FLUSH_CFG_FLUSH_UPPER_LIMIT_SHFT		= 0x8,
+	S_SCMO_FLUSH_CFG_FLUSH_LOWER_LIMIT_BMSK		= 0xf,
+	S_SCMO_FLUSH_CFG_FLUSH_LOWER_LIMIT_SHFT		= 0x0,
+};
+
+#define S_SCMO_FLUSH_CMD_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x000005c4)
+enum bimc_s_scmo_flush_cmd {
+	S_SCMO_FLUSH_CMD_RMSK				= 0xf,
+	S_SCMO_FLUSH_CMD_FLUSH_ALL_BUF_BMSK		= 0x3,
+	S_SCMO_FLUSH_CMD_FLUSH_ALL_BUF_SHFT		= 0x0,
+};
+
+#define S_SCMO_CMD_OPT_CFG0_ADDR(b, n) \
+	(S_SCM0_REG_BASE(b) + (0x8000 * (n)) + 0x00000700)
+enum bimc_s_scmo_cmd_opt_cfg0 {
+	S_SCMO_CMD_OPT_CFG0_RMSK		= 0xffffff,
+	S_SCMO_CMD_OPT_CFG0_IGNORE_BANK_UNAVL_BMSK	= 0x100000,
+	S_SCMO_CMD_OPT_CFG0_IGNORE_BANK_UNAVL_SHFT	= 0x14,
+	S_SCMO_CMD_OPT_CFG0_MASK_CMDOUT_PRI_BMSK	= 0x10000,
+	S_SCMO_CMD_OPT_CFG0_MASK_CMDOUT_PRI_SHFT	= 0x10,
+	S_SCMO_CMD_OPT_CFG0_DPE_CMD_REORDERING_BMSK	= 0x1000,
+	S_SCMO_CMD_OPT_CFG0_DPE_CMD_REORDERING_SHFT	= 0xc,
+	S_SCMO_CMD_OPT_CFG0_WR_OPT_EN_BMSK		= 0x100,
+	S_SCMO_CMD_OPT_CFG0_WR_OPT_EN_SHFT		= 0x8,
+	S_SCMO_CMD_OPT_CFG0_RD_OPT_EN_BMSK		= 0x10,
+	S_SCMO_CMD_OPT_CFG0_RD_OPT_EN_SHFT		= 0x4,
+	S_SCMO_CMD_OPT_CFG0_PAGE_MGMT_POLICY_BMSK	= 0x1,
+	S_SCMO_CMD_OPT_CFG0_PAGE_MGMT_POLICY_SHFT	= 0x0,
+};
+
+#define S_SCMO_CMD_OPT_CFG1_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000704)
+enum bimc_s_scmo_cmd_opt_cfg1 {
+	S_SCMO_CMD_OPT_CFG1_RMSK			= 0xffffffff,
+	S_SCMO_CMD_OPT_CFG1_HSTP_CMD_TIMEOUT_BMSK	= 0x1f000000,
+	S_SCMO_CMD_OPT_CFG1_HSTP_CMD_TIMEOUT_SHFT	= 0x18,
+	S_SCMO_CMD_OPT_CFG1_HP_CMD_TIMEOUT_BMSK		= 0x1f0000,
+	S_SCMO_CMD_OPT_CFG1_HP_CMD_TIMEOUT_SHFT		= 0x10,
+	S_SCMO_CMD_OPT_CFG1_MP_CMD_TIMEOUT_BMSK		= 0x1f00,
+	S_SCMO_CMD_OPT_CFG1_MP_CMD_TIMEOUT_SHFT		= 0x8,
+	S_SCMO_CMD_OPT_CFG1_LP_CMD_TIMEOUT_BMSK		= 0x1f,
+	S_SCMO_CMD_OPT_CFG1_LP_CMD_TIMEOUT_SHFT		= 0x0,
+};
+
+#define S_SCMO_CMD_OPT_CFG2_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000708)
+enum bimc_s_scmo_cmd_opt_cfg2 {
+	S_SCMO_CMD_OPT_CFG2_RMSK			= 0xff,
+	S_SCMO_CMD_OPT_CFG2_RWOPT_CMD_TIMEOUT_BMSK	= 0xf,
+	S_SCMO_CMD_OPT_CFG2_RWOPT_CMD_TIMEOUT_SHFT	= 0x0,
+};
+
+#define S_SCMO_CMD_OPT_CFG3_ADDR(b, n) \
+	(S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x0000070c)
+enum bimc_s_scmo_cmd_opt_cfg3 {
+	S_SCMO_CMD_OPT_CFG3_RMSK			= 0xff,
+	S_SCMO_CMD_OPT_CFG3_FLUSH_CMD_TIMEOUT_BMSK	= 0xf,
+	S_SCMO_CMD_OPT_CFG3_FLUSH_CMD_TIMEOUT_SHFT	= 0x0,
+};
+
+/* S_SWAY_GENERIC */
+#define S_SWAY_REG_BASE(b)	((b) + 0x00048000)
+
+#define S_SWAY_CONFIG_INFO_0_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000020)
+enum bimc_s_sway_config_info_0 {
+	S_SWAY_CONFIG_INFO_0_RMSK		= 0xff0000ff,
+	S_SWAY_CONFIG_INFO_0_SYNC_MODE_BMSK	= 0xff000000,
+	S_SWAY_CONFIG_INFO_0_SYNC_MODE_SHFT	= 0x18,
+	S_SWAY_CONFIG_INFO_0_FUNC_BMSK		= 0xff,
+	S_SWAY_CONFIG_INFO_0_FUNC_SHFT		= 0x0,
+};
+
+#define S_SWAY_CONFIG_INFO_1_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000030)
+enum bimc_s_sway_config_info_1 {
+	S_SWAY_CONFIG_INFO_1_RMSK			= 0xffffffff,
+	S_SWAY_CONFIG_INFO_1_MPORT_CONNECTIVITY_BMSK	= 0xffffffff,
+	S_SWAY_CONFIG_INFO_1_MPORT_CONNECTIVITY_SHFT	= 0x0,
+};
+
+#define S_SWAY_CONFIG_INFO_2_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000040)
+enum bimc_s_sway_config_info_2 {
+	S_SWAY_CONFIG_INFO_2_RMSK			= 0xffff0000,
+	S_SWAY_CONFIG_INFO_2_MPORT_CONNECTIVITY_BMSK	= 0xffff0000,
+	S_SWAY_CONFIG_INFO_2_MPORT_CONNECTIVITY_SHFT	= 0x10,
+};
+
+#define S_SWAY_CONFIG_INFO_3_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000050)
+enum bimc_s_sway_config_info_3 {
+	S_SWAY_CONFIG_INFO_3_RMSK			= 0xffffffff,
+	S_SWAY_CONFIG_INFO_3_RCH0_DEPTH_BMSK		= 0xff000000,
+	S_SWAY_CONFIG_INFO_3_RCH0_DEPTH_SHFT		= 0x18,
+	S_SWAY_CONFIG_INFO_3_BCH_DEPTH_BMSK		= 0xff0000,
+	S_SWAY_CONFIG_INFO_3_BCH_DEPTH_SHFT		= 0x10,
+	S_SWAY_CONFIG_INFO_3_WCH_DEPTH_BMSK		= 0xff,
+	S_SWAY_CONFIG_INFO_3_WCH_DEPTH_SHFT		= 0x0,
+};
+
+#define S_SWAY_CONFIG_INFO_4_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000060)
+enum bimc_s_sway_config_info_4 {
+	S_SWAY_CONFIG_INFO_4_RMSK			= 0x800000ff,
+	S_SWAY_CONFIG_INFO_4_DUAL_RCH_EN_BMSK		= 0x80000000,
+	S_SWAY_CONFIG_INFO_4_DUAL_RCH_EN_SHFT		= 0x1f,
+	S_SWAY_CONFIG_INFO_4_RCH1_DEPTH_BMSK		= 0xff,
+	S_SWAY_CONFIG_INFO_4_RCH1_DEPTH_SHFT		= 0x0,
+};
+
+#define S_SWAY_CONFIG_INFO_5_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000070)
+enum bimc_s_sway_config_info_5 {
+	S_SWAY_CONFIG_INFO_5_RMSK			= 0x800000ff,
+	S_SWAY_CONFIG_INFO_5_QCH_EN_BMSK		= 0x80000000,
+	S_SWAY_CONFIG_INFO_5_QCH_EN_SHFT		= 0x1f,
+	S_SWAY_CONFIG_INFO_5_QCH_DEPTH_BMSK		= 0xff,
+	S_SWAY_CONFIG_INFO_5_QCH_DEPTH_SHFT		= 0x0,
+};
+
+#define S_SWAY_CONFIG_INFO_6_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000080)
+enum bimc_s_sway_config_info_6 {
+	S_SWAY_CONFIG_INFO_6_RMSK			= 0x1,
+	S_SWAY_CONFIG_INFO_6_S2SW_PIPELINE_EN_BMSK	= 0x1,
+	S_SWAY_CONFIG_INFO_6_S2SW_PIPELINE_EN_SHFT	= 0x0,
+};
+
+#define S_SWAY_INT_STATUS_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000100)
+enum bimc_s_sway_int_status {
+	S_SWAY_INT_STATUS_RMSK		= 0x3,
+	S_SWAY_INT_STATUS_RFU_BMSK	= 0x3,
+	S_SWAY_INT_STATUS_RFU_SHFT	= 0x0,
+};
+
+#define S_SWAY_INT_CLR_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000108)
+enum bimc_s_sway_int_clr {
+	S_SWAY_INT_CLR_RMSK		= 0x3,
+	S_SWAY_INT_CLR_RFU_BMSK		= 0x3,
+	S_SWAY_INT_CLR_RFU_SHFT		= 0x0,
+};
+
+
+#define S_SWAY_INT_EN_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x0000010c)
+enum bimc_s_sway_int_en {
+	S_SWAY_INT_EN_RMSK		= 0x3,
+	S_SWAY_INT_EN_RFU_BMSK		= 0x3,
+	S_SWAY_INT_EN_RFU_SHFT		= 0x0,
+};
+
+#define S_SWAY_CLK_CTRL_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000200)
+enum bimc_s_sway_clk_ctrl {
+	S_SWAY_CLK_CTRL_RMSK				= 0x3,
+	S_SWAY_CLK_CTRL_SLAVE_CLK_GATING_EN_BMSK	= 0x2,
+	S_SWAY_CLK_CTRL_SLAVE_CLK_GATING_EN_SHFT	= 0x1,
+	S_SWAY_CLK_CTRL_CORE_CLK_GATING_EN_BMSK		= 0x1,
+	S_SWAY_CLK_CTRL_CORE_CLK_GATING_EN_SHFT		= 0x0,
+};
+
+#define S_SWAY_RCH_SEL_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000210)
+enum bimc_s_sway_rch_sel {
+	S_SWAY_RCH_SEL_RMSK		= 0x7f,
+	S_SWAY_RCH_SEL_UNUSED_BMSK	= 0x7f,
+	S_SWAY_RCH_SEL_UNUSED_SHFT	= 0x0,
+};
+
+
+#define S_SWAY_MAX_OUTSTANDING_REQS_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000220)
+enum bimc_s_sway_max_outstanding_reqs {
+	S_SWAY_MAX_OUTSTANDING_REQS_RMSK	= 0xffff,
+	S_SWAY_MAX_OUTSTANDING_REQS_WRITE_BMSK	= 0xff00,
+	S_SWAY_MAX_OUTSTANDING_REQS_WRITE_SHFT	= 0x8,
+	S_SWAY_MAX_OUTSTANDING_REQS_READ_BMSK	= 0xff,
+	S_SWAY_MAX_OUTSTANDING_REQS_READ_SHFT	= 0x0,
+};
+
+
+#define S_SWAY_BUF_STATUS_0_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000400)
+enum bimc_s_sway_buf_status_0 {
+	S_SWAY_BUF_STATUS_0_RMSK			= 0xf0300f03,
+	S_SWAY_BUF_STATUS_0_RCH0_DATA_RD_FULL_BMSK	= 0x80000000,
+	S_SWAY_BUF_STATUS_0_RCH0_DATA_RD_FULL_SHFT	= 0x1f,
+	S_SWAY_BUF_STATUS_0_RCH0_DATA_RD_EMPTY_BMSK	= 0x40000000,
+	S_SWAY_BUF_STATUS_0_RCH0_DATA_RD_EMPTY_SHFT	= 0x1e,
+	S_SWAY_BUF_STATUS_0_RCH0_CTRL_RD_FULL_BMSK	= 0x20000000,
+	S_SWAY_BUF_STATUS_0_RCH0_CTRL_RD_FULL_SHFT	= 0x1d,
+	S_SWAY_BUF_STATUS_0_RCH0_CTRL_RD_EMPTY_BMSK	= 0x10000000,
+	S_SWAY_BUF_STATUS_0_RCH0_CTRL_RD_EMPTY_SHFT	= 0x1c,
+	S_SWAY_BUF_STATUS_0_BCH_RD_FULL_BMSK		= 0x200000,
+	S_SWAY_BUF_STATUS_0_BCH_RD_FULL_SHFT		= 0x15,
+	S_SWAY_BUF_STATUS_0_BCH_RD_EMPTY_BMSK		= 0x100000,
+	S_SWAY_BUF_STATUS_0_BCH_RD_EMPTY_SHFT		= 0x14,
+	S_SWAY_BUF_STATUS_0_WCH_DATA_WR_FULL_BMSK	= 0x800,
+	S_SWAY_BUF_STATUS_0_WCH_DATA_WR_FULL_SHFT	= 0xb,
+	S_SWAY_BUF_STATUS_0_WCH_DATA_WR_EMPTY_BMSK	= 0x400,
+	S_SWAY_BUF_STATUS_0_WCH_DATA_WR_EMPTY_SHFT	= 0xa,
+	S_SWAY_BUF_STATUS_0_WCH_CTRL_WR_FULL_BMSK	= 0x200,
+	S_SWAY_BUF_STATUS_0_WCH_CTRL_WR_FULL_SHFT	= 0x9,
+	S_SWAY_BUF_STATUS_0_WCH_CTRL_WR_EMPTY_BMSK	= 0x100,
+	S_SWAY_BUF_STATUS_0_WCH_CTRL_WR_EMPTY_SHFT	= 0x8,
+	S_SWAY_BUF_STATUS_0_ACH_WR_FULL_BMSK		= 0x2,
+	S_SWAY_BUF_STATUS_0_ACH_WR_FULL_SHFT		= 0x1,
+	S_SWAY_BUF_STATUS_0_ACH_WR_EMPTY_BMSK		= 0x1,
+	S_SWAY_BUF_STATUS_0_ACH_WR_EMPTY_SHFT		= 0x0,
+};
+
+#define S_SWAY_BUF_STATUS_1_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000410)
+enum bimc_s_sway_buf_status_1 {
+	S_SWAY_BUF_STATUS_1_RMSK			= 0xf0,
+	S_SWAY_BUF_STATUS_1_RCH1_DATA_RD_FULL_BMSK	= 0x80,
+	S_SWAY_BUF_STATUS_1_RCH1_DATA_RD_FULL_SHFT	= 0x7,
+	S_SWAY_BUF_STATUS_1_RCH1_DATA_RD_EMPTY_BMSK	= 0x40,
+	S_SWAY_BUF_STATUS_1_RCH1_DATA_RD_EMPTY_SHFT	= 0x6,
+	S_SWAY_BUF_STATUS_1_RCH1_CTRL_RD_FULL_BMSK	= 0x20,
+	S_SWAY_BUF_STATUS_1_RCH1_CTRL_RD_FULL_SHFT	= 0x5,
+	S_SWAY_BUF_STATUS_1_RCH1_CTRL_RD_EMPTY_BMSK	= 0x10,
+	S_SWAY_BUF_STATUS_1_RCH1_CTRL_RD_EMPTY_SHFT	= 0x4,
+};
+
+#define S_SWAY_BUF_STATUS_2_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000420)
+enum bimc_s_sway_buf_status_2 {
+	S_SWAY_BUF_STATUS_2_RMSK		= 0x30,
+	S_SWAY_BUF_STATUS_2_QCH_RD_FULL_BMSK	= 0x20,
+	S_SWAY_BUF_STATUS_2_QCH_RD_FULL_SHFT	= 0x5,
+	S_SWAY_BUF_STATUS_2_QCH_RD_EMPTY_BMSK	= 0x10,
+	S_SWAY_BUF_STATUS_2_QCH_RD_EMPTY_SHFT	= 0x4,
+};
+
+/* S_ARB_GENERIC */
+
+#define S_ARB_REG_BASE(b)	((b) + 0x00049000)
+
+#define S_ARB_COMPONENT_INFO_ADDR(b, n) \
+	(S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000000)
+enum bimc_s_arb_component_info {
+	S_ARB_COMPONENT_INFO_RMSK		= 0xffffff,
+	S_ARB_COMPONENT_INFO_INSTANCE_BMSK	= 0xff0000,
+	S_ARB_COMPONENT_INFO_INSTANCE_SHFT	= 0x10,
+	S_ARB_COMPONENT_INFO_SUB_TYPE_BMSK	= 0xff00,
+	S_ARB_COMPONENT_INFO_SUB_TYPE_SHFT	= 0x8,
+	S_ARB_COMPONENT_INFO_TYPE_BMSK		= 0xff,
+	S_ARB_COMPONENT_INFO_TYPE_SHFT		= 0x0,
+};
+
+#define S_ARB_CONFIG_INFO_0_ADDR(b, n) \
+		(S_ARB_REG_BASE(b) + (0x8000 * (n)) + 0x00000020)
+enum bimc_s_arb_config_info_0 {
+	S_ARB_CONFIG_INFO_0_RMSK			= 0x800000ff,
+	S_ARB_CONFIG_INFO_0_ARB2SW_PIPELINE_EN_BMSK	= 0x80000000,
+	S_ARB_CONFIG_INFO_0_ARB2SW_PIPELINE_EN_SHFT	= 0x1f,
+	S_ARB_CONFIG_INFO_0_FUNC_BMSK			= 0xff,
+	S_ARB_CONFIG_INFO_0_FUNC_SHFT			= 0x0,
+};
+
+#define S_ARB_CONFIG_INFO_1_ADDR(b, n) \
+		(S_ARB_REG_BASE(b) + (0x8000 * (n)) + 0x00000030)
+enum bimc_s_arb_config_info_1 {
+	S_ARB_CONFIG_INFO_1_RMSK			= 0xffffffff,
+	S_ARB_CONFIG_INFO_1_MPORT_CONNECTIVITY_BMSK	= 0xffffffff,
+	S_ARB_CONFIG_INFO_1_MPORT_CONNECTIVITY_SHFT	= 0x0,
+};
+
+#define S_ARB_CLK_CTRL_ADDR(b) \
+	(S_ARB_REG_BASE(b) + (0x8000 * (n)) + 0x00000200)
+enum bimc_s_arb_clk_ctrl {
+	S_ARB_CLK_CTRL_RMSK				= 0x1,
+	S_ARB_CLK_CTRL_SLAVE_CLK_GATING_EN_BMSK		= 0x2,
+	S_ARB_CLK_CTRL_SLAVE_CLK_GATING_EN_SHFT		= 0x1,
+	S_ARB_CLK_CTRL_CORE_CLK_GATING_EN_BMSK		= 0x1,
+	S_ARB_CLK_CTRL_CORE_CLK_GATING_EN_SHFT		= 0x0,
+	S_ARB_CLK_CTRL_CLK_GATING_EN_BMSK		= 0x1,
+	S_ARB_CLK_CTRL_CLK_GATING_EN_SHFT		= 0x0,
+};
+
+#define S_ARB_MODE_ADDR(b, n) \
+	(S_ARB_REG_BASE(b) + (0x8000 * (n)) + 0x00000210)
+enum bimc_s_arb_mode {
+	S_ARB_MODE_RMSK				= 0xf0000001,
+	S_ARB_MODE_WR_GRANTS_AHEAD_BMSK		= 0xf0000000,
+	S_ARB_MODE_WR_GRANTS_AHEAD_SHFT		= 0x1c,
+	S_ARB_MODE_PRIO_RR_EN_BMSK		= 0x1,
+	S_ARB_MODE_PRIO_RR_EN_SHFT		= 0x0,
+};
+
+#define BKE_HEALTH_MASK \
+	(M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_BMSK |\
+	M_BKE_HEALTH_0_CONFIG_AREQPRIO_BMSK |\
+	M_BKE_HEALTH_0_CONFIG_PRIOLVL_BMSK)
+
+#define BKE_HEALTH_VAL(limit, areq, plvl) \
+	((((limit) << M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_SHFT) & \
+	M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_BMSK) | \
+	(((areq) << M_BKE_HEALTH_0_CONFIG_AREQPRIO_SHFT) & \
+	M_BKE_HEALTH_0_CONFIG_AREQPRIO_BMSK) | \
+	(((plvl) << M_BKE_HEALTH_0_CONFIG_PRIOLVL_SHFT) & \
+	M_BKE_HEALTH_0_CONFIG_PRIOLVL_BMSK))
+
+#define MAX_GRANT_PERIOD \
+	(M_BKE_GP_GP_BMSK >> \
+	M_BKE_GP_GP_SHFT)
+
+#define MAX_GC \
+	(M_BKE_GC_GC_BMSK >> \
+	M_BKE_GC_GC_SHFT)
+
+static int bimc_div(uint64_t *a, uint32_t b)
+{
+	if ((*a > 0) && (*a < b))
+		return 1;
+	else
+		return do_div(*a, b);
+}
+
+#define ENABLE(val) ((val) == 1 ? 1 : 0)
+void msm_bus_bimc_set_mas_clk_gate(struct msm_bus_bimc_info *binfo,
+	uint32_t mas_index, struct msm_bus_bimc_clk_gate *bgate)
+{
+	uint32_t val, mask, reg_val;
+	void __iomem *addr;
+
+	reg_val = readl_relaxed(M_CLK_CTRL_ADDR(binfo->base,
+			mas_index)) & M_CLK_CTRL_RMSK;
+	addr = M_CLK_CTRL_ADDR(binfo->base, mas_index);
+	mask = (M_CLK_CTRL_MAS_CLK_GATING_EN_BMSK |
+		M_CLK_CTRL_CORE_CLK_GATING_EN_BMSK);
+	val = (bgate->core_clk_gate_en <<
+		M_CLK_CTRL_MAS_CLK_GATING_EN_SHFT) |
+		bgate->port_clk_gate_en;
+	writel_relaxed(((reg_val & (~mask)) | (val & mask)), addr);
+	/* Ensure clock gating enable mask is set before exiting */
+	wmb();
+}
+
+void msm_bus_bimc_arb_en(struct msm_bus_bimc_info *binfo,
+	uint32_t slv_index, bool en)
+{
+	uint32_t reg_val, reg_mask_val, enable, val;
+
+	reg_mask_val = (readl_relaxed(S_ARB_CONFIG_INFO_0_ADDR(binfo->
+		base, slv_index)) & S_ARB_CONFIG_INFO_0_FUNC_BMSK)
+		>> S_ARB_CONFIG_INFO_0_FUNC_SHFT;
+	enable = ENABLE(en);
+	val = enable << S_ARB_MODE_PRIO_RR_EN_SHFT;
+	if (reg_mask_val == BIMC_ARB_MODE_PRIORITY_RR) {
+		reg_val = readl_relaxed(S_ARB_CONFIG_INFO_0_ADDR(binfo->
+			base, slv_index)) & S_ARB_MODE_RMSK;
+		writel_relaxed(((reg_val & (~(S_ARB_MODE_PRIO_RR_EN_BMSK))) |
+			(val & S_ARB_MODE_PRIO_RR_EN_BMSK)),
+			S_ARB_MODE_ADDR(binfo->base, slv_index));
+		/* Ensure arbitration mode is set before returning */
+		wmb();
+	}
+}
+
+static void set_qos_mode(void __iomem *baddr, uint32_t index, uint32_t val0,
+	uint32_t val1, uint32_t val2)
+{
+	uint32_t reg_val, val;
+
+	reg_val = readl_relaxed(M_PRIOLVL_OVERRIDE_ADDR(baddr,
+		index)) & M_PRIOLVL_OVERRIDE_RMSK;
+	val = val0 << M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_SHFT;
+	writel_relaxed(((reg_val & ~(M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_BMSK))
+		| (val & M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_BMSK)),
+		M_PRIOLVL_OVERRIDE_ADDR(baddr, index));
+	reg_val = readl_relaxed(M_RD_CMD_OVERRIDE_ADDR(baddr, index)) &
+		M_RD_CMD_OVERRIDE_RMSK;
+	val = val1 << M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT;
+	writel_relaxed(((reg_val & ~(M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK
+		)) | (val & M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK)),
+		M_RD_CMD_OVERRIDE_ADDR(baddr, index));
+	reg_val = readl_relaxed(M_WR_CMD_OVERRIDE_ADDR(baddr, index)) &
+		M_WR_CMD_OVERRIDE_RMSK;
+	val = val2 << M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT;
+	writel_relaxed(((reg_val & ~(M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK
+		)) | (val & M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK)),
+		M_WR_CMD_OVERRIDE_ADDR(baddr, index));
+	/* Ensure the priority register writes go through */
+	wmb();
+}
+
+static void msm_bus_bimc_set_qos_mode(struct msm_bus_bimc_info *binfo,
+	uint32_t mas_index, uint8_t qmode_sel)
+{
+	uint32_t reg_val, val;
+
+	switch (qmode_sel) {
+	case BIMC_QOS_MODE_FIXED:
+		reg_val = readl_relaxed(M_BKE_EN_ADDR(binfo->base,
+			mas_index)) & M_BKE_EN_RMSK;
+		writel_relaxed((reg_val & (~M_BKE_EN_EN_BMSK)),
+			M_BKE_EN_ADDR(binfo->base, mas_index));
+		/* Ensure that the book-keeping register writes
+		 * go through before setting QoS mode.
+		 * QoS mode registers might write beyond 1K
+		 * boundary in future
+		 */
+		wmb();
+		set_qos_mode(binfo->base, mas_index, 1, 1, 1);
+		break;
+
+	case BIMC_QOS_MODE_BYPASS:
+		reg_val = readl_relaxed(M_BKE_EN_ADDR(binfo->base,
+			mas_index)) & M_BKE_EN_RMSK;
+		writel_relaxed((reg_val & (~M_BKE_EN_EN_BMSK)),
+			M_BKE_EN_ADDR(binfo->base, mas_index));
+		/* Ensure that the book-keeping register writes
+		 * go through before setting QoS mode.
+		 * QoS mode registers might write beyond 1K
+		 * boundary in future
+		 */
+		wmb();
+		set_qos_mode(binfo->base, mas_index, 0, 0, 0);
+		break;
+
+	case BIMC_QOS_MODE_REGULATOR:
+	case BIMC_QOS_MODE_LIMITER:
+		set_qos_mode(binfo->base, mas_index, 0, 0, 0);
+		reg_val = readl_relaxed(M_BKE_EN_ADDR(binfo->base,
+			mas_index)) & M_BKE_EN_RMSK;
+		val = 1 << M_BKE_EN_EN_SHFT;
+		/* Ensure that the book-keeping register writes
+		 * go through before setting QoS mode.
+		 * QoS mode registers might write beyond 1K
+		 * boundary in future
+		 */
+		wmb();
+		writel_relaxed(((reg_val & (~M_BKE_EN_EN_BMSK)) | (val &
+			M_BKE_EN_EN_BMSK)), M_BKE_EN_ADDR(binfo->base,
+			mas_index));
+		break;
+	default:
+		break;
+	}
+}
+
+static void set_qos_prio_rl(void __iomem *addr, uint32_t rmsk,
+	uint8_t index, struct msm_bus_bimc_qos_mode *qmode)
+{
+	uint32_t reg_val, val0, val;
+
+	/* Note, addr is already passed with right mas_index */
+	reg_val = readl_relaxed(addr) & rmsk;
+	val0 = BKE_HEALTH_VAL(qmode->rl.qhealth[index].limit_commands,
+		qmode->rl.qhealth[index].areq_prio,
+		qmode->rl.qhealth[index].prio_level);
+	val = (reg_val & (~(BKE_HEALTH_MASK) | (val0 & BKE_HEALTH_MASK)));
+	writel_relaxed(val, addr);
+	/* Ensure that priority for regulator/limiter modes are
+	 * set before returning
+	 */
+	wmb();
+
+}
+
+static void msm_bus_bimc_set_qos_prio(struct msm_bus_bimc_info *binfo,
+	uint32_t mas_index, uint8_t qmode_sel,
+	struct msm_bus_bimc_qos_mode *qmode)
+{
+	uint32_t reg_val, val;
+
+	switch (qmode_sel) {
+	case BIMC_QOS_MODE_FIXED:
+		reg_val = readl_relaxed(M_PRIOLVL_OVERRIDE_ADDR(binfo->
+			base, mas_index)) & M_PRIOLVL_OVERRIDE_RMSK;
+		val =  qmode->fixed.prio_level <<
+			M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_SHFT;
+		writel_relaxed(((reg_val &
+			~(M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_BMSK)) | (val
+			& M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_BMSK)),
+			M_PRIOLVL_OVERRIDE_ADDR(binfo->base, mas_index));
+
+		reg_val = readl_relaxed(M_RD_CMD_OVERRIDE_ADDR(binfo->
+			base, mas_index)) & M_RD_CMD_OVERRIDE_RMSK;
+		val =  qmode->fixed.areq_prio_rd <<
+			M_RD_CMD_OVERRIDE_AREQPRIO_SHFT;
+		writel_relaxed(((reg_val & ~(M_RD_CMD_OVERRIDE_AREQPRIO_BMSK))
+			| (val & M_RD_CMD_OVERRIDE_AREQPRIO_BMSK)),
+			M_RD_CMD_OVERRIDE_ADDR(binfo->base, mas_index));
+
+		reg_val = readl_relaxed(M_WR_CMD_OVERRIDE_ADDR(binfo->
+			base, mas_index)) & M_WR_CMD_OVERRIDE_RMSK;
+		val =  qmode->fixed.areq_prio_wr <<
+			M_WR_CMD_OVERRIDE_AREQPRIO_SHFT;
+		writel_relaxed(((reg_val & ~(M_WR_CMD_OVERRIDE_AREQPRIO_BMSK))
+			| (val & M_WR_CMD_OVERRIDE_AREQPRIO_BMSK)),
+			M_WR_CMD_OVERRIDE_ADDR(binfo->base, mas_index));
+		/* Ensure that fixed mode register writes go through
+		 * before returning
+		 */
+		wmb();
+		break;
+
+	case BIMC_QOS_MODE_REGULATOR:
+	case BIMC_QOS_MODE_LIMITER:
+		set_qos_prio_rl(M_BKE_HEALTH_3_CONFIG_ADDR(binfo->base,
+			mas_index), M_BKE_HEALTH_3_CONFIG_RMSK, 3, qmode);
+		set_qos_prio_rl(M_BKE_HEALTH_2_CONFIG_ADDR(binfo->base,
+			mas_index), M_BKE_HEALTH_2_CONFIG_RMSK, 2, qmode);
+		set_qos_prio_rl(M_BKE_HEALTH_1_CONFIG_ADDR(binfo->base,
+			mas_index), M_BKE_HEALTH_1_CONFIG_RMSK, 1, qmode);
+		set_qos_prio_rl(M_BKE_HEALTH_1_CONFIG_ADDR(binfo->base,
+			mas_index), M_BKE_HEALTH_0_CONFIG_RMSK, 0 , qmode);
+		break;
+	case BIMC_QOS_MODE_BYPASS:
+	default:
+		break;
+	}
+}
+
+static void set_qos_bw_regs(void __iomem *baddr, uint32_t mas_index,
+	long int th, long int tm, long int tl, uint32_t gp,
+	uint32_t gc, bool bke_en)
+{
+	uint32_t reg_val, val;
+
+	/* Disable BKE before writing to registers as per spec */
+	reg_val = readl_relaxed(M_BKE_EN_ADDR(baddr, mas_index)) &
+		M_BKE_EN_RMSK;
+	writel_relaxed((reg_val & ~(M_BKE_EN_EN_BMSK)),
+		M_BKE_EN_ADDR(baddr, mas_index));
+
+	/* Write values of registers calculated */
+	reg_val = readl_relaxed(M_BKE_GP_ADDR(baddr, mas_index))
+		& M_BKE_GP_RMSK;
+	val =  gp << M_BKE_GP_GP_SHFT;
+	writel_relaxed(((reg_val & ~(M_BKE_GP_GP_BMSK)) | (val &
+		M_BKE_GP_GP_BMSK)), M_BKE_GP_ADDR(baddr, mas_index));
+
+	reg_val = readl_relaxed(M_BKE_GC_ADDR(baddr, mas_index)) &
+		M_BKE_GC_RMSK;
+	val =  gc << M_BKE_GC_GC_SHFT;
+	writel_relaxed(((reg_val & ~(M_BKE_GC_GC_BMSK)) | (val &
+		M_BKE_GC_GC_BMSK)), M_BKE_GC_ADDR(baddr, mas_index));
+
+	reg_val = readl_relaxed(M_BKE_THH_ADDR(baddr, mas_index)) &
+		M_BKE_THH_RMSK;
+	val =  th << M_BKE_THH_THRESH_SHFT;
+	writel_relaxed(((reg_val & ~(M_BKE_THH_THRESH_BMSK)) | (val &
+		M_BKE_THH_THRESH_BMSK)), M_BKE_THH_ADDR(baddr, mas_index));
+
+	reg_val = readl_relaxed(M_BKE_THM_ADDR(baddr, mas_index)) &
+		M_BKE_THM_RMSK;
+	val =  tm << M_BKE_THM_THRESH_SHFT;
+	writel_relaxed(((reg_val & ~(M_BKE_THM_THRESH_BMSK)) | (val &
+		M_BKE_THM_THRESH_BMSK)), M_BKE_THM_ADDR(baddr, mas_index));
+
+	reg_val = readl_relaxed(M_BKE_THL_ADDR(baddr, mas_index)) &
+		M_BKE_THL_RMSK;
+	val =  tl << M_BKE_THL_THRESH_SHFT;
+	writel_relaxed(((reg_val & ~(M_BKE_THL_THRESH_BMSK)) |
+		(val & M_BKE_THL_THRESH_BMSK)), M_BKE_THL_ADDR(baddr,
+		mas_index));
+
+	/* Set BKE enable to the value it was */
+	reg_val = readl_relaxed(M_BKE_EN_ADDR(baddr, mas_index)) &
+		M_BKE_EN_RMSK;
+	val =  bke_en << M_BKE_EN_EN_SHFT;
+	writel_relaxed(((reg_val & ~(M_BKE_EN_EN_BMSK)) | (val &
+		M_BKE_EN_EN_BMSK)), M_BKE_EN_ADDR(baddr, mas_index));
+	/* Ensure that all bandwidth register writes have completed
+	 * before returning
+	 */
+	wmb();
+}
+
+static void msm_bus_bimc_set_qos_bw(struct msm_bus_bimc_info *binfo,
+	uint32_t mas_index, struct msm_bus_bimc_qos_bw *qbw)
+{
+	uint32_t bke_en;
+
+	/* Validate QOS Frequency */
+	if (binfo->qos_freq == 0) {
+		MSM_BUS_DBG("Zero frequency\n");
+		return;
+	}
+
+	/* Get enable bit for BKE before programming the period */
+	bke_en = (readl_relaxed(M_BKE_EN_ADDR(binfo->base, mas_index)) &
+		M_BKE_EN_EN_BMSK) >> M_BKE_EN_EN_SHFT;
+
+	/* Only calculate if there's a requested bandwidth and window */
+	if (qbw->bw && qbw->ws) {
+		uint64_t th, tm, tl;
+		uint32_t gp, gc, data_width;
+		uint64_t gp_nominal, gp_required, gp_calc, data, temp;
+		uint64_t win = qbw->ws * binfo->qos_freq;
+		temp = win;
+		/*
+		 * Calculate nominal grant period defined by requested
+		 * window size.
+		 * Ceil this value to max grant period.
+		 */
+		bimc_div(&temp, 1000000);
+		gp_nominal = min_t(uint64_t, MAX_GRANT_PERIOD, temp);
+		/*
+		 * Calculate max window size, defined by bw request.
+		 * Units: (KHz, MB/s)
+		 */
+		data_width = (readl_relaxed(M_CONFIG_INFO_2_ADDR(
+			binfo->base, mas_index)) &
+			M_CONFIG_INFO_2_M_DATA_WIDTH_BMSK) >>
+			M_CONFIG_INFO_2_M_DATA_WIDTH_SHFT;
+
+		/* If unspecified, use data-width 8 by default */
+		if (!data_width)
+			data_width = 8;
+
+		gp_calc = MAX_GC * data_width * binfo->qos_freq * 1000;
+		gp_required = gp_calc;
+		bimc_div(&gp_required, qbw->bw);
+
+		/* User min of two grant periods */
+		gp = min_t(uint64_t, gp_nominal, gp_required);
+
+		/* Calculate bandwith in grants and ceil. */
+		temp = qbw->bw * gp;
+		data = data_width * binfo->qos_freq * 1000;
+		bimc_div(&temp, data);
+		gc = min_t(uint64_t, MAX_GC, temp);
+
+		/* Calculate thresholds */
+		th = qbw->bw - qbw->thh;
+		tm = qbw->bw - qbw->thm;
+		tl = qbw->bw - qbw->thl;
+
+		th = th * gp;
+		bimc_div(&th, data);
+		tm = tm * gp;
+		bimc_div(&tm, data);
+		tl = tl * gp;
+		bimc_div(&tl, data);
+
+		MSM_BUS_DBG("BIMC: BW: mas_index: %d, th: %llu tm: %llu\n",
+			mas_index, th, tm);
+		MSM_BUS_DBG("BIMC: tl: %llu gp:%u gc: %u bke_en: %u\n",
+			tl, gp, gc, bke_en);
+		set_qos_bw_regs(binfo->base, mas_index, th, tm, tl, gp,
+			gc, bke_en);
+	} else
+		/* Clear bandwidth registers */
+		set_qos_bw_regs(binfo->base, mas_index, 0, 0, 0, 0, 0,
+			bke_en);
+}
+
+static int msm_bus_bimc_allocate_commit_data(struct msm_bus_fabric_registration
+	*fab_pdata, void **cdata, int ctx)
+{
+	struct msm_bus_bimc_commit **cd = (struct msm_bus_bimc_commit **)cdata;
+	struct msm_bus_bimc_info *binfo =
+		(struct msm_bus_bimc_info *)fab_pdata->hw_data;
+
+	MSM_BUS_DBG("Allocating BIMC commit data\n");
+	*cd = kzalloc(sizeof(struct msm_bus_bimc_commit), GFP_KERNEL);
+	if (!*cd) {
+		MSM_BUS_DBG("Couldn't alloc mem for cdata\n");
+		return -ENOMEM;
+	}
+
+	(*cd)->mas = binfo->cdata[ctx].mas;
+	(*cd)->slv = binfo->cdata[ctx].slv;
+
+	return 0;
+}
+
+static void *msm_bus_bimc_allocate_bimc_data(struct platform_device *pdev,
+	struct msm_bus_fabric_registration *fab_pdata)
+{
+	struct resource *bimc_mem;
+	struct resource *bimc_io;
+	struct msm_bus_bimc_info *binfo;
+	int i;
+
+	MSM_BUS_DBG("Allocating BIMC data\n");
+	binfo = kzalloc(sizeof(struct msm_bus_bimc_info), GFP_KERNEL);
+	if (!binfo) {
+		WARN(!binfo, "Couldn't alloc mem for bimc_info\n");
+		return NULL;
+	}
+
+	binfo->qos_freq = fab_pdata->qos_freq;
+
+	binfo->params.nmasters = fab_pdata->nmasters;
+	binfo->params.nslaves = fab_pdata->nslaves;
+	binfo->params.bus_id = fab_pdata->id;
+
+	for (i = 0; i < NUM_CTX; i++) {
+		binfo->cdata[i].mas = kzalloc(sizeof(struct
+			msm_bus_node_hw_info) * fab_pdata->nmasters * 2,
+			GFP_KERNEL);
+		if (!binfo->cdata[i].mas) {
+			MSM_BUS_ERR("Couldn't alloc mem for bimc master hw\n");
+			kfree(binfo);
+			return NULL;
+		}
+
+		binfo->cdata[i].slv = kzalloc(sizeof(struct
+			msm_bus_node_hw_info) * fab_pdata->nslaves * 2,
+			GFP_KERNEL);
+		if (!binfo->cdata[i].slv) {
+			MSM_BUS_DBG("Couldn't alloc mem for bimc slave hw\n");
+			kfree(binfo->cdata[i].mas);
+			kfree(binfo);
+			return NULL;
+		}
+	}
+
+	bimc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!bimc_mem && !fab_pdata->virt) {
+		MSM_BUS_ERR("Cannot get BIMC Base address\n");
+		kfree(binfo);
+		return NULL;
+	}
+
+	bimc_io = request_mem_region(bimc_mem->start,
+			resource_size(bimc_mem), pdev->name);
+	if (!bimc_io) {
+		MSM_BUS_ERR("BIMC memory unavailable\n");
+		kfree(binfo);
+		return NULL;
+	}
+
+	binfo->base = ioremap(bimc_mem->start, resource_size(bimc_mem));
+	if (!binfo->base) {
+		MSM_BUS_ERR("IOremap failed for BIMC!\n");
+		release_mem_region(bimc_mem->start, resource_size(bimc_mem));
+		kfree(binfo);
+		return NULL;
+	}
+
+	fab_pdata->hw_data = (void *)binfo;
+	return (void *)binfo;
+}
+
+static void free_commit_data(void *cdata)
+{
+	struct msm_bus_bimc_commit *cd = (struct msm_bus_bimc_commit *)cdata;
+
+	kfree(cd->mas);
+	kfree(cd->slv);
+	kfree(cd);
+}
+
+static void msm_bus_bimc_update_bw(struct msm_bus_inode_info *hop,
+	struct msm_bus_inode_info *info,
+	struct msm_bus_fabric_registration *fab_pdata,
+	void *sel_cdata, int *master_tiers,
+	long int add_bw)
+{
+	struct msm_bus_bimc_info *binfo;
+	struct msm_bus_bimc_qos_bw qbw;
+	int i;
+	long int bw;
+	int ports = info->node_info->num_mports;
+	struct msm_bus_bimc_commit *sel_cd =
+		(struct msm_bus_bimc_commit *)sel_cdata;
+
+	MSM_BUS_DBG("BIMC: Update bw for ID %d, with IID: %d: %ld\n",
+		info->node_info->id, info->node_info->priv_id, add_bw);
+
+	binfo = (struct msm_bus_bimc_info *)fab_pdata->hw_data;
+	if (!info->node_info->qport) {
+		MSM_BUS_DBG("No qos ports to update!\n");
+		return;
+	}
+
+	if (info->node_info->num_mports == 0) {
+		MSM_BUS_DBG("BIMC: Skip Master BW\n");
+		goto skip_mas_bw;
+	}
+
+	bw = INTERLEAVED_BW(fab_pdata, add_bw, ports);
+	ports = INTERLEAVED_VAL(fab_pdata, ports);
+
+	for (i = 0; i < ports; i++) {
+		MSM_BUS_DBG("qport: %d\n", info->node_info->qport[i]);
+		sel_cd->mas[info->node_info->masterp[i]].bw += bw;
+		sel_cd->mas[info->node_info->masterp[i]].hw_id =
+			info->node_info->mas_hw_id;
+		qbw.bw = sel_cd->mas[info->node_info->masterp[i]].bw;
+		qbw.ws = info->node_info->ws;
+		/* Threshold low = 90% of bw */
+		qbw.thl = (90 * bw) / 100;
+		/* Threshold medium = bw */
+		qbw.thm = bw;
+		/* Threshold high = 10% more than bw */
+		qbw.thh = (110 * bw) / 100;
+		/* Check if info is a shared master.
+		 * If it is, mark it dirty
+		 * If it isn't, then set QOS Bandwidth
+		 **/
+		MSM_BUS_DBG("BIMC: Update mas_bw for ID: %d -> %ld\n",
+			info->node_info->priv_id,
+			sel_cd->mas[info->node_info->masterp[i]].bw);
+		if (info->node_info->hw_sel == MSM_BUS_RPM)
+			sel_cd->mas[info->node_info->masterp[i]].dirty = 1;
+		else
+			msm_bus_bimc_set_qos_bw(binfo,
+				info->node_info->qport[i], &qbw);
+	}
+
+skip_mas_bw:
+	ports = hop->node_info->num_sports;
+	MSM_BUS_DBG("BIMC: ID: %d, Sports: %d\n", hop->node_info->priv_id,
+		ports);
+	if (ports)
+		bw = INTERLEAVED_BW(fab_pdata, add_bw, ports);
+	else
+		return;
+
+	for (i = 0; i < ports; i++) {
+		sel_cd->slv[hop->node_info->slavep[i]].bw += bw;
+		sel_cd->slv[hop->node_info->slavep[i]].hw_id =
+			hop->node_info->slv_hw_id;
+		MSM_BUS_DBG("BIMC: Update slave_bw: ID: %d -> %ld\n",
+			hop->node_info->priv_id,
+			sel_cd->slv[hop->node_info->slavep[i]].bw);
+		MSM_BUS_DBG("BIMC: Update slave_bw: index: %d\n",
+			hop->node_info->slavep[i]);
+		/* Check if hop is a shared slave.
+		 * If it is, mark it dirty
+		 * If it isn't, then nothing to be done as the
+		 * slaves are in bypass mode.
+		 **/
+		if (hop->node_info->hw_sel == MSM_BUS_RPM) {
+			MSM_BUS_DBG("Slave dirty: %d, slavep: %d\n",
+				hop->node_info->priv_id,
+				hop->node_info->slavep[i]);
+			sel_cd->slv[hop->node_info->slavep[i]].dirty = 1;
+		}
+	}
+}
+
+static int msm_bus_bimc_commit(struct msm_bus_fabric_registration
+	*fab_pdata, void *hw_data, void **cdata)
+{
+	MSM_BUS_DBG("\nReached BIMC Commit\n");
+	return 0;
+}
+
+static int msm_bus_bimc_mas_init(struct msm_bus_bimc_info *binfo,
+	struct msm_bus_inode_info *info)
+{
+	int i;
+	struct msm_bus_bimc_qos_mode *qmode;
+	qmode = kzalloc(sizeof(struct msm_bus_bimc_qos_mode),
+		GFP_KERNEL);
+	if (!qmode) {
+		MSM_BUS_WARN("Couldn't alloc prio data for node: %d\n",
+			info->node_info->id);
+		return -ENOMEM;
+	}
+
+	switch (info->node_info->mode) {
+	case BIMC_QOS_MODE_FIXED:
+		qmode->fixed.prio_level = info->node_info->prio_lvl;
+		qmode->fixed.areq_prio_rd = info->node_info->prio_rd;
+		qmode->fixed.areq_prio_wr = info->node_info->prio_wr;
+		break;
+	default:
+		break;
+	}
+
+	info->hw_data = (void *)qmode;
+	if (!info->node_info->qport) {
+		MSM_BUS_DBG("No QoS Ports to init\n");
+		return 0;
+	}
+
+	for (i = 0; i < info->node_info->num_mports; i++) {
+		/* If in bypass mode, update priority */
+		if (info->node_info->mode != BIMC_QOS_MODE_BYPASS)
+			msm_bus_bimc_set_qos_prio(binfo, info->node_info->
+				qport[i], info->node_info->mode, qmode);
+
+		/* If in fixed mode, update bandwidth */
+		if (info->node_info->mode != BIMC_QOS_MODE_FIXED) {
+			struct msm_bus_bimc_qos_bw qbw;
+			qbw.ws = info->node_info->ws;
+			msm_bus_bimc_set_qos_bw(binfo,
+				info->node_info->qport[i], &qbw);
+		}
+
+		/* set mode */
+		msm_bus_bimc_set_qos_mode(binfo, info->node_info->qport[i],
+			info->node_info->mode);
+	}
+
+	return 0;
+}
+
+static void msm_bus_bimc_node_init(void *hw_data,
+	struct msm_bus_inode_info *info)
+{
+	struct msm_bus_bimc_info *binfo =
+		(struct msm_bus_bimc_info *)hw_data;
+
+	if (!IS_SLAVE(info->node_info->priv_id))
+		msm_bus_bimc_mas_init(binfo, info);
+}
+
+static int msm_bus_bimc_port_halt(uint32_t haltid, uint8_t mport)
+{
+	return 0;
+}
+
+static int msm_bus_bimc_port_unhalt(uint32_t haltid, uint8_t mport)
+{
+	return 0;
+}
+
+
+int msm_bus_bimc_hw_init(struct msm_bus_fabric_registration *pdata,
+	struct msm_bus_hw_algorithm *hw_algo)
+{
+	/* Set interleaving to true by default */
+	MSM_BUS_DBG("\nInitializing BIMC...\n");
+	pdata->il_flag = true;
+	hw_algo->allocate_commit_data = msm_bus_bimc_allocate_commit_data;
+	hw_algo->allocate_hw_data = msm_bus_bimc_allocate_bimc_data;
+	hw_algo->node_init = msm_bus_bimc_node_init;
+	hw_algo->free_commit_data = free_commit_data;
+	hw_algo->update_bw = msm_bus_bimc_update_bw;
+	hw_algo->commit = msm_bus_bimc_commit;
+	hw_algo->port_halt = msm_bus_bimc_port_halt;
+	hw_algo->port_unhalt = msm_bus_bimc_port_unhalt;
+	/* BIMC slaves are shared. Slave registers are set through RPM */
+	if (!pdata->ahb)
+		pdata->rpm_enabled = 1;
+	return 0;
+}
+
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.h b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.h
new file mode 100644
index 0000000..249e8bb
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.h
@@ -0,0 +1,125 @@
+/* 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_BUS_BIMC_H
+#define _ARCH_ARM_MACH_MSM_BUS_BIMC_H
+
+struct msm_bus_bimc_params {
+	uint32_t bus_id;
+	uint32_t addr_width;
+	uint32_t data_width;
+	uint32_t nmasters;
+	uint32_t nslaves;
+};
+
+struct msm_bus_bimc_commit {
+	struct msm_bus_node_hw_info *mas;
+	struct msm_bus_node_hw_info *slv;
+};
+
+struct msm_bus_bimc_info {
+	void __iomem *base;
+	uint32_t base_addr;
+	uint32_t qos_freq;
+	struct msm_bus_bimc_params params;
+	struct msm_bus_bimc_commit cdata[NUM_CTX];
+};
+
+struct msm_bus_bimc_node {
+	uint32_t conn_mask;
+	uint32_t data_width;
+	uint8_t slv_arb_mode;
+};
+
+enum msm_bus_bimc_arb_mode {
+	BIMC_ARB_MODE_RR = 0,
+	BIMC_ARB_MODE_PRIORITY_RR,
+	BIMC_ARB_MODE_TIERED_RR,
+};
+
+
+enum msm_bus_bimc_interleave {
+	BIMC_INTERLEAVE_NONE = 0,
+	BIMC_INTERLEAVE_ODD,
+	BIMC_INTERLEAVE_EVEN,
+};
+
+struct msm_bus_bimc_slave_seg {
+	bool enable;
+	uint64_t start_addr;
+	uint64_t seg_size;
+	uint8_t interleave;
+};
+
+enum msm_bus_bimc_qos_mode_type {
+	BIMC_QOS_MODE_FIXED = 0,
+	BIMC_QOS_MODE_LIMITER,
+	BIMC_QOS_MODE_BYPASS,
+	BIMC_QOS_MODE_REGULATOR,
+};
+
+struct msm_bus_bimc_qos_health {
+	bool limit_commands;
+	uint32_t areq_prio;
+	uint32_t prio_level;
+};
+
+struct msm_bus_bimc_mode_fixed {
+	uint32_t prio_level;
+	uint32_t areq_prio_rd;
+	uint32_t areq_prio_wr;
+};
+
+struct msm_bus_bimc_mode_rl {
+	uint8_t qhealthnum;
+	struct msm_bus_bimc_qos_health qhealth[4];
+};
+
+struct msm_bus_bimc_qos_mode {
+	uint8_t mode;
+	struct msm_bus_bimc_mode_fixed fixed;
+	struct msm_bus_bimc_mode_rl rl;
+};
+
+struct msm_bus_bimc_qos_bw {
+	uint64_t bw;	/* bw is in Bytes/sec */
+	uint32_t ws;	/* Window size in nano seconds*/
+	uint64_t thh;	/* Threshold high, bytes per second */
+	uint64_t thm;	/* Threshold medium, bytes per second */
+	uint64_t thl;	/* Threshold low, bytes per second */
+};
+
+struct msm_bus_bimc_clk_gate {
+	bool core_clk_gate_en;
+	bool arb_clk_gate_en;	/* For arbiter */
+	bool port_clk_gate_en;	/* For regs on BIMC core clock */
+};
+
+void msm_bus_bimc_set_slave_seg(struct msm_bus_bimc_info *binfo,
+	uint32_t slv_index, uint32_t seg_index,
+	struct msm_bus_bimc_slave_seg *bsseg);
+void msm_bus_bimc_set_slave_clk_gate(struct msm_bus_bimc_info *binfo,
+	uint32_t slv_index, struct msm_bus_bimc_clk_gate *bgate);
+void msm_bus_bimc_set_mas_clk_gate(struct msm_bus_bimc_info *binfo,
+	uint32_t mas_index, struct msm_bus_bimc_clk_gate *bgate);
+void msm_bus_bimc_arb_en(struct msm_bus_bimc_info *binfo,
+	uint32_t slv_index, bool en);
+void msm_bus_bimc_get_params(struct msm_bus_bimc_info *binfo,
+	struct msm_bus_bimc_params *params);
+void msm_bus_bimc_get_mas_params(struct msm_bus_bimc_info *binfo,
+	uint32_t mas_index, struct msm_bus_bimc_node *mparams);
+void msm_bus_bimc_get_slv_params(struct msm_bus_bimc_info *binfo,
+	uint32_t slv_index, struct msm_bus_bimc_node *sparams);
+bool msm_bus_bimc_get_arb_en(struct msm_bus_bimc_info *binfo,
+	uint32_t slv_index);
+
+#endif /*_ARCH_ARM_MACH_MSM_BUS_BIMC_H*/
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 341fda8..a9d6e4f 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -46,13 +46,22 @@
 	MSM_BUS_DBG_OP = 1,
 };
 
+enum msm_bus_hw_sel {
+	MSM_BUS_RPM = 0,
+	MSM_BUS_NOC,
+	MSM_BUS_BIMC,
+};
+
 extern struct bus_type msm_bus_type;
 
 struct msm_bus_node_info {
 	unsigned int id;
 	unsigned int priv_id;
+	unsigned int mas_hw_id;
+	unsigned int slv_hw_id;
 	int gateway;
 	int *masterp;
+	int *qport;
 	int num_mports;
 	int *slavep;
 	int num_sports;
@@ -65,6 +74,12 @@
 	unsigned int buswidth;
 	unsigned int ws;
 	unsigned int mode;
+	unsigned int perm_mode;
+	unsigned int prio_lvl;
+	unsigned int prio_rd;
+	unsigned int prio_wr;
+	unsigned int prio1;
+	unsigned int prio0;
 };
 
 struct path_node {
@@ -105,6 +120,12 @@
 	void *hw_data;
 };
 
+struct msm_bus_node_hw_info {
+	bool dirty;
+	unsigned int hw_id;
+	unsigned long bw;
+};
+
 struct msm_bus_hw_algorithm {
 	int (*allocate_commit_data)(struct msm_bus_fabric_registration
 		*fab_pdata, void **cdata, int ctx);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 8c015d1..3671916 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -594,12 +594,22 @@
 	struct msm_bus_hw_algorithm *hw_algo)
 {
 	int ret = 0;
-	ret = msm_bus_rpm_hw_init(pdata, hw_algo);
-	if (ret) {
-		MSM_BUS_ERR("RPM initialization failed\n");
-		ret = -EINVAL;
-	}
 
+	switch (pdata->hw_sel) {
+	case MSM_BUS_NOC:
+		msm_bus_noc_hw_init(pdata, hw_algo);
+		break;
+	case MSM_BUS_BIMC:
+		msm_bus_bimc_hw_init(pdata, hw_algo);
+		break;
+	default:
+		ret = msm_bus_rpm_hw_init(pdata, hw_algo);
+		if (ret) {
+			MSM_BUS_ERR("RPM initialization failed\n");
+			ret = -EINVAL;
+		}
+		break;
+	}
 	return ret;
 }
 
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
new file mode 100644
index 0000000..5179d2a
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
@@ -0,0 +1,613 @@
+/* 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) "AXI: NOC: %s(): " fmt, __func__
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <mach/msm_bus_board.h>
+#include "msm_bus_core.h"
+#include "msm_bus_noc.h"
+
+/* NOC_QOS generic */
+#define __CLZ(x) ((8 * sizeof(uint32_t)) - 1 - __fls(x))
+#define SAT_SCALE 16	/* 16 bytes minimum for saturation */
+#define BW_SCALE  256	/* 1/256 byte per cycle unit */
+#define MAX_BW_FIELD (NOC_QOS_BWn_BW_BMSK >> NOC_QOS_BWn_BW_SHFT)
+#define MAX_SAT_FIELD (NOC_QOS_SATn_SAT_BMSK >> NOC_QOS_SATn_SAT_SHFT)
+
+#define NOC_QOS_REG_BASE(b)		((b) + 0x00003000)
+
+#define NOC_QOS_ID_COREIDn_ADDR(b, n)	(NOC_QOS_REG_BASE(b) + 0x80 * (n))
+enum noc_qos_id_coreidn {
+	NOC_QOS_ID_COREIDn_RMSK			= 0xffffffff,
+	NOC_QOS_ID_COREIDn_MAXn			= 32,
+	NOC_QOS_ID_COREIDn_CORECHSUM_BMSK	= 0xffffff00,
+	NOC_QOS_ID_COREIDn_CORECHSUM_SHFT	= 0x8,
+	NOC_QOS_ID_COREIDn_CORETYPEID_BMSK	= 0xff,
+	NOC_QOS_ID_COREIDn_CORETYPEID_SHFT	= 0x0,
+};
+
+#define NOC_QOS_ID_REVISIONIDn_ADDR(b, n) \
+	(NOC_QOS_REG_BASE(b) + 0x4 + 0x80 * (n))
+enum noc_qos_id_revisionidn {
+	NOC_QOS_ID_REVISIONIDn_RMSK		= 0xffffffff,
+	NOC_QOS_ID_REVISIONIDn_MAXn		= 32,
+	NOC_QOS_ID_REVISIONIDn_FLEXNOCID_BMSK	= 0xffffff00,
+	NOC_QOS_ID_REVISIONIDn_FLEXNOCID_SHFT	= 0x8,
+	NOC_QOS_ID_REVISIONIDn_USERID_BMSK	= 0xff,
+	NOC_QOS_ID_REVISIONIDn_USERID_SHFT	= 0x0,
+};
+
+#define NOC_QOS_PRIORITYn_ADDR(b, n)	\
+	(NOC_QOS_REG_BASE(b) + 0x8 + 0x80 * (n))
+enum noc_qos_id_priorityn {
+	NOC_QOS_PRIORITYn_RMSK		= 0x0000000f,
+	NOC_QOS_PRIORITYn_MAXn		= 32,
+	NOC_QOS_PRIORITYn_P1_BMSK	= 0xc,
+	NOC_QOS_PRIORITYn_P1_SHFT	= 0x2,
+	NOC_QOS_PRIORITYn_P0_BMSK	= 0x3,
+	NOC_QOS_PRIORITYn_P0_SHFT	= 0x0,
+};
+
+#define NOC_QOS_MODEn_ADDR(b, n) \
+	(NOC_QOS_REG_BASE(b) + 0xC + 0x80 * (n))
+enum noc_qos_id_moden_rmsk {
+	NOC_QOS_MODEn_RMSK		= 0x00000003,
+	NOC_QOS_MODEn_MAXn		= 32,
+	NOC_QOS_MODEn_MODE_BMSK		= 0x3,
+	NOC_QOS_MODEn_MODE_SHFT		= 0x0,
+};
+
+#define NOC_QOS_BWn_ADDR(b, n) \
+	(NOC_QOS_REG_BASE(b) + 0x10 + 0x80 * (n))
+enum noc_qos_id_bwn {
+	NOC_QOS_BWn_RMSK		= 0x0000ffff,
+	NOC_QOS_BWn_MAXn		= 32,
+	NOC_QOS_BWn_BW_BMSK		= 0xffff,
+	NOC_QOS_BWn_BW_SHFT		= 0x0,
+};
+
+/* QOS Saturation registers */
+#define NOC_QOS_SATn_ADDR(b, n) \
+	(NOC_QOS_REG_BASE(b) + 0x14 + 0x80 * (n))
+enum noc_qos_id_saturationn {
+	NOC_QOS_SATn_RMSK		= 0x000003ff,
+	NOC_QOS_SATn_MAXn		= 32,
+	NOC_QOS_SATn_SAT_BMSK		= 0x3ff,
+	NOC_QOS_SATn_SAT_SHFT		= 0x0,
+};
+
+static int noc_div(uint64_t *a, uint32_t b)
+{
+	if ((*a > 0) && (*a < b))
+		return 1;
+	else
+		return do_div(*a, b);
+}
+
+/**
+ * Calculates bw hardware is using from register values
+ * bw returned is in bytes/sec
+ */
+static uint64_t noc_bw(uint32_t bw_field, uint32_t qos_freq)
+{
+	uint64_t res;
+	uint32_t rem, scale;
+
+	res = 2 * qos_freq * bw_field;
+	scale = BW_SCALE * 1000;
+	rem = noc_div(&res, scale);
+	MSM_BUS_DBG("NOC: Calculated bw: %llu\n", res * 1000000ULL);
+	return res * 1000000ULL;
+}
+
+static uint32_t noc_bw_ceil(long int bw_field, uint32_t qos_freq)
+{
+	uint64_t bw_temp = 2 * qos_freq * bw_field;
+	uint32_t scale = 1000 * BW_SCALE;
+	noc_div(&bw_temp, scale);
+	return bw_temp * 1000000;
+}
+#define MAX_BW(timebase) noc_bw_ceil(MAX_BW_FIELD, (timebase))
+
+/**
+ * Calculates ws hardware is using from register values
+ * ws returned is in nanoseconds
+ */
+static uint32_t noc_ws(uint64_t bw, uint32_t sat, uint32_t qos_freq)
+{
+	if (bw && qos_freq) {
+		uint32_t bwf = bw * qos_freq;
+		uint64_t scale = 1000000000000LL * BW_SCALE *
+			SAT_SCALE * sat;
+		noc_div(&scale, bwf);
+		MSM_BUS_DBG("NOC: Calculated ws: %llu\n", scale);
+		return scale;
+	}
+
+	return 0;
+}
+#define MAX_WS(bw, timebase) noc_ws((bw), MAX_SAT_FIELD, (timebase))
+
+/* Calculate bandwidth field value for requested bandwidth  */
+static uint32_t noc_bw_field(uint64_t bw, uint32_t qos_freq)
+{
+	uint32_t bw_field = 0;
+
+	if (bw) {
+		uint32_t rem;
+		uint64_t bw_capped = min_t(uint64_t, bw, MAX_BW(qos_freq));
+		uint64_t bwc = bw_capped * BW_SCALE;
+		uint64_t qf = 2 * qos_freq * 1000;
+
+		rem = noc_div(&bwc, qf);
+		bw_field = (uint32_t)min_t(uint64_t, bwc, MAX_BW_FIELD);
+	}
+
+	MSM_BUS_DBG("NOC: bw_field: %u\n", bw_field);
+	return bw_field;
+}
+
+static uint32_t noc_sat_field(uint64_t bw, uint32_t ws, uint32_t qos_freq)
+{
+	uint32_t sat_field = 0, win;
+
+	if (bw) {
+		/* Limit to max bw and scale bw to 100 KB increments */
+		uint64_t tbw, tscale;
+		uint64_t bw_scaled = min_t(uint64_t, bw, MAX_BW(qos_freq));
+		uint32_t rem = noc_div(&bw_scaled, 100000);
+
+		/**
+		 * Calculate saturation from windows size.
+		 * WS must be at least one arb period.
+		 * Saturation must not exceed max field size
+		 *
+		 * Bandwidth is in 100KB increments
+		 * Window size is in ns
+		 * qos_freq is in KHz
+		 */
+		win = max(ws, 1000000 / qos_freq);
+		tbw = bw_scaled * win * qos_freq;
+		tscale = 10000000ULL * BW_SCALE * SAT_SCALE;
+		rem = noc_div(&tbw, tscale);
+		sat_field = (uint32_t)min_t(uint64_t, tbw, MAX_SAT_FIELD);
+	}
+
+	MSM_BUS_DBG("NOC: sat_field: %d\n", sat_field);
+	return sat_field;
+}
+
+static void noc_set_qos_mode(struct msm_bus_noc_info *ninfo, uint32_t mport,
+	uint8_t mode)
+{
+	if (mode < NOC_QOS_MODE_MAX &&
+		((1 << mode) & ninfo->mas_modes[mport])) {
+		uint32_t reg_val;
+
+		reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
+			mport)) & NOC_QOS_MODEn_RMSK;
+		writel_relaxed(((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK))) |
+			(mode & NOC_QOS_MODEn_MODE_BMSK)),
+			NOC_QOS_MODEn_ADDR(ninfo->base, mport));
+	}
+	/* Ensure qos mode is set before exiting */
+	wmb();
+}
+
+static void noc_set_qos_priority(struct msm_bus_noc_info *ninfo, uint32_t mport,
+	struct msm_bus_noc_qos_priority *priority)
+{
+	uint32_t reg_val, val;
+
+	reg_val = readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base, mport))
+		& NOC_QOS_PRIORITYn_RMSK;
+	val = priority->p1 << NOC_QOS_PRIORITYn_P1_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_PRIORITYn_P1_BMSK))) |
+		(val & NOC_QOS_PRIORITYn_P1_BMSK)),
+		NOC_QOS_PRIORITYn_ADDR(ninfo->base, mport));
+
+	reg_val = readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base, mport))
+		& NOC_QOS_PRIORITYn_RMSK;
+	writel_relaxed(((reg_val & (~(NOC_QOS_PRIORITYn_P0_BMSK))) |
+		(priority->p0 & NOC_QOS_PRIORITYn_P0_BMSK)),
+		NOC_QOS_PRIORITYn_ADDR(ninfo->base, mport));
+	/* Ensure qos priority is set before exiting */
+	wmb();
+}
+
+static void msm_bus_noc_set_qos_bw(struct msm_bus_noc_info *ninfo,
+	uint32_t mport, uint8_t perm_mode, struct msm_bus_noc_qos_bw *qbw)
+{
+	uint32_t reg_val, val, mode;
+
+	if (!ninfo->qos_freq) {
+		MSM_BUS_DBG("Zero QoS Freq\n");
+		return;
+	}
+
+
+	/* If Limiter or Regulator modes are not supported, bw not available*/
+	if (perm_mode & (NOC_QOS_PERM_MODE_LIMITER |
+		NOC_QOS_PERM_MODE_REGULATOR)) {
+		uint32_t bw_val = noc_bw_field(qbw->bw, ninfo->qos_freq);
+		uint32_t sat_val = noc_sat_field(qbw->bw, qbw->ws,
+			ninfo->qos_freq);
+
+		MSM_BUS_DBG("NOC: BW: perm_mode: %d bw_val: %d, sat_val: %d\n",
+			perm_mode, bw_val, sat_val);
+		/*
+		 * If in Limiter/Regulator mode, first go to fixed mode.
+		 * Clear QoS accumulator
+		 **/
+		mode = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
+			mport)) & NOC_QOS_MODEn_MODE_BMSK;
+		if (mode == NOC_QOS_MODE_REGULATOR || mode ==
+			NOC_QOS_MODE_LIMITER) {
+			reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->
+				base, mport));
+			val = NOC_QOS_MODE_FIXED;
+			writel_relaxed((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK)))
+				| (val & NOC_QOS_MODEn_MODE_BMSK),
+				NOC_QOS_MODEn_ADDR(ninfo->base, mport));
+		}
+
+		reg_val = readl_relaxed(NOC_QOS_BWn_ADDR(ninfo->base, mport));
+		val = bw_val << NOC_QOS_BWn_BW_SHFT;
+		writel_relaxed(((reg_val & (~(NOC_QOS_BWn_BW_BMSK))) |
+			(val & NOC_QOS_BWn_BW_BMSK)),
+			NOC_QOS_BWn_ADDR(ninfo->base, mport));
+
+		MSM_BUS_DBG("NOC: BW: Wrote value: 0x%x\n", ((reg_val &
+			(~NOC_QOS_BWn_BW_BMSK)) | (val &
+			NOC_QOS_BWn_BW_BMSK)));
+
+		reg_val = readl_relaxed(NOC_QOS_SATn_ADDR(ninfo->base,
+			mport));
+		val = sat_val << NOC_QOS_SATn_SAT_SHFT;
+		writel_relaxed(((reg_val & (~(NOC_QOS_SATn_SAT_BMSK))) |
+			(val & NOC_QOS_SATn_SAT_BMSK)),
+			NOC_QOS_SATn_ADDR(ninfo->base, mport));
+
+		MSM_BUS_DBG("NOC: SAT: Wrote value: 0x%x\n", ((reg_val &
+			(~NOC_QOS_SATn_SAT_BMSK)) | (val &
+			NOC_QOS_SATn_SAT_BMSK)));
+
+		/* Set mode back to what it was initially */
+		reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
+			mport));
+		writel_relaxed((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK)))
+			| (mode & NOC_QOS_MODEn_MODE_BMSK),
+			NOC_QOS_MODEn_ADDR(ninfo->base, mport));
+		/* Ensure that all writes for bandwidth registers have
+		 * completed before returning
+		 */
+		wmb();
+	}
+}
+
+uint8_t msm_bus_noc_get_qos_mode(struct msm_bus_noc_info *ninfo,
+	uint32_t mport)
+{
+	if (NOC_QOS_MODES_ALL_PERM == ninfo->mas_modes[mport])
+		return readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
+			mport)) & NOC_QOS_MODEn_MODE_BMSK;
+	else
+		return 31 - __CLZ(ninfo->mas_modes[mport] &
+			NOC_QOS_MODES_ALL_PERM);
+}
+
+void msm_bus_noc_get_qos_priority(struct msm_bus_noc_info *ninfo,
+	uint32_t mport, struct msm_bus_noc_qos_priority *priority)
+{
+	priority->p1 = (readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base,
+		mport)) & NOC_QOS_PRIORITYn_P1_BMSK) >>
+		NOC_QOS_PRIORITYn_P1_SHFT;
+
+	priority->p0 = (readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base,
+		mport)) & NOC_QOS_PRIORITYn_P0_BMSK) >>
+		NOC_QOS_PRIORITYn_P0_SHFT;
+}
+
+void msm_bus_noc_get_qos_bw(struct msm_bus_noc_info *ninfo,
+	uint32_t mport, struct msm_bus_noc_qos_bw *qbw)
+{
+	if (ninfo->mas_modes[mport] & (NOC_QOS_PERM_MODE_LIMITER |
+		NOC_QOS_PERM_MODE_REGULATOR)) {
+		uint32_t bw_val = readl_relaxed(NOC_QOS_BWn_ADDR(ninfo->
+			base, mport)) & NOC_QOS_BWn_BW_BMSK;
+		uint32_t sat = readl_relaxed(NOC_QOS_SATn_ADDR(ninfo->
+			base, mport)) & NOC_QOS_SATn_SAT_BMSK;
+
+		qbw->bw = noc_bw(bw_val, ninfo->qos_freq);
+		qbw->ws = noc_ws(qbw->bw, sat, ninfo->qos_freq);
+	} else {
+		qbw->bw = 0;
+		qbw->ws = 0;
+	}
+}
+
+static int msm_bus_noc_mas_init(struct msm_bus_noc_info *ninfo,
+	struct msm_bus_inode_info *info)
+{
+	int i;
+	struct msm_bus_noc_qos_priority *prio;
+	prio = kzalloc(sizeof(struct msm_bus_noc_qos_priority),
+		GFP_KERNEL);
+	if (!prio) {
+		MSM_BUS_WARN("Couldn't alloc prio data for node: %d\n",
+			info->node_info->id);
+		return -ENOMEM;
+	}
+
+	prio->read_prio = info->node_info->prio_rd;
+	prio->write_prio = info->node_info->prio_wr;
+	prio->p1 = info->node_info->prio1;
+	prio->p0 = info->node_info->prio0;
+	info->hw_data = (void *)prio;
+
+	if (!info->node_info->qport) {
+		MSM_BUS_DBG("No QoS Ports to init\n");
+		return 0;
+	}
+
+	for (i = 0; i < info->node_info->num_mports; i++) {
+		if (info->node_info->mode != NOC_QOS_MODE_BYPASS)
+			noc_set_qos_priority(ninfo, info->node_info->qport[i],
+				prio);
+
+		if (info->node_info->mode != NOC_QOS_MODE_FIXED) {
+			struct msm_bus_noc_qos_bw qbw;
+			qbw.ws = info->node_info->ws;
+			qbw.bw = 0;
+			msm_bus_noc_set_qos_bw(ninfo, info->node_info->qport[i],
+				info->node_info->perm_mode, &qbw);
+		}
+
+		noc_set_qos_mode(ninfo, info->node_info->qport[i], info->
+			node_info->mode);
+	}
+
+	return 0;
+}
+
+static void msm_bus_noc_node_init(void *hw_data,
+	struct msm_bus_inode_info *info)
+{
+	struct msm_bus_noc_info *ninfo =
+		(struct msm_bus_noc_info *)hw_data;
+
+	if (!IS_SLAVE(info->node_info->priv_id))
+		msm_bus_noc_mas_init(ninfo, info);
+}
+
+static int msm_bus_noc_allocate_commit_data(struct msm_bus_fabric_registration
+	*fab_pdata, void **cdata, int ctx)
+{
+	struct msm_bus_noc_commit **cd = (struct msm_bus_noc_commit **)cdata;
+	struct msm_bus_noc_info *ninfo =
+		(struct msm_bus_noc_info *)fab_pdata->hw_data;
+
+	*cd = kzalloc(sizeof(struct msm_bus_noc_commit), GFP_KERNEL);
+	if (!*cd) {
+		MSM_BUS_DBG("Couldn't alloc mem for cdata\n");
+		return -ENOMEM;
+	}
+
+	(*cd)->mas = ninfo->cdata[ctx].mas;
+	(*cd)->slv = ninfo->cdata[ctx].slv;
+
+	return 0;
+}
+
+static void *msm_bus_noc_allocate_noc_data(struct platform_device *pdev,
+	struct msm_bus_fabric_registration *fab_pdata)
+{
+	struct resource *noc_mem;
+	struct resource *noc_io;
+	struct msm_bus_noc_info *ninfo;
+	int i;
+
+	ninfo = kzalloc(sizeof(struct msm_bus_noc_info), GFP_KERNEL);
+	if (!ninfo) {
+		MSM_BUS_DBG("Couldn't alloc mem for noc info\n");
+		return NULL;
+	}
+
+	ninfo->nmasters = fab_pdata->nmasters;
+	ninfo->nqos_masters = fab_pdata->nmasters;
+	ninfo->nslaves = fab_pdata->nslaves;
+	ninfo->qos_freq = fab_pdata->qos_freq;
+	ninfo->mas_modes = kzalloc(sizeof(uint32_t) * fab_pdata->nmasters,
+		GFP_KERNEL);
+	if (!ninfo->mas_modes) {
+		MSM_BUS_DBG("Couldn't alloc mem for noc master-modes\n");
+		return NULL;
+	}
+
+	for (i = 0; i < NUM_CTX; i++) {
+		ninfo->cdata[i].mas = kzalloc(sizeof(struct
+			msm_bus_node_hw_info) * fab_pdata->nmasters * 2,
+			GFP_KERNEL);
+		if (!ninfo->cdata[i].mas) {
+			MSM_BUS_DBG("Couldn't alloc mem for noc master-bw\n");
+			kfree(ninfo->mas_modes);
+			kfree(ninfo);
+			return NULL;
+		}
+
+		ninfo->cdata[i].slv = kzalloc(sizeof(struct
+			msm_bus_node_hw_info) * fab_pdata->nslaves * 2,
+			GFP_KERNEL);
+		if (!ninfo->cdata[i].slv) {
+			MSM_BUS_DBG("Couldn't alloc mem for noc master-bw\n");
+			kfree(ninfo->cdata[i].mas);
+			goto err;
+		}
+	}
+
+	/* If it's a virtual fabric, don't get memory info */
+	if (fab_pdata->virt)
+		goto skip_mem;
+
+	noc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!noc_mem && !fab_pdata->virt) {
+		MSM_BUS_ERR("Cannot get NoC Base address\n");
+		goto err;
+	}
+
+	noc_io = request_mem_region(noc_mem->start,
+			resource_size(noc_mem), pdev->name);
+	if (!noc_io) {
+		MSM_BUS_ERR("NoC memory unavailable\n");
+		goto err;
+	}
+
+	ninfo->base = ioremap(noc_mem->start, resource_size(noc_mem));
+	if (!ninfo->base) {
+		MSM_BUS_ERR("IOremap failed for NoC!\n");
+		release_mem_region(noc_mem->start, resource_size(noc_mem));
+		goto err;
+	}
+
+skip_mem:
+	fab_pdata->hw_data = (void *)ninfo;
+	return (void *)ninfo;
+
+err:
+	kfree(ninfo->mas_modes);
+	kfree(ninfo);
+	return NULL;
+}
+
+static void free_commit_data(void *cdata)
+{
+	struct msm_bus_noc_commit *cd = (struct msm_bus_noc_commit *)cdata;
+
+	kfree(cd->mas);
+	kfree(cd->slv);
+	kfree(cd);
+}
+
+static void msm_bus_noc_update_bw(struct msm_bus_inode_info *hop,
+	struct msm_bus_inode_info *info,
+	struct msm_bus_fabric_registration *fab_pdata,
+	void *sel_cdata, int *master_tiers,
+	long int add_bw)
+{
+	struct msm_bus_noc_info *ninfo;
+	struct msm_bus_noc_qos_bw qos_bw;
+	int i, ports;
+	long int bw;
+	struct msm_bus_noc_commit *sel_cd =
+		(struct msm_bus_noc_commit *)sel_cdata;
+
+	ninfo = (struct msm_bus_noc_info *)fab_pdata->hw_data;
+	if (!ninfo->qos_freq) {
+		MSM_BUS_DBG("NOC: No qos frequency to update bw\n");
+		return;
+	}
+
+	if (!info->node_info->qport) {
+		MSM_BUS_DBG("NOC: No QoS Ports to update bw\n");
+		return;
+	}
+
+	ports = info->node_info->num_mports;
+	qos_bw.ws = info->node_info->ws;
+
+	bw = INTERLEAVED_BW(fab_pdata, add_bw, ports);
+
+	MSM_BUS_DBG("NOC: Update bw for: %d: %ld\n",
+		info->node_info->priv_id, add_bw);
+	for (i = 0; i < ports; i++) {
+		sel_cd->mas[info->node_info->masterp[i]].bw += bw;
+		sel_cd->mas[info->node_info->masterp[i]].hw_id =
+			info->node_info->mas_hw_id;
+		qos_bw.bw = sel_cd->mas[info->node_info->masterp[i]].bw;
+		MSM_BUS_DBG("NOC: Update mas_bw for ID: %d, BW: %ld, QoS: %u\n",
+			info->node_info->priv_id,
+			sel_cd->mas[info->node_info->masterp[i]].bw,
+			qos_bw.ws);
+		/* Check if info is a shared master.
+		 * If it is, mark it dirty
+		 * If it isn't, then set QOS Bandwidth
+		 **/
+		if (info->node_info->hw_sel == MSM_BUS_RPM)
+			sel_cd->mas[info->node_info->masterp[i]].dirty = 1;
+		else
+			msm_bus_noc_set_qos_bw(ninfo,
+				info->node_info->qport[i],
+				info->node_info->perm_mode, &qos_bw);
+	}
+
+	ports = hop->node_info->num_sports;
+	if (ports == 0) {
+		MSM_BUS_ERR("\nDIVIDE BY 0, hop: %d\n",
+			hop->node_info->priv_id);
+		return;
+	}
+	bw = INTERLEAVED_BW(fab_pdata, add_bw, ports);
+	for (i = 0; i < ports; i++) {
+		sel_cd->slv[hop->node_info->slavep[i]].bw += bw;
+		sel_cd->slv[hop->node_info->slavep[i]].hw_id =
+			hop->node_info->slv_hw_id;
+		MSM_BUS_DBG("NOC: Update slave_bw for ID: %d -> %ld\n",
+			hop->node_info->priv_id,
+			sel_cd->slv[hop->node_info->slavep[i]].bw);
+		MSM_BUS_DBG("NOC: Update slave_bw for hw_id: %d, index: %d\n",
+			hop->node_info->slv_hw_id, hop->node_info->slavep[i]);
+		/* Check if hop is a shared slave.
+		 * If it is, mark it dirty
+		 * If it isn't, then nothing to be done as the
+		 * slaves are in bypass mode.
+		 **/
+		if (hop->node_info->hw_sel == MSM_BUS_RPM)
+			sel_cd->slv[hop->node_info->slavep[i]].dirty = 1;
+	}
+}
+
+static int msm_bus_noc_commit(struct msm_bus_fabric_registration
+	*fab_pdata, void *hw_data, void **cdata)
+{
+	MSM_BUS_DBG("\nReached NOC Commit\n");
+	return 0;
+}
+
+static int msm_bus_noc_port_halt(uint32_t haltid, uint8_t mport)
+{
+	return 0;
+}
+
+static int msm_bus_noc_port_unhalt(uint32_t haltid, uint8_t mport)
+{
+	return 0;
+}
+
+int msm_bus_noc_hw_init(struct msm_bus_fabric_registration *pdata,
+	struct msm_bus_hw_algorithm *hw_algo)
+{
+	/* Set interleaving to true by default */
+	pdata->il_flag = true;
+	hw_algo->allocate_commit_data = msm_bus_noc_allocate_commit_data;
+	hw_algo->allocate_hw_data = msm_bus_noc_allocate_noc_data;
+	hw_algo->node_init = msm_bus_noc_node_init;
+	hw_algo->free_commit_data = free_commit_data;
+	hw_algo->update_bw = msm_bus_noc_update_bw;
+	hw_algo->commit = msm_bus_noc_commit;
+	hw_algo->port_halt = msm_bus_noc_port_halt;
+	hw_algo->port_unhalt = msm_bus_noc_port_unhalt;
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.h b/arch/arm/mach-msm/msm_bus/msm_bus_noc.h
new file mode 100644
index 0000000..407d3ec
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.h
@@ -0,0 +1,73 @@
+/* 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_BUS_BIMC_H
+#define _ARCH_ARM_MACH_MSM_BUS_BIMC_H
+
+enum msm_bus_noc_qos_mode_type {
+	NOC_QOS_MODE_FIXED = 0,
+	NOC_QOS_MODE_LIMITER,
+	NOC_QOS_MODE_BYPASS,
+	NOC_QOS_MODE_REGULATOR,
+	NOC_QOS_MODE_MAX,
+};
+
+enum msm_bus_noc_qos_mode_perm {
+	NOC_QOS_PERM_MODE_FIXED = (1 << NOC_QOS_MODE_FIXED),
+	NOC_QOS_PERM_MODE_LIMITER = (1 << NOC_QOS_MODE_LIMITER),
+	NOC_QOS_PERM_MODE_BYPASS = (1 << NOC_QOS_MODE_BYPASS),
+	NOC_QOS_PERM_MODE_REGULATOR = (1 << NOC_QOS_MODE_REGULATOR),
+};
+
+#define NOC_QOS_MODES_ALL_PERM (NOC_QOS_PERM_MODE_FIXED | \
+	NOC_QOS_PERM_MODE_LIMITER | NOC_QOS_PERM_MODE_BYPASS | \
+	NOC_QOS_PERM_MODE_REGULATOR)
+
+struct msm_bus_noc_commit {
+	struct msm_bus_node_hw_info *mas;
+	struct msm_bus_node_hw_info *slv;
+};
+
+struct msm_bus_noc_info {
+	void __iomem *base;
+	uint32_t base_addr;
+	uint32_t nmasters;
+	uint32_t nqos_masters;
+	uint32_t nslaves;
+	uint32_t qos_freq; /* QOS Clock in KHz */
+	uint32_t *mas_modes;
+	struct msm_bus_noc_commit cdata[NUM_CTX];
+};
+
+struct msm_bus_noc_qos_priority {
+	uint32_t high_prio;
+	uint32_t low_prio;
+	uint32_t read_prio;
+	uint32_t write_prio;
+	uint32_t p1;
+	uint32_t p0;
+};
+
+struct msm_bus_noc_qos_bw {
+	uint64_t bw; /* Bandwidth in bytes per second */
+	uint32_t ws; /* Window size in nano seconds */
+};
+
+void msm_bus_noc_init(struct msm_bus_noc_info *ninfo);
+uint8_t msm_bus_noc_get_qos_mode(struct msm_bus_noc_info *ninfo,
+	uint32_t mport);
+void msm_bus_noc_get_qos_priority(struct msm_bus_noc_info *ninfo,
+	uint32_t mport, struct msm_bus_noc_qos_priority *qprio);
+void msm_bus_noc_get_qos_bw(struct msm_bus_noc_info *ninfo,
+	uint32_t mport, struct msm_bus_noc_qos_bw *qbw);
+
+#endif /*_ARCH_ARM_MACH_MSM_BUS_NOC_H */
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index ddfc906..43c7fc8 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -23,6 +23,15 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
+/* This code is to temporarily work around the default state of OCMEM
+   regions in Virtio. These registers will be read from DT in a subsequent
+   patch which initializes the regions to appropriate default state.
+*/
+
+#define OCMEM_REGION_CTL_BASE 0xFDD0003C
+#define OCMEM_REGION_CTL_SIZE 0xC
+#define REGION_ENABLE 0x00003333
+
 struct ocmem_partition {
 	const char *name;
 	int id;
@@ -97,6 +106,25 @@
 	return -EINVAL;
 }
 
+inline unsigned long phys_to_offset(unsigned long addr)
+{
+	if (!ocmem_pdata)
+		return 0;
+	if (addr < ocmem_pdata->base ||
+		addr > (ocmem_pdata->base + ocmem_pdata->size))
+		return 0;
+	return addr - ocmem_pdata->base;
+}
+
+inline unsigned long offset_to_phys(unsigned long offset)
+{
+	if (!ocmem_pdata)
+		return 0;
+	if (offset > ocmem_pdata->size)
+		return 0;
+	return offset + ocmem_pdata->base;
+}
+
 static struct ocmem_plat_data *parse_static_config(struct platform_device *pdev)
 {
 	struct ocmem_plat_data *pdata = NULL;
@@ -252,6 +280,7 @@
 static int __devinit msm_ocmem_probe(struct platform_device *pdev)
 {
 	struct device   *dev = &pdev->dev;
+	void *ocmem_region_vbase = NULL;
 
 	if (!pdev->dev.of_node->child) {
 		dev_info(dev, "Missing Configuration in Device Tree\n");
@@ -276,6 +305,17 @@
 	if (ocmem_notifier_init())
 		return -EBUSY;
 
+	if (ocmem_sched_init())
+		return -EBUSY;
+
+	ocmem_region_vbase = devm_ioremap_nocache(dev, OCMEM_REGION_CTL_BASE,
+							OCMEM_REGION_CTL_SIZE);
+	if (!ocmem_region_vbase)
+		return -EBUSY;
+	/* Enable all the 3 regions until we have support for power features */
+	writel_relaxed(REGION_ENABLE, ocmem_region_vbase);
+	writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 4);
+	writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 8);
 	dev_info(dev, "initialized successfully\n");
 	return 0;
 }
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
new file mode 100644
index 0000000..bed13de
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -0,0 +1,327 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <mach/ocmem_priv.h>
+
+static inline int check_id(int id)
+{
+	return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
+}
+
+static struct ocmem_handle *generate_handle(void)
+{
+	struct ocmem_handle *handle = NULL;
+
+	handle = kzalloc(sizeof(struct ocmem_handle), GFP_KERNEL);
+	if (!handle) {
+		pr_err("ocmem: Unable to generate buffer handle\n");
+		return NULL;
+	}
+	mutex_init(&handle->handle_mutex);
+	return handle;
+}
+
+static int free_handle(struct ocmem_handle *handle)
+{
+	if (!handle)
+		return -EINVAL;
+
+	mutex_destroy(&handle->handle_mutex);
+	kfree(handle);
+	handle = NULL;
+	return 0;
+}
+
+static int __ocmem_free(int id, struct ocmem_buf *buf)
+{
+	int ret = 0;
+	struct ocmem_handle *handle = buffer_to_handle(buf);
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_mutex);
+	ret = process_free(id, handle);
+	mutex_unlock(&handle->handle_mutex);
+
+	if (ret)
+		return -EINVAL;
+
+	free_handle(handle);
+	return 0;
+}
+
+static struct ocmem_buf *__ocmem_allocate_range(int id, unsigned long min,
+		unsigned long max, unsigned long step, bool block, bool wait)
+{
+	struct ocmem_handle *handle = NULL;
+	int ret = 0;
+
+	handle = generate_handle();
+	if (!handle) {
+		pr_err("ocmem: Unable to generate handle\n");
+		return NULL;
+	}
+
+	mutex_lock(&handle->handle_mutex);
+	ret = process_allocate(id, handle, min, max, step, block, wait);
+	mutex_unlock(&handle->handle_mutex);
+	if (ret) {
+		pr_err("ocmem allocation failed\n");
+		free_handle(handle);
+		return NULL;
+	} else
+		return handle_to_buffer(handle);
+}
+
+struct ocmem_buf *ocmem_allocate(int client_id, unsigned long size)
+{
+	bool can_block = false;
+	bool can_wait = true;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return NULL;
+	}
+
+	if (size < OCMEM_MIN_ALLOC) {
+		pr_err("ocmem: requested size %lx must be at least %x\n",
+				size, OCMEM_MIN_ALLOC);
+		return NULL;
+	}
+
+	if (!IS_ALIGNED(size, OCMEM_MIN_ALIGN)) {
+		pr_err("ocmem: Invalid alignment, size must be %x aligned\n",
+				OCMEM_MIN_ALIGN);
+		return NULL;
+	}
+
+	return __ocmem_allocate_range(client_id, size, size,
+					size, can_block, can_wait);
+}
+
+struct ocmem_buf *ocmem_allocate_nowait(int client_id, unsigned long size)
+{
+	bool can_block = false;
+	bool can_wait = false;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return NULL;
+	}
+
+	if (size < OCMEM_MIN_ALLOC) {
+		pr_err("ocmem: requested size %lx must be at least %x\n",
+				size, OCMEM_MIN_ALLOC);
+		return NULL;
+	}
+
+	if (!IS_ALIGNED(size, OCMEM_MIN_ALIGN)) {
+		pr_err("ocmem: Invalid alignment, size must be %x aligned\n",
+				OCMEM_MIN_ALIGN);
+		return NULL;
+	}
+	return __ocmem_allocate_range(client_id, size, size,
+					size, can_block, can_wait);
+}
+
+struct ocmem_buf *ocmem_allocate_range(int client_id, unsigned long min,
+		unsigned long goal, unsigned long step)
+{
+	bool can_block = true;
+	bool can_wait = false;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return NULL;
+	}
+
+	/* Asynchronous API requires notifier registration */
+	if (!check_notifier(client_id)) {
+		pr_err("ocmem: No notifier registered for client %d\n",
+				client_id);
+		return NULL;
+	}
+
+	if (min < OCMEM_MIN_ALLOC) {
+		pr_err("ocmem: requested min size %lx must be at least %x\n",
+				min, OCMEM_MIN_ALLOC);
+		return NULL;
+	}
+
+	if (!IS_ALIGNED(min | goal | step, OCMEM_MIN_ALIGN)) {
+		pr_err("ocmem: Invalid alignment, args must be %x aligned\n",
+				OCMEM_MIN_ALIGN);
+		return NULL;
+	}
+
+	return __ocmem_allocate_range(client_id, min, goal,
+				step, can_block, can_wait);
+}
+
+struct ocmem_buf *ocmem_allocate_nb(int client_id, unsigned long size)
+{
+	bool can_block = true;
+	bool can_wait = false;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return NULL;
+	}
+
+	/* Asynchronous API requires notifier registration */
+	if (!check_notifier(client_id)) {
+		pr_err("ocmem: No notifier registered for client %d\n",
+				client_id);
+		return NULL;
+	}
+
+	if (size < OCMEM_MIN_ALLOC) {
+		pr_err("ocmem: requested size %lx must be at least %x\n",
+				size, OCMEM_MIN_ALLOC);
+		return NULL;
+	}
+
+	if (!IS_ALIGNED(size, OCMEM_MIN_ALIGN)) {
+		pr_err("ocmem: Invalid alignment, args must be %x aligned\n",
+				OCMEM_MIN_ALIGN);
+		return NULL;
+	}
+
+	return __ocmem_allocate_range(client_id, 0, size, size,
+						can_block, can_wait);
+
+}
+
+int ocmem_free(int client_id, struct ocmem_buf *buffer)
+{
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		pr_err("ocmem: Invalid buffer\n");
+		return -EINVAL;
+	}
+
+	return __ocmem_free(client_id, buffer);
+}
+
+int pre_validate_chunk_list(struct ocmem_map_list *list)
+{
+	int i = 0;
+	struct ocmem_chunk *chunks;
+
+	if (!list)
+		return -EINVAL;
+
+	if (list->num_chunks > OCMEM_MAX_CHUNKS || list->num_chunks == 0)
+		return -EINVAL;
+
+	chunks = list->chunks;
+
+	if (!chunks)
+		return -EINVAL;
+
+	for (i = 0; i < list->num_chunks; i++) {
+		if (!chunks[i].ddr_paddr ||
+			chunks[i].size < MIN_CHUNK_SIZE)
+			return -EINVAL;
+	}
+	return 0;
+}
+
+int ocmem_map(int client_id, struct ocmem_buf *buffer,
+			struct ocmem_map_list *list)
+{
+	int ret = 0;
+	struct ocmem_handle *handle = NULL;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return -EINVAL;
+	}
+
+	/* Asynchronous API requires notifier registration */
+	if (!check_notifier(client_id)) {
+		pr_err("ocmem: No notifier registered for client %d\n",
+				client_id);
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		pr_err("ocmem: Invalid buffer\n");
+		return -EINVAL;
+	}
+
+	if (!pre_validate_chunk_list(list))
+		return -EINVAL;
+
+	handle = buffer_to_handle(buffer);
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_mutex);
+	ret = process_xfer(client_id, handle, list, TO_OCMEM);
+	mutex_unlock(&handle->handle_mutex);
+	return ret;
+}
+
+int ocmem_unmap(int client_id, struct ocmem_buf *buffer,
+			struct ocmem_map_list *list)
+{
+
+	int ret = 0;
+	struct ocmem_handle *handle = NULL;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return -EINVAL;
+	}
+
+	/* Asynchronous API requires notifier registration */
+	if (!check_notifier(client_id)) {
+		pr_err("ocmem: No notifier registered for client %d\n",
+				client_id);
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		pr_err("ocmem: Invalid buffer\n");
+		return -EINVAL;
+	}
+
+	if (!pre_validate_chunk_list(list))
+		return -EINVAL;
+
+	handle = buffer_to_handle(buffer);
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_mutex);
+	ret = process_xfer(client_id, handle, list, TO_DDR);
+	mutex_unlock(&handle->handle_mutex);
+	return ret;
+}
+
+unsigned long get_max_quota(int client_id)
+{
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return 0x0;
+	}
+	return process_quota(client_id);
+}
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
new file mode 100644
index 0000000..10a267c
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -0,0 +1,1255 @@
+/* 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/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/rbtree.h>
+#include <linux/idr.h>
+#include <linux/genalloc.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <mach/ocmem_priv.h>
+
+enum request_states {
+	R_FREE = 0x0,	/* request is not allocated */
+	R_PENDING,	/* request has a pending operation */
+	R_ALLOCATED,	/* request has been allocated */
+	R_MUST_GROW,	/* request must grow as a part of pending operation */
+	R_MUST_SHRINK,	/* request must shrink as a part of pending operation */
+	R_MUST_MAP,	/* request must be mapped before being used */
+	R_MUST_UNMAP,	/* request must be unmapped when not being used */
+	R_MAPPED,	/* request is mapped and actively used by client */
+	R_UNMAPPED,	/* request is not mapped, so it's not in active use */
+	R_EVICTED,	/* request is evicted and must be restored */
+};
+
+#define SET_STATE(x, val) (set_bit((val), &(x)->state))
+#define CLEAR_STATE(x, val) (clear_bit((val), &(x)->state))
+#define TEST_STATE(x, val) (test_bit((val), &(x)->state))
+
+enum op_res {
+	OP_COMPLETE = 0x0,
+	OP_RESCHED,
+	OP_PARTIAL,
+	OP_FAIL = ~0x0,
+};
+
+/* Represents various client priorities */
+/* Note: More than one client can share a priority level */
+enum client_prio {
+	MIN_PRIO = 0x0,
+	NO_PRIO = MIN_PRIO,
+	PRIO_SENSORS = 0x1,
+	PRIO_BLAST = 0x1,
+	PRIO_LP_AUDIO = 0x1,
+	PRIO_HP_AUDIO = 0x2,
+	PRIO_VOICE = 0x3,
+	PRIO_GFX_GROWTH = 0x4,
+	PRIO_VIDEO = 0x5,
+	PRIO_GFX = 0x6,
+	PRIO_OCMEM = 0x7,
+	MAX_OCMEM_PRIO = PRIO_OCMEM + 1,
+};
+
+static struct list_head sched_queue[MAX_OCMEM_PRIO];
+static struct mutex sched_queue_mutex;
+
+/* The duration in msecs before a pending operation is scheduled
+ * This allows an idle window between use case boundaries where various
+ * hardware state changes can occur. The value will be tweaked on actual
+ * hardware.
+*/
+#define SCHED_DELAY 10
+
+/* OCMEM Operational modes */
+enum ocmem_client_modes {
+	OCMEM_PERFORMANCE = 1,
+	OCMEM_PASSIVE,
+	OCMEM_LOW_POWER,
+	OCMEM_MODE_MAX = OCMEM_LOW_POWER
+};
+
+/* OCMEM Addressing modes */
+enum ocmem_interconnects {
+	OCMEM_BLOCKED = 0,
+	OCMEM_PORT = 1,
+	OCMEM_OCMEMNOC = 2,
+	OCMEM_SYSNOC = 3,
+};
+
+/**
+ * Primary OCMEM Arbitration Table
+ **/
+struct ocmem_table {
+	int client_id;
+	int priority;
+	int mode;
+	int hw_interconnect;
+} ocmem_client_table[OCMEM_CLIENT_MAX] = {
+	{OCMEM_GRAPHICS, PRIO_GFX, OCMEM_PERFORMANCE, OCMEM_PORT},
+	{OCMEM_VIDEO, PRIO_VIDEO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
+	{OCMEM_CAMERA, NO_PRIO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
+	{OCMEM_HP_AUDIO, PRIO_HP_AUDIO, OCMEM_PASSIVE, OCMEM_BLOCKED},
+	{OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED},
+	{OCMEM_LP_AUDIO, PRIO_LP_AUDIO, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+	{OCMEM_SENSORS, PRIO_SENSORS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+	{OCMEM_BLAST, PRIO_BLAST, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+};
+
+static struct rb_root sched_tree;
+static struct mutex sched_mutex;
+
+/* A region represents a continuous interval in OCMEM address space */
+struct ocmem_region {
+	/* Chain in Interval Tree */
+	struct rb_node region_rb;
+	/* Hash map of requests */
+	struct idr region_idr;
+	unsigned long r_start;
+	unsigned long r_end;
+	unsigned long r_sz;
+	/* Highest priority of all requests served by this region */
+	int max_prio;
+};
+
+/* Is OCMEM tightly coupled to the client ?*/
+static inline int is_tcm(int id)
+{
+	if (ocmem_client_table[id].hw_interconnect == OCMEM_PORT ||
+		ocmem_client_table[id].hw_interconnect == OCMEM_OCMEMNOC)
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_blocked(int id)
+{
+	return ocmem_client_table[id].hw_interconnect == OCMEM_BLOCKED ? 1 : 0;
+}
+
+/* Returns the address that can be used by a device core to access OCMEM */
+static unsigned long device_address(int id, unsigned long addr)
+{
+	int hw_interconnect = ocmem_client_table[id].hw_interconnect;
+	unsigned long ret_addr = 0x0;
+
+	switch (hw_interconnect) {
+	case OCMEM_PORT:
+		ret_addr = phys_to_offset(addr);
+		break;
+	case OCMEM_OCMEMNOC:
+	case OCMEM_SYSNOC:
+		ret_addr = addr;
+		break;
+	case OCMEM_BLOCKED:
+		ret_addr = 0x0;
+		break;
+	}
+	return ret_addr;
+}
+
+/* Returns the address as viewed by the core */
+static unsigned long core_address(int id, unsigned long addr)
+{
+	int hw_interconnect = ocmem_client_table[id].hw_interconnect;
+	unsigned long ret_addr = 0x0;
+
+	switch (hw_interconnect) {
+	case OCMEM_PORT:
+		ret_addr = offset_to_phys(addr);
+		break;
+	case OCMEM_OCMEMNOC:
+	case OCMEM_SYSNOC:
+		ret_addr = addr;
+		break;
+	case OCMEM_BLOCKED:
+		ret_addr = 0x0;
+		break;
+	}
+	return ret_addr;
+}
+
+static int insert_region(struct ocmem_region *region)
+{
+
+	struct rb_root *root = &sched_tree;
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	struct ocmem_region *tmp = NULL;
+	unsigned long addr = region->r_start;
+
+	while (*p) {
+		parent = *p;
+		tmp = rb_entry(parent, struct ocmem_region, region_rb);
+
+		if (tmp->r_end > addr) {
+			if (tmp->r_start <= addr)
+				break;
+			p =  &(*p)->rb_left;
+		} else if (tmp->r_end <= addr)
+			p = &(*p)->rb_right;
+	}
+	rb_link_node(&region->region_rb, parent, p);
+	rb_insert_color(&region->region_rb, root);
+	return 0;
+}
+
+static int remove_region(struct ocmem_region *region)
+{
+	struct rb_root *root = &sched_tree;
+	rb_erase(&region->region_rb, root);
+	return 0;
+}
+
+static struct ocmem_req *ocmem_create_req(void)
+{
+	struct ocmem_req *p = NULL;
+
+	p =  kzalloc(sizeof(struct ocmem_req), GFP_KERNEL);
+	if (!p)
+		return NULL;
+
+	INIT_LIST_HEAD(&p->zone_list);
+	INIT_LIST_HEAD(&p->sched_list);
+	init_rwsem(&p->rw_sem);
+	SET_STATE(p, R_FREE);
+	return p;
+}
+
+static int ocmem_destroy_req(struct ocmem_req *req)
+{
+	kfree(req);
+	return 0;
+}
+
+static struct ocmem_region *create_region(void)
+{
+	struct ocmem_region *p = NULL;
+
+	p =  kzalloc(sizeof(struct ocmem_region), GFP_KERNEL);
+	if (!p)
+		return NULL;
+	idr_init(&p->region_idr);
+	p->r_start = p->r_end = p->r_sz = 0x0;
+	p->max_prio = NO_PRIO;
+	return p;
+}
+
+static int destroy_region(struct ocmem_region *region)
+{
+	kfree(region);
+	return 0;
+}
+
+static int attach_req(struct ocmem_region *region, struct ocmem_req *req)
+{
+	int ret, id;
+
+	while (1) {
+		if (idr_pre_get(&region->region_idr, GFP_KERNEL) == 0)
+			return -ENOMEM;
+
+		ret = idr_get_new_above(&region->region_idr, req, 1, &id);
+
+		if (ret != -EAGAIN)
+			break;
+	}
+
+	if (!ret) {
+		req->req_id = id;
+		pr_debug("ocmem: request %p(id:%d) attached to region %p\n",
+				req, id, region);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int detach_req(struct ocmem_region *region, struct ocmem_req *req)
+{
+	idr_remove(&region->region_idr, req->req_id);
+	return 0;
+}
+
+static int populate_region(struct ocmem_region *region, struct ocmem_req *req)
+{
+	region->r_start = req->req_start;
+	region->r_end = req->req_end;
+	region->r_sz =  req->req_end - req->req_start + 1;
+	return 0;
+}
+
+static int region_req_count(int id, void *ptr, void *data)
+{
+	int *count = data;
+	*count = *count + 1;
+	return 0;
+}
+
+static int req_count(struct ocmem_region *region)
+{
+	int count = 0;
+	idr_for_each(&region->region_idr, region_req_count, &count);
+	return count;
+}
+
+static int compute_max_prio(int id, void *ptr, void *data)
+{
+	int *max = data;
+	struct ocmem_req *req = ptr;
+
+	if (req->prio > *max)
+		*max = req->prio;
+	return 0;
+}
+
+static int update_region_prio(struct ocmem_region *region)
+{
+	int max_prio;
+	if (req_count(region) != 0) {
+		idr_for_each(&region->region_idr, compute_max_prio, &max_prio);
+		region->max_prio = max_prio;
+	} else {
+		region->max_prio = NO_PRIO;
+	}
+	pr_debug("ocmem: Updating prio of region %p as %d\n",
+			region, max_prio);
+
+	return 0;
+}
+
+static struct ocmem_region *find_region(unsigned long addr)
+{
+	struct ocmem_region *region = NULL;
+	struct rb_node *rb_node = NULL;
+
+	rb_node = sched_tree.rb_node;
+
+	while (rb_node) {
+		struct ocmem_region *tmp_region = NULL;
+		tmp_region = rb_entry(rb_node, struct ocmem_region, region_rb);
+
+		if (tmp_region->r_end > addr) {
+			region = tmp_region;
+			if (tmp_region->r_start <= addr)
+				break;
+			rb_node = rb_node->rb_left;
+		} else {
+			rb_node = rb_node->rb_right;
+		}
+	}
+	return region;
+}
+
+static struct ocmem_region *find_region_intersection(unsigned long start,
+					unsigned long end)
+{
+
+	struct ocmem_region *region = NULL;
+	region = find_region(start);
+	if (region && end <= region->r_start)
+		region = NULL;
+	return region;
+}
+
+static struct ocmem_region *find_region_match(unsigned long start,
+					unsigned long end)
+{
+
+	struct ocmem_region *region = NULL;
+	region = find_region(start);
+	if (region && start == region->r_start && end == region->r_end)
+		return region;
+	return NULL;
+}
+
+static struct ocmem_req *find_req_match(int owner, struct ocmem_region *region)
+{
+	struct ocmem_req *req = NULL;
+
+	if (!region)
+		return NULL;
+
+	req = idr_find(&region->region_idr, owner);
+
+	return req;
+}
+
+/* Must be called with req->sem held */
+static inline int is_mapped(struct ocmem_req *req)
+{
+	return TEST_STATE(req, R_MAPPED);
+}
+
+/* Must be called with sched_mutex held */
+static int __sched_unmap(struct ocmem_req *req)
+{
+	struct ocmem_req *matched_req = NULL;
+	struct ocmem_region *matched_region = NULL;
+
+	matched_region = find_region_match(req->req_start, req->req_end);
+	matched_req = find_req_match(req->req_id, matched_region);
+
+	if (!matched_region || !matched_req) {
+		pr_err("Could not find backing region for req");
+		goto invalid_op_error;
+	}
+
+	if (matched_req != req) {
+		pr_err("Request does not match backing req");
+		goto invalid_op_error;
+	}
+
+	if (!is_mapped(req)) {
+		pr_err("Request is not currently mapped");
+		goto invalid_op_error;
+	}
+
+	/* Update the request state */
+	CLEAR_STATE(req, R_MAPPED);
+	SET_STATE(req, R_MUST_MAP);
+
+	return OP_COMPLETE;
+
+invalid_op_error:
+	return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
+static int __sched_map(struct ocmem_req *req)
+{
+	struct ocmem_req *matched_req = NULL;
+	struct ocmem_region *matched_region = NULL;
+
+	matched_region = find_region_match(req->req_start, req->req_end);
+	matched_req = find_req_match(req->req_id, matched_region);
+
+	if (!matched_region || !matched_req) {
+		pr_err("Could not find backing region for req");
+		goto invalid_op_error;
+	}
+
+	if (matched_req != req) {
+		pr_err("Request does not match backing req");
+		goto invalid_op_error;
+	}
+
+	/* Update the request state */
+	CLEAR_STATE(req, R_MUST_MAP);
+	SET_STATE(req, R_MAPPED);
+
+	return OP_COMPLETE;
+
+invalid_op_error:
+	return OP_FAIL;
+}
+
+static int do_map(struct ocmem_req *req)
+{
+	int rc = 0;
+
+	mutex_lock(&sched_mutex);
+	rc = __sched_map(req);
+	mutex_unlock(&sched_mutex);
+
+	if (rc == OP_FAIL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int do_unmap(struct ocmem_req *req)
+{
+	int rc = 0;
+
+	mutex_lock(&sched_mutex);
+	rc = __sched_unmap(req);
+	mutex_unlock(&sched_mutex);
+
+	if (rc == OP_FAIL)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* process map is a wrapper where power control will be added later */
+static int process_map(struct ocmem_req *req, unsigned long start,
+				unsigned long end)
+{
+	return do_map(req);
+}
+
+/* process unmap is a wrapper where power control will be added later */
+static int process_unmap(struct ocmem_req *req, unsigned long start,
+				unsigned long end)
+{
+	return do_unmap(req);
+}
+
+static int __sched_grow(struct ocmem_req *req, bool can_block)
+{
+	unsigned long min = req->req_min;
+	unsigned long max = req->req_max;
+	unsigned long step = req->req_step;
+	int owner = req->owner;
+	unsigned long curr_sz = 0;
+	unsigned long growth_sz = 0;
+	unsigned long curr_start = 0;
+	enum client_prio prio = req->prio;
+	unsigned long alloc_addr = 0x0;
+	bool retry;
+	struct ocmem_region *spanned_r = NULL;
+	struct ocmem_region *overlap_r = NULL;
+
+	struct ocmem_req *matched_req = NULL;
+	struct ocmem_region *matched_region = NULL;
+
+	struct ocmem_zone *zone = get_zone(owner);
+	struct ocmem_region *region = NULL;
+
+	matched_region = find_region_match(req->req_start, req->req_end);
+	matched_req = find_req_match(req->req_id, matched_region);
+
+	if (!matched_region || !matched_req) {
+		pr_err("Could not find backing region for req");
+		goto invalid_op_error;
+	}
+
+	if (matched_req != req) {
+		pr_err("Request does not match backing req");
+		goto invalid_op_error;
+	}
+
+	curr_sz = matched_req->req_sz;
+	curr_start = matched_req->req_start;
+	growth_sz = matched_req->req_max - matched_req->req_sz;
+
+	pr_debug("Attempting to grow req %p from %lx to %lx\n",
+			req, matched_req->req_sz, matched_req->req_max);
+
+	retry = false;
+
+	pr_debug("ocmem: GROW: growth size %lx\n", growth_sz);
+
+retry_next_step:
+
+	spanned_r = NULL;
+	overlap_r = NULL;
+
+	spanned_r = find_region(zone->z_head);
+	overlap_r = find_region_intersection(zone->z_head,
+				zone->z_head + growth_sz);
+
+	if (overlap_r == NULL) {
+		/* no conflicting regions, schedule this region */
+		zone->z_ops->free(zone, curr_start, curr_sz);
+		alloc_addr = zone->z_ops->allocate(zone, curr_sz + growth_sz);
+
+		if (alloc_addr < 0) {
+			pr_err("ocmem: zone allocation operation failed\n");
+			goto internal_error;
+		}
+
+		curr_sz += growth_sz;
+		/* Detach the region from the interval tree */
+		/* This is to guarantee that any change in size
+		 * causes the tree to be rebalanced if required */
+
+		detach_req(matched_region, req);
+		if (req_count(matched_region) == 0) {
+			remove_region(matched_region);
+			region = matched_region;
+		} else {
+			region = create_region();
+			if (!region) {
+				pr_err("ocmem: Unable to create region\n");
+				goto region_error;
+			}
+		}
+
+		/* update the request */
+		req->req_start = alloc_addr;
+		/* increment the size to reflect new length */
+		req->req_sz = curr_sz;
+		req->req_end = alloc_addr + req->req_sz - 1;
+
+		/* update request state */
+		CLEAR_STATE(req, R_MUST_GROW);
+		SET_STATE(req, R_ALLOCATED);
+		SET_STATE(req, R_MUST_MAP);
+		req->op = SCHED_MAP;
+
+		/* update the region with new req */
+		attach_req(region, req);
+		populate_region(region, req);
+		update_region_prio(region);
+
+		/* update the tree with new region */
+		if (insert_region(region)) {
+			pr_err("ocmem: Failed to insert the region\n");
+			goto region_error;
+		}
+
+		if (retry) {
+			SET_STATE(req, R_MUST_GROW);
+			SET_STATE(req, R_PENDING);
+			req->op = SCHED_GROW;
+			return OP_PARTIAL;
+		}
+	} else if (spanned_r != NULL && overlap_r != NULL) {
+		/* resolve conflicting regions based on priority */
+		if (overlap_r->max_prio < prio) {
+			/* Growth cannot be triggered unless a previous
+			 * client of lower priority was evicted */
+			pr_err("ocmem: Invalid growth scheduled\n");
+			/* This is serious enough to fail */
+			BUG();
+			return OP_FAIL;
+		} else if (overlap_r->max_prio > prio) {
+			if (min == max) {
+				/* Cannot grow at this time, try later */
+				SET_STATE(req, R_PENDING);
+				SET_STATE(req, R_MUST_GROW);
+				return OP_RESCHED;
+			} else {
+			/* Try to grow in steps */
+				growth_sz -= step;
+				/* We are OOM at this point so need to retry */
+				if (growth_sz <= curr_sz) {
+					SET_STATE(req, R_PENDING);
+					SET_STATE(req, R_MUST_GROW);
+					return OP_RESCHED;
+				}
+				retry = true;
+				pr_debug("ocmem: Attempting with reduced size %lx\n",
+						growth_sz);
+				goto retry_next_step;
+			}
+		} else {
+			pr_err("ocmem: grow: New Region %p Existing %p\n",
+				matched_region, overlap_r);
+			pr_err("ocmem: Undetermined behavior\n");
+			/* This is serious enough to fail */
+			BUG();
+		}
+	} else if (spanned_r == NULL && overlap_r != NULL) {
+		goto err_not_supported;
+	}
+
+	return OP_COMPLETE;
+
+err_not_supported:
+	pr_err("ocmem: Scheduled unsupported operation\n");
+	return OP_FAIL;
+region_error:
+	zone->z_ops->free(zone, alloc_addr, curr_sz);
+	detach_req(region, req);
+	update_region_prio(region);
+	/* req is going to be destroyed by the caller anyways */
+internal_error:
+	destroy_region(region);
+invalid_op_error:
+	return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
+static int __sched_free(struct ocmem_req *req)
+{
+	int owner = req->owner;
+	int ret = 0;
+
+	struct ocmem_req *matched_req = NULL;
+	struct ocmem_region *matched_region = NULL;
+
+	struct ocmem_zone *zone = get_zone(owner);
+
+	BUG_ON(!zone);
+
+	matched_region = find_region_match(req->req_start, req->req_end);
+	matched_req = find_req_match(req->req_id, matched_region);
+
+	if (!matched_region || !matched_req)
+		goto invalid_op_error;
+	if (matched_req != req)
+		goto invalid_op_error;
+
+	ret = zone->z_ops->free(zone,
+		matched_req->req_start, matched_req->req_sz);
+
+	if (ret < 0)
+		goto err_op_fail;
+
+	detach_req(matched_region, matched_req);
+	update_region_prio(matched_region);
+	if (req_count(matched_region) == 0) {
+		remove_region(matched_region);
+		destroy_region(matched_region);
+	}
+
+	/* Update the request */
+	req->req_start = 0x0;
+	req->req_sz = 0x0;
+	req->req_end = 0x0;
+	SET_STATE(req, R_FREE);
+	return OP_COMPLETE;
+invalid_op_error:
+	pr_err("ocmem: free: Failed to find matching region\n");
+err_op_fail:
+	pr_err("ocmem: free: Failed\n");
+	return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
+static int __sched_allocate(struct ocmem_req *req, bool can_block,
+				bool can_wait)
+{
+	unsigned long min = req->req_min;
+	unsigned long max = req->req_max;
+	unsigned long step = req->req_step;
+	int owner = req->owner;
+	unsigned long sz = max;
+	enum client_prio prio = req->prio;
+	unsigned long alloc_addr = 0x0;
+	bool retry;
+
+	struct ocmem_region *spanned_r = NULL;
+	struct ocmem_region *overlap_r = NULL;
+
+	struct ocmem_zone *zone = get_zone(owner);
+	struct ocmem_region *region = NULL;
+
+	BUG_ON(!zone);
+
+	if (min > (zone->z_end - zone->z_start)) {
+		pr_err("ocmem: requested minimum size exceeds quota\n");
+		goto invalid_op_error;
+	}
+
+	if (max > (zone->z_end - zone->z_start)) {
+		pr_err("ocmem: requested maximum size exceeds quota\n");
+		goto invalid_op_error;
+	}
+
+	if (min > zone->z_free) {
+			pr_err("ocmem: out of memory for zone %d\n", owner);
+			goto invalid_op_error;
+	}
+
+	region = create_region();
+
+	if (!region) {
+		pr_err("ocmem: Unable to create region\n");
+		goto invalid_op_error;
+	}
+
+	retry = false;
+
+	pr_debug("ocmem: ALLOCATE: request size %lx\n", sz);
+
+retry_next_step:
+
+	spanned_r = NULL;
+	overlap_r = NULL;
+
+	spanned_r = find_region(zone->z_head);
+	overlap_r = find_region_intersection(zone->z_head, zone->z_head + sz);
+
+	if (overlap_r == NULL) {
+		/* no conflicting regions, schedule this region */
+		alloc_addr = zone->z_ops->allocate(zone, sz);
+
+		if (alloc_addr < 0) {
+			pr_err("Zone Allocation operation failed\n");
+			goto internal_error;
+		}
+
+		/* update the request */
+		req->req_start = alloc_addr;
+		req->req_end = alloc_addr + sz - 1;
+		req->req_sz = sz;
+		req->zone = zone;
+
+		/* update request state */
+		CLEAR_STATE(req, R_FREE);
+		SET_STATE(req, R_ALLOCATED);
+		SET_STATE(req, R_MUST_MAP);
+		req->op = SCHED_NOP;
+
+		/* attach the request to the region */
+		attach_req(region, req);
+		populate_region(region, req);
+		update_region_prio(region);
+
+		/* update the tree with new region */
+		if (insert_region(region)) {
+			pr_err("ocmem: Failed to insert the region\n");
+			zone->z_ops->free(zone, alloc_addr, sz);
+			detach_req(region, req);
+			update_region_prio(region);
+			/* req will be destroyed by the caller */
+			goto internal_error;
+		}
+
+		if (retry) {
+			SET_STATE(req, R_MUST_GROW);
+			SET_STATE(req, R_PENDING);
+			req->op = SCHED_GROW;
+			return OP_PARTIAL;
+		}
+	} else if (spanned_r != NULL && overlap_r != NULL) {
+		/* resolve conflicting regions based on priority */
+		if (overlap_r->max_prio < prio) {
+			if (min == max) {
+				pr_err("ocmem: Requires eviction support\n");
+				goto err_not_supported;
+			} else {
+			/* Try to allocate atleast >= 'min' immediately */
+				sz -= step;
+				if (sz < min)
+					goto err_out_of_mem;
+				retry = true;
+				pr_debug("ocmem: Attempting with reduced size %lx\n",
+						sz);
+				goto retry_next_step;
+			}
+		} else if (overlap_r->max_prio > prio) {
+			if (can_block == true) {
+				SET_STATE(req, R_PENDING);
+				SET_STATE(req, R_MUST_GROW);
+				return OP_RESCHED;
+			} else {
+				if (min == max) {
+					pr_err("Cannot allocate %lx synchronously\n",
+							sz);
+					goto err_out_of_mem;
+				} else {
+					sz -= step;
+					if (sz < min)
+						goto err_out_of_mem;
+					retry = true;
+					pr_debug("ocmem: Attempting reduced size %lx\n",
+							sz);
+					goto retry_next_step;
+				}
+			}
+		} else {
+			pr_err("ocmem: Undetermined behavior\n");
+			pr_err("ocmem: New Region %p Existing %p\n", region,
+					overlap_r);
+			/* This is serious enough to fail */
+			BUG();
+		}
+	} else if (spanned_r == NULL && overlap_r != NULL)
+		goto err_not_supported;
+
+	return OP_COMPLETE;
+
+err_not_supported:
+	pr_err("ocmem: Scheduled unsupported operation\n");
+	return OP_FAIL;
+
+err_out_of_mem:
+	pr_err("ocmem: Out of memory during allocation\n");
+internal_error:
+	destroy_region(region);
+invalid_op_error:
+	return OP_FAIL;
+}
+
+static int sched_enqueue(struct ocmem_req *priv)
+{
+	struct ocmem_req *next = NULL;
+	mutex_lock(&sched_queue_mutex);
+	list_add_tail(&priv->sched_list, &sched_queue[priv->owner]);
+	pr_debug("enqueued req %p\n", priv);
+	list_for_each_entry(next, &sched_queue[priv->owner], sched_list) {
+		pr_debug("pending requests for client %p\n", next);
+	}
+	mutex_unlock(&sched_queue_mutex);
+	return 0;
+}
+
+static struct ocmem_req *ocmem_fetch_req(void)
+{
+	int i;
+	struct ocmem_req *req = NULL;
+	struct ocmem_req *next = NULL;
+
+	mutex_lock(&sched_queue_mutex);
+	for (i = MIN_PRIO; i < MAX_OCMEM_PRIO; i++) {
+		if (list_empty(&sched_queue[i]))
+			continue;
+		list_for_each_entry_safe(req, next, &sched_queue[i], sched_list)
+		{
+			if (req) {
+				pr_debug("ocmem: Fetched pending request %p\n",
+									req);
+				list_del(&req->sched_list);
+			break;
+			}
+		}
+	}
+	mutex_unlock(&sched_queue_mutex);
+	return req;
+}
+
+int process_xfer(int id, struct ocmem_handle *handle,
+		struct ocmem_map_list *list, int direction)
+{
+
+	return 0;
+}
+
+unsigned long process_quota(int id)
+{
+	struct ocmem_zone *zone = NULL;
+
+	if (is_blocked(id))
+		return 0;
+
+	zone = get_zone(id);
+
+	if (zone && zone->z_pool)
+		return zone->z_end - zone->z_start;
+	else
+		return 0;
+}
+
+static int do_grow(struct ocmem_req *req)
+{
+	struct ocmem_buf *buffer = NULL;
+	bool can_block = true;
+	int rc = 0;
+
+	down_write(&req->rw_sem);
+	buffer = req->buffer;
+
+	/* Take the scheduler mutex */
+	mutex_lock(&sched_mutex);
+	rc = __sched_grow(req, can_block);
+	mutex_unlock(&sched_mutex);
+
+	if (rc == OP_FAIL)
+		goto err_op_fail;
+
+	if (rc == OP_RESCHED) {
+		pr_debug("ocmem: Enqueue this allocation");
+		sched_enqueue(req);
+	}
+
+	else if (rc == OP_COMPLETE || rc == OP_PARTIAL) {
+		buffer->addr = device_address(req->owner, req->req_start);
+		buffer->len = req->req_sz;
+	}
+
+	up_write(&req->rw_sem);
+	return 0;
+err_op_fail:
+	up_write(&req->rw_sem);
+	return -EINVAL;
+}
+
+static int process_grow(struct ocmem_req *req)
+{
+	int rc = 0;
+
+	/* Attempt to grow the region */
+	rc = do_grow(req);
+
+	if (rc < 0)
+		return -EINVAL;
+
+	/* Map the newly grown region */
+	if (is_tcm(req->owner)) {
+		rc = process_map(req, req->req_start, req->req_end);
+		if (rc < 0)
+			return -EINVAL;
+	}
+
+	/* Notify the client about the buffer growth */
+	rc = dispatch_notification(req->owner, OCMEM_ALLOC_GROW, req->buffer);
+	if (rc < 0) {
+		pr_err("No notifier callback to cater for req %p event: %d\n",
+				req, OCMEM_ALLOC_GROW);
+		BUG();
+	}
+	return 0;
+}
+
+static void ocmem_sched_wk_func(struct work_struct *work);
+DECLARE_DELAYED_WORK(ocmem_sched_thread, ocmem_sched_wk_func);
+
+static int ocmem_schedule_pending(void)
+{
+	schedule_delayed_work(&ocmem_sched_thread,
+				msecs_to_jiffies(SCHED_DELAY));
+	return 0;
+}
+
+static int do_free(struct ocmem_req *req)
+{
+	int rc = 0;
+	struct ocmem_buf *buffer = req->buffer;
+
+	down_write(&req->rw_sem);
+
+	if (is_mapped(req)) {
+		pr_err("ocmem: Buffer needs to be unmapped before free\n");
+		goto err_free_fail;
+	}
+
+	/* Grab the sched mutex */
+	mutex_lock(&sched_mutex);
+	rc = __sched_free(req);
+	mutex_unlock(&sched_mutex);
+
+	switch (rc) {
+
+	case OP_COMPLETE:
+		buffer->addr = 0x0;
+		buffer->len = 0x0;
+		break;
+	case OP_FAIL:
+	default:
+		goto err_free_fail;
+		break;
+	}
+
+	up_write(&req->rw_sem);
+	return 0;
+err_free_fail:
+	up_write(&req->rw_sem);
+	pr_err("ocmem: freeing req %p failed\n", req);
+	return -EINVAL;
+}
+
+int process_free(int id, struct ocmem_handle *handle)
+{
+	struct ocmem_req *req = NULL;
+	struct ocmem_buf *buffer = NULL;
+	int rc = 0;
+
+	if (is_blocked(id)) {
+		pr_err("Client %d cannot request free\n", id);
+		return -EINVAL;
+	}
+
+	req = handle_to_req(handle);
+	buffer = handle_to_buffer(handle);
+
+	if (!req)
+		return -EINVAL;
+
+	if (req->req_start != core_address(id, buffer->addr)) {
+		pr_err("Invalid buffer handle passed for free\n");
+		return -EINVAL;
+	}
+
+	if (is_tcm(req->owner)) {
+		rc = process_unmap(req, req->req_start, req->req_end);
+		if (rc < 0)
+			return -EINVAL;
+	}
+
+	rc = do_free(req);
+
+	if (rc < 0)
+		return -EINVAL;
+
+	ocmem_destroy_req(req);
+	handle->req = NULL;
+
+	ocmem_schedule_pending();
+	return 0;
+}
+
+static int do_allocate(struct ocmem_req *req, bool can_block, bool can_wait)
+{
+	int rc = 0;
+	struct ocmem_buf *buffer = req->buffer;
+
+	down_write(&req->rw_sem);
+
+	/* Take the scheduler mutex */
+	mutex_lock(&sched_mutex);
+	rc = __sched_allocate(req, can_block, can_wait);
+	mutex_unlock(&sched_mutex);
+
+	if (rc == OP_FAIL)
+		goto err_allocate_fail;
+
+	if (rc == OP_RESCHED) {
+		buffer->addr = 0x0;
+		buffer->len = 0x0;
+		pr_debug("ocmem: Enqueuing req %p\n", req);
+		sched_enqueue(req);
+	} else if (rc == OP_PARTIAL) {
+		buffer->addr = device_address(req->owner, req->req_start);
+		buffer->len = req->req_sz;
+		pr_debug("ocmem: Enqueuing req %p\n", req);
+		sched_enqueue(req);
+	} else if (rc == OP_COMPLETE) {
+		buffer->addr = device_address(req->owner, req->req_start);
+		buffer->len = req->req_sz;
+	}
+
+	up_write(&req->rw_sem);
+	return 0;
+err_allocate_fail:
+	up_write(&req->rw_sem);
+	return -EINVAL;
+}
+
+
+int process_allocate(int id, struct ocmem_handle *handle,
+			unsigned long min, unsigned long max,
+			unsigned long step, bool can_block, bool can_wait)
+{
+
+	struct ocmem_req *req = NULL;
+	struct ocmem_buf *buffer = NULL;
+	int rc = 0;
+
+	/* sanity checks */
+	if (is_blocked(id)) {
+		pr_err("Client %d cannot request allocation\n", id);
+		return -EINVAL;
+	}
+
+	if (handle->req != NULL) {
+		pr_err("Invalid handle passed in\n");
+		return -EINVAL;
+	}
+
+	buffer = handle_to_buffer(handle);
+	BUG_ON(buffer == NULL);
+
+	/* prepare a request structure to represent this transaction */
+	req = ocmem_create_req();
+	if (!req)
+		return -ENOMEM;
+
+	req->owner = id;
+	req->req_min = min;
+	req->req_max = max;
+	req->req_step = step;
+	req->prio = ocmem_client_table[id].priority;
+	req->op = SCHED_ALLOCATE;
+	req->buffer = buffer;
+
+	rc = do_allocate(req, can_block, can_wait);
+
+	if (rc < 0)
+		goto do_allocate_error;
+
+	handle->req = req;
+
+	if (is_tcm(id)) {
+		rc = process_map(req, req->req_start, req->req_end);
+		if (rc < 0)
+			goto map_error;
+	}
+
+	return 0;
+
+map_error:
+	handle->req = NULL;
+	do_free(req);
+do_allocate_error:
+	ocmem_destroy_req(req);
+	return -EINVAL;
+}
+
+int process_delayed_allocate(struct ocmem_req *req)
+{
+
+	struct ocmem_handle *handle = NULL;
+	int rc = 0;
+	int id = req->owner;
+
+	handle = req_to_handle(req);
+	BUG_ON(handle == NULL);
+
+	rc = do_allocate(req, true, false);
+
+	if (rc < 0)
+		goto do_allocate_error;
+
+	if (is_tcm(id)) {
+		rc = process_map(req, req->req_start, req->req_end);
+		if (rc < 0)
+			goto map_error;
+	}
+
+	/* Notify the client about the buffer growth */
+	rc = dispatch_notification(id, OCMEM_ALLOC_GROW, req->buffer);
+	if (rc < 0) {
+		pr_err("No notifier callback to cater for req %p event: %d\n",
+				req, OCMEM_ALLOC_GROW);
+		BUG();
+	}
+	return 0;
+
+map_error:
+	handle->req = NULL;
+	do_free(req);
+do_allocate_error:
+	ocmem_destroy_req(req);
+	return -EINVAL;
+}
+
+static void ocmem_sched_wk_func(struct work_struct *work)
+{
+
+	struct ocmem_buf *buffer = NULL;
+	struct ocmem_handle *handle = NULL;
+	struct ocmem_req *req = ocmem_fetch_req();
+
+	if (!req) {
+		pr_debug("No Pending Requests found\n");
+		return;
+	}
+
+	pr_debug("ocmem: sched_wk pending req %p\n", req);
+	handle = req_to_handle(req);
+	buffer = handle_to_buffer(handle);
+	BUG_ON(req->op == SCHED_NOP);
+
+	switch (req->op) {
+	case SCHED_GROW:
+		process_grow(req);
+		break;
+	case SCHED_ALLOCATE:
+		process_delayed_allocate(req);
+		break;
+	default:
+		pr_err("ocmem: Unknown operation encountered\n");
+		break;
+	}
+	return;
+}
+
+int ocmem_sched_init(void)
+{
+	int i = 0;
+	sched_tree = RB_ROOT;
+	mutex_init(&sched_mutex);
+	mutex_init(&sched_queue_mutex);
+	for (i = MIN_PRIO; i < MAX_OCMEM_PRIO; i++)
+		INIT_LIST_HEAD(&sched_queue[i]);
+
+	return 0;
+}
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
new file mode 100644
index 0000000..d82f4dd
--- /dev/null
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2011, 2012 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irq.h>
+#include <asm/pmu.h>
+#include <linux/platform_device.h>
+
+#include <mach/msm-krait-l2-accessors.h>
+
+#define MAX_L2_PERIOD	((1ULL << 32) - 1)
+#define MAX_KRAIT_L2_CTRS 5
+
+#define L2PMCCNTR 0x409
+#define L2PMCCNTCR 0x408
+#define L2PMCCNTSR 0x40A
+#define L2CYCLE_CTR_BIT 31
+#define L2CYCLE_CTR_EVENT_IDX 4
+#define L2CYCLE_CTR_RAW_CODE 0xfe
+
+#define L2PMOVSR	0x406
+
+#define L2PMCR	0x400
+#define L2PMCR_RESET_ALL	0x6
+#define L2PMCR_GLOBAL_ENABLE	0x1
+#define L2PMCR_GLOBAL_DISABLE	0x0
+
+#define L2PMCNTENSET	0x403
+#define L2PMCNTENCLR	0x402
+
+#define L2PMINTENSET	0x405
+#define L2PMINTENCLR	0x404
+
+#define IA_L2PMXEVCNTCR_BASE	0x420
+#define IA_L2PMXEVTYPER_BASE	0x424
+#define IA_L2PMRESX_BASE	0x410
+#define IA_L2PMXEVFILTER_BASE	0x423
+#define IA_L2PMXEVCNTR_BASE	0x421
+
+/* event format is -e rsRCCG See get_event_desc() */
+
+#define EVENT_REG_MASK		0xf000
+#define EVENT_GROUPSEL_MASK	0x000f
+#define	EVENT_GROUPCODE_MASK	0x0ff0
+#define EVENT_REG_SHIFT		12
+#define EVENT_GROUPCODE_SHIFT	4
+
+#define	RESRX_VALUE_EN	0x80000000
+
+static u32 l2_orig_filter_prefix = 0x000f0030;
+
+static u32 pmu_type;
+
+static struct arm_pmu krait_l2_pmu;
+
+static struct perf_event *l2_events[MAX_KRAIT_L2_CTRS];
+static unsigned long l2_used_mask[BITS_TO_LONGS(MAX_KRAIT_L2_CTRS)];
+
+static struct pmu_hw_events krait_l2_pmu_hw_events = {
+	.events = l2_events,
+	.used_mask = l2_used_mask,
+	.pmu_lock = __RAW_SPIN_LOCK_UNLOCKED(krait_l2_pmu_hw_events.pmu_lock),
+};
+
+struct event_desc {
+	int event_groupsel;
+	int event_reg;
+	int event_group_code;
+};
+
+static struct pmu_hw_events *krait_l2_get_hw_events(void)
+{
+	return &krait_l2_pmu_hw_events;
+}
+
+void get_event_desc(u64 config, struct event_desc *evdesc)
+{
+	/* L2PMEVCNTRX */
+	evdesc->event_reg = (config & EVENT_REG_MASK) >> EVENT_REG_SHIFT;
+	/* Group code (row ) */
+	evdesc->event_group_code =
+	    (config & EVENT_GROUPCODE_MASK) >> EVENT_GROUPCODE_SHIFT;
+	/* Group sel (col) */
+	evdesc->event_groupsel = (config & EVENT_GROUPSEL_MASK);
+
+	pr_debug("%s: reg: %x, group_code: %x, groupsel: %x\n", __func__,
+		 evdesc->event_reg, evdesc->event_group_code,
+		 evdesc->event_groupsel);
+}
+
+static void set_evcntcr(int ctr)
+{
+	u32 evtcr_reg = (ctr * 16) + IA_L2PMXEVCNTCR_BASE;
+
+	set_l2_indirect_reg(evtcr_reg, 0x0);
+}
+
+static void set_evtyper(int event_groupsel, int event_reg, int ctr)
+{
+	u32 evtype_reg = (ctr * 16) + IA_L2PMXEVTYPER_BASE;
+	u32 evtype_val = event_groupsel + (4 * event_reg);
+
+	set_l2_indirect_reg(evtype_reg, evtype_val);
+}
+
+static void set_evres(int event_groupsel, int event_reg, int event_group_code)
+{
+	u32 group_reg = event_reg + IA_L2PMRESX_BASE;
+	u32 group_val =
+		RESRX_VALUE_EN | (event_group_code << (8 * event_groupsel));
+	u32 resr_val;
+	u32 group_byte = 0xff;
+	u32 group_mask = ~(group_byte << (8 * event_groupsel));
+
+	resr_val = get_l2_indirect_reg(group_reg);
+	resr_val &= group_mask;
+	resr_val |= group_val;
+
+	set_l2_indirect_reg(group_reg, resr_val);
+}
+
+static void set_evfilter_task_mode(int ctr)
+{
+	u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
+	u32 filter_val = l2_orig_filter_prefix | 1 << smp_processor_id();
+
+	set_l2_indirect_reg(filter_reg, filter_val);
+}
+
+static void set_evfilter_sys_mode(int ctr)
+{
+	u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
+	u32 filter_val = l2_orig_filter_prefix | 0xf;
+
+	set_l2_indirect_reg(filter_reg, filter_val);
+}
+
+static void enable_intenset(u32 idx)
+{
+	if (idx == L2CYCLE_CTR_EVENT_IDX)
+		set_l2_indirect_reg(L2PMINTENSET, 1 << L2CYCLE_CTR_BIT);
+	else
+		set_l2_indirect_reg(L2PMINTENSET, 1 << idx);
+}
+
+static void disable_intenclr(u32 idx)
+{
+	if (idx == L2CYCLE_CTR_EVENT_IDX)
+		set_l2_indirect_reg(L2PMINTENCLR, 1 << L2CYCLE_CTR_BIT);
+	else
+		set_l2_indirect_reg(L2PMINTENCLR, 1 << idx);
+}
+
+static void enable_counter(u32 idx)
+{
+	if (idx == L2CYCLE_CTR_EVENT_IDX)
+		set_l2_indirect_reg(L2PMCNTENSET, 1 << L2CYCLE_CTR_BIT);
+	else
+		set_l2_indirect_reg(L2PMCNTENSET, 1 << idx);
+}
+
+static void disable_counter(u32 idx)
+{
+	if (idx == L2CYCLE_CTR_EVENT_IDX)
+		set_l2_indirect_reg(L2PMCNTENCLR, 1 << L2CYCLE_CTR_BIT);
+	else
+		set_l2_indirect_reg(L2PMCNTENCLR, 1 << idx);
+}
+
+static u32 krait_l2_read_counter(int idx)
+{
+	u32 val;
+	u32 counter_reg = (idx * 16) + IA_L2PMXEVCNTR_BASE;
+
+	if (idx == L2CYCLE_CTR_EVENT_IDX)
+		val = get_l2_indirect_reg(L2PMCCNTR);
+	else
+		val = get_l2_indirect_reg(counter_reg);
+
+	return val;
+}
+
+static void krait_l2_write_counter(int idx, u32 val)
+{
+	u32 counter_reg = (idx * 16) + IA_L2PMXEVCNTR_BASE;
+
+	if (idx == L2CYCLE_CTR_EVENT_IDX)
+		set_l2_indirect_reg(L2PMCCNTR, val);
+	else
+		set_l2_indirect_reg(counter_reg, val);
+}
+
+static void krait_l2_stop_counter(struct hw_perf_event *hwc, int idx)
+{
+	disable_intenclr(idx);
+	disable_counter(idx);
+
+	pr_debug("%s: event: %ld ctr: %d stopped\n", __func__,
+			hwc->config_base, idx);
+}
+
+static void krait_l2_enable(struct hw_perf_event *hwc, int idx, int cpu)
+{
+	struct event_desc evdesc;
+	unsigned long iflags;
+
+	raw_spin_lock_irqsave(&krait_l2_pmu_hw_events.pmu_lock, iflags);
+
+	if (hwc->config_base == L2CYCLE_CTR_RAW_CODE)
+		goto out;
+
+	set_evcntcr(idx);
+
+	memset(&evdesc, 0, sizeof(evdesc));
+
+	get_event_desc(hwc->config_base, &evdesc);
+
+	set_evtyper(evdesc.event_groupsel, evdesc.event_reg, idx);
+
+	set_evres(evdesc.event_groupsel, evdesc.event_reg,
+		  evdesc.event_group_code);
+
+	if (cpu < 0)
+		set_evfilter_task_mode(idx);
+	else
+		set_evfilter_sys_mode(idx);
+
+out:
+	enable_intenset(idx);
+	enable_counter(idx);
+
+	raw_spin_unlock_irqrestore(&krait_l2_pmu_hw_events.pmu_lock, iflags);
+
+	pr_debug("%s: ctr: %d group: %ld group_code: %lld started from cpu:%d\n",
+	     __func__, idx, hwc->config_base, hwc->config, smp_processor_id());
+}
+
+static void krait_l2_disable(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long iflags;
+
+	raw_spin_lock_irqsave(&krait_l2_pmu_hw_events.pmu_lock, iflags);
+
+	krait_l2_stop_counter(hwc, idx);
+
+	raw_spin_unlock_irqrestore(&krait_l2_pmu_hw_events.pmu_lock, iflags);
+
+	pr_debug("%s: event: %ld deleted\n", __func__, hwc->config_base);
+
+}
+
+static int krait_l2_get_event_idx(struct pmu_hw_events *cpuc,
+				  struct hw_perf_event *hwc)
+{
+	int ctr = 0;
+
+	if (hwc->config_base == L2CYCLE_CTR_RAW_CODE) {
+		if (!test_and_set_bit(L2CYCLE_CTR_EVENT_IDX, cpuc->used_mask))
+			return L2CYCLE_CTR_EVENT_IDX;
+	}
+
+	for (ctr = 0; ctr < MAX_KRAIT_L2_CTRS - 1; ctr++) {
+		if (!test_and_set_bit(ctr, cpuc->used_mask))
+			return ctr;
+	}
+
+	return -EAGAIN;
+}
+
+static void krait_l2_start(void)
+{
+	isb();
+	set_l2_indirect_reg(L2PMCR, L2PMCR_GLOBAL_ENABLE);
+}
+
+static void krait_l2_stop(void)
+{
+	set_l2_indirect_reg(L2PMCR, L2PMCR_GLOBAL_DISABLE);
+	isb();
+}
+
+u32 get_reset_pmovsr(void)
+{
+	int val;
+
+	val = get_l2_indirect_reg(L2PMOVSR);
+	/* reset it */
+	val &= 0xffffffff;
+	set_l2_indirect_reg(L2PMOVSR, val);
+
+	return val;
+}
+
+static irqreturn_t krait_l2_handle_irq(int irq_num, void *dev)
+{
+	unsigned long pmovsr;
+	struct perf_sample_data data;
+	struct pt_regs *regs;
+	struct perf_event *event;
+	struct hw_perf_event *hwc;
+	int bitp;
+	int idx = 0;
+
+	pmovsr = get_reset_pmovsr();
+
+	if (!(pmovsr & 0xffffffff))
+		return IRQ_NONE;
+
+	regs = get_irq_regs();
+
+	perf_sample_data_init(&data, 0);
+
+	while (pmovsr) {
+		bitp = __ffs(pmovsr);
+
+		if (bitp == L2CYCLE_CTR_BIT)
+			idx = L2CYCLE_CTR_EVENT_IDX;
+		else
+			idx = bitp;
+
+		event = krait_l2_pmu_hw_events.events[idx];
+
+		if (!event)
+			goto next;
+
+		if (!test_bit(idx, krait_l2_pmu_hw_events.used_mask))
+			goto next;
+
+		hwc = &event->hw;
+
+		armpmu_event_update(event, hwc, idx);
+
+		data.period = event->hw.last_period;
+
+		if (!armpmu_event_set_period(event, hwc, idx))
+			goto next;
+
+		if (perf_event_overflow(event, &data, regs))
+			disable_counter(hwc->idx);
+next:
+		pmovsr &= (pmovsr - 1);
+	}
+
+	irq_work_run();
+
+	return IRQ_HANDLED;
+}
+
+static int krait_l2_map_event(struct perf_event *event)
+{
+	if (pmu_type > 0 && pmu_type == event->attr.type)
+		return event->attr.config & 0xfffff;
+	else
+		return -ENOENT;
+}
+
+static int
+krait_l2_pmu_generic_request_irq(int irq, irq_handler_t *handle_irq)
+{
+	return request_irq(irq, *handle_irq,
+			IRQF_DISABLED | IRQF_NOBALANCING,
+			"krait-l2-armpmu", NULL);
+}
+
+static void
+krait_l2_pmu_generic_free_irq(int irq)
+{
+	if (irq >= 0)
+		free_irq(irq, NULL);
+}
+
+static struct arm_pmu krait_l2_pmu = {
+	.id		=	ARM_PERF_PMU_ID_KRAIT_L2,
+	.type		=	ARM_PMU_DEVICE_L2CC,
+	.name		=	"Krait L2CC PMU",
+	.start		=	krait_l2_start,
+	.stop		=	krait_l2_stop,
+	.handle_irq	=	krait_l2_handle_irq,
+	.request_pmu_irq	= krait_l2_pmu_generic_request_irq,
+	.free_pmu_irq		= krait_l2_pmu_generic_free_irq,
+	.enable		=	krait_l2_enable,
+	.disable	=	krait_l2_disable,
+	.get_event_idx	=	krait_l2_get_event_idx,
+	.read_counter	=	krait_l2_read_counter,
+	.write_counter	=	krait_l2_write_counter,
+	.map_event	=	krait_l2_map_event,
+	.max_period	=	(1LLU << 32) - 1,
+	.get_hw_events	=	krait_l2_get_hw_events,
+	.num_events	=	MAX_KRAIT_L2_CTRS,
+};
+
+static int __devinit krait_l2_pmu_device_probe(struct platform_device *pdev)
+{
+	krait_l2_pmu.plat_device = pdev;
+
+	if (!armpmu_register(&krait_l2_pmu, "krait-l2", -1))
+		pmu_type = krait_l2_pmu.pmu.type;
+
+	return 0;
+}
+
+static struct platform_driver krait_l2_pmu_driver = {
+	.driver		= {
+		.name	= "l2-arm-pmu",
+	},
+	.probe		= krait_l2_pmu_device_probe,
+};
+
+static int __init register_krait_l2_pmu_driver(void)
+{
+	/* Reset all ctrs */
+	set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
+
+	/* Avoid spurious interrupt if any */
+	get_reset_pmovsr();
+
+	return platform_driver_register(&krait_l2_pmu_driver);
+}
+device_initcall(register_krait_l2_pmu_driver);
diff --git a/arch/arm/mach-msm/perf_event_msm_l2.c b/arch/arm/mach-msm/perf_event_msm_l2.c
new file mode 100644
index 0000000..3310d92
--- /dev/null
+++ b/arch/arm/mach-msm/perf_event_msm_l2.c
@@ -0,0 +1,760 @@
+/*
+ * Copyright (c) 2011, 2012 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/irq.h>
+#include <asm/pmu.h>
+#include <linux/platform_device.h>
+
+
+#define MAX_SCORPION_L2_CTRS 5
+#define SCORPION_L2CYCLE_CTR_BIT 31
+#define SCORPION_L2CYCLE_CTR_EVENT_IDX 4
+#define SCORPION_L2CYCLE_CTR_RAW_CODE 0xfe
+#define SCORPIONL2_PMNC_E       (1 << 0)	/* Enable all counters */
+#define SCORPION_L2_EVT_PREFIX 3
+#define SCORPION_MAX_L2_REG 4
+
+static u32 pmu_type;
+
+static struct arm_pmu scorpion_l2_pmu;
+
+static struct perf_event *l2_events[MAX_SCORPION_L2_CTRS];
+static unsigned long l2_used_mask[BITS_TO_LONGS(MAX_SCORPION_L2_CTRS)];
+
+static struct pmu_hw_events scorpion_l2_pmu_hw_events = {
+	.events = l2_events,
+	.used_mask = l2_used_mask,
+	.pmu_lock =
+		__RAW_SPIN_LOCK_UNLOCKED(scorpion_l2_pmu_hw_events.pmu_lock),
+};
+
+struct scorpion_l2_scorp_evt {
+	u32 evt_type;
+	u32 val;
+	u8 grp;
+	u32 evt_type_act;
+};
+
+enum scorpion_perf_types {
+	SCORPIONL2_TOTAL_BANK_REQ = 0x90,
+	SCORPIONL2_DSIDE_READ = 0x91,
+	SCORPIONL2_DSIDE_WRITE = 0x92,
+	SCORPIONL2_ISIDE_READ = 0x93,
+	SCORPIONL2_L2CACHE_ISIDE_READ = 0x94,
+	SCORPIONL2_L2CACHE_BANK_REQ = 0x95,
+	SCORPIONL2_L2CACHE_DSIDE_READ = 0x96,
+	SCORPIONL2_L2CACHE_DSIDE_WRITE = 0x97,
+	SCORPIONL2_L2NOCACHE_DSIDE_WRITE = 0x98,
+	SCORPIONL2_L2NOCACHE_ISIDE_READ = 0x99,
+	SCORPIONL2_L2NOCACHE_TOTAL_REQ = 0x9a,
+	SCORPIONL2_L2NOCACHE_DSIDE_READ = 0x9b,
+	SCORPIONL2_DSIDE_READ_NOL1 = 0x9c,
+	SCORPIONL2_L2CACHE_WRITETHROUGH = 0x9d,
+	SCORPIONL2_BARRIERS = 0x9e,
+	SCORPIONL2_HARDWARE_TABLE_WALKS = 0x9f,
+	SCORPIONL2_MVA_POC = 0xa0,
+	SCORPIONL2_L2CACHE_HW_TABLE_WALKS = 0xa1,
+	SCORPIONL2_SETWAY_CACHE_OPS = 0xa2,
+	SCORPIONL2_DSIDE_WRITE_HITS = 0xa3,
+	SCORPIONL2_ISIDE_READ_HITS = 0xa4,
+	SCORPIONL2_CACHE_DSIDE_READ_NOL1 = 0xa5,
+	SCORPIONL2_TOTAL_CACHE_HITS = 0xa6,
+	SCORPIONL2_CACHE_MATCH_MISS = 0xa7,
+	SCORPIONL2_DREAD_HIT_L1_DATA = 0xa8,
+	SCORPIONL2_L2LINE_LOCKED = 0xa9,
+	SCORPIONL2_HW_TABLE_WALK_HIT = 0xaa,
+	SCORPIONL2_CACHE_MVA_POC = 0xab,
+	SCORPIONL2_L2ALLOC_DWRITE_MISS = 0xac,
+	SCORPIONL2_CORRECTED_TAG_ARRAY = 0xad,
+	SCORPIONL2_CORRECTED_DATA_ARRAY = 0xae,
+	SCORPIONL2_CORRECTED_REPLACEMENT_ARRAY = 0xaf,
+	SCORPIONL2_PMBUS_MPAAF = 0xb0,
+	SCORPIONL2_PMBUS_MPWDAF = 0xb1,
+	SCORPIONL2_PMBUS_MPBRT = 0xb2,
+	SCORPIONL2_CPU0_GRANT = 0xb3,
+	SCORPIONL2_CPU1_GRANT = 0xb4,
+	SCORPIONL2_CPU0_NOGRANT = 0xb5,
+	SCORPIONL2_CPU1_NOGRANT = 0xb6,
+	SCORPIONL2_CPU0_LOSING_ARB = 0xb7,
+	SCORPIONL2_CPU1_LOSING_ARB = 0xb8,
+	SCORPIONL2_SLAVEPORT_NOGRANT = 0xb9,
+	SCORPIONL2_SLAVEPORT_BPQ_FULL = 0xba,
+	SCORPIONL2_SLAVEPORT_LOSING_ARB = 0xbb,
+	SCORPIONL2_SLAVEPORT_GRANT = 0xbc,
+	SCORPIONL2_SLAVEPORT_GRANTLOCK = 0xbd,
+	SCORPIONL2_L2EM_STREX_PASS = 0xbe,
+	SCORPIONL2_L2EM_STREX_FAIL = 0xbf,
+	SCORPIONL2_LDREX_RESERVE_L2EM = 0xc0,
+	SCORPIONL2_SLAVEPORT_LDREX = 0xc1,
+	SCORPIONL2_CPU0_L2EM_CLEARED = 0xc2,
+	SCORPIONL2_CPU1_L2EM_CLEARED = 0xc3,
+	SCORPIONL2_SLAVEPORT_L2EM_CLEARED = 0xc4,
+	SCORPIONL2_CPU0_CLAMPED = 0xc5,
+	SCORPIONL2_CPU1_CLAMPED = 0xc6,
+	SCORPIONL2_CPU0_WAIT = 0xc7,
+	SCORPIONL2_CPU1_WAIT = 0xc8,
+	SCORPIONL2_CPU0_NONAMBAS_WAIT = 0xc9,
+	SCORPIONL2_CPU1_NONAMBAS_WAIT = 0xca,
+	SCORPIONL2_CPU0_DSB_WAIT = 0xcb,
+	SCORPIONL2_CPU1_DSB_WAIT = 0xcc,
+	SCORPIONL2_AXI_READ = 0xcd,
+	SCORPIONL2_AXI_WRITE = 0xce,
+
+	SCORPIONL2_1BEAT_WRITE = 0xcf,
+	SCORPIONL2_2BEAT_WRITE = 0xd0,
+	SCORPIONL2_4BEAT_WRITE = 0xd1,
+	SCORPIONL2_8BEAT_WRITE = 0xd2,
+	SCORPIONL2_12BEAT_WRITE = 0xd3,
+	SCORPIONL2_16BEAT_WRITE = 0xd4,
+	SCORPIONL2_1BEAT_DSIDE_READ = 0xd5,
+	SCORPIONL2_2BEAT_DSIDE_READ = 0xd6,
+	SCORPIONL2_4BEAT_DSIDE_READ = 0xd7,
+	SCORPIONL2_8BEAT_DSIDE_READ = 0xd8,
+	SCORPIONL2_CSYS_READ_1BEAT = 0xd9,
+	SCORPIONL2_CSYS_READ_2BEAT = 0xda,
+	SCORPIONL2_CSYS_READ_4BEAT = 0xdb,
+	SCORPIONL2_CSYS_READ_8BEAT = 0xdc,
+	SCORPIONL2_4BEAT_IFETCH_READ = 0xdd,
+	SCORPIONL2_8BEAT_IFETCH_READ = 0xde,
+	SCORPIONL2_CSYS_WRITE_1BEAT = 0xdf,
+	SCORPIONL2_CSYS_WRITE_2BEAT = 0xe0,
+	SCORPIONL2_AXI_READ_DATA_BEAT = 0xe1,
+	SCORPIONL2_AXI_WRITE_EVT1 = 0xe2,
+	SCORPIONL2_AXI_WRITE_EVT2 = 0xe3,
+	SCORPIONL2_LDREX_REQ = 0xe4,
+	SCORPIONL2_STREX_PASS = 0xe5,
+	SCORPIONL2_STREX_FAIL = 0xe6,
+	SCORPIONL2_CPREAD = 0xe7,
+	SCORPIONL2_CPWRITE = 0xe8,
+	SCORPIONL2_BARRIER_REQ = 0xe9,
+	SCORPIONL2_AXI_READ_SLVPORT = 0xea,
+	SCORPIONL2_AXI_WRITE_SLVPORT = 0xeb,
+	SCORPIONL2_AXI_READ_SLVPORT_DATABEAT = 0xec,
+	SCORPIONL2_AXI_WRITE_SLVPORT_DATABEAT = 0xed,
+	SCORPIONL2_SNOOPKILL_PREFILTER = 0xee,
+	SCORPIONL2_SNOOPKILL_FILTEROUT = 0xef,
+	SCORPIONL2_SNOOPED_IC = 0xf0,
+	SCORPIONL2_SNOOPED_BP = 0xf1,
+	SCORPIONL2_SNOOPED_BARRIERS = 0xf2,
+	SCORPIONL2_SNOOPED_TLB = 0xf3,
+	SCORPION_L2_MAX_EVT,
+};
+
+static const struct scorpion_l2_scorp_evt sc_evt[] = {
+	{SCORPIONL2_TOTAL_BANK_REQ, 0x80000001, 0, 0x00},
+	{SCORPIONL2_DSIDE_READ, 0x80000100, 0, 0x01},
+	{SCORPIONL2_DSIDE_WRITE, 0x80010000, 0, 0x02},
+	{SCORPIONL2_ISIDE_READ, 0x81000000, 0, 0x03},
+	{SCORPIONL2_L2CACHE_ISIDE_READ, 0x80000002, 0, 0x00},
+	{SCORPIONL2_L2CACHE_BANK_REQ, 0x80000200, 0, 0x01},
+	{SCORPIONL2_L2CACHE_DSIDE_READ, 0x80020000, 0, 0x02},
+	{SCORPIONL2_L2CACHE_DSIDE_WRITE, 0x82000000, 0, 0x03},
+	{SCORPIONL2_L2NOCACHE_DSIDE_WRITE, 0x80000003, 0, 0x00},
+	{SCORPIONL2_L2NOCACHE_ISIDE_READ, 0x80000300, 0, 0x01},
+	{SCORPIONL2_L2NOCACHE_TOTAL_REQ, 0x80030000, 0, 0x02},
+	{SCORPIONL2_L2NOCACHE_DSIDE_READ, 0x83000000, 0, 0x03},
+	{SCORPIONL2_DSIDE_READ_NOL1, 0x80000004, 0, 0x00},
+	{SCORPIONL2_L2CACHE_WRITETHROUGH, 0x80000400, 0, 0x01},
+	{SCORPIONL2_BARRIERS, 0x84000000, 0, 0x03},
+	{SCORPIONL2_HARDWARE_TABLE_WALKS, 0x80000005, 0, 0x00},
+	{SCORPIONL2_MVA_POC, 0x80000500, 0, 0x01},
+	{SCORPIONL2_L2CACHE_HW_TABLE_WALKS, 0x80050000, 0, 0x02},
+	{SCORPIONL2_SETWAY_CACHE_OPS, 0x85000000, 0, 0x03},
+	{SCORPIONL2_DSIDE_WRITE_HITS, 0x80000006, 0, 0x00},
+	{SCORPIONL2_ISIDE_READ_HITS, 0x80000600, 0, 0x01},
+	{SCORPIONL2_CACHE_DSIDE_READ_NOL1, 0x80060000, 0, 0x02},
+	{SCORPIONL2_TOTAL_CACHE_HITS, 0x86000000, 0, 0x03},
+	{SCORPIONL2_CACHE_MATCH_MISS, 0x80000007, 0, 0x00},
+	{SCORPIONL2_DREAD_HIT_L1_DATA, 0x87000000, 0, 0x03},
+	{SCORPIONL2_L2LINE_LOCKED, 0x80000008, 0, 0x00},
+	{SCORPIONL2_HW_TABLE_WALK_HIT, 0x80000800, 0, 0x01},
+	{SCORPIONL2_CACHE_MVA_POC, 0x80080000, 0, 0x02},
+	{SCORPIONL2_L2ALLOC_DWRITE_MISS, 0x88000000, 0, 0x03},
+	{SCORPIONL2_CORRECTED_TAG_ARRAY, 0x80001A00, 0, 0x01},
+	{SCORPIONL2_CORRECTED_DATA_ARRAY, 0x801A0000, 0, 0x02},
+	{SCORPIONL2_CORRECTED_REPLACEMENT_ARRAY, 0x9A000000, 0, 0x03},
+	{SCORPIONL2_PMBUS_MPAAF, 0x80001C00, 0, 0x01},
+	{SCORPIONL2_PMBUS_MPWDAF, 0x801C0000, 0, 0x02},
+	{SCORPIONL2_PMBUS_MPBRT, 0x9C000000, 0, 0x03},
+
+	{SCORPIONL2_CPU0_GRANT, 0x80000001, 1, 0x04},
+	{SCORPIONL2_CPU1_GRANT, 0x80000100, 1, 0x05},
+	{SCORPIONL2_CPU0_NOGRANT, 0x80020000, 1, 0x06},
+	{SCORPIONL2_CPU1_NOGRANT, 0x82000000, 1, 0x07},
+	{SCORPIONL2_CPU0_LOSING_ARB, 0x80040000, 1, 0x06},
+	{SCORPIONL2_CPU1_LOSING_ARB, 0x84000000, 1, 0x07},
+	{SCORPIONL2_SLAVEPORT_NOGRANT, 0x80000007, 1, 0x04},
+	{SCORPIONL2_SLAVEPORT_BPQ_FULL, 0x80000700, 1, 0x05},
+	{SCORPIONL2_SLAVEPORT_LOSING_ARB, 0x80070000, 1, 0x06},
+	{SCORPIONL2_SLAVEPORT_GRANT, 0x87000000, 1, 0x07},
+	{SCORPIONL2_SLAVEPORT_GRANTLOCK, 0x80000008, 1, 0x04},
+	{SCORPIONL2_L2EM_STREX_PASS, 0x80000009, 1, 0x04},
+	{SCORPIONL2_L2EM_STREX_FAIL, 0x80000900, 1, 0x05},
+	{SCORPIONL2_LDREX_RESERVE_L2EM, 0x80090000, 1, 0x06},
+	{SCORPIONL2_SLAVEPORT_LDREX, 0x89000000, 1, 0x07},
+	{SCORPIONL2_CPU0_L2EM_CLEARED, 0x800A0000, 1, 0x06},
+	{SCORPIONL2_CPU1_L2EM_CLEARED, 0x8A000000, 1, 0x07},
+	{SCORPIONL2_SLAVEPORT_L2EM_CLEARED, 0x80000B00, 1, 0x05},
+	{SCORPIONL2_CPU0_CLAMPED, 0x8000000E, 1, 0x04},
+	{SCORPIONL2_CPU1_CLAMPED, 0x80000E00, 1, 0x05},
+	{SCORPIONL2_CPU0_WAIT, 0x800F0000, 1, 0x06},
+	{SCORPIONL2_CPU1_WAIT, 0x8F000000, 1, 0x07},
+	{SCORPIONL2_CPU0_NONAMBAS_WAIT, 0x80000010, 1, 0x04},
+	{SCORPIONL2_CPU1_NONAMBAS_WAIT, 0x80001000, 1, 0x05},
+	{SCORPIONL2_CPU0_DSB_WAIT, 0x80000014, 1, 0x04},
+	{SCORPIONL2_CPU1_DSB_WAIT, 0x80001400, 1, 0x05},
+
+	{SCORPIONL2_AXI_READ, 0x80000001, 2, 0x08},
+	{SCORPIONL2_AXI_WRITE, 0x80000100, 2, 0x09},
+	{SCORPIONL2_1BEAT_WRITE, 0x80010000, 2, 0x0a},
+	{SCORPIONL2_2BEAT_WRITE, 0x80010000, 2, 0x0b},
+	{SCORPIONL2_4BEAT_WRITE, 0x80000002, 2, 0x08},
+	{SCORPIONL2_8BEAT_WRITE, 0x80000200, 2, 0x09},
+	{SCORPIONL2_12BEAT_WRITE, 0x80020000, 2, 0x0a},
+	{SCORPIONL2_16BEAT_WRITE, 0x82000000, 2, 0x0b},
+	{SCORPIONL2_1BEAT_DSIDE_READ, 0x80000003, 2, 0x08},
+	{SCORPIONL2_2BEAT_DSIDE_READ, 0x80000300, 2, 0x09},
+	{SCORPIONL2_4BEAT_DSIDE_READ, 0x80030000, 2, 0x0a},
+	{SCORPIONL2_8BEAT_DSIDE_READ, 0x83000000, 2, 0x0b},
+	{SCORPIONL2_CSYS_READ_1BEAT, 0x80000004, 2, 0x08},
+	{SCORPIONL2_CSYS_READ_2BEAT, 0x80000400, 2, 0x09},
+	{SCORPIONL2_CSYS_READ_4BEAT, 0x80040000, 2, 0x0a},
+	{SCORPIONL2_CSYS_READ_8BEAT, 0x84000000, 2, 0x0b},
+	{SCORPIONL2_4BEAT_IFETCH_READ, 0x80000005, 2, 0x08},
+	{SCORPIONL2_8BEAT_IFETCH_READ, 0x80000500, 2, 0x09},
+	{SCORPIONL2_CSYS_WRITE_1BEAT, 0x80050000, 2, 0x0a},
+	{SCORPIONL2_CSYS_WRITE_2BEAT, 0x85000000, 2, 0x0b},
+	{SCORPIONL2_AXI_READ_DATA_BEAT, 0x80000600, 2, 0x09},
+	{SCORPIONL2_AXI_WRITE_EVT1, 0x80060000, 2, 0x0a},
+	{SCORPIONL2_AXI_WRITE_EVT2, 0x86000000, 2, 0x0b},
+	{SCORPIONL2_LDREX_REQ, 0x80000007, 2, 0x08},
+	{SCORPIONL2_STREX_PASS, 0x80000700, 2, 0x09},
+	{SCORPIONL2_STREX_FAIL, 0x80070000, 2, 0x0a},
+	{SCORPIONL2_CPREAD, 0x80000008, 2, 0x08},
+	{SCORPIONL2_CPWRITE, 0x80000800, 2, 0x09},
+	{SCORPIONL2_BARRIER_REQ, 0x88000000, 2, 0x0b},
+
+	{SCORPIONL2_AXI_READ_SLVPORT, 0x80000001, 3, 0x0c},
+	{SCORPIONL2_AXI_WRITE_SLVPORT, 0x80000100, 3, 0x0d},
+	{SCORPIONL2_AXI_READ_SLVPORT_DATABEAT, 0x80010000, 3, 0x0e},
+	{SCORPIONL2_AXI_WRITE_SLVPORT_DATABEAT, 0x81000000, 3, 0x0f},
+
+	{SCORPIONL2_SNOOPKILL_PREFILTER, 0x80000001, 4, 0x10},
+	{SCORPIONL2_SNOOPKILL_FILTEROUT, 0x80000100, 4, 0x11},
+	{SCORPIONL2_SNOOPED_IC, 0x80000002, 4, 0x10},
+	{SCORPIONL2_SNOOPED_BP, 0x80000200, 4, 0x11},
+	{SCORPIONL2_SNOOPED_BARRIERS, 0x80020000, 4, 0x12},
+	{SCORPIONL2_SNOOPED_TLB, 0x82000000, 4, 0x13},
+};
+
+static struct pmu_hw_events *scorpion_l2_get_hw_events(void)
+{
+	return &scorpion_l2_pmu_hw_events;
+}
+static u32 scorpion_l2_read_l2pm0(void)
+{
+	u32 val;
+	asm volatile ("mrc p15, 3, %0, c15, c7, 0" : "=r" (val));
+	return val;
+}
+
+static void scorpion_l2_write_l2pm0(u32 val)
+{
+	asm volatile ("mcr p15, 3, %0, c15, c7, 0" : : "r" (val));
+}
+
+static u32 scorpion_l2_read_l2pm1(void)
+{
+	u32 val;
+	asm volatile ("mrc p15, 3, %0, c15, c7, 1" : "=r" (val));
+	return val;
+}
+
+static void scorpion_l2_write_l2pm1(u32 val)
+{
+	asm volatile ("mcr p15, 3, %0, c15, c7, 1" : : "r" (val));
+}
+
+static u32 scorpion_l2_read_l2pm2(void)
+{
+	u32 val;
+	asm volatile ("mrc p15, 3, %0, c15, c7, 2" : "=r" (val));
+	return val;
+}
+
+static void scorpion_l2_write_l2pm2(u32 val)
+{
+	asm volatile ("mcr p15, 3, %0, c15, c7, 2" : : "r" (val));
+}
+
+static u32 scorpion_l2_read_l2pm3(void)
+{
+	u32 val;
+	asm volatile ("mrc p15, 3, %0, c15, c7, 3" : "=r" (val));
+	return val;
+}
+
+static void scorpion_l2_write_l2pm3(u32 val)
+{
+	asm volatile ("mcr p15, 3, %0, c15, c7, 3" : : "r" (val));
+}
+
+static u32 scorpion_l2_read_l2pm4(void)
+{
+	u32 val;
+	asm volatile ("mrc p15, 3, %0, c15, c7, 4" : "=r" (val));
+	return val;
+}
+
+static void scorpion_l2_write_l2pm4(u32 val)
+{
+	asm volatile ("mcr p15, 3, %0, c15, c7, 4" : : "r" (val));
+}
+
+struct scorpion_scorpion_access_funcs {
+	u32(*read) (void);
+	void (*write) (u32);
+	void (*pre) (void);
+	void (*post) (void);
+};
+
+struct scorpion_scorpion_access_funcs scorpion_l2_func[] = {
+	{scorpion_l2_read_l2pm0, scorpion_l2_write_l2pm0, NULL, NULL},
+	{scorpion_l2_read_l2pm1, scorpion_l2_write_l2pm1, NULL, NULL},
+	{scorpion_l2_read_l2pm2, scorpion_l2_write_l2pm2, NULL, NULL},
+	{scorpion_l2_read_l2pm3, scorpion_l2_write_l2pm3, NULL, NULL},
+	{scorpion_l2_read_l2pm4, scorpion_l2_write_l2pm4, NULL, NULL},
+};
+
+#define COLMN0MASK 0x000000ff
+#define COLMN1MASK 0x0000ff00
+#define COLMN2MASK 0x00ff0000
+
+static u32 scorpion_l2_get_columnmask(u32 setval)
+{
+	if (setval & COLMN0MASK)
+		return 0xffffff00;
+	else if (setval & COLMN1MASK)
+		return 0xffff00ff;
+	else if (setval & COLMN2MASK)
+		return 0xff00ffff;
+	else
+		return 0x80ffffff;
+}
+
+static void scorpion_l2_evt_setup(u32 gr, u32 setval)
+{
+	u32 val;
+	if (scorpion_l2_func[gr].pre)
+		scorpion_l2_func[gr].pre();
+	val = scorpion_l2_get_columnmask(setval) & scorpion_l2_func[gr].read();
+	val = val | setval;
+	scorpion_l2_func[gr].write(val);
+	if (scorpion_l2_func[gr].post)
+		scorpion_l2_func[gr].post();
+}
+
+#define SCORPION_L2_EVT_START_IDX 0x90
+#define SCORPION_L2_INV_EVTYPE 0
+
+static unsigned int get_scorpion_l2_evtinfo(unsigned int evt_type,
+				      struct scorpion_l2_scorp_evt *evtinfo)
+{
+	u32 idx;
+	u8 prefix;
+	u8 reg;
+	u8 code;
+	u8 group;
+
+	prefix = (evt_type & 0xF0000) >> 16;
+	if (prefix == SCORPION_L2_EVT_PREFIX) {
+		reg   = (evt_type & 0x0F000) >> 12;
+		code  = (evt_type & 0x00FF0) >> 4;
+		group =  evt_type & 0x0000F;
+
+		if ((group > 3) || (reg > SCORPION_MAX_L2_REG))
+			return SCORPION_L2_INV_EVTYPE;
+
+		evtinfo->val = 0x80000000 | (code << (group * 8));
+		evtinfo->grp = reg;
+		evtinfo->evt_type_act = group | (reg << 2);
+		return evtinfo->evt_type_act;
+	}
+
+	if (evt_type < SCORPION_L2_EVT_START_IDX
+			|| evt_type >= SCORPION_L2_MAX_EVT)
+		return SCORPION_L2_INV_EVTYPE;
+
+	idx = evt_type - SCORPION_L2_EVT_START_IDX;
+
+	if (sc_evt[idx].evt_type == evt_type) {
+		evtinfo->val = sc_evt[idx].val;
+		evtinfo->grp = sc_evt[idx].grp;
+		evtinfo->evt_type_act = sc_evt[idx].evt_type_act;
+		return sc_evt[idx].evt_type_act;
+	}
+	return SCORPION_L2_INV_EVTYPE;
+}
+
+static inline void scorpion_l2_pmnc_write(unsigned long val)
+{
+	val &= 0xff;
+	asm volatile ("mcr p15, 3, %0, c15, c4, 0" : : "r" (val));
+}
+
+static inline unsigned long scorpion_l2_pmnc_read(void)
+{
+	u32 val;
+	asm volatile ("mrc p15, 3, %0, c15, c4, 0" : "=r" (val));
+	return val;
+}
+
+static void scorpion_l2_set_evcntcr(void)
+{
+	u32 val = 0x0;
+	asm volatile ("mcr p15, 3, %0, c15, c6, 4" : : "r" (val));
+}
+
+static inline void scorpion_l2_set_evtyper(int ctr, int val)
+{
+	/* select ctr */
+	asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (ctr));
+
+	/* write into EVTYPER */
+	asm volatile ("mcr p15, 3, %0, c15, c6, 7" : : "r" (val));
+}
+
+static void scorpion_l2_set_evfilter_task_mode(void)
+{
+	u32 filter_val = 0x000f0030 | 1 << smp_processor_id();
+
+	asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
+}
+
+static void scorpion_l2_set_evfilter_sys_mode(void)
+{
+	u32 filter_val = 0x000f003f;
+
+	asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
+}
+
+static void scorpion_l2_enable_intenset(u32 idx)
+{
+	if (idx == SCORPION_L2CYCLE_CTR_EVENT_IDX) {
+		asm volatile ("mcr p15, 3, %0, c15, c5, 1" : : "r"
+			      (1 << SCORPION_L2CYCLE_CTR_BIT));
+	} else {
+		asm volatile ("mcr p15, 3, %0, c15, c5, 1" : : "r" (1 << idx));
+	}
+}
+
+static void scorpion_l2_disable_intenclr(u32 idx)
+{
+	if (idx == SCORPION_L2CYCLE_CTR_EVENT_IDX) {
+		asm volatile ("mcr p15, 3, %0, c15, c5, 0" : : "r"
+			      (1 << SCORPION_L2CYCLE_CTR_BIT));
+	} else {
+		asm volatile ("mcr p15, 3, %0, c15, c5, 0" : : "r" (1 << idx));
+	}
+}
+
+static void scorpion_l2_enable_counter(u32 idx)
+{
+	if (idx == SCORPION_L2CYCLE_CTR_EVENT_IDX) {
+		asm volatile ("mcr p15, 3, %0, c15, c4, 3" : : "r"
+			      (1 << SCORPION_L2CYCLE_CTR_BIT));
+	} else {
+		asm volatile ("mcr p15, 3, %0, c15, c4, 3" : : "r" (1 << idx));
+	}
+}
+
+static void scorpion_l2_disable_counter(u32 idx)
+{
+	if (idx == SCORPION_L2CYCLE_CTR_EVENT_IDX) {
+		asm volatile ("mcr p15, 3, %0, c15, c4, 2" : : "r"
+			      (1 << SCORPION_L2CYCLE_CTR_BIT));
+	} else {
+		asm volatile ("mcr p15, 3, %0, c15, c4, 2" : : "r" (1 << idx));
+	}
+}
+
+static u32 scorpion_l2_read_counter(int idx)
+{
+	u32 val;
+	unsigned long iflags;
+
+	if (idx == SCORPION_L2CYCLE_CTR_EVENT_IDX) {
+		asm volatile ("mrc p15, 3, %0, c15, c4, 5" : "=r" (val));
+	} else {
+		raw_spin_lock_irqsave(&scorpion_l2_pmu_hw_events.pmu_lock,
+				iflags);
+		asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (idx));
+
+		/* read val from counter */
+		asm volatile ("mrc p15, 3, %0, c15, c6, 5" : "=r" (val));
+		raw_spin_unlock_irqrestore(&scorpion_l2_pmu_hw_events.pmu_lock,
+				iflags);
+	}
+
+	return val;
+}
+
+static void scorpion_l2_write_counter(int idx, u32 val)
+{
+	unsigned long iflags;
+
+	if (idx == SCORPION_L2CYCLE_CTR_EVENT_IDX) {
+		asm volatile ("mcr p15, 3, %0, c15, c4, 5" : : "r" (val));
+	} else {
+		raw_spin_lock_irqsave(&scorpion_l2_pmu_hw_events.pmu_lock,
+				iflags);
+
+		/* select counter */
+		asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (idx));
+
+		/* write val into counter */
+		asm volatile ("mcr p15, 3, %0, c15, c6, 5" : : "r" (val));
+		raw_spin_unlock_irqrestore(&scorpion_l2_pmu_hw_events.pmu_lock,
+				iflags);
+	}
+}
+
+static void scorpion_l2_stop_counter(struct hw_perf_event *hwc, int idx)
+{
+	scorpion_l2_disable_intenclr(idx);
+	scorpion_l2_disable_counter(idx);
+	pr_debug("%s: event: %ld ctr: %d stopped\n", __func__,
+			hwc->config_base, idx);
+}
+
+static void scorpion_l2_enable(struct hw_perf_event *hwc, int idx, int cpu)
+{
+	struct scorpion_l2_scorp_evt evtinfo;
+	int evtype = hwc->config_base;
+	int ev_typer;
+	unsigned long iflags;
+
+	raw_spin_lock_irqsave(&scorpion_l2_pmu_hw_events.pmu_lock, iflags);
+
+	if (hwc->config_base == SCORPION_L2CYCLE_CTR_RAW_CODE)
+		goto out;
+
+	memset(&evtinfo, 0, sizeof(evtinfo));
+
+	ev_typer = get_scorpion_l2_evtinfo(evtype, &evtinfo);
+
+	scorpion_l2_set_evtyper(idx, ev_typer);
+
+	scorpion_l2_set_evcntcr();
+
+	if (cpu < 0)
+		scorpion_l2_set_evfilter_task_mode();
+	else
+		scorpion_l2_set_evfilter_sys_mode();
+
+	scorpion_l2_evt_setup(evtinfo.grp, evtinfo.val);
+
+out:
+
+	scorpion_l2_enable_intenset(idx);
+
+	scorpion_l2_enable_counter(idx);
+
+	raw_spin_unlock_irqrestore(&scorpion_l2_pmu_hw_events.pmu_lock, iflags);
+
+	pr_debug("%s: ctr: %d group: %ld group_code: %lld started from cpu:%d\n",
+	     __func__, idx, hwc->config_base, hwc->config, smp_processor_id());
+}
+
+static void scorpion_l2_disable(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long iflags;
+
+	raw_spin_lock_irqsave(&scorpion_l2_pmu_hw_events.pmu_lock, iflags);
+
+	scorpion_l2_stop_counter(hwc, idx);
+
+	raw_spin_unlock_irqrestore(&scorpion_l2_pmu_hw_events.pmu_lock, iflags);
+
+	pr_debug("%s: event: %ld deleted\n", __func__, hwc->config_base);
+}
+
+static int scorpion_l2_get_event_idx(struct pmu_hw_events *cpuc,
+				  struct hw_perf_event *hwc)
+{
+	int ctr = 0;
+
+	if (hwc->config_base == SCORPION_L2CYCLE_CTR_RAW_CODE) {
+		if (!test_and_set_bit(SCORPION_L2CYCLE_CTR_EVENT_IDX,
+					cpuc->used_mask))
+			return SCORPION_L2CYCLE_CTR_EVENT_IDX;
+	}
+
+	for (ctr = 0; ctr < MAX_SCORPION_L2_CTRS - 1; ctr++) {
+		if (!test_and_set_bit(ctr, cpuc->used_mask))
+			return ctr;
+	}
+
+	return -EAGAIN;
+}
+
+static void scorpion_l2_start(void)
+{
+	isb();
+	/* Enable all counters */
+	scorpion_l2_pmnc_write(scorpion_l2_pmnc_read() | SCORPIONL2_PMNC_E);
+}
+
+static void scorpion_l2_stop(void)
+{
+	/* Disable all counters */
+	scorpion_l2_pmnc_write(scorpion_l2_pmnc_read() & ~SCORPIONL2_PMNC_E);
+	isb();
+}
+
+static inline u32 scorpion_l2_get_reset_pmovsr(void)
+{
+	u32 val;
+
+	/* Read */
+	asm volatile ("mrc p15, 3, %0, c15, c4, 1" : "=r" (val));
+
+	/* Write to clear flags */
+	val &= 0xffffffff;
+	asm volatile ("mcr p15, 3, %0, c15, c4, 1" : : "r" (val));
+
+	return val;
+}
+
+static irqreturn_t scorpion_l2_handle_irq(int irq_num, void *dev)
+{
+	unsigned long pmovsr;
+	struct perf_sample_data data;
+	struct pt_regs *regs;
+	struct perf_event *event;
+	struct hw_perf_event *hwc;
+	int bitp;
+	int idx = 0;
+
+	pmovsr = scorpion_l2_get_reset_pmovsr();
+
+	if (!(pmovsr & 0xffffffff))
+		return IRQ_NONE;
+
+	regs = get_irq_regs();
+
+	perf_sample_data_init(&data, 0);
+
+	while (pmovsr) {
+		bitp = __ffs(pmovsr);
+
+		if (bitp == SCORPION_L2CYCLE_CTR_BIT)
+			idx = SCORPION_L2CYCLE_CTR_EVENT_IDX;
+		else
+			idx = bitp;
+
+		event = scorpion_l2_pmu_hw_events.events[idx];
+
+		if (!event)
+			goto next;
+
+		if (!test_bit(idx, scorpion_l2_pmu_hw_events.used_mask))
+			goto next;
+
+		hwc = &event->hw;
+
+		armpmu_event_update(event, hwc, idx);
+
+		data.period = event->hw.last_period;
+
+		if (!armpmu_event_set_period(event, hwc, idx))
+			goto next;
+
+		if (perf_event_overflow(event, &data, regs))
+			scorpion_l2_disable_counter(hwc->idx);
+next:
+		pmovsr &= (pmovsr - 1);
+	}
+
+	irq_work_run();
+
+	return IRQ_HANDLED;
+}
+
+static int scorpion_l2_map_event(struct perf_event *event)
+{
+	if (pmu_type > 0 && pmu_type == event->attr.type)
+		return event->attr.config & 0xfffff;
+	else
+		return -ENOENT;
+}
+
+static int
+scorpion_l2_pmu_generic_request_irq(int irq, irq_handler_t *handle_irq)
+{
+	return request_irq(irq, *handle_irq,
+			IRQF_DISABLED | IRQF_NOBALANCING,
+			"scorpion-l2-armpmu", NULL);
+}
+
+static void
+scorpion_l2_pmu_generic_free_irq(int irq)
+{
+	if (irq >= 0)
+		free_irq(irq, NULL);
+}
+
+static struct arm_pmu scorpion_l2_pmu = {
+	.id		=	ARM_PERF_PMU_ID_SCORPIONMP_L2,
+	.type		=	ARM_PMU_DEVICE_L2CC,
+	.name		=	"Scorpion L2CC PMU",
+	.start		=	scorpion_l2_start,
+	.stop		=	scorpion_l2_stop,
+	.handle_irq	=	scorpion_l2_handle_irq,
+	.request_pmu_irq	= scorpion_l2_pmu_generic_request_irq,
+	.free_pmu_irq		= scorpion_l2_pmu_generic_free_irq,
+	.enable		=	scorpion_l2_enable,
+	.disable	=	scorpion_l2_disable,
+	.read_counter	=	scorpion_l2_read_counter,
+	.get_event_idx	=	scorpion_l2_get_event_idx,
+	.write_counter	=	scorpion_l2_write_counter,
+	.map_event	=	scorpion_l2_map_event,
+	.max_period	=	(1LLU << 32) - 1,
+	.get_hw_events	=	scorpion_l2_get_hw_events,
+	.num_events	=	MAX_SCORPION_L2_CTRS,
+};
+
+static int __devinit scorpion_l2_pmu_device_probe(struct platform_device *pdev)
+{
+	scorpion_l2_pmu.plat_device = pdev;
+
+	if (!armpmu_register(&scorpion_l2_pmu, "scorpion-l2", -1))
+		pmu_type = scorpion_l2_pmu.pmu.type;
+
+	return 0;
+}
+
+static struct platform_driver scorpion_l2_pmu_driver = {
+	.driver		= {
+		.name	= "l2-arm-pmu",
+	},
+	.probe		= scorpion_l2_pmu_device_probe,
+};
+
+static int __init register_scorpion_l2_pmu_driver(void)
+{
+	/* Avoid spurious interrupt if any */
+	scorpion_l2_get_reset_pmovsr();
+
+	return platform_driver_register(&scorpion_l2_pmu_driver);
+}
+device_initcall(register_scorpion_l2_pmu_driver);
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index b40c0c7..49e63aa 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -202,8 +202,6 @@
 	pen_release = cpu_logical_map(cpu);
 	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
 	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
-	__asm__("sev");
-	mb();
 
 	/*
 	 * Send the secondary CPU a soft interrupt, thereby causing
diff --git a/arch/arm/mach-msm/pm-stats.c b/arch/arm/mach-msm/pm-stats.c
index 936820a..675febb 100644
--- a/arch/arm/mach-msm/pm-stats.c
+++ b/arch/arm/mach-msm/pm-stats.c
@@ -188,18 +188,19 @@
 	int ret;
 	unsigned long flags;
 	unsigned int cpu;
+	size_t len = strnlen(MSM_PM_STATS_RESET, sizeof(MSM_PM_STATS_RESET));
 
 	if (count < sizeof(MSM_PM_STATS_RESET)) {
 		ret = -EINVAL;
 		goto write_proc_failed;
 	}
 
-	if (copy_from_user(buf, buffer, sizeof(MSM_PM_STATS_RESET))) {
+	if (copy_from_user(buf, buffer, len)) {
 		ret = -EFAULT;
 		goto write_proc_failed;
 	}
 
-	if (memcmp(buf, MSM_PM_STATS_RESET, sizeof(MSM_PM_STATS_RESET))) {
+	if (strncmp(buf, MSM_PM_STATS_RESET, len)) {
 		ret = -EINVAL;
 		goto write_proc_failed;
 	}
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index 1f82468..5e339da 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -33,7 +33,7 @@
 
 static struct platform_device l2_pmu_device = {
 	.name		= "l2-arm-pmu",
-	.id		= ARM_PMU_DEVICE_L2,
+	.id		= ARM_PMU_DEVICE_L2CC,
 	.resource	= l2_pmu_resource,
 	.num_resources	= ARRAY_SIZE(l2_pmu_resource),
 };
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index cee8f04..2ea1bc9 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -1,4 +1,3 @@
-obj-y += rtac.o
 ifdef CONFIG_ARCH_MSM8X60
 obj-y += audio_dev_ctl.o
 obj-y += board-msm8x60-audio.o
@@ -13,10 +12,15 @@
 endif
 obj-$(CONFIG_MSM_QDSP6_APR) += apr.o apr_tal.o q6core.o dsp_debug.o
 obj-y += audio_acdb.o
-ifndef CONFIG_ARCH_MSM9615
-obj-y += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
-obj-y += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
-obj-$(CONFIG_MSM_QDSP6_CODECS) += q6audio_v1.o q6audio_v1_aio.o
-obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/
-obj-y += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
+ifdef CONFIG_ARCH_MSM9615
+obj-y += rtac.o
 endif
+obj-$(CONFIG_MSM_QDSP6_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
+obj-$(CONFIG_MSM_QDSP6_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
+obj-$(CONFIG_MSM_QDSP6_CODECS) += rtac.o q6audio_v1.o q6audio_v1_aio.o
+obj-$(CONFIG_MSM_QDSP6_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += rtac_v2.o q6audio_v2.o q6audio_v2_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
+obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_common.h b/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
index e108de5..fc20847 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
@@ -15,8 +15,13 @@
 #ifndef __Q6_AUDIO_COMMON_H__
 #define __Q6_AUDIO_COMMON_H__
 
+#ifdef CONFIG_ARCH_MSMCOPPER
+#include <sound/apr_audio-v2.h>
+#include <sound/q6asm-v2.h>
+#else
 #include <sound/apr_audio.h>
 #include <sound/q6asm.h>
+#endif
 
 void q6_audio_cb(uint32_t opcode, uint32_t token,
 		uint32_t *payload, void *priv);
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_v2.c b/arch/arm/mach-msm/qdsp6v2/q6audio_v2.c
new file mode 100644
index 0000000..0db1ef4
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_v2.c
@@ -0,0 +1,90 @@
+/* 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/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <asm/atomic.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+void q6asm_in_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_in *audio = (struct q6audio_in *)priv;
+	unsigned long flags;
+
+	pr_debug("%s:session id %d: opcode[0x%x]\n", __func__,
+			audio->ac->session, opcode);
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+	switch (opcode) {
+	case ASM_DATA_EVENT_READ_DONE_V2:
+		audio_in_get_dsp_frames(audio, token, payload);
+		break;
+	case ASM_DATA_EVENT_WRITE_DONE_V2:
+		atomic_inc(&audio->in_count);
+		wake_up(&audio->write_wait);
+		break;
+	case ASM_DATA_EVENT_RENDERED_EOS:
+		audio->eos_rsp = 1;
+		wake_up(&audio->read_wait);
+		break;
+	case ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2:
+		break;
+	case ASM_SESSION_EVENTX_OVERFLOW:
+		pr_err("%s:session id %d: ASM_SESSION_EVENT_TX_OVERFLOW\n",
+			__func__, audio->ac->session);
+		break;
+	default:
+		pr_debug("%s:session id %d: Ignore opcode[0x%x]\n", __func__,
+			audio->ac->session, opcode);
+		break;
+	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
+}
+
+void  audio_in_get_dsp_frames(void *priv,
+	uint32_t token,	uint32_t *payload)
+{
+	struct q6audio_in *audio = (struct q6audio_in *)priv;
+	uint32_t index;
+
+	index = token;
+	pr_debug("%s:session id %d: index=%d nr frames=%d offset[%d]\n",
+			__func__, audio->ac->session, token, payload[9],
+			payload[5]);
+	pr_debug("%s:session id %d: timemsw=%d lsw=%d\n", __func__,
+			audio->ac->session, payload[7], payload[6]);
+	pr_debug("%s:session id %d: uflags=0x%8x uid=0x%8x\n", __func__,
+			audio->ac->session, payload[8], payload[10]);
+	pr_debug("%s:session id %d: enc_framesotal_size=0x%8x\n", __func__,
+			audio->ac->session, payload[4]);
+
+	audio->out_frame_info[index][0] = payload[9];
+	audio->out_frame_info[index][1] = payload[5];
+
+	/* statistics of read */
+	atomic_add(payload[4], &audio->in_bytes);
+	atomic_add(payload[9], &audio->in_samples);
+
+	if (atomic_read(&audio->out_count) <= audio->str_cfg.buffer_count) {
+		atomic_inc(&audio->out_count);
+		wake_up(&audio->read_wait);
+	}
+}
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c b/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
new file mode 100644
index 0000000..aab7b19
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
@@ -0,0 +1,112 @@
+/* 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/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <asm/atomic.h>
+#include <asm/ioctls.h>
+#include "audio_utils_aio.h"
+
+void q6_audio_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+
+	pr_debug("%s:opcode = %x token = 0x%x\n", __func__, opcode, token);
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE_V2:
+	case ASM_DATA_EVENT_READ_DONE_V2:
+	case ASM_DATA_EVENT_RENDERED_EOS:
+	case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
+	case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
+	case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
+	case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY:
+		audio_aio_cb(opcode, token, payload, audio);
+		break;
+	default:
+		pr_debug("%s:Unhandled event = 0x%8x\n", __func__, opcode);
+		break;
+	}
+}
+
+void audio_aio_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload,  void *priv/*struct q6audio_aio *audio*/)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+	union msm_audio_event_payload e_payload;
+
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE_V2:
+		pr_debug("%s[%p]:ASM_DATA_EVENT_WRITE_DONE token = 0x%x\n",
+			__func__, audio, token);
+		audio_aio_async_write_ack(audio, token, payload);
+		break;
+	case ASM_DATA_EVENT_READ_DONE_V2:
+		pr_debug("%s[%p]:ASM_DATA_EVENT_READ_DONE token = 0x%x\n",
+			__func__, audio, token);
+		audio_aio_async_read_ack(audio, token, payload);
+		break;
+	case ASM_DATA_EVENT_RENDERED_EOS:
+		/* EOS Handle */
+		pr_debug("%s[%p]:ASM_DATA_CMDRSP_EOS\n", __func__, audio);
+		if (audio->feedback) { /* Non-Tunnel mode */
+			audio->eos_rsp = 1;
+			/* propagate input EOS i/p buffer,
+			after receiving DSP acknowledgement */
+			if (audio->eos_flag &&
+				(audio->eos_write_payload.aio_buf.buf_addr)) {
+				audio_aio_post_event(audio,
+						AUDIO_EVENT_WRITE_DONE,
+						audio->eos_write_payload);
+				memset(&audio->eos_write_payload , 0,
+					sizeof(union msm_audio_event_payload));
+				audio->eos_flag = 0;
+			}
+		} else { /* Tunnel mode */
+			audio->eos_rsp = 1;
+			wake_up(&audio->write_wait);
+			wake_up(&audio->cmd_wait);
+		}
+		break;
+	case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
+	case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
+		pr_debug("%s[%p]:payload0[%x] payloa1d[%x]opcode= 0x%x\n",
+			__func__, audio, payload[0], payload[1], opcode);
+		break;
+	case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
+	case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY:
+
+		pr_debug("%s[%p]: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0]-sr = %d, payload[1]-chl = %d, payload[2] = %d, payload[3] = %d\n",
+					 __func__, audio, payload[0],
+					 payload[1], payload[2], payload[3]);
+
+		pr_debug("%s[%p]: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, sr(prev) = %d, chl(prev) = %d,",
+				__func__, audio, audio->pcm_cfg.sample_rate,
+				audio->pcm_cfg.channel_count);
+
+		audio->pcm_cfg.sample_rate = payload[0];
+		audio->pcm_cfg.channel_count = payload[1] & 0xFFFF;
+		e_payload.stream_info.chan_info = audio->pcm_cfg.channel_count;
+		e_payload.stream_info.sample_rate = audio->pcm_cfg.sample_rate;
+		audio_aio_post_event(audio, AUDIO_EVENT_STREAM_INFO, e_payload);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 4ce9b030..8808375 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -22,8 +22,8 @@
 #include <asm/atomic.h>
 #include <mach/qdsp6v2/audio_acdb.h>
 #include <mach/qdsp6v2/rtac.h>
-#include <sound/q6asm.h>
-#include <sound/q6adm.h>
+#include "q6audio_common.h"
+#include <sound/q6afe.h>
 
 #ifndef CONFIG_RTAC
 
@@ -400,10 +400,8 @@
 	memcpy(rtac_adm_buffer, &payload_size, sizeof(u32));
 	if (payload_size != 0) {
 		if (payload_size > rtac_adm_user_buf_size) {
-			pr_err("%s: Buffer set not big enough for "
-				"returned data, buf size = %d, "
-				"ret data = %d\n", __func__,
-				rtac_adm_user_buf_size, payload_size);
+			pr_err("%s: Buffer set not big enough for returned data, buf size = %d,ret data = %d\n",
+				__func__, rtac_adm_user_buf_size, payload_size);
 			goto done;
 		}
 		memcpy(rtac_adm_buffer + sizeof(u32), payload, payload_size);
@@ -414,20 +412,20 @@
 
 u32 send_adm_apr(void *buf, u32 opcode)
 {
-	s32				result;
-	u32				count = 0;
-	u32				bytes_returned = 0;
-	u32				port_index = 0;
-	u32				copp_id;
-	u32				payload_size;
-	struct apr_hdr			adm_params;
+	s32	result;
+	u32	count = 0;
+	u32	bytes_returned = 0;
+	u32	port_index = 0;
+	u32	copp_id;
+	u32	payload_size;
+	struct apr_hdr	adm_params;
 	pr_debug("%s\n", __func__);
 
 	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
-			pr_err("%s: Copy to user failed! buf = 0x%x\n",
-			       __func__, (unsigned int)buf);
-			result = -EFAULT;
-			goto done;
+		pr_err("%s: Copy to user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		result = -EFAULT;
+		goto done;
 	}
 
 	if (count <= 0) {
@@ -443,9 +441,8 @@
 
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
-
-			pr_err("%s: Invalid payload size = %d\n",
-				__func__, payload_size);
+		pr_err("%s: Invalid payload size = %d\n",
+			__func__, payload_size);
 		goto done;
 	}
 
@@ -521,9 +518,9 @@
 
 	if (rtac_adm_payload_size != 0) {
 		if (copy_to_user(buf, rtac_adm_buffer,
-				rtac_adm_payload_size + sizeof(u32))) {
-			pr_err("%s: Could not copy buffer to user,"
-				"size = %d\n", __func__, payload_size);
+			rtac_adm_payload_size + sizeof(u32))) {
+			pr_err("%s: Could not copy buffer to user, size = %d\n",
+				 __func__, payload_size);
 			goto done;
 		}
 	}
@@ -573,10 +570,8 @@
 	memcpy(rtac_asm_buffer, &payload_size, sizeof(u32));
 	if (payload_size) {
 		if (payload_size > rtac_asm_user_buf_size) {
-			pr_err("%s: Buffer set not big enough for "
-				"returned data, buf size = %d, "
-				"ret data = %d\n", __func__,
-				rtac_asm_user_buf_size, payload_size);
+			pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
+			 __func__, rtac_asm_user_buf_size, payload_size);
 			goto done;
 		}
 		memcpy(rtac_asm_buffer + sizeof(u32), payload, payload_size);
@@ -587,19 +582,19 @@
 
 u32 send_rtac_asm_apr(void *buf, u32 opcode)
 {
-	s32				result;
-	u32				count = 0;
-	u32				bytes_returned = 0;
-	u32				session_id = 0;
-	u32				payload_size;
-	struct apr_hdr			asm_params;
+	s32	result;
+	u32	count = 0;
+	u32	bytes_returned = 0;
+	u32	session_id = 0;
+	u32	payload_size;
+	struct apr_hdr	asm_params;
 	pr_debug("%s\n", __func__);
 
 	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
-			pr_err("%s: Copy to user failed! buf = 0x%x\n",
-			       __func__, (unsigned int)buf);
-			result = -EFAULT;
-			goto done;
+		pr_err("%s: Copy to user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		result = -EFAULT;
+		goto done;
 	}
 
 	if (count <= 0) {
@@ -614,9 +609,8 @@
 	}
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
-
-			pr_err("%s: Invalid payload size = %d\n",
-				__func__, payload_size);
+		pr_err("%s: Invalid payload size = %d\n",
+			__func__, payload_size);
 		goto done;
 	}
 
@@ -643,7 +637,7 @@
 
 	/* Copy buffer to in-band payload */
 	if (copy_from_user(rtac_asm_buffer + sizeof(asm_params),
-			buf + 3 * sizeof(u32), payload_size)) {
+		buf + 3 * sizeof(u32), payload_size)) {
 		pr_err("%s: Could not copy payload from user buffer\n",
 			__func__);
 		goto err;
@@ -691,9 +685,9 @@
 
 	if (rtac_asm_payload_size != 0) {
 		if (copy_to_user(buf, rtac_asm_buffer,
-				rtac_asm_payload_size + sizeof(u32))) {
-			pr_err("%s: Could not copy buffer to user,"
-				"size = %d\n", __func__, payload_size);
+			rtac_asm_payload_size + sizeof(u32))) {
+			pr_err("%s: Could not copy buffer to user,size = %d\n",
+				 __func__, payload_size);
 			goto done;
 		}
 	}
@@ -715,7 +709,6 @@
 void rtac_set_voice_handle(u32 mode, void *handle)
 {
 	pr_debug("%s\n", __func__);
-
 	mutex_lock(&rtac_voice_apr_mutex);
 	rtac_voice_apr_data[mode].apr_handle = handle;
 	mutex_unlock(&rtac_voice_apr_mutex);
@@ -724,7 +717,7 @@
 bool rtac_make_voice_callback(u32 mode, uint32_t *payload, u32 payload_size)
 {
 	if ((atomic_read(&rtac_voice_apr_data[mode].cmd_state) != 1) ||
-			(mode >= RTAC_VOICE_MODES))
+		(mode >= RTAC_VOICE_MODES))
 		return false;
 
 	pr_debug("%s\n", __func__);
@@ -743,10 +736,8 @@
 	memcpy(rtac_voice_buffer, &payload_size, sizeof(u32));
 	if (payload_size) {
 		if (payload_size > rtac_voice_user_buf_size) {
-			pr_err("%s: Buffer set not big enough for "
-				"returned data, buf size = %d, "
-				"ret data = %d\n", __func__,
-				rtac_voice_user_buf_size, payload_size);
+			pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
+			 __func__, rtac_voice_user_buf_size, payload_size);
 			goto done;
 		}
 		memcpy(rtac_voice_buffer + sizeof(u32), payload, payload_size);
@@ -757,19 +748,19 @@
 
 u32 send_voice_apr(u32 mode, void *buf, u32 opcode)
 {
-	s32				result;
-	u32				count = 0;
-	u32				bytes_returned = 0;
-	u32				payload_size;
-	u16				dest_port;
-	struct apr_hdr			voice_params;
+	s32	result;
+	u32	count = 0;
+	u32	bytes_returned = 0;
+	u32	payload_size;
+	u16	dest_port;
+	struct	apr_hdr	voice_params;
 	pr_debug("%s\n", __func__);
 
 	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
-			pr_err("%s: Copy to user failed! buf = 0x%x\n",
-			       __func__, (unsigned int)buf);
-			result = -EFAULT;
-			goto done;
+		pr_err("%s: Copy to user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		result = -EFAULT;
+		goto done;
 	}
 
 	if (count <= 0) {
@@ -785,7 +776,7 @@
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
 		pr_err("%s: Invalid payload size = %d\n",
-				__func__, payload_size);
+			__func__, payload_size);
 		goto done;
 	}
 
@@ -812,7 +803,7 @@
 
 	/* Copy buffer to in-band payload */
 	if (copy_from_user(rtac_voice_buffer + sizeof(voice_params),
-			buf + 3 * sizeof(u32), payload_size)) {
+		buf + 3 * sizeof(u32), payload_size)) {
 		pr_err("%s: Could not copy payload from user buffer\n",
 			__func__);
 		goto err;
@@ -860,8 +851,8 @@
 	if (rtac_voice_payload_size != 0) {
 		if (copy_to_user(buf, rtac_voice_buffer,
 				rtac_voice_payload_size + sizeof(u32))) {
-			pr_err("%s: Could not copy buffer to user,"
-				"size = %d\n", __func__, payload_size);
+			pr_err("%s: Could not copy buffer to user,size = %d\n",
+						 __func__, payload_size);
 			goto done;
 		}
 	}
@@ -972,7 +963,7 @@
 	mutex_init(&rtac_adm_mutex);
 	mutex_init(&rtac_adm_apr_mutex);
 
-	rtac_adm_buffer = kmalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	rtac_adm_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
 	if (rtac_adm_buffer == NULL) {
 		pr_err("%s: Could not allocate payload of size = %d\n",
 			__func__, RTAC_BUF_SIZE);
@@ -987,10 +978,11 @@
 	}
 	mutex_init(&rtac_asm_apr_mutex);
 
-	rtac_asm_buffer = kmalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	rtac_asm_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
 	if (rtac_asm_buffer == NULL) {
 		pr_err("%s: Could not allocate payload of size = %d\n",
 			__func__, RTAC_BUF_SIZE);
+		kzfree(rtac_adm_buffer);
 		goto nomem;
 	}
 
@@ -1004,10 +996,12 @@
 	mutex_init(&rtac_voice_mutex);
 	mutex_init(&rtac_voice_apr_mutex);
 
-	rtac_voice_buffer = kmalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	rtac_voice_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
 	if (rtac_voice_buffer == NULL) {
 		pr_err("%s: Could not allocate payload of size = %d\n",
 			__func__, RTAC_BUF_SIZE);
+		kzfree(rtac_adm_buffer);
+		kzfree(rtac_asm_buffer);
 		goto nomem;
 	}
 
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac_v2.c b/arch/arm/mach-msm/qdsp6v2/rtac_v2.c
new file mode 100644
index 0000000..2d0607c
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/rtac_v2.c
@@ -0,0 +1,1019 @@
+/* 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/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/msm_audio_acdb.h>
+#include <asm/atomic.h>
+#include <mach/qdsp6v2/audio_acdb.h>
+#include <mach/qdsp6v2/rtac.h>
+#include "q6audio_common.h"
+#include <sound/q6afe-v2.h>
+
+#ifndef CONFIG_RTAC
+
+void rtac_add_adm_device(u32 port_id, u32 copp_id, u32 path_id, u32 popp_id) {}
+void rtac_remove_adm_device(u32 port_id) {}
+void rtac_remove_popp_from_adm_devices(u32 popp_id) {}
+void rtac_set_adm_handle(void *handle) {}
+bool rtac_make_adm_callback(uint32_t *payload, u32 payload_size)
+	{return false; }
+void rtac_set_asm_handle(u32 session_id, void *handle) {}
+bool rtac_make_asm_callback(u32 session_id, uint32_t *payload,
+	u32 payload_size) {return false; }
+void rtac_add_voice(u32 cvs_handle, u32 cvp_handle, u32 rx_afe_port,
+	u32 tx_afe_port, u32 session_id) {}
+void rtac_remove_voice(u32 cvs_handle) {}
+void rtac_set_voice_handle(u32 mode, void *handle) {}
+bool rtac_make_voice_callback(u32 mode, uint32_t *payload,
+		u32 payload_size) {return false; }
+
+#else
+
+#define VOICE_CMD_SET_PARAM		0x00011006
+#define VOICE_CMD_GET_PARAM		0x00011007
+#define VOICE_EVT_GET_PARAM_ACK		0x00011008
+
+/* Max size of payload (buf size - apr header) */
+#define MAX_PAYLOAD_SIZE		4076
+#define RTAC_MAX_ACTIVE_DEVICES		4
+#define RTAC_MAX_ACTIVE_VOICE_COMBOS	2
+#define RTAC_MAX_ACTIVE_POPP		8
+#define RTAC_BUF_SIZE			4096
+
+#define TIMEOUT_MS	1000
+
+/* APR data */
+struct rtac_apr_data {
+	void			*apr_handle;
+	atomic_t		cmd_state;
+	wait_queue_head_t	cmd_wait;
+};
+
+static struct rtac_apr_data	rtac_adm_apr_data;
+static struct rtac_apr_data	rtac_asm_apr_data[SESSION_MAX+1];
+static struct rtac_apr_data	rtac_voice_apr_data[RTAC_VOICE_MODES];
+
+
+/* ADM info & APR */
+struct rtac_adm_data {
+	uint32_t	topology_id;
+	uint32_t	afe_port;
+	uint32_t	copp;
+	uint32_t	num_of_popp;
+	uint32_t	popp[RTAC_MAX_ACTIVE_POPP];
+};
+
+struct rtac_adm {
+	uint32_t		num_of_dev;
+	struct rtac_adm_data	device[RTAC_MAX_ACTIVE_DEVICES];
+};
+static struct rtac_adm		rtac_adm_data;
+static u32			rtac_adm_payload_size;
+static u32			rtac_adm_user_buf_size;
+static u8			*rtac_adm_buffer;
+
+
+/* ASM APR */
+static u32			rtac_asm_payload_size;
+static u32			rtac_asm_user_buf_size;
+static u8			*rtac_asm_buffer;
+
+
+/* Voice info & APR */
+struct rtac_voice_data {
+	uint32_t	tx_topology_id;
+	uint32_t	rx_topology_id;
+	uint32_t	tx_afe_port;
+	uint32_t	rx_afe_port;
+	uint16_t	cvs_handle;
+	uint16_t	cvp_handle;
+};
+
+struct rtac_voice {
+	uint32_t		num_of_voice_combos;
+	struct rtac_voice_data	voice[RTAC_MAX_ACTIVE_VOICE_COMBOS];
+};
+
+static struct rtac_voice	rtac_voice_data;
+static u32			rtac_voice_payload_size;
+static u32			rtac_voice_user_buf_size;
+static u8			*rtac_voice_buffer;
+static u32			voice_session_id[RTAC_MAX_ACTIVE_VOICE_COMBOS];
+
+
+struct mutex			rtac_adm_mutex;
+struct mutex			rtac_adm_apr_mutex;
+struct mutex			rtac_asm_apr_mutex;
+struct mutex			rtac_voice_mutex;
+struct mutex			rtac_voice_apr_mutex;
+
+static int rtac_open(struct inode *inode, struct file *f)
+{
+	pr_debug("%s\n", __func__);
+	return 0;
+}
+
+static int rtac_release(struct inode *inode, struct file *f)
+{
+	pr_debug("%s\n", __func__);
+	return 0;
+}
+
+/* ADM Info */
+void add_popp(u32 dev_idx, u32 port_id, u32 popp_id)
+{
+	u32 i = 0;
+
+	for (; i < rtac_adm_data.device[dev_idx].num_of_popp; i++)
+		if (rtac_adm_data.device[dev_idx].popp[i] == popp_id)
+			goto done;
+
+	if (rtac_adm_data.device[dev_idx].num_of_popp ==
+			RTAC_MAX_ACTIVE_POPP) {
+		pr_err("%s, Max POPP!\n", __func__);
+		goto done;
+	}
+	rtac_adm_data.device[dev_idx].popp[
+		rtac_adm_data.device[dev_idx].num_of_popp++] = popp_id;
+done:
+	return;
+}
+
+void rtac_add_adm_device(u32 port_id, u32 copp_id, u32 path_id, u32 popp_id)
+{
+	u32 i = 0;
+	pr_debug("%s: port_id = %d, popp_id = %d\n", __func__, port_id,
+		popp_id);
+
+	mutex_lock(&rtac_adm_mutex);
+	if (rtac_adm_data.num_of_dev == RTAC_MAX_ACTIVE_DEVICES) {
+		pr_err("%s, Can't add anymore RTAC devices!\n", __func__);
+		goto done;
+	}
+
+	/* Check if device already added */
+	if (rtac_adm_data.num_of_dev != 0) {
+		for (; i < rtac_adm_data.num_of_dev; i++) {
+			if (rtac_adm_data.device[i].afe_port == port_id) {
+				add_popp(i, port_id, popp_id);
+				goto done;
+			}
+			if (rtac_adm_data.device[i].num_of_popp ==
+						RTAC_MAX_ACTIVE_POPP) {
+				pr_err("%s, Max POPP!\n", __func__);
+				goto done;
+			}
+		}
+	}
+
+	/* Add device */
+	rtac_adm_data.num_of_dev++;
+
+	if (path_id == ADM_PATH_PLAYBACK)
+		rtac_adm_data.device[i].topology_id =
+						get_adm_rx_topology();
+	else
+		rtac_adm_data.device[i].topology_id =
+						get_adm_tx_topology();
+	rtac_adm_data.device[i].afe_port = port_id;
+	rtac_adm_data.device[i].copp = copp_id;
+	rtac_adm_data.device[i].popp[
+		rtac_adm_data.device[i].num_of_popp++] = popp_id;
+done:
+	mutex_unlock(&rtac_adm_mutex);
+	return;
+}
+
+static void shift_adm_devices(u32 dev_idx)
+{
+	for (; dev_idx < rtac_adm_data.num_of_dev; dev_idx++) {
+		memcpy(&rtac_adm_data.device[dev_idx],
+			&rtac_adm_data.device[dev_idx + 1],
+			sizeof(rtac_adm_data.device[dev_idx]));
+		memset(&rtac_adm_data.device[dev_idx + 1], 0,
+			   sizeof(rtac_adm_data.device[dev_idx]));
+	}
+}
+
+static void shift_popp(u32 copp_idx, u32 popp_idx)
+{
+	for (; popp_idx < rtac_adm_data.device[copp_idx].num_of_popp;
+							popp_idx++) {
+		memcpy(&rtac_adm_data.device[copp_idx].popp[popp_idx],
+			&rtac_adm_data.device[copp_idx].popp[popp_idx + 1],
+			sizeof(uint32_t));
+		memset(&rtac_adm_data.device[copp_idx].popp[popp_idx + 1], 0,
+			   sizeof(uint32_t));
+	}
+}
+
+void rtac_remove_adm_device(u32 port_id)
+{
+	s32 i;
+	pr_debug("%s: port_id = %d\n", __func__, port_id);
+
+	mutex_lock(&rtac_adm_mutex);
+	/* look for device */
+	for (i = 0; i < rtac_adm_data.num_of_dev; i++) {
+		if (rtac_adm_data.device[i].afe_port == port_id) {
+			memset(&rtac_adm_data.device[i], 0,
+				   sizeof(rtac_adm_data.device[i]));
+			rtac_adm_data.num_of_dev--;
+
+			if (rtac_adm_data.num_of_dev >= 1) {
+				shift_adm_devices(i);
+				break;
+			}
+		}
+	}
+
+	mutex_unlock(&rtac_adm_mutex);
+	return;
+}
+
+void rtac_remove_popp_from_adm_devices(u32 popp_id)
+{
+	s32 i, j;
+	pr_debug("%s: popp_id = %d\n", __func__, popp_id);
+
+	mutex_lock(&rtac_adm_mutex);
+
+	for (i = 0; i < rtac_adm_data.num_of_dev; i++) {
+		for (j = 0; j < rtac_adm_data.device[i].num_of_popp; j++) {
+			if (rtac_adm_data.device[i].popp[j] == popp_id) {
+				rtac_adm_data.device[i].popp[j] = 0;
+				rtac_adm_data.device[i].num_of_popp--;
+				shift_popp(i, j);
+			}
+		}
+	}
+
+	mutex_unlock(&rtac_adm_mutex);
+}
+
+/* Voice Info */
+static void set_rtac_voice_data(int idx, u32 cvs_handle, u32 cvp_handle,
+					u32 rx_afe_port, u32 tx_afe_port,
+					u32 session_id)
+{
+	rtac_voice_data.voice[idx].tx_topology_id = get_voice_tx_topology();
+	rtac_voice_data.voice[idx].rx_topology_id = get_voice_rx_topology();
+	rtac_voice_data.voice[idx].tx_afe_port = tx_afe_port;
+	rtac_voice_data.voice[idx].rx_afe_port = rx_afe_port;
+	rtac_voice_data.voice[idx].cvs_handle = cvs_handle;
+	rtac_voice_data.voice[idx].cvp_handle = cvp_handle;
+
+	/* Store session ID for voice RTAC */
+	voice_session_id[idx] = session_id;
+}
+
+void rtac_add_voice(u32 cvs_handle, u32 cvp_handle, u32 rx_afe_port,
+			u32 tx_afe_port, u32 session_id)
+{
+	u32 i = 0;
+	pr_debug("%s\n", __func__);
+	mutex_lock(&rtac_voice_mutex);
+
+	if (rtac_voice_data.num_of_voice_combos ==
+			RTAC_MAX_ACTIVE_VOICE_COMBOS) {
+		pr_err("%s, Can't add anymore RTAC devices!\n", __func__);
+		goto done;
+	}
+
+	/* Check if device already added */
+	if (rtac_voice_data.num_of_voice_combos != 0) {
+		for (; i < rtac_voice_data.num_of_voice_combos; i++) {
+			if (rtac_voice_data.voice[i].cvs_handle ==
+							cvs_handle) {
+				set_rtac_voice_data(i, cvs_handle, cvp_handle,
+					rx_afe_port, tx_afe_port,
+					session_id);
+				goto done;
+			}
+		}
+	}
+
+	/* Add device */
+	rtac_voice_data.num_of_voice_combos++;
+	set_rtac_voice_data(i, cvs_handle, cvp_handle,
+				rx_afe_port, tx_afe_port,
+				session_id);
+done:
+	mutex_unlock(&rtac_voice_mutex);
+	return;
+}
+
+static void shift_voice_devices(u32 idx)
+{
+	for (; idx < rtac_voice_data.num_of_voice_combos - 1; idx++) {
+		memcpy(&rtac_voice_data.voice[idx],
+			&rtac_voice_data.voice[idx + 1],
+			sizeof(rtac_voice_data.voice[idx]));
+		voice_session_id[idx] = voice_session_id[idx + 1];
+	}
+}
+
+void rtac_remove_voice(u32 cvs_handle)
+{
+	u32 i = 0;
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&rtac_voice_mutex);
+	/* look for device */
+	for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
+		if (rtac_voice_data.voice[i].cvs_handle == cvs_handle) {
+			shift_voice_devices(i);
+			rtac_voice_data.num_of_voice_combos--;
+			memset(&rtac_voice_data.voice[
+				rtac_voice_data.num_of_voice_combos], 0,
+				sizeof(rtac_voice_data.voice
+				[rtac_voice_data.num_of_voice_combos]));
+			voice_session_id[rtac_voice_data.num_of_voice_combos]
+				= 0;
+			break;
+		}
+	}
+	mutex_unlock(&rtac_voice_mutex);
+	return;
+}
+
+static int get_voice_index(u32 cvs_handle)
+{
+	u32 i;
+
+	for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
+		if (rtac_voice_data.voice[i].cvs_handle == cvs_handle)
+			return i;
+	}
+
+	pr_err("%s: No voice index for CVS handle %d found returning 0\n",
+	       __func__, cvs_handle);
+	return 0;
+}
+
+
+/* ADM APR */
+void rtac_set_adm_handle(void *handle)
+{
+	pr_debug("%s: handle = %d\n", __func__, (unsigned int)handle);
+
+	mutex_lock(&rtac_adm_apr_mutex);
+	rtac_adm_apr_data.apr_handle = handle;
+	mutex_unlock(&rtac_adm_apr_mutex);
+}
+
+bool rtac_make_adm_callback(uint32_t *payload, u32 payload_size)
+{
+	pr_debug("%s:cmd_state = %d\n", __func__,
+			atomic_read(&rtac_adm_apr_data.cmd_state));
+	if (atomic_read(&rtac_adm_apr_data.cmd_state) != 1)
+		return false;
+
+	/* Offset data for in-band payload */
+	rtac_copy_adm_payload_to_user(payload, payload_size);
+	atomic_set(&rtac_adm_apr_data.cmd_state, 0);
+	wake_up(&rtac_adm_apr_data.cmd_wait);
+	return true;
+}
+
+void rtac_copy_adm_payload_to_user(void *payload, u32 payload_size)
+{
+	pr_debug("%s\n", __func__);
+	rtac_adm_payload_size = payload_size;
+
+	memcpy(rtac_adm_buffer, &payload_size, sizeof(u32));
+	if (payload_size != 0) {
+		if (payload_size > rtac_adm_user_buf_size) {
+			pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
+			 __func__, rtac_adm_user_buf_size, payload_size);
+			goto done;
+		}
+		memcpy(rtac_adm_buffer + sizeof(u32), payload, payload_size);
+	}
+done:
+	return;
+}
+
+u32 send_adm_apr(void *buf, u32 opcode)
+{
+	s32	result;
+	u32	count = 0;
+	u32	bytes_returned = 0;
+	u32	port_index = 0;
+	u32	copp_id;
+	u32	payload_size;
+	struct apr_hdr	adm_params;
+	pr_debug("%s\n", __func__);
+
+	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
+		pr_err("%s: Copy to user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		result = -EFAULT;
+		goto done;
+	}
+
+	if (count <= 0) {
+		pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+		goto done;
+	}
+
+	if (copy_from_user(&payload_size, buf + sizeof(u32), sizeof(u32))) {
+		pr_err("%s: Could not copy payload size from user buffer\n",
+			__func__);
+		goto done;
+	}
+
+
+	if (payload_size > MAX_PAYLOAD_SIZE) {
+		pr_err("%s: Invalid payload size = %d\n",
+			__func__, payload_size);
+		goto done;
+	}
+
+	if (copy_from_user(&copp_id, buf + 2 * sizeof(u32), sizeof(u32))) {
+		pr_err("%s: Could not copy port id from user buffer\n",
+			__func__);
+		goto done;
+	}
+
+	for (port_index = 0; port_index < AFE_MAX_PORTS; port_index++) {
+		if (adm_get_copp_id(port_index) == copp_id)
+			break;
+	}
+	if (port_index >= AFE_MAX_PORTS) {
+		pr_err("%s: Could not find port index for copp = %d\n",
+		       __func__, copp_id);
+		goto done;
+	}
+
+	mutex_lock(&rtac_adm_apr_mutex);
+	if (rtac_adm_apr_data.apr_handle == NULL) {
+		pr_err("%s: APR not initialized\n", __func__);
+		goto err;
+	}
+
+	/* Set globals for copy of returned payload */
+	rtac_adm_user_buf_size = count;
+	/* Copy buffer to in-band payload */
+	if (copy_from_user(rtac_adm_buffer + sizeof(adm_params),
+			buf + 3 * sizeof(u32), payload_size)) {
+		pr_err("%s: Could not copy payload from user buffer\n",
+			__func__);
+		goto err;
+	}
+
+	/* Pack header */
+	adm_params.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+		APR_HDR_LEN(20), APR_PKT_VER);
+	adm_params.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+		payload_size);
+	adm_params.src_svc = APR_SVC_ADM;
+	adm_params.src_domain = APR_DOMAIN_APPS;
+	adm_params.src_port = copp_id;
+	adm_params.dest_svc = APR_SVC_ADM;
+	adm_params.dest_domain = APR_DOMAIN_ADSP;
+	adm_params.dest_port = copp_id;
+	adm_params.token = copp_id;
+	adm_params.opcode = opcode;
+
+	memcpy(rtac_adm_buffer, &adm_params, sizeof(adm_params));
+	atomic_set(&rtac_adm_apr_data.cmd_state, 1);
+
+	pr_debug("%s: Sending RTAC command size = %d\n",
+		__func__, adm_params.pkt_size);
+
+	result = apr_send_pkt(rtac_adm_apr_data.apr_handle,
+		(uint32_t *)rtac_adm_buffer);
+	if (result < 0) {
+		pr_err("%s: Set params failed port = %d, copp = %d\n",
+			__func__, port_index, copp_id);
+		goto err;
+	}
+	/* Wait for the callback */
+	result = wait_event_timeout(rtac_adm_apr_data.cmd_wait,
+		(atomic_read(&rtac_adm_apr_data.cmd_state) == 0),
+		msecs_to_jiffies(TIMEOUT_MS));
+	mutex_unlock(&rtac_adm_apr_mutex);
+	if (!result) {
+		pr_err("%s: Set params timed out port = %d, copp = %d\n",
+			__func__, port_index, copp_id);
+		goto done;
+	}
+
+	if (rtac_adm_payload_size != 0) {
+		if (copy_to_user(buf, rtac_adm_buffer,
+			rtac_adm_payload_size + sizeof(u32))) {
+			pr_err("%s: Could not copy buffer to user,size = %d\n",
+				__func__, payload_size);
+			goto done;
+		}
+	}
+
+	/* Return data written for SET & data read for GET */
+	if (opcode == ADM_CMD_GET_PP_PARAMS_V5)
+		bytes_returned = rtac_adm_payload_size;
+	else
+		bytes_returned = payload_size;
+done:
+	return bytes_returned;
+err:
+	mutex_unlock(&rtac_adm_apr_mutex);
+	return bytes_returned;
+}
+
+
+/* ASM APR */
+void rtac_set_asm_handle(u32 session_id, void *handle)
+{
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&rtac_asm_apr_mutex);
+	rtac_asm_apr_data[session_id].apr_handle = handle;
+	mutex_unlock(&rtac_asm_apr_mutex);
+}
+
+bool rtac_make_asm_callback(u32 session_id, uint32_t *payload,
+	u32 payload_size)
+{
+	if (atomic_read(&rtac_asm_apr_data[session_id].cmd_state) != 1)
+		return false;
+
+	pr_debug("%s\n", __func__);
+	/* Offset data for in-band payload */
+	rtac_copy_asm_payload_to_user(payload, payload_size);
+	atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 0);
+	wake_up(&rtac_asm_apr_data[session_id].cmd_wait);
+	return true;
+}
+
+void rtac_copy_asm_payload_to_user(void *payload, u32 payload_size)
+{
+	pr_debug("%s\n", __func__);
+	rtac_asm_payload_size = payload_size;
+
+	memcpy(rtac_asm_buffer, &payload_size, sizeof(u32));
+	if (payload_size) {
+		if (payload_size > rtac_asm_user_buf_size) {
+			pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
+			 __func__, rtac_asm_user_buf_size, payload_size);
+			goto done;
+		}
+		memcpy(rtac_asm_buffer + sizeof(u32), payload, payload_size);
+	}
+done:
+	return;
+}
+
+u32 send_rtac_asm_apr(void *buf, u32 opcode)
+{
+	s32	result;
+	u32	count = 0;
+	u32	bytes_returned = 0;
+	u32	session_id = 0;
+	u32	payload_size;
+	struct apr_hdr		asm_params;
+	pr_debug("%s\n", __func__);
+
+	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
+		pr_err("%s: Copy to user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		result = -EFAULT;
+		goto done;
+	}
+
+	if (count <= 0) {
+		pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+		goto done;
+	}
+
+	if (copy_from_user(&payload_size, buf + sizeof(u32), sizeof(u32))) {
+		pr_err("%s: Could not copy payload size from user buffer\n",
+			__func__);
+		goto done;
+	}
+
+	if (payload_size > MAX_PAYLOAD_SIZE) {
+		pr_err("%s: Invalid payload size = %d\n",
+			__func__, payload_size);
+		goto done;
+	}
+
+	if (copy_from_user(&session_id, buf + 2 * sizeof(u32), sizeof(u32))) {
+		pr_err("%s: Could not copy session id from user buffer\n",
+			__func__);
+		goto done;
+	}
+	if (session_id > (SESSION_MAX + 1)) {
+		pr_err("%s: Invalid Session = %d\n", __func__, session_id);
+		goto done;
+	}
+
+	mutex_lock(&rtac_asm_apr_mutex);
+	if (session_id < SESSION_MAX+1) {
+		if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
+			pr_err("%s: APR not initialized\n", __func__);
+			goto err;
+		}
+	}
+
+	/* Set globals for copy of returned payload */
+	rtac_asm_user_buf_size = count;
+
+	/* Copy buffer to in-band payload */
+	if (copy_from_user(rtac_asm_buffer + sizeof(asm_params),
+			buf + 3 * sizeof(u32), payload_size)) {
+		pr_err("%s: Could not copy payload from user buffer\n",
+			__func__);
+		goto err;
+	}
+
+	/* Pack header */
+	asm_params.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+		APR_HDR_LEN(20), APR_PKT_VER);
+	asm_params.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+		payload_size);
+	asm_params.src_svc = q6asm_get_apr_service_id(session_id);
+	asm_params.src_domain = APR_DOMAIN_APPS;
+	asm_params.src_port = (session_id << 8) | 0x0001;
+	asm_params.dest_svc = APR_SVC_ASM;
+	asm_params.dest_domain = APR_DOMAIN_ADSP;
+	asm_params.dest_port = (session_id << 8) | 0x0001;
+	asm_params.token = session_id;
+	asm_params.opcode = opcode;
+
+	memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params));
+	if (session_id < SESSION_MAX+1)
+		atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);
+
+	pr_debug("%s: Sending RTAC command size = %d, session_id=%d\n",
+		__func__, asm_params.pkt_size, session_id);
+
+	result = apr_send_pkt(rtac_asm_apr_data[session_id].apr_handle,
+				(uint32_t *)rtac_asm_buffer);
+	if (result < 0) {
+		pr_err("%s: Set params failed session = %d\n",
+			__func__, session_id);
+		goto err;
+	}
+
+	/* Wait for the callback */
+	result = wait_event_timeout(rtac_asm_apr_data[session_id].cmd_wait,
+		(atomic_read(&rtac_asm_apr_data[session_id].cmd_state) == 0),
+		5 * HZ);
+	mutex_unlock(&rtac_asm_apr_mutex);
+	if (!result) {
+		pr_err("%s: Set params timed out session = %d\n",
+			__func__, session_id);
+		goto done;
+	}
+
+	if (rtac_asm_payload_size != 0) {
+		if (copy_to_user(buf, rtac_asm_buffer,
+			rtac_asm_payload_size + sizeof(u32))) {
+			pr_err("%s: Could not copy buffer to user,size = %d\n",
+				 __func__, payload_size);
+			goto done;
+		}
+	}
+
+	/* Return data written for SET & data read for GET */
+	if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS_V2)
+		bytes_returned = rtac_asm_payload_size;
+	else
+		bytes_returned = payload_size;
+done:
+	return bytes_returned;
+err:
+	mutex_unlock(&rtac_asm_apr_mutex);
+	return bytes_returned;
+}
+
+
+/* Voice APR */
+void rtac_set_voice_handle(u32 mode, void *handle)
+{
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&rtac_voice_apr_mutex);
+	rtac_voice_apr_data[mode].apr_handle = handle;
+	mutex_unlock(&rtac_voice_apr_mutex);
+}
+
+bool rtac_make_voice_callback(u32 mode, uint32_t *payload, u32 payload_size)
+{
+	if ((atomic_read(&rtac_voice_apr_data[mode].cmd_state) != 1) ||
+		(mode >= RTAC_VOICE_MODES))
+		return false;
+
+	pr_debug("%s\n", __func__);
+	/* Offset data for in-band payload */
+	rtac_copy_voice_payload_to_user(payload, payload_size);
+	atomic_set(&rtac_voice_apr_data[mode].cmd_state, 0);
+	wake_up(&rtac_voice_apr_data[mode].cmd_wait);
+	return true;
+}
+
+void rtac_copy_voice_payload_to_user(void *payload, u32 payload_size)
+{
+	pr_debug("%s\n", __func__);
+	rtac_voice_payload_size = payload_size;
+
+	memcpy(rtac_voice_buffer, &payload_size, sizeof(u32));
+	if (payload_size) {
+		if (payload_size > rtac_voice_user_buf_size) {
+			pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
+			 __func__, rtac_voice_user_buf_size, payload_size);
+			goto done;
+		}
+		memcpy(rtac_voice_buffer + sizeof(u32), payload, payload_size);
+	}
+done:
+	return;
+}
+
+u32 send_voice_apr(u32 mode, void *buf, u32 opcode)
+{
+	s32	result;
+	u32	count = 0;
+	u32	bytes_returned = 0;
+	u32	payload_size;
+	u16	dest_port;
+	struct apr_hdr		voice_params;
+	pr_debug("%s\n", __func__);
+
+	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
+		pr_err("%s: Copy to user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		result = -EFAULT;
+		goto done;
+	}
+
+	if (count <= 0) {
+		pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+		goto done;
+	}
+
+	if (copy_from_user(&payload_size, buf + sizeof(u32), sizeof(u32))) {
+		pr_err("%s: Could not copy payload size from user buffer\n",
+			__func__);
+		goto done;
+	}
+
+	if (payload_size > MAX_PAYLOAD_SIZE) {
+		pr_err("%s: Invalid payload size = %d\n",
+				__func__, payload_size);
+		goto done;
+	}
+
+	if (copy_from_user(&dest_port, buf + 2 * sizeof(u32), sizeof(u32))) {
+		pr_err("%s: Could not copy port id from user buffer\n",
+			__func__);
+		goto done;
+	}
+
+	if ((mode != RTAC_CVP) && (mode != RTAC_CVS)) {
+		pr_err("%s: Invalid Mode for APR, mode = %d\n",
+			__func__, mode);
+		goto done;
+	}
+
+	mutex_lock(&rtac_voice_apr_mutex);
+	if (rtac_voice_apr_data[mode].apr_handle == NULL) {
+		pr_err("%s: APR not initialized\n", __func__);
+		goto err;
+	}
+
+	/* Set globals for copy of returned payload */
+	rtac_voice_user_buf_size = count;
+
+	/* Copy buffer to in-band payload */
+	if (copy_from_user(rtac_voice_buffer + sizeof(voice_params),
+			buf + 3 * sizeof(u32), payload_size)) {
+		pr_err("%s: Could not copy payload from user buffer\n",
+			__func__);
+		goto err;
+	}
+
+	/* Pack header */
+	voice_params.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+		APR_HDR_LEN(20), APR_PKT_VER);
+	voice_params.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+		payload_size);
+	voice_params.src_svc = 0;
+	voice_params.src_domain = APR_DOMAIN_APPS;
+	voice_params.src_port = voice_session_id[
+					get_voice_index(dest_port)];
+	voice_params.dest_svc = 0;
+	voice_params.dest_domain = APR_DOMAIN_MODEM;
+	voice_params.dest_port = dest_port;
+	voice_params.token = 0;
+	voice_params.opcode = opcode;
+
+	memcpy(rtac_voice_buffer, &voice_params, sizeof(voice_params));
+	atomic_set(&rtac_voice_apr_data[mode].cmd_state, 1);
+
+	pr_debug("%s: Sending RTAC command size = %d, opcode = %x\n",
+		__func__, voice_params.pkt_size, opcode);
+
+	result = apr_send_pkt(rtac_voice_apr_data[mode].apr_handle,
+					(uint32_t *)rtac_voice_buffer);
+	if (result < 0) {
+		pr_err("%s: apr_send_pkt failed opcode = %x\n",
+			__func__, opcode);
+		goto err;
+	}
+	/* Wait for the callback */
+	result = wait_event_timeout(rtac_voice_apr_data[mode].cmd_wait,
+		(atomic_read(&rtac_voice_apr_data[mode].cmd_state) == 0),
+		msecs_to_jiffies(TIMEOUT_MS));
+	mutex_unlock(&rtac_voice_apr_mutex);
+	if (!result) {
+		pr_err("%s: apr_send_pkt timed out opcode = %x\n",
+			__func__, opcode);
+		goto done;
+	}
+
+	if (rtac_voice_payload_size != 0) {
+		if (copy_to_user(buf, rtac_voice_buffer,
+			rtac_voice_payload_size + sizeof(u32))) {
+			pr_err("%s: Could not copy buffer to user, size = %d\n",
+				 __func__, payload_size);
+			goto done;
+		}
+	}
+
+	/* Return data written for SET & data read for GET */
+	if (opcode == VOICE_CMD_GET_PARAM)
+		bytes_returned = rtac_voice_payload_size;
+	else
+		bytes_returned = payload_size;
+done:
+	return bytes_returned;
+err:
+	mutex_unlock(&rtac_voice_apr_mutex);
+	return bytes_returned;
+}
+
+
+
+static long rtac_ioctl(struct file *f,
+		unsigned int cmd, unsigned long arg)
+{
+	s32 result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (arg == 0) {
+		pr_err("%s: No data sent to driver!\n", __func__);
+		result = -EFAULT;
+		goto done;
+	}
+
+	switch (cmd) {
+	case AUDIO_GET_RTAC_ADM_INFO:
+		if (copy_to_user((void *)arg, &rtac_adm_data,
+						sizeof(rtac_adm_data)))
+			pr_err("%s: Could not copy to userspace!\n", __func__);
+		else
+			result = sizeof(rtac_adm_data);
+		break;
+	case AUDIO_GET_RTAC_VOICE_INFO:
+		if (copy_to_user((void *)arg, &rtac_voice_data,
+						sizeof(rtac_voice_data)))
+			pr_err("%s: Could not copy to userspace!\n", __func__);
+		else
+			result = sizeof(rtac_voice_data);
+		break;
+	case AUDIO_GET_RTAC_ADM_CAL:
+		result = send_adm_apr((void *)arg, ADM_CMD_GET_PP_PARAMS_V5);
+		break;
+	case AUDIO_SET_RTAC_ADM_CAL:
+		result = send_adm_apr((void *)arg, ADM_CMD_SET_PP_PARAMS_V5);
+		break;
+	case AUDIO_GET_RTAC_ASM_CAL:
+		result = send_rtac_asm_apr((void *)arg,
+			ASM_STREAM_CMD_GET_PP_PARAMS_V2);
+		break;
+	case AUDIO_SET_RTAC_ASM_CAL:
+		result = send_rtac_asm_apr((void *)arg,
+			ASM_STREAM_CMD_SET_PP_PARAMS_V2);
+		break;
+	case AUDIO_GET_RTAC_CVS_CAL:
+		result = send_voice_apr(RTAC_CVS, (void *)arg,
+			VOICE_CMD_GET_PARAM);
+		break;
+	case AUDIO_SET_RTAC_CVS_CAL:
+		result = send_voice_apr(RTAC_CVS, (void *)arg,
+			VOICE_CMD_SET_PARAM);
+		break;
+	case AUDIO_GET_RTAC_CVP_CAL:
+		result = send_voice_apr(RTAC_CVP, (void *)arg,
+			VOICE_CMD_GET_PARAM);
+		break;
+	case AUDIO_SET_RTAC_CVP_CAL:
+		result = send_voice_apr(RTAC_CVP, (void *)arg,
+			VOICE_CMD_SET_PARAM);
+		break;
+	default:
+		pr_err("%s: Invalid IOCTL, command = %d!\n",
+		       __func__, cmd);
+	}
+done:
+	return result;
+}
+
+
+static const struct file_operations rtac_fops = {
+	.owner = THIS_MODULE,
+	.open = rtac_open,
+	.release = rtac_release,
+	.unlocked_ioctl = rtac_ioctl,
+};
+
+struct miscdevice rtac_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_rtac",
+	.fops	= &rtac_fops,
+};
+
+static int __init rtac_init(void)
+{
+	int i = 0;
+	pr_debug("%s\n", __func__);
+
+	/* ADM */
+	memset(&rtac_adm_data, 0, sizeof(rtac_adm_data));
+	rtac_adm_apr_data.apr_handle = NULL;
+	atomic_set(&rtac_adm_apr_data.cmd_state, 0);
+	init_waitqueue_head(&rtac_adm_apr_data.cmd_wait);
+	mutex_init(&rtac_adm_mutex);
+	mutex_init(&rtac_adm_apr_mutex);
+
+	rtac_adm_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	if (rtac_adm_buffer == NULL) {
+		pr_err("%s: Could not allocate payload of size = %d\n",
+			__func__, RTAC_BUF_SIZE);
+		goto nomem;
+	}
+
+	/* ASM */
+	for (i = 0; i < SESSION_MAX+1; i++) {
+		rtac_asm_apr_data[i].apr_handle = NULL;
+		atomic_set(&rtac_asm_apr_data[i].cmd_state, 0);
+		init_waitqueue_head(&rtac_asm_apr_data[i].cmd_wait);
+	}
+	mutex_init(&rtac_asm_apr_mutex);
+
+	rtac_asm_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	if (rtac_asm_buffer == NULL) {
+		pr_err("%s: Could not allocate payload of size = %d\n",
+			__func__, RTAC_BUF_SIZE);
+		kzfree(rtac_adm_buffer);
+		goto nomem;
+	}
+
+	/* Voice */
+	memset(&rtac_voice_data, 0, sizeof(rtac_voice_data));
+	for (i = 0; i < RTAC_VOICE_MODES; i++) {
+		rtac_voice_apr_data[i].apr_handle = NULL;
+		atomic_set(&rtac_voice_apr_data[i].cmd_state, 0);
+		init_waitqueue_head(&rtac_voice_apr_data[i].cmd_wait);
+	}
+	mutex_init(&rtac_voice_mutex);
+	mutex_init(&rtac_voice_apr_mutex);
+
+	rtac_voice_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	if (rtac_voice_buffer == NULL) {
+		pr_err("%s: Could not allocate payload of size = %d\n",
+			__func__, RTAC_BUF_SIZE);
+		kzfree(rtac_adm_buffer);
+		kzfree(rtac_asm_buffer);
+		goto nomem;
+	}
+
+	return misc_register(&rtac_misc);
+nomem:
+	return -ENOMEM;
+}
+
+module_init(rtac_init);
+
+MODULE_DESCRIPTION("MSM 8x60 Real-Time Audio Calibration driver");
+MODULE_LICENSE("GPL v2");
+
+#endif
diff --git a/arch/arm/mach-msm/rpm-regulator-9615.c b/arch/arm/mach-msm/rpm-regulator-9615.c
index 23c0ee3..82ac3d8 100644
--- a/arch/arm/mach-msm/rpm-regulator-9615.c
+++ b/arch/arm/mach-msm/rpm-regulator-9615.c
@@ -50,6 +50,11 @@
 	.hpm		= REQUEST_MEMBER(0, 0x00000C00, 10),
 };
 
+static struct rpm_vreg_parts corner_parts = {
+	.request_len	= 1,
+	.uV		= REQUEST_MEMBER(0, 0x00000003,  0),
+};
+
 /* Physically available PMIC regulator voltage setpoint ranges */
 static struct vreg_range pldo_ranges[] = {
 	VOLTAGE_RANGE( 750000, 1487500, 12500),
@@ -72,16 +77,22 @@
 	VOLTAGE_RANGE(1500000, 3075000, 25000),
 };
 
+static struct vreg_range corner_ranges[] = {
+	VOLTAGE_RANGE(RPM_VREG_CORNER_NONE, RPM_VREG_CORNER_HIGH, 1),
+};
+
 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 corner_set_points = SET_POINTS(corner_ranges);
 
 static struct vreg_set_points *all_set_points[] = {
 	&pldo_set_points,
 	&nldo_set_points,
 	&nldo1200_set_points,
 	&smps_set_points,
+	&corner_set_points,
 };
 
 #define LDO(_id, _name, _name_pc, _ranges, _hpm_min_load) \
@@ -127,6 +138,19 @@
 		.rdesc_pc.name	 = _name_pc, \
 	}
 
+#define CORNER(_id, _rpm_id, _name, _ranges) \
+	[RPM_VREG_ID_PM8018_##_id] = { \
+		.req = { \
+			[0] = { .id = MSM_RPM_ID_##_rpm_id, }, \
+			[1] = { .id = -1, }, \
+		}, \
+		.type		 = RPM_REGULATOR_TYPE_CORNER, \
+		.set_points	 = &_ranges##_set_points, \
+		.part		 = &corner_parts, \
+		.id		 = RPM_VREG_ID_PM8018_##_id, \
+		.rdesc.name	 = _name, \
+	}
+
 static struct vreg vregs[] = {
 	LDO(L2,   "8018_l2",   "8018_l2_pc",  pldo,     LDO_50),
 	LDO(L3,   "8018_l3",   "8018_l3_pc",  pldo,     LDO_50),
@@ -149,6 +173,8 @@
 	SMPS(S5,  "8018_s5",   "8018_s5_pc",  smps,     SMPS_1500),
 
 	LVS(LVS1, "8018_lvs1", "8018_lvs1_pc"),
+
+	CORNER(VDD_DIG_CORNER, VOLTAGE_CORNER, "vdd_dig_corner", corner),
 };
 
 static const char *pin_control_label[] = {
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index b892d05..152b6e5 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -762,10 +762,11 @@
 	struct rpm_vreg *rpm_vreg;
 
 	regulator = regulator_get(dev, supply);
-	if (regulator == NULL) {
-		pr_err("could not find regulator for: dev=%s, id=%s\n",
-			(dev ? dev_name(dev) : ""), (supply ? supply : ""));
-		return ERR_PTR(-ENODEV);
+	if (IS_ERR(regulator)) {
+		pr_err("could not find regulator for: dev=%s, supply=%s, rc=%ld\n",
+			(dev ? dev_name(dev) : ""), (supply ? supply : ""),
+			PTR_ERR(regulator));
+		return ERR_CAST(regulator);
 	}
 
 	framework_reg = regulator_get_drvdata(regulator);
@@ -818,7 +819,7 @@
 
 static int rpm_regulator_check_input(struct rpm_regulator *regulator)
 {
-	if (regulator == NULL || regulator->rpm_vreg == NULL) {
+	if (IS_ERR_OR_NULL(regulator) || regulator->rpm_vreg == NULL) {
 		pr_err("invalid rpm_regulator pointer\n");
 		return -EINVAL;
 	}
@@ -1142,7 +1143,7 @@
 	reg->set_active = !!(val & RPM_SET_CONFIG_ACTIVE);
 	reg->set_sleep = !!(val & RPM_SET_CONFIG_SLEEP);
 
-	init_data = of_get_regulator_init_data(dev);
+	init_data = of_get_regulator_init_data(dev, node);
 	if (init_data == NULL) {
 		dev_err(dev, "%s: unable to allocate memory\n", __func__);
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 2980811..6e81be6 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -282,14 +282,22 @@
 		uint32_t notify_rpm;
 	};
 
-	struct mode_of mode_of_data[] = {
-		{"qcom,spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING, 0},
-		{"qcom,spm-cmd-ret", MSM_SPM_MODE_POWER_RETENTION, 0},
-		{"qcom,spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE, 0},
-		{"qcom,spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE, 1},
+	struct mode_of of_cpu_modes[] = {
+		{"qcom,saw2-spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING, 0},
+		{"qcom,saw2-spm-cmd-ret", MSM_SPM_MODE_POWER_RETENTION, 0},
+		{"qcom,saw2-spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE, 0},
+		{"qcom,saw2-spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE, 1},
 	};
 
-	BUG_ON(ARRAY_SIZE(mode_of_data) > MSM_SPM_MODE_NR);
+	struct mode_of of_l2_modes[] = {
+		{"qcom,saw2-spm-cmd-ret", MSM_SPM_L2_MODE_RETENTION, 1},
+		{"qcom,saw2-spm-cmd-gdhs", MSM_SPM_L2_MODE_GDHS, 1},
+		{"qcom,saw2-spm-cmd-pc", MSM_SPM_L2_MODE_POWER_COLLAPSE, 1},
+	};
+
+	struct mode_of *mode_of_data;
+	int num_modes;
+
 	memset(&spm_data, 0, sizeof(struct msm_spm_platform_data));
 	memset(&modes, 0,
 		(MSM_SPM_MODE_NR - 2) * sizeof(struct msm_spm_seq_entry));
@@ -339,7 +347,22 @@
 		spm_data.reg_init_values[spm_of_data[i].id] = val;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(mode_of_data); i++) {
+	/*
+	 * Device with id 0..NR_CPUS are SPM for apps cores
+	 * Device with id 0xFFFF is for L2 SPM.
+	 */
+	if (cpu >= 0 && cpu < num_possible_cpus()) {
+		mode_of_data = of_cpu_modes;
+		num_modes = ARRAY_SIZE(of_cpu_modes);
+		dev = &per_cpu(msm_cpu_spm_device, cpu);
+
+	} else {
+		mode_of_data = of_l2_modes;
+		num_modes = ARRAY_SIZE(of_l2_modes);
+		dev = &msm_spm_l2_device;
+	}
+
+	for (i = 0; i < num_modes; i++) {
 		key = mode_of_data[i].key;
 		modes[mode_count].cmd =
 			(uint8_t *)of_get_property(node, key, &len);
@@ -353,16 +376,8 @@
 	spm_data.modes = modes;
 	spm_data.num_modes = mode_count;
 
-	/*
-	 * Device with id 0..NR_CPUS are SPM for apps cores
-	 * Device with id 0xFFFF is for L2 SPM.
-	 */
-	if (cpu >= 0 && cpu < num_possible_cpus())
-		dev = &per_cpu(msm_cpu_spm_device, cpu);
-	else
-		dev = &msm_spm_l2_device;
-
 	ret = msm_spm_dev_init(dev, &spm_data);
+
 	if (ret < 0)
 		pr_warn("%s():failed core-id:%u ret:%d\n", __func__, cpu, ret);
 
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 266c8b4..793ef7f 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -30,11 +30,7 @@
 #define MODULE_NAME			"wcnss_8960"
 #define MAX_BUF_SIZE			0x51
 
-static void riva_smsm_cb_fn(struct work_struct *);
-static DECLARE_WORK(riva_smsm_cb_work, riva_smsm_cb_fn);
 
-static void riva_fatal_fn(struct work_struct *);
-static DECLARE_WORK(riva_fatal_work, riva_fatal_fn);
 
 static struct delayed_work cancel_vote_work;
 static void *riva_ramdump_dev;
@@ -42,14 +38,6 @@
 static int ss_restart_inprogress;
 static int enable_riva_ssr;
 
-static void riva_smsm_cb_fn(struct work_struct *work)
-{
-	if (!enable_riva_ssr)
-		panic(MODULE_NAME ": SMSM reset request received from Riva");
-	else
-		subsystem_restart("riva");
-}
-
 static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
 					uint32_t new_state)
 {
@@ -58,60 +46,62 @@
 	unsigned smem_reset_size;
 	unsigned size;
 
+	riva_crash = true;
+
+	pr_err("%s: smsm state changed\n", MODULE_NAME);
+
 	if (!(new_state & SMSM_RESET))
 		return;
 
-	riva_crash = true;
-	pr_err("%s: smsm state changed to smsm reset\n", MODULE_NAME);
-
-	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
-		&smem_reset_size);
-
-	if (!smem_reset_reason || !smem_reset_size) {
-		pr_err("%s: wcnss subsystem failure reason: %s\n", __func__,
-				"(unknown, smem_get_entry failed)");
-	} else if (!smem_reset_reason[0]) {
-		pr_err("%s: wcnss subsystem failure reason: %s\n", __func__,
-				"(unknown, init string found)");
-	} else {
-		size = smem_reset_size < MAX_BUF_SIZE ? smem_reset_size :
-				(MAX_BUF_SIZE - 1);
-		memcpy(buffer, smem_reset_reason, size);
-		buffer[size] = '\0';
-		pr_err("%s: wcnss subsystem failure reason: %s\n", __func__,
-				buffer);
-		memset(smem_reset_reason, 0, smem_reset_size);
-		wmb();
-	}
-
 	if (ss_restart_inprogress) {
 		pr_err("%s: Ignoring smsm reset req, restart in progress\n",
 						MODULE_NAME);
 		return;
 	}
-	ss_restart_inprogress = true;
-	schedule_work(&riva_smsm_cb_work);
-}
 
-static void riva_fatal_fn(struct work_struct *work)
-{
 	if (!enable_riva_ssr)
-		panic(MODULE_NAME ": Watchdog bite received from Riva");
-	else
-		subsystem_restart("riva");
+		panic(MODULE_NAME ": SMSM reset request received from Riva");
+
+	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
+			&smem_reset_size);
+
+	if (!smem_reset_reason || !smem_reset_size) {
+		pr_err("%s: wcnss subsystem failure reason: %s\n",
+				__func__, "(unknown, smem_get_entry failed)");
+	} else if (!smem_reset_reason[0]) {
+		pr_err("%s: wcnss subsystem failure reason: %s\n",
+				__func__, "(unknown, init string found)");
+	} else {
+		size = smem_reset_size < MAX_BUF_SIZE ? smem_reset_size :
+			(MAX_BUF_SIZE - 1);
+		memcpy(buffer, smem_reset_reason, size);
+		buffer[size] = '\0';
+		pr_err("%s: wcnss subsystem failure reason: %s\n",
+				__func__, buffer);
+		memset(smem_reset_reason, 0, smem_reset_size);
+		wmb();
+	}
+
+	ss_restart_inprogress = true;
+	subsystem_restart("riva");
 }
 
 static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
 {
-	int ret;
+	riva_crash = true;
 
 	if (ss_restart_inprogress) {
 		pr_err("%s: Ignoring riva bite irq, restart in progress\n",
 						MODULE_NAME);
 		return IRQ_HANDLED;
 	}
+
+	if (!enable_riva_ssr)
+		panic(MODULE_NAME ": Watchdog bite received from Riva");
+
 	ss_restart_inprogress = true;
-	ret = schedule_work(&riva_fatal_work);
+	subsystem_restart("riva");
+
 	return IRQ_HANDLED;
 }
 
@@ -229,8 +219,8 @@
 	ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
 					smsm_state_cb_hdlr, 0);
 	if (ret < 0) {
-		pr_err("%s: Unable to register smsm callback for Riva Reset!"
-				" (%d)\n", MODULE_NAME, ret);
+		pr_err("%s: Unable to register smsm callback for Riva Reset! %d\n",
+				MODULE_NAME, ret);
 		goto out;
 	}
 	ret = request_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
@@ -238,8 +228,8 @@
 				"riva_wdog", NULL);
 
 	if (ret < 0) {
-		pr_err("%s: Unable to register for Riva bite interrupt"
-				" (%d)\n", MODULE_NAME, ret);
+		pr_err("%s: Unable to register for Riva bite interrupt (%d)\n",
+				MODULE_NAME, ret);
 		goto out;
 	}
 	ret = riva_restart_init();
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 4387287..e62af21 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/uaccess.h>
 #include <linux/user.h>
+#include <linux/proc_fs.h>
 
 #include <asm/cp15.h>
 #include <asm/cputype.h>
@@ -87,6 +88,11 @@
 }
 
 /*
+ * Used for reporting emulation statistics via /proc
+ */
+static atomic64_t vfp_bounce_count = ATOMIC64_INIT(0);
+
+/*
  * Per-thread VFP initialization.
  */
 static void vfp_thread_flush(struct thread_info *thread)
@@ -337,6 +343,7 @@
 	u32 fpscr, orig_fpscr, fpsid, exceptions;
 
 	pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
+	atomic64_inc(&vfp_bounce_count);
 
 	/*
 	 * At this point, FPEXC can have the following configuration:
@@ -648,6 +655,26 @@
 	return NOTIFY_OK;
 }
 
+#ifdef CONFIG_PROC_FS
+static int proc_read_status(char *page, char **start, off_t off, int count,
+			    int *eof, void *data)
+{
+	char *p = page;
+	int len;
+
+	p += snprintf(p, PAGE_SIZE, "%llu\n", atomic64_read(&vfp_bounce_count));
+
+	len = (p - page) - off;
+	if (len < 0)
+		len = 0;
+
+	*eof = (len <= count) ? 1 : 0;
+	*start = page + off;
+
+	return len;
+}
+#endif
+
 /*
  * VFP support code initialisation.
  */
@@ -655,7 +682,9 @@
 {
 	unsigned int vfpsid;
 	unsigned int cpu_arch = cpu_architecture();
-
+#ifdef CONFIG_PROC_FS
+	static struct proc_dir_entry *procfs_entry;
+#endif
 	if (cpu_arch >= CPU_ARCH_ARMv6)
 		on_each_cpu(vfp_enable, NULL, 1);
 
@@ -724,6 +753,16 @@
 				elf_hwcap |= HWCAP_VFPv4;
 		}
 	}
+
+#ifdef CONFIG_PROC_FS
+	procfs_entry = create_proc_entry("cpu/vfp_bounce", S_IRUGO, NULL);
+
+	if (procfs_entry)
+		procfs_entry->read_proc = proc_read_status;
+	else
+		pr_err("Failed to create procfs node for VFP bounce reporting\n");
+#endif
+
 	return 0;
 }
 
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 5e1d7af..aed71c0 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -34,7 +34,15 @@
 #define GENLOCK_LOG_ERR(fmt, args...) \
 pr_err("genlock: %s: " fmt, __func__, ##args)
 
+/* The genlock magic stored in the kernel private data is used to protect
+ * against the possibility of user space passing a valid fd to a
+ * non-genlock file for genlock_attach_lock()
+ */
+#define GENLOCK_MAGIC_OK  0xD2EAD10C
+#define GENLOCK_MAGIC_BAD 0xD2EADBAD
+
 struct genlock {
+	unsigned int magic;       /* Magic for attach verification */
 	struct list_head active;  /* List of handles holding lock */
 	spinlock_t lock;          /* Spinlock to protect the lock internals */
 	wait_queue_head_t queue;  /* Holding pen for processes pending lock */
@@ -56,7 +64,7 @@
  * released while another process tries to attach it
  */
 
-static DEFINE_SPINLOCK(genlock_file_lock);
+static DEFINE_SPINLOCK(genlock_ref_lock);
 
 static void genlock_destroy(struct kref *kref)
 {
@@ -68,10 +76,9 @@
 	 * still active after the lock gets released
 	 */
 
-	spin_lock(&genlock_file_lock);
 	if (lock->file)
 		lock->file->private_data = NULL;
-	spin_unlock(&genlock_file_lock);
+	lock->magic = GENLOCK_MAGIC_BAD;
 
 	kfree(lock);
 }
@@ -130,6 +137,7 @@
 	init_waitqueue_head(&lock->queue);
 	spin_lock_init(&lock->lock);
 
+	lock->magic = GENLOCK_MAGIC_OK;
 	lock->state = _UNLOCKED;
 
 	/*
@@ -203,21 +211,30 @@
 	 * released and then attached
 	 */
 
-	spin_lock(&genlock_file_lock);
+	spin_lock(&genlock_ref_lock);
 	lock = file->private_data;
-	spin_unlock(&genlock_file_lock);
 
 	fput(file);
 
 	if (lock == NULL) {
 		GENLOCK_LOG_ERR("File descriptor is invalid\n");
-		return ERR_PTR(-EINVAL);
+		goto fail_invalid;
+	}
+
+	if (lock->magic != GENLOCK_MAGIC_OK) {
+		GENLOCK_LOG_ERR("Magic is invalid - 0x%X\n", lock->magic);
+		goto fail_invalid;
 	}
 
 	handle->lock = lock;
 	kref_get(&lock->refcount);
+	spin_unlock(&genlock_ref_lock);
 
 	return lock;
+
+fail_invalid:
+	spin_unlock(&genlock_ref_lock);
+	return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL(genlock_attach_lock);
 
@@ -595,7 +612,9 @@
 	}
 	spin_unlock_irqrestore(&handle->lock->lock, flags);
 
+	spin_lock(&genlock_ref_lock);
 	kref_put(&handle->lock->refcount, genlock_destroy);
+	spin_unlock(&genlock_ref_lock);
 	handle->lock = NULL;
 	handle->active = 0;
 }
diff --git a/drivers/bluetooth/hci_ibs.c b/drivers/bluetooth/hci_ibs.c
index 2a6f3f8..6845020 100644
--- a/drivers/bluetooth/hci_ibs.c
+++ b/drivers/bluetooth/hci_ibs.c
@@ -5,7 +5,7 @@
  *  protocol extension to H4.
  *
  *  Copyright (C) 2007 Texas Instruments, Inc.
- *  Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2010, 2012 Code Aurora Forum. All rights reserved.
  *
  *  Acknowledgements:
  *  This file is based on hci_ll.c, which was...
@@ -37,7 +37,9 @@
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
+#include <linux/ftrace.h>
 #include <linux/poll.h>
+#include <linux/workqueue.h>
 
 #include <linux/slab.h>
 #include <linux/tty.h>
@@ -92,6 +94,15 @@
 	HCI_IBS_RX_VOTE_CLOCK_OFF,
 };
 
+/* HCI_IBS state for the WorkQueue */
+enum hci_ibs_wq_state_e {
+	HCI_IBS_WQ_INIT_STATE = 0,
+	HCI_IBS_WQ_TX_VOTE_OFF,
+	HCI_IBS_WQ_RX_VOTE_OFF,
+	HCI_IBS_WQ_AWAKE_RX,
+	HCI_IBS_WQ_AWAKE_DEVICE,
+};
+
 static unsigned long wake_retrans = 1;
 static unsigned long tx_idle_delay = (HZ * 2);
 
@@ -112,6 +123,11 @@
 	unsigned long rx_vote;		/* clock must be on for RX */
 	struct	timer_list tx_idle_timer;
 	struct	timer_list wake_retrans_timer;
+	struct	workqueue_struct *workqueue;
+	struct	work_struct ws_ibs;
+	unsigned long ibs_wq_state;
+	void *ibs_hu; /* keeps the hci_uart pointer for reference */
+
 	/* debug */
 	unsigned long ibs_sent_wacks;
 	unsigned long ibs_sent_slps;
@@ -242,6 +258,56 @@
 	return err;
 }
 
+static void ibs_wq(struct work_struct *work)
+{
+	unsigned long flags = 0;
+	struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+						ws_ibs);
+	struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+	BT_DBG("hu %p, ibs_wq state: %lu\n", hu, ibs->ibs_wq_state);
+
+	/* lock hci_ibs state */
+	spin_lock_irqsave(&ibs->hci_ibs_lock, flags);
+
+	switch (ibs->ibs_wq_state) {
+	case HCI_IBS_WQ_AWAKE_DEVICE:
+		/* Vote for serial clock */
+		ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
+
+		/* send wake indication to device */
+		if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
+			BT_ERR("cannot send WAKE to device");
+
+		ibs->ibs_sent_wakes++; /* debug */
+
+		/* start retransmit timer */
+		mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
+		break;
+	case HCI_IBS_WQ_AWAKE_RX:
+		ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
+		ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
+
+		if (send_hci_ibs_cmd(HCI_IBS_WAKE_ACK, hu) < 0)
+			BT_ERR("cannot acknowledge device wake up");
+
+		ibs->ibs_sent_wacks++; /* debug */
+		/* actually send the packets */
+		hci_uart_tx_wakeup(hu);
+		break;
+	case HCI_IBS_WQ_RX_VOTE_OFF:
+		ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);
+		break;
+	case HCI_IBS_WQ_TX_VOTE_OFF:
+		ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
+		break;
+	default:
+		BT_DBG("Invalid state in ibs workqueue");
+		break;
+	}
+	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+}
+
 static void hci_ibs_tx_idle_timeout(unsigned long arg)
 {
 	struct hci_uart *hu = (struct hci_uart *) arg;
@@ -282,7 +348,9 @@
 
 	spin_lock_irqsave_nested(&ibs->hci_ibs_lock,
 					flags, SINGLE_DEPTH_NESTING);
-	ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
+	/* vote off tx clock */
+	ibs->ibs_wq_state = HCI_IBS_WQ_TX_VOTE_OFF;
+	queue_work(ibs->workqueue, &ibs->ws_ibs);
 out:
 	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
 }
@@ -336,6 +404,16 @@
 	skb_queue_head_init(&ibs->txq);
 	skb_queue_head_init(&ibs->tx_wait_q);
 	spin_lock_init(&ibs->hci_ibs_lock);
+	ibs->workqueue = create_singlethread_workqueue("ibs_wq");
+	if (!ibs->workqueue) {
+		BT_ERR("IBS Workqueue not initialized properly");
+		kfree(ibs);
+		return -ENOMEM;
+	}
+
+	INIT_WORK(&ibs->ws_ibs, ibs_wq);
+	ibs->ibs_hu = (void *)hu;
+	ibs->ibs_wq_state = HCI_IBS_WQ_INIT_STATE;
 
 	/* Assume we start with both sides asleep -- extra wakes OK */
 	ibs->tx_ibs_state = HCI_IBS_TX_ASLEEP;
@@ -432,6 +510,8 @@
 	skb_queue_purge(&ibs->txq);
 	del_timer(&ibs->tx_idle_timer);
 	del_timer(&ibs->wake_retrans_timer);
+	destroy_workqueue(ibs->workqueue);
+	ibs->ibs_hu = NULL;
 
 	kfree_skb(ibs->rx_skb);
 
@@ -463,9 +543,11 @@
 		/* Make sure clock is on - we may have turned clock off since
 		 * receiving the wake up indicator
 		 */
-		ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
-		ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
-		/* deliberate fall-through */
+		/* awake rx clock */
+		ibs->ibs_wq_state = HCI_IBS_WQ_AWAKE_RX;
+		queue_work(ibs->workqueue, &ibs->ws_ibs);
+		spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+		return;
 	case HCI_IBS_RX_AWAKE:
 		/* Always acknowledge device wake up,
 		 * sending IBS message doesn't count as TX ON.
@@ -510,7 +592,9 @@
 	case HCI_IBS_RX_AWAKE:
 		/* update state */
 		ibs->rx_ibs_state = HCI_IBS_RX_ASLEEP;
-		ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);
+		/* vote off rx clock under workqueue */
+		ibs->ibs_wq_state = HCI_IBS_WQ_RX_VOTE_OFF;
+		queue_work(ibs->workqueue, &ibs->ws_ibs);
 		break;
 	case HCI_IBS_RX_ASLEEP:
 		/* deliberate fall-through */
@@ -595,20 +679,12 @@
 
 	case HCI_IBS_TX_ASLEEP:
 		BT_DBG("device asleep, waking up and queueing packet");
-		ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
 		/* save packet for later */
 		skb_queue_tail(&ibs->tx_wait_q, skb);
-		/* awake device */
-		if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
-			BT_ERR("cannot send WAKE to device");
-			break;
-		}
-		ibs->ibs_sent_wakes++; /* debug */
-
-		/* start retransmit timer */
-		mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
-
 		ibs->tx_ibs_state = HCI_IBS_TX_WAKING;
+		/* schedule a work queue to wake up device */
+		ibs->ibs_wq_state = HCI_IBS_WQ_AWAKE_DEVICE;
+		queue_work(ibs->workqueue, &ibs->ws_ibs);
 		break;
 
 	case HCI_IBS_TX_WAKING:
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 83d65b1..69aa411 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1016,7 +1016,7 @@
 					ENCODE_RSP_AND_SEND(8+rt_mask_size-1);
 					return 0;
 				}
-				ptr += MAX_SSID_PER_RANGE*4;
+				rt_mask_ptr += MAX_SSID_PER_RANGE*4;
 			}
 		} else
 			buf = temp;
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index d54d3dc..fedcf03 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -16,6 +16,7 @@
 #include <linux/diagchar.h>
 #include <linux/sched.h>
 #include <linux/err.h>
+#include <linux/ratelimit.h>
 #include <linux/workqueue.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
@@ -55,7 +56,7 @@
 		err = diag_bridge_read((char *)driver->buf_in_hsic,
 					IN_BUF_SIZE);
 		if (err) {
-			pr_err("DIAG: Error initiating HSIC read, err: %d\n",
+			pr_err_ratelimited("DIAG: Error initiating HSIC read, err: %d\n",
 				err);
 			/*
 			 * If the error is recoverable, then clear
@@ -63,7 +64,7 @@
 			 * read on the next frame.  Otherwise, don't
 			 * resubmit a read on the next frame.
 			 */
-			if ((-ESHUTDOWN) != err)
+			if ((-ENODEV) != err)
 				driver->in_busy_hsic_read = 0;
 		}
 	}
@@ -373,14 +374,15 @@
 		err = diag_bridge_write(driver->usb_buf_mdm_out,
 					driver->read_len_mdm);
 		if (err) {
-			pr_err("DIAG: mdm data on hsic write err: %d\n", err);
+			pr_err_ratelimited("DIAG: mdm data on hsic write err: %d\n",
+					err);
 			/*
 			 * If the error is recoverable, then clear
 			 * the write flag, so we will resubmit a
 			 * write on the next frame.  Otherwise, don't
 			 * resubmit a write on the next frame.
 			 */
-			if ((-ESHUTDOWN) != err)
+			if ((-ENODEV) != err)
 				driver->in_busy_hsic_write = 0;
 		}
 	}
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 5997405..5798c94 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -837,15 +837,16 @@
 	struct cpu_dbs_info_s *this_dbs_info;
 	unsigned int cpu = smp_processor_id();
 
+	get_online_cpus();
+
 	if (lock_policy_rwsem_write(cpu) < 0)
-		return;
+		goto bail_acq_sema_failed;
 
 	this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
 	policy = this_dbs_info->cur_policy;
 	if (!policy) {
 		/* CPU not using ondemand governor */
-		unlock_policy_rwsem_write(cpu);
-		return;
+		goto bail_incorrect_governor;
 	}
 
 	if (policy->cur < policy->max) {
@@ -856,7 +857,13 @@
 		this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu,
 				&this_dbs_info->prev_cpu_wall);
 	}
+
+bail_incorrect_governor:
 	unlock_policy_rwsem_write(cpu);
+
+bail_acq_sema_failed:
+	put_online_cpus();
+	return;
 }
 
 static void dbs_input_event(struct input_handle *handle, unsigned int type,
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index fb43562..bac9f8a 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -12,6 +12,7 @@
  */
 #include <linux/bitmap.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -147,14 +148,12 @@
 void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val)
 {
 	if (val) {
-		set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE,
-				GPIO_INTR_CFG(gpio));
+		set_gpio_bits(INTR_ENABLE, GPIO_INTR_CFG(gpio));
 		__raw_writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
 
 	} else {
 		__raw_writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
-		clr_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE,
-				GPIO_INTR_CFG(gpio));
+		clr_gpio_bits(INTR_ENABLE, GPIO_INTR_CFG(gpio));
 	}
 }
 
@@ -173,7 +172,23 @@
 	else
 		cfg &= ~INTR_POL_CTL_HI;
 
+	/* RAW_STATUS_EN is left on for all gpio irqs. Due to the
+	 * internal circuitry of TLMM, toggling the RAW_STATUS
+	 * could cause the INTR_STATUS to be set for EDGE interrupts.
+	 */
+	cfg |= INTR_RAW_STATUS_EN;
 	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
+
+	/* Sometimes it might take a little while to update
+	 * the interrupt status after the RAW_STATUS is enabled
+	 */
+	udelay(5);
+
+	/* Clear the interrupt status to clear out any spurious
+	 * irq as a result of the above operation
+	 */
+	__msm_gpio_set_intr_status(gpio);
+
 }
 
 void __gpio_tlmm_config(unsigned config)
diff --git a/drivers/gpio/gpio-msm-v3.c b/drivers/gpio/gpio-msm-v3.c
index 49ad517..6086de3 100644
--- a/drivers/gpio/gpio-msm-v3.c
+++ b/drivers/gpio/gpio-msm-v3.c
@@ -12,6 +12,7 @@
  */
 #include <linux/bitmap.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -155,10 +156,9 @@
 	cfg = __raw_readl(GPIO_INTR_CFG(gpio));
 	if (val) {
 		cfg &= ~(INTR_TARGET_PROC_NONE | INTR_DIR_CONN_EN);
-		cfg |= INTR_RAW_STATUS_EN | INTR_ENABLE | INTR_TARGET_PROC_APPS;
+		cfg |= INTR_ENABLE | INTR_TARGET_PROC_APPS;
 	} else {
-		cfg &= ~(INTR_TARGET_PROC_APPS | INTR_RAW_STATUS_EN |
-			INTR_ENABLE);
+		cfg &= ~(INTR_TARGET_PROC_APPS | INTR_ENABLE);
 		cfg |= INTR_TARGET_PROC_NONE;
 	}
 	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
@@ -184,7 +184,22 @@
 	else
 		cfg &= ~INTR_POL_CTL_HI;
 
+	/* RAW_STATUS_EN is left on for all gpio irqs. Due to the
+	 * internal circuitry of TLMM, toggling the RAW_STATUS
+	 * could cause the INTR_STATUS to be set for EDGE interrupts.
+	 */
+	cfg |= INTR_RAW_STATUS_EN;
 	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
+
+	/* Sometimes it might take a little while to update
+	 * the interrupt status after the RAW_STATUS is enabled
+	 */
+	udelay(5);
+
+	/* Clear the interrupt status to clear out any spurious
+	 * irq as a result of the above operation
+	 */
+	__msm_gpio_set_intr_status(gpio);
 }
 
 void __gpio_tlmm_config(unsigned config)
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 7e84aa7..5c7ab3a 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1898,7 +1898,8 @@
 	mutex_unlock(&dev->lock);
 }
 
-int ion_secure_heap(struct ion_device *dev, int heap_id)
+int ion_secure_heap(struct ion_device *dev, int heap_id, int version,
+			void *data)
 {
 	struct rb_node *n;
 	int ret_val = 0;
@@ -1915,7 +1916,7 @@
 		if (ION_HEAP(heap->id) != heap_id)
 			continue;
 		if (heap->ops->secure_heap)
-			ret_val = heap->ops->secure_heap(heap);
+			ret_val = heap->ops->secure_heap(heap, version, data);
 		else
 			ret_val = -EINVAL;
 		break;
@@ -1924,7 +1925,8 @@
 	return ret_val;
 }
 
-int ion_unsecure_heap(struct ion_device *dev, int heap_id)
+int ion_unsecure_heap(struct ion_device *dev, int heap_id, int version,
+			void *data)
 {
 	struct rb_node *n;
 	int ret_val = 0;
@@ -1941,7 +1943,7 @@
 		if (ION_HEAP(heap->id) != heap_id)
 			continue;
 		if (heap->ops->secure_heap)
-			ret_val = heap->ops->unsecure_heap(heap);
+			ret_val = heap->ops->unsecure_heap(heap, version, data);
 		else
 			ret_val = -EINVAL;
 		break;
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index a857988a..c5e9caf 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -40,6 +40,7 @@
 #include <asm/mach/map.h>
 #include <asm/cacheflush.h>
 
+#include "msm/ion_cp_common.h"
 /**
  * struct ion_cp_heap - container for the heap and shared heap data
 
@@ -97,6 +98,7 @@
 	int iommu_map_all;
 	int iommu_2x_map_domain;
 	unsigned int has_outer_cache;
+	atomic_t protect_cnt;
 };
 
 enum {
@@ -105,10 +107,12 @@
 };
 
 static int ion_cp_protect_mem(unsigned int phy_base, unsigned int size,
-			unsigned int permission_type);
+			unsigned int permission_type, int version,
+			void *data);
 
 static int ion_cp_unprotect_mem(unsigned int phy_base, unsigned int size,
-				unsigned int permission_type);
+				unsigned int permission_type, int version,
+				void *data);
 
 /**
  * Get the total number of kernel mappings.
@@ -125,13 +129,13 @@
  * 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)
+static int ion_cp_protect(struct ion_heap *heap, int version, void *data)
 {
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 	int ret_value = 0;
 
-	if (cp_heap->heap_protected == HEAP_NOT_PROTECTED) {
+	if (atomic_inc_return(&cp_heap->protect_cnt) == 1) {
 		/* 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);
@@ -140,7 +144,8 @@
 		}
 
 		ret_value = ion_cp_protect_mem(cp_heap->secure_base,
-				cp_heap->secure_size, cp_heap->permission_type);
+				cp_heap->secure_size, cp_heap->permission_type,
+				version, data);
 		if (ret_value) {
 			pr_err("Failed to protect memory for heap %s - "
 				"error code: %d\n", heap->name, ret_value);
@@ -150,6 +155,7 @@
 					pr_err("%s: unable to transition heap to T-state\n",
 						__func__);
 			}
+			atomic_dec(&cp_heap->protect_cnt);
 		} else {
 			cp_heap->heap_protected = HEAP_PROTECTED;
 			pr_debug("Protected heap %s @ 0x%lx\n",
@@ -157,6 +163,9 @@
 		}
 	}
 out:
+	pr_debug("%s: protect count is %d\n", __func__,
+		atomic_read(&cp_heap->protect_cnt));
+	BUG_ON(atomic_read(&cp_heap->protect_cnt) < 0);
 	return ret_value;
 }
 
@@ -165,15 +174,15 @@
  * 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)
+static void ion_cp_unprotect(struct ion_heap *heap, int version, void *data)
 {
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 
-	if (cp_heap->heap_protected == HEAP_PROTECTED) {
+	if (atomic_dec_and_test(&cp_heap->protect_cnt)) {
 		int error_code = ion_cp_unprotect_mem(
 			cp_heap->secure_base, cp_heap->secure_size,
-			cp_heap->permission_type);
+			cp_heap->permission_type, version, data);
 		if (error_code) {
 			pr_err("Failed to un-protect memory for heap %s - "
 				"error code: %d\n", heap->name, error_code);
@@ -189,6 +198,9 @@
 			}
 		}
 	}
+	pr_debug("%s: protect count is %d\n", __func__,
+		atomic_read(&cp_heap->protect_cnt));
+	BUG_ON(atomic_read(&cp_heap->protect_cnt) < 0);
 }
 
 ion_phys_addr_t ion_cp_allocate(struct ion_heap *heap,
@@ -641,14 +653,14 @@
 	return 0;
 }
 
-int ion_cp_secure_heap(struct ion_heap *heap)
+int ion_cp_secure_heap(struct ion_heap *heap, int version, void *data)
 {
 	int ret_value;
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 	mutex_lock(&cp_heap->lock);
 	if (cp_heap->umap_count == 0 && cp_heap->kmap_cached_count == 0) {
-		ret_value = ion_cp_protect(heap);
+		ret_value = ion_cp_protect(heap, version, data);
 	} else {
 		pr_err("ION cannot secure heap with outstanding mappings: "
 		       "User space: %lu, kernel space (cached): %lu\n",
@@ -660,13 +672,13 @@
 	return ret_value;
 }
 
-int ion_cp_unsecure_heap(struct ion_heap *heap)
+int ion_cp_unsecure_heap(struct ion_heap *heap, int version, void *data)
 {
 	int ret_value = 0;
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 	mutex_lock(&cp_heap->lock);
-	ion_cp_unprotect(heap);
+	ion_cp_unprotect(heap, version, data);
 	mutex_unlock(&cp_heap->lock);
 	return ret_value;
 }
@@ -925,6 +937,7 @@
 	cp_heap->secure_base = cp_heap->base;
 	cp_heap->secure_size = heap_data->size;
 	cp_heap->has_outer_cache = heap_data->has_outer_cache;
+	atomic_set(&cp_heap->protect_cnt, 0);
 	if (heap_data->extra_data) {
 		struct ion_cp_heap_pdata *extra_data =
 				heap_data->extra_data;
@@ -991,8 +1004,7 @@
 	unsigned char lock;
 } __attribute__ ((__packed__));
 
-
-static int ion_cp_protect_mem(unsigned int phy_base, unsigned int size,
+static int ion_cp_protect_mem_v1(unsigned int phy_base, unsigned int size,
 			      unsigned int permission_type)
 {
 	struct cp_lock_msg cmd;
@@ -1005,7 +1017,7 @@
 			&cmd, sizeof(cmd), NULL, 0);
 }
 
-static int ion_cp_unprotect_mem(unsigned int phy_base, unsigned int size,
+static int ion_cp_unprotect_mem_v1(unsigned int phy_base, unsigned int size,
 				unsigned int permission_type)
 {
 	struct cp_lock_msg cmd;
@@ -1017,3 +1029,70 @@
 	return scm_call(SCM_SVC_CP, SCM_CP_LOCK_CMD_ID,
 			&cmd, sizeof(cmd), NULL, 0);
 }
+
+#define V2_CHUNK_SIZE	SZ_1M
+
+static int ion_cp_change_mem_v2(unsigned int phy_base, unsigned int size,
+			      void *data, int lock)
+{
+	enum cp_mem_usage usage = (enum cp_mem_usage) data;
+	unsigned long *chunk_list;
+	int nchunks;
+	int ret;
+	int i;
+
+	if (usage < 0 || usage >= MAX_USAGE)
+		return -EINVAL;
+
+	if (!IS_ALIGNED(size, V2_CHUNK_SIZE)) {
+		pr_err("%s: heap size is not aligned to %x\n",
+			__func__, V2_CHUNK_SIZE);
+		return -EINVAL;
+	}
+
+	nchunks = size / V2_CHUNK_SIZE;
+
+	chunk_list = allocate_contiguous_ebi(sizeof(unsigned long)*nchunks,
+						SZ_4K, 0);
+	if (!chunk_list)
+		return -ENOMEM;
+
+	for (i = 0; i < nchunks; i++)
+		chunk_list[i] = phy_base + i * V2_CHUNK_SIZE;
+
+	ret = ion_cp_change_chunks_state(memory_pool_node_paddr(chunk_list),
+					nchunks, V2_CHUNK_SIZE, usage, lock);
+
+	free_contiguous_memory(chunk_list);
+	return ret;
+}
+
+static int ion_cp_protect_mem(unsigned int phy_base, unsigned int size,
+			      unsigned int permission_type, int version,
+			      void *data)
+{
+	switch (version) {
+	case ION_CP_V1:
+		return ion_cp_protect_mem_v1(phy_base, size, permission_type);
+	case ION_CP_V2:
+		return ion_cp_change_mem_v2(phy_base, size, data,
+						SCM_CP_PROTECT);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ion_cp_unprotect_mem(unsigned int phy_base, unsigned int size,
+			      unsigned int permission_type, int version,
+			      void *data)
+{
+	switch (version) {
+	case ION_CP_V1:
+		return ion_cp_unprotect_mem_v1(phy_base, size, permission_type);
+	case ION_CP_V2:
+		return ion_cp_change_mem_v2(phy_base, size, data,
+						SCM_CP_UNPROTECT);
+	default:
+		return -EINVAL;
+	}
+}
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 621144b..9ea6f2b 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -196,7 +196,7 @@
 						data->mapped_size, align,
 						&data->iova_addr);
 
-	if (!data->iova_addr)
+	if (ret)
 		goto out;
 
 	domain = msm_get_iommu_domain(domain_num);
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 6d636ee..6940e2f 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -158,8 +158,8 @@
 	void (*unmap_iommu)(struct ion_iommu_map *data);
 	int (*print_debug)(struct ion_heap *heap, struct seq_file *s,
 			   const struct rb_root *mem_map);
-	int (*secure_heap)(struct ion_heap *heap);
-	int (*unsecure_heap)(struct ion_heap *heap);
+	int (*secure_heap)(struct ion_heap *heap, int version, void *data);
+	int (*unsecure_heap)(struct ion_heap *heap, int version, void *data);
 };
 
 /**
diff --git a/drivers/gpu/ion/msm/Makefile b/drivers/gpu/ion/msm/Makefile
index bedd8d2..1893405 100644
--- a/drivers/gpu/ion/msm/Makefile
+++ b/drivers/gpu/ion/msm/Makefile
@@ -1 +1 @@
-obj-y += msm_ion.o
+obj-y += msm_ion.o ion_cp_common.o
diff --git a/drivers/gpu/ion/msm/ion_cp_common.c b/drivers/gpu/ion/msm/ion_cp_common.c
new file mode 100644
index 0000000..b274ba2
--- /dev/null
+++ b/drivers/gpu/ion/msm/ion_cp_common.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 Google, Inc
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/types.h>
+#include <mach/scm.h>
+
+#include "ion_cp_common.h"
+
+#define MEM_PROTECT_LOCK_ID	0x05
+
+struct cp2_mem_chunks {
+	unsigned int *chunk_list;
+	unsigned int chunk_list_size;
+	unsigned int chunk_size;
+} __attribute__ ((__packed__));
+
+struct cp2_lock_req {
+	struct cp2_mem_chunks chunks;
+	unsigned int mem_usage;
+	unsigned int lock;
+} __attribute__ ((__packed__));
+
+int ion_cp_change_chunks_state(unsigned long chunks, unsigned int nchunks,
+				unsigned int chunk_size,
+				enum cp_mem_usage usage,
+				int lock)
+{
+	struct cp2_lock_req request;
+
+	request.mem_usage = usage;
+	request.lock = lock;
+
+	request.chunks.chunk_list = (unsigned int *)chunks;
+	request.chunks.chunk_list_size = nchunks;
+	request.chunks.chunk_size = chunk_size;
+
+	return scm_call(SCM_SVC_CP, MEM_PROTECT_LOCK_ID,
+			&request, sizeof(request), NULL, 0);
+
+}
+
diff --git a/drivers/gpu/ion/msm/ion_cp_common.h b/drivers/gpu/ion/msm/ion_cp_common.h
new file mode 100644
index 0000000..69dd19e
--- /dev/null
+++ b/drivers/gpu/ion/msm/ion_cp_common.h
@@ -0,0 +1,49 @@
+/*
+ * 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 ION_CP_COMMON_H
+#define ION_CP_COMMON_H
+
+#include <asm-generic/errno-base.h>
+#include <linux/ion.h>
+
+#define ION_CP_V1	1
+#define ION_CP_V2	2
+
+#if defined(CONFIG_ION_MSM)
+/*
+ * ion_cp2_protect_mem - secures memory via trustzone
+ *
+ * @chunks - physical address of the array containing the chunks to
+ *		be locked down
+ * @nchunks - number of entries in the array
+ * @chunk_size - size of each memory chunk
+ * @usage - usage hint
+ * @lock - 1 for lock, 0 for unlock
+ *
+ * return value is the result of the scm call
+ */
+int ion_cp_change_chunks_state(unsigned long chunks, unsigned int nchunks,
+			unsigned int chunk_size, enum cp_mem_usage usage,
+			int lock);
+
+#else
+static inline int ion_cp_change_chunks_state(unsigned long chunks,
+			unsigned int nchunks, unsigned int chunk_size,
+			enum cp_mem_usage usage, int lock)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index f6a4cf4..eec3fe0 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -21,6 +21,7 @@
 #include <mach/ion.h>
 #include <mach/msm_memtypes.h>
 #include "../ion_priv.h"
+#include "ion_cp_common.h"
 
 static struct ion_device *idev;
 static int num_heaps;
@@ -35,16 +36,28 @@
 
 int msm_ion_secure_heap(int heap_id)
 {
-	return ion_secure_heap(idev, heap_id);
+	return ion_secure_heap(idev, heap_id, ION_CP_V1, NULL);
 }
 EXPORT_SYMBOL(msm_ion_secure_heap);
 
 int msm_ion_unsecure_heap(int heap_id)
 {
-	return ion_unsecure_heap(idev, heap_id);
+	return ion_unsecure_heap(idev, heap_id, ION_CP_V1, NULL);
 }
 EXPORT_SYMBOL(msm_ion_unsecure_heap);
 
+int msm_ion_secure_heap_2_0(int heap_id, enum cp_mem_usage usage)
+{
+	return ion_secure_heap(idev, heap_id, ION_CP_V2, (void *)usage);
+}
+EXPORT_SYMBOL(msm_ion_secure_heap_2_0);
+
+int msm_ion_unsecure_heap_2_0(int heap_id, enum cp_mem_usage usage)
+{
+	return ion_unsecure_heap(idev, heap_id, ION_CP_V2, (void *)usage);
+}
+EXPORT_SYMBOL(msm_ion_unsecure_heap_2_0);
+
 int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
 			void *vaddr, unsigned long len, unsigned int cmd)
 {
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 0a71982..bd58b4e 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -46,6 +46,7 @@
 #define A3XX_RBBM_HW_VERSION 0x000
 #define A3XX_RBBM_HW_RELEASE 0x001
 #define A3XX_RBBM_HW_CONFIGURATION 0x002
+#define A3XX_RBBM_CLOCK_CTL 0x010
 #define A3XX_RBBM_SP_HYST_CNT 0x012
 #define A3XX_RBBM_SW_RESET_CMD 0x018
 #define A3XX_RBBM_AHB_CTL0 0x020
@@ -507,4 +508,7 @@
 #define RBBM_BLOCK_ID_MARB_2           0x2a
 #define RBBM_BLOCK_ID_MARB_3           0x2b
 
+/* RBBM_CLOCK_CTL default value */
+#define A3XX_RBBM_CLOCK_CTL_DEFAULT 0x00000000
+
 #endif
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 3de3af9..4991a2e 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1592,10 +1592,17 @@
 	adreno_dev->gpudev->irq_control(adreno_dev, state);
 }
 
-static unsigned int adreno_gpuid(struct kgsl_device *device)
+static unsigned int adreno_gpuid(struct kgsl_device *device,
+	unsigned int *chipid)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
+	/* Some applications need to know the chip ID too, so pass
+	 * that as a parameter */
+
+	if (chipid != NULL)
+		*chipid = adreno_dev->chip_id;
+
 	/* Standard KGSL gpuid format:
 	 * top word is 0x0002 for 2D or 0x0003 for 3D
 	 * Bottom word is core specific identifer
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index c3c266e..d846d3d 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1450,43 +1450,55 @@
 	return ret;
 }
 
-static void a2xx_drawctxt_draw_workaround(struct adreno_device *adreno_dev)
+static void a2xx_drawctxt_workaround(struct adreno_device *adreno_dev)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 	unsigned int cmd[11];
 	unsigned int *cmds = &cmd[0];
 
-	adreno_dev->gpudev->ctx_switches_since_last_draw++;
-	/* If there have been > than ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW
-	 * calls to context switches w/o gmem being saved then we need to
-	 * execute this workaround */
-	if (adreno_dev->gpudev->ctx_switches_since_last_draw >
-		ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW)
-		adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
-	else
-		return;
-	/*
-	 * Issue an empty draw call to avoid possible hangs due to
-	 * repeated idles without intervening draw calls.
-	 * On adreno 225 the PC block has a cache that is only
-	 * flushed on draw calls and repeated idles can make it
-	 * overflow. The gmem save path contains draw calls so
-	 * this workaround isn't needed there.
-	 */
-	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
-	*cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
-	*cmds++ = 0;
-	*cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
-	*cmds++ = 0;
-	*cmds++ = 1<<14;
-	*cmds++ = 0;
-	*cmds++ = device->mmu.setstate_memory.gpuaddr;
-	*cmds++ = 0;
-	*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
-	*cmds++ = 0x00000000;
+	if (adreno_is_a225(adreno_dev)) {
+		adreno_dev->gpudev->ctx_switches_since_last_draw++;
+		/* If there have been > than
+		 * ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW calls to context
+		 * switches w/o gmem being saved then we need to execute
+		 * this workaround */
+		if (adreno_dev->gpudev->ctx_switches_since_last_draw >
+				ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW)
+			adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
+		else
+			return;
+		/*
+		 * Issue an empty draw call to avoid possible hangs due to
+		 * repeated idles without intervening draw calls.
+		 * On adreno 225 the PC block has a cache that is only
+		 * flushed on draw calls and repeated idles can make it
+		 * overflow. The gmem save path contains draw calls so
+		 * this workaround isn't needed there.
+		 */
+		*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+		*cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
+		*cmds++ = 0;
+		*cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
+		*cmds++ = 0;
+		*cmds++ = 1<<14;
+		*cmds++ = 0;
+		*cmds++ = device->mmu.setstate_memory.gpuaddr;
+		*cmds++ = 0;
+		*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+		*cmds++ = 0x00000000;
+	} else {
+		/* On Adreno 20x/220, if the events for shader space reuse
+		 * gets dropped, the CP block would wait indefinitely.
+		 * Sending CP_SET_SHADER_BASES packet unblocks the CP from
+		 * this wait.
+		 */
+		*cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
+		*cmds++ = adreno_encode_istore_size(adreno_dev)
+					| adreno_dev->pix_shader_start;
+	}
 
 	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
-				    &cmd[0], 11);
+			&cmd[0], cmds - cmd);
 }
 
 static void a2xx_drawctxt_save(struct adreno_device *adreno_dev,
@@ -1540,8 +1552,8 @@
 		adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
 
 		context->flags |= CTXT_FLAGS_GMEM_RESTORE;
-	} else if (adreno_is_a225(adreno_dev))
-		a2xx_drawctxt_draw_workaround(adreno_dev);
+	} else if (adreno_is_a2xx(adreno_dev))
+		a2xx_drawctxt_workaround(adreno_dev);
 }
 
 static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
@@ -1999,7 +2011,7 @@
 	.ctxt_create = a2xx_drawctxt_create,
 	.ctxt_save = a2xx_drawctxt_save,
 	.ctxt_restore = a2xx_drawctxt_restore,
-	.ctxt_draw_workaround = a2xx_drawctxt_draw_workaround,
+	.ctxt_draw_workaround = a2xx_drawctxt_workaround,
 	.irq_handler = a2xx_irq_handler,
 	.irq_control = a2xx_irq_control,
 	.snapshot = a2xx_snapshot,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 600e04f..58a0963 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -433,6 +433,9 @@
 	unsigned int *cmds = tmp_ctx.cmd;
 	unsigned int *start = cmds;
 
+	*cmds++ = cp_type0_packet(A3XX_RBBM_CLOCK_CTL, 1);
+	*cmds++ = A3XX_RBBM_CLOCK_CTL_DEFAULT;
+
 	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
 	*cmds++ = CP_REG(A3XX_RB_MODE_CONTROL);
 
@@ -1162,6 +1165,9 @@
 	unsigned int *cmds = tmp_ctx.cmd;
 	unsigned int *start = cmds;
 
+	*cmds++ = cp_type0_packet(A3XX_RBBM_CLOCK_CTL, 1);
+	*cmds++ = A3XX_RBBM_CLOCK_CTL_DEFAULT;
+
 	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
 	*cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
 	/* HLSQ_CONTROL_0_REG */
@@ -2409,30 +2415,29 @@
 
 static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq)
 {
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+	struct kgsl_device *device = &adreno_dev->dev;
 
 	if (irq == A3XX_INT_CP_RB_INT) {
 		unsigned int context_id;
-		kgsl_sharedmem_readl(&adreno_dev->dev.memstore,
-				&context_id,
+		kgsl_sharedmem_readl(&device->memstore, &context_id,
 				KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 					current_context));
 		if (context_id < KGSL_MEMSTORE_MAX) {
-			kgsl_sharedmem_writel(&rb->device->memstore,
+			kgsl_sharedmem_writel(&device->memstore,
 					KGSL_MEMSTORE_OFFSET(context_id,
 						ts_cmp_enable), 0);
 			wmb();
 		}
-		KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
+		KGSL_CMD_WARN(device, "ringbuffer rb interrupt\n");
 	}
 
-	wake_up_interruptible_all(&rb->device->wait_queue);
+	wake_up_interruptible_all(&device->wait_queue);
 
 	/* Schedule work to free mem and issue ibs */
-	queue_work(rb->device->work_queue, &rb->device->ts_expired_ws);
+	queue_work(device->work_queue, &device->ts_expired_ws);
 
-	atomic_notifier_call_chain(&rb->device->ts_notifier_list,
-				   rb->device->id, NULL);
+	atomic_notifier_call_chain(&device->ts_notifier_list,
+				   device->id, NULL);
 }
 
 #define A3XX_IRQ_CALLBACK(_c) { .func = _c }
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index c8c7c44..60aab64 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -19,6 +19,29 @@
 #define DEBUG_SECTION_SZ(_dwords) (((_dwords) * sizeof(unsigned int)) \
 		+ sizeof(struct kgsl_snapshot_debug))
 
+#define SHADER_MEMORY_SIZE 0x4000
+
+static int a3xx_snapshot_shader_memory(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(SHADER_MEMORY_SIZE)) {
+		SNAPSHOT_ERR_NOMEM(device, "SHADER MEMORY");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_SHADER_MEMORY;
+	header->size = SHADER_MEMORY_SIZE;
+
+	for (i = 0; i < SHADER_MEMORY_SIZE; i++)
+		adreno_regread(device, 0x4000 + i, &data[i]);
+
+	return DEBUG_SECTION_SZ(SHADER_MEMORY_SIZE);
+}
+
 #define VPC_MEMORY_BANKS 4
 #define VPC_MEMORY_SIZE 512
 
@@ -272,6 +295,12 @@
 			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
 			a3xx_snapshot_cp_meq, NULL);
 
+	/* Shader working/shadow memory */
+	snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a3xx_snapshot_shader_memory, NULL);
+
+
 	/* CP PFP and PM4 */
 	/* Reading these will hang the GPU if it isn't already hung */
 
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 49d035f..267fd45 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -199,7 +199,7 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_context *drawctxt;
 
-	if (context == NULL)
+	if (context == NULL || context->devctxt == NULL)
 		return;
 
 	drawctxt = context->devctxt;
diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h
index fb44b25..016862b 100644
--- a/drivers/gpu/msm/adreno_pm4types.h
+++ b/drivers/gpu/msm/adreno_pm4types.h
@@ -203,7 +203,14 @@
 #define type0_pkt_size(pkt) ((((pkt) >> 16) & 0x3FFF) + 1)
 #define type0_pkt_offset(pkt) ((pkt) & 0x7FFF)
 
-#define pkt_is_type3(pkt) (((pkt) & 0xC0000000) == CP_TYPE3_PKT)
+/*
+ * Check both for the type3 opcode and make sure that the reserved bits [1:7]
+ * and 15 are 0
+ */
+
+#define pkt_is_type3(pkt) \
+	((((pkt) & 0xC0000000) == CP_TYPE3_PKT) && \
+	 (((pkt) & 0x80FE) == 0))
 
 #define cp_type3_opcode(pkt) (((pkt) >> 8) & 0xFF)
 #define type3_pkt_size(pkt) ((((pkt) >> 16) & 0x3FFF) + 1)
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 5572695..08a01b0 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -161,6 +161,22 @@
 static unsigned int sp_vs_pvt_mem_addr;
 static unsigned int sp_fs_pvt_mem_addr;
 
+/*
+ * Each load state block has two possible types.  Each type has a different
+ * number of dwords per unit.  Use this handy lookup table to make sure
+ * we dump the right amount of data from the indirect buffer
+ */
+
+static int load_state_unit_sizes[7][2] = {
+	{ 2, 4 },
+	{ 0, 1 },
+	{ 2, 4 },
+	{ 0, 1 },
+	{ 8, 2 },
+	{ 8, 2 },
+	{ 8, 2 },
+};
+
 static void ib_parse_load_state(struct kgsl_device *device, unsigned int *pkt,
 	unsigned int ptbase)
 {
@@ -170,11 +186,9 @@
 	 * The object here is to find indirect shaders i.e - shaders loaded from
 	 * GPU memory instead of directly in the command.  These should be added
 	 * to the list of memory objects to dump. So look at the load state
-	 * call and see if 1) the shader block is a shader (block = 4, 5 or 6)
-	 * 2) that the block is indirect (source = 4). If these all match then
-	 * add the memory address to the list.  The size of the object will
-	 * differ depending on the type.  Type 0 (instructions) are 8 dwords per
-	 * unit and type 1 (constants) are 2 dwords per unit.
+	 * if the block is indirect (source = 4). If so then add the memory
+	 * address to the list.  The size of the object differs depending on the
+	 * type per the load_state_unit_sizes array above.
 	 */
 
 	if (type3_pkt_size(pkt[0]) < 2)
@@ -192,9 +206,13 @@
 	source = (pkt[1] >> 16) & 0x07;
 	type = pkt[2] & 0x03;
 
-	if ((block == 4 || block == 5 || block == 6) && source == 4) {
-		int unitsize = (type == 0) ? 8 : 2;
-		int ret;
+	if (source == 4) {
+		int unitsize, ret;
+
+		if (type == 0)
+			unitsize = load_state_unit_sizes[block][0];
+		else
+			unitsize = load_state_unit_sizes[block][1];
 
 		/* Freeze the GPU buffer containing the shader */
 
@@ -528,7 +546,6 @@
 	unsigned int ptbase, rptr, *rbptr, ibbase;
 	int index, size, i;
 	int parse_ibs = 0, ib_parse_start;
-	int skip_pktsize = 1;
 
 	/* Get the physical address of the MMU pagetable */
 	ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
@@ -541,13 +558,14 @@
 
 	/*
 	 * Figure out the window of ringbuffer data to dump.  First we need to
-	 * find where the last processed IB ws submitted
+	 * find where the last processed IB ws submitted.  Start walking back
+	 * from the rptr
 	 */
 
 	index = rptr;
 	rbptr = rb->buffer_desc.hostptr;
 
-	while (index != rb->wptr) {
+	do {
 		index--;
 
 		if (index < 0) {
@@ -563,7 +581,7 @@
 		if (adreno_cmd_is_ib(rbptr[index]) &&
 			rbptr[index + 1] == ibbase)
 			break;
-	}
+	} while (index != rb->wptr);
 
 	/*
 	 * index points at the last submitted IB. We can only trust that the
@@ -636,18 +654,15 @@
 		 * try to adust for that by modifying the rptr to match a
 		 * packet boundary. Unfortunately for us, it is hard to tell
 		 * which dwords are legitimate type0 header and which are just
-		 * random data so just walk over type0 packets until we get
-		 * to the first type3, and from that point on start checking the
-		 * size of the packet and adjusting accordingly
+		 * random data so only do the adjustments for type3 packets
 		 */
 
-		if (skip_pktsize && pkt_is_type3(rbptr[index]))
-			skip_pktsize = 0;
-
-		if (skip_pktsize == 0) {
-			unsigned int pktsize = type3_pkt_size(rbptr[index]);
+		if (pkt_is_type3(rbptr[index])) {
+			unsigned int pktsize =
+				type3_pkt_size(rbptr[index]);
 			if (index +  pktsize > rptr)
-				rptr = (index + pktsize) % rb->sizedwords;
+				rptr = (index + pktsize) %
+					rb->sizedwords;
 		}
 
 		/*
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e789733..5883f08 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2523,7 +2523,7 @@
 	}
 
 	status = kgsl_allocate_contiguous(&device->memstore,
-		sizeof(struct kgsl_devmemstore));
+		KGSL_MEMSTORE_SIZE);
 
 	if (status != 0) {
 		KGSL_DRV_ERR(device, "kgsl_allocate_contiguous failed %d\n",
@@ -2598,9 +2598,17 @@
 	kgsl_drm_exit();
 	kgsl_cffdump_destroy();
 	kgsl_core_debugfs_close();
-	kgsl_sharedmem_uninit_sysfs();
 
-	device_unregister(&kgsl_driver.virtdev);
+	/*
+	 * We call kgsl_sharedmem_uninit_sysfs() and device_unregister()
+	 * only if kgsl_driver.virtdev has been populated.
+	 * We check at least one member of kgsl_driver.virtdev to
+	 * see if it is not NULL (and thus, has been populated).
+	 */
+	if (kgsl_driver.virtdev.class) {
+		kgsl_sharedmem_uninit_sysfs();
+		device_unregister(&kgsl_driver.virtdev);
+	}
 
 	if (kgsl_driver.class) {
 		class_destroy(kgsl_driver.class);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 64acff8..932c995 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -90,7 +90,7 @@
 	void (*power_stats)(struct kgsl_device *device,
 		struct kgsl_power_stats *stats);
 	void (*irqctrl)(struct kgsl_device *device, int state);
-	unsigned int (*gpuid)(struct kgsl_device *device);
+	unsigned int (*gpuid)(struct kgsl_device *device, unsigned int *chipid);
 	void * (*snapshot)(struct kgsl_device *device, void *snapshot,
 		int *remain, int hang);
 	irqreturn_t (*irq_handler)(struct kgsl_device *device);
@@ -287,9 +287,10 @@
 	return device->ftbl->idle(device, timeout);
 }
 
-static inline unsigned int kgsl_gpuid(struct kgsl_device *device)
+static inline unsigned int kgsl_gpuid(struct kgsl_device *device,
+	unsigned int *chipid)
 {
-	return device->ftbl->gpuid(device);
+	return device->ftbl->gpuid(device, chipid);
 }
 
 static inline unsigned int kgsl_readtimestamp(struct kgsl_device *device,
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index b3f2d1e..e42c7b6 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -837,6 +837,10 @@
 {
 	unsigned int pt_base;
 	struct kgsl_iommu *iommu = mmu->priv;
+	/* We cannot enable or disable the clocks in interrupt context, this
+	 function is called from interrupt context if there is an axi error */
+	if (in_interrupt())
+		return 0;
 	/* Return the current pt base by reading IOMMU pt_base register */
 	kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER);
 	pt_base = readl_relaxed(iommu->iommu_units[0].reg_map.hostptr +
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 8935b29..824d806 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -35,6 +35,56 @@
 	struct list_head node;
 };
 
+struct snapshot_obj_itr {
+	void *buf;      /* Buffer pointer to write to */
+	int pos;        /* Current position in the sequence */
+	loff_t offset;  /* file offset to start writing from */
+	size_t remain;  /* Bytes remaining in buffer */
+	size_t write;   /* Bytes written so far */
+};
+
+static void obj_itr_init(struct snapshot_obj_itr *itr, void *buf,
+	loff_t offset, size_t remain)
+{
+	itr->buf = buf;
+	itr->offset = offset;
+	itr->remain = remain;
+	itr->pos = 0;
+	itr->write = 0;
+}
+
+static int obj_itr_out(struct snapshot_obj_itr *itr, void *src, int size)
+{
+	if (itr->remain == 0)
+		return 0;
+
+	if ((itr->pos + size) <= itr->offset)
+		goto done;
+
+	/* Handle the case that offset is in the middle of the buffer */
+
+	if (itr->offset > itr->pos) {
+		src += (itr->offset - itr->pos);
+		size -= (itr->offset - itr->pos);
+
+		/* Advance pos to the offset start */
+		itr->pos = itr->offset;
+	}
+
+	if (size > itr->remain)
+		size = itr->remain;
+
+	memcpy(itr->buf, src, size);
+
+	itr->buf += size;
+	itr->write += size;
+	itr->remain -= size;
+
+done:
+	itr->pos += size;
+	return size;
+}
+
 /* idr_for_each function to count the number of contexts */
 
 static int snapshot_context_count(int id, void *ptr, void *data)
@@ -182,76 +232,46 @@
 	(sizeof(struct kgsl_snapshot_section_header) + \
 	 sizeof(struct kgsl_snapshot_gpu_object))
 
-#define GPU_OBJ_SECTION_SIZE(_o) \
-	(GPU_OBJ_HEADER_SZ + ((_o)->size))
-
 static int kgsl_snapshot_dump_object(struct kgsl_device *device,
-		struct kgsl_snapshot_object *obj, void *buf,
-		unsigned int off, unsigned int count)
+	struct kgsl_snapshot_object *obj, struct snapshot_obj_itr *itr)
 {
-	unsigned char headers[GPU_OBJ_HEADER_SZ];
-	struct kgsl_snapshot_section_header *sect =
-		(struct kgsl_snapshot_section_header *) headers;
-	struct kgsl_snapshot_gpu_object *header =
-		(struct kgsl_snapshot_gpu_object *) (headers + sizeof(*sect));
-	int ret = 0;
+	struct kgsl_snapshot_section_header sect;
+	struct kgsl_snapshot_gpu_object header;
+	int ret;
 
-	/* Construct a local copy of the headers */
+	sect.magic = SNAPSHOT_SECTION_MAGIC;
+	sect.id = KGSL_SNAPSHOT_SECTION_GPU_OBJECT;
 
-	sect->magic = SNAPSHOT_SECTION_MAGIC;
-	sect->id = KGSL_SNAPSHOT_SECTION_GPU_OBJECT;
-	sect->size = GPU_OBJ_SECTION_SIZE(obj);
+	/*
+	 * Header size is in dwords, object size is in bytes -
+	 * round up if the object size isn't dword aligned
+	 */
 
-	header->type = obj->type;
+	sect.size = GPU_OBJ_HEADER_SZ + ALIGN(obj->size, 4);
 
-	/* Header size is in dwords, object size is in bytes */
-	header->size = obj->size >> 2;
-	header->gpuaddr = obj->gpuaddr;
-	header->ptbase = obj->ptbase;
+	ret = obj_itr_out(itr, &sect, sizeof(sect));
+	if (ret == 0)
+		return 0;
 
-	/* Copy out any part of the header block that is needed */
+	header.size = ALIGN(obj->size, 4) >> 2;
+	header.gpuaddr = obj->gpuaddr;
+	header.ptbase = obj->ptbase;
+	header.type = obj->type;
 
-	if (off < GPU_OBJ_HEADER_SZ) {
-		int size = count < GPU_OBJ_HEADER_SZ - off ?
-			count : GPU_OBJ_HEADER_SZ - off;
+	ret = obj_itr_out(itr, &header, sizeof(header));
+	if (ret == 0)
+		return 0;
 
-		memcpy(buf, headers + off, size);
+	ret = obj_itr_out(itr, obj->entry->memdesc.hostptr + obj->offset,
+		obj->size);
+	if (ret == 0)
+		return 0;
 
-		count -= size;
-		ret += size;
-	}
+	/* Pad the end to a dword boundary if we need to */
 
-	/* Now copy whatever part of the data is needed */
-
-	if (off < (GPU_OBJ_HEADER_SZ + obj->size)) {
-		int offset;
-		int size = count < obj->size ? count : obj->size;
-
-		/*
-		 * If the desired gpuaddr isn't at the beginning of the region,
-		 * then offset the source pointer
-		 */
-
-		offset = obj->offset;
-
-		/*
-		 * Then  adjust it to account for the offset for the output
-		 * buffer.
-		 */
-
-		if (off > GPU_OBJ_HEADER_SZ) {
-			int loff = (off - GPU_OBJ_HEADER_SZ);
-
-			/* Adjust the size so we don't walk off the end */
-
-			if ((loff + size) > obj->size)
-				size = obj->size - loff;
-
-			offset += loff;
-		}
-
-		memcpy(buf + ret, obj->entry->memdesc.hostptr + offset, size);
-		ret += size;
+	if (obj->size % 4) {
+		unsigned int dummy = 0;
+		ret = obj_itr_out(itr, &dummy, obj->size % 4);
 	}
 
 	return ret;
@@ -488,7 +508,7 @@
 
 	header->magic = SNAPSHOT_MAGIC;
 
-	header->gpuid = kgsl_gpuid(device);
+	header->gpuid = kgsl_gpuid(device, &header->chipid);
 
 	/* Get a pointer to the first section (right after the header) */
 	snapshot = ((void *) device->snapshot) + sizeof(*header);
@@ -539,7 +559,9 @@
 {
 	struct kgsl_device *device = kobj_to_device(kobj);
 	struct kgsl_snapshot_object *obj, *tmp;
-	unsigned int size, src, dst = 0;
+	struct kgsl_snapshot_section_header head;
+	struct snapshot_obj_itr itr;
+	int ret;
 
 	if (device == NULL)
 		return 0;
@@ -551,80 +573,46 @@
 	/* Get the mutex to keep things from changing while we are dumping */
 	mutex_lock(&device->mutex);
 
-	if (off < device->snapshot_size) {
-		size = count < (device->snapshot_size - off) ?
-			count : device->snapshot_size - off;
+	obj_itr_init(&itr, buf, off, count);
 
-		memcpy(buf, device->snapshot + off, size);
+	ret = obj_itr_out(&itr, device->snapshot, device->snapshot_size);
 
-		count -= size;
-		dst += size;
-	}
-
-	if (count == 0)
+	if (ret == 0)
 		goto done;
 
-	src = device->snapshot_size;
+	list_for_each_entry(obj, &device->snapshot_obj_list, node)
+		kgsl_snapshot_dump_object(device, obj, &itr);
 
-	list_for_each_entry(obj, &device->snapshot_obj_list, node) {
+	{
+		head.magic = SNAPSHOT_SECTION_MAGIC;
+		head.id = KGSL_SNAPSHOT_SECTION_END;
+		head.size = sizeof(head);
 
-		int objsize = GPU_OBJ_SECTION_SIZE(obj);
-		int offset;
-
-		/* If the offset is beyond this object, then move on */
-
-		if (off >= (src + objsize)) {
-			src += objsize;
-			continue;
-		}
-
-		/* Adjust the offset to be relative to the object */
-		offset = (off >= src) ? (off - src) : 0;
-
-		size = kgsl_snapshot_dump_object(device, obj, buf + dst,
-			offset, count);
-
-		count -= size;
-		dst += size;
-
-		if (count == 0)
-			goto done;
-
-		/* Move on to the next object - update src accordingly */
-		src += objsize;
+		obj_itr_out(&itr, &head, sizeof(head));
 	}
 
-	/* Add the end section */
+	/*
+	 * Make sure everything has been written out before destroying things.
+	 * The best way to confirm this is to go all the way through without
+	 * writing any bytes - so only release if we get this far and
+	 * itr->write is 0
+	 */
 
-	if (off < (src + sizeof(struct kgsl_snapshot_section_header))) {
-		if (count >= sizeof(struct kgsl_snapshot_section_header)) {
-			struct kgsl_snapshot_section_header *head =
-				(void *) (buf + dst);
+	if (itr.write == 0) {
+		list_for_each_entry_safe(obj, tmp, &device->snapshot_obj_list,
+			node)
+			kgsl_snapshot_put_object(device, obj);
 
-			head->magic = SNAPSHOT_SECTION_MAGIC;
-			head->id = KGSL_SNAPSHOT_SECTION_END;
-			head->size = sizeof(*head);
+		if (device->snapshot_frozen)
+			KGSL_DRV_ERR(device, "Snapshot objects released\n");
 
-			dst += sizeof(*head);
-		} else {
-			goto done;
-		}
+		device->snapshot_frozen = 0;
 	}
 
-	/* Release the buffers and unfreeze the snapshot */
-
-	list_for_each_entry_safe(obj, tmp, &device->snapshot_obj_list, node)
-		kgsl_snapshot_put_object(device, obj);
-
-	if (device->snapshot_frozen)
-		KGSL_DRV_ERR(device, "Snapshot objects released\n");
-
-	device->snapshot_frozen = 0;
-
 done:
 	mutex_unlock(&device->mutex);
 
-	return dst;
+	return itr.write;
 }
 
 /* Show the timestamp of the last collected snapshot */
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
index 304f4bb..d54afcf 100644
--- a/drivers/gpu/msm/kgsl_snapshot.h
+++ b/drivers/gpu/msm/kgsl_snapshot.h
@@ -18,7 +18,8 @@
 
 /* Snapshot header */
 
-#define SNAPSHOT_MAGIC 0x504D0001
+/* High word is static, low word is snapshot version ID */
+#define SNAPSHOT_MAGIC 0x504D0002
 
 /* GPU ID scheme:
  * [16:31] - core identifer (0x0002 for 2D or 0x0003 for 3D)
@@ -28,6 +29,8 @@
 struct kgsl_snapshot_header {
 	__u32 magic; /* Magic identifier */
 	__u32 gpuid; /* GPU ID - see above */
+	/* Added in snapshot version 2 */
+	__u32 chipid; /* Chip ID from the GPU */
 } __packed;
 
 /* Section header */
@@ -140,6 +143,7 @@
 #define SNAPSHOT_DEBUG_CP_PM4_RAM 8
 #define SNAPSHOT_DEBUG_CP_PFP_RAM 9
 #define SNAPSHOT_DEBUG_CP_ROQ     10
+#define SNAPSHOT_DEBUG_SHADER_MEMORY 11
 
 struct kgsl_snapshot_debug {
 	int type;    /* Type identifier for the attached tata */
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index f4bbf69..bc2685c 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -896,8 +896,11 @@
 	}
 }
 
-static unsigned int z180_gpuid(struct kgsl_device *device)
+static unsigned int z180_gpuid(struct kgsl_device *device, unsigned int *chipid)
 {
+	if (chipid != NULL)
+		*chipid = 0;
+
 	/* Standard KGSL gpuid format:
 	 * top word is 0x0002 for 2D or 0x0003 for 3D
 	 * Bottom word is core specific identifer
diff --git a/drivers/i2c/busses/i2c-msm.c b/drivers/i2c/busses/i2c-msm.c
index b753fd0..4b48a69 100644
--- a/drivers/i2c/busses/i2c-msm.c
+++ b/drivers/i2c/busses/i2c-msm.c
@@ -636,7 +636,7 @@
 	spin_lock_init(&dev->lock);
 	platform_set_drvdata(pdev, dev);
 
-	clk_enable(clk);
+	clk_prepare_enable(clk);
 
 	if (pdata->rmutex) {
 		struct remote_mutex_id rmid;
@@ -697,7 +697,8 @@
 	/* Config GPIOs for primary and secondary lines */
 	pdata->msm_i2c_config_gpio(dev->adap_pri.nr, 1);
 	pdata->msm_i2c_config_gpio(dev->adap_aux.nr, 1);
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
+	clk_prepare(dev->clk);
 	setup_timer(&dev->pwr_timer, msm_i2c_pwr_timer, (unsigned long) dev);
 
 	return 0;
@@ -706,7 +707,7 @@
 	i2c_del_adapter(&dev->adap_pri);
 	i2c_del_adapter(&dev->adap_aux);
 err_i2c_add_adapter_failed:
-	clk_disable(clk);
+	clk_disable_unprepare(clk);
 	iounmap(dev->base);
 err_ioremap_failed:
 	kfree(dev);
@@ -736,6 +737,7 @@
 	free_irq(dev->irq, dev);
 	i2c_del_adapter(&dev->adap_pri);
 	i2c_del_adapter(&dev->adap_aux);
+	clk_unprepare(dev->clk);
 	clk_put(dev->clk);
 	iounmap(dev->base);
 	kfree(dev);
@@ -759,6 +761,7 @@
 		del_timer_sync(&dev->pwr_timer);
 		if (dev->clk_state != 0)
 			msm_i2c_pwr_mgmt(dev, 0);
+		clk_unprepare(dev->clk);
 	}
 
 	return 0;
@@ -767,6 +770,7 @@
 static int msm_i2c_resume(struct platform_device *pdev)
 {
 	struct msm_i2c_dev *dev = platform_get_drvdata(pdev);
+	clk_prepare(dev->clk);
 	dev->suspended = 0;
 	return 0;
 }
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 5403c57..8b6e172 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -40,6 +40,8 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/input/mpu3050.h>
+#include <linux/regulator/consumer.h>
 
 #define MPU3050_CHIP_ID		0x69
 
@@ -112,8 +114,81 @@
 	struct i2c_client *client;
 	struct device *dev;
 	struct input_dev *idev;
+	struct mpu3050_gyro_platform_data *platform_data;
+	struct delayed_work input_work;
+	u32    use_poll;
 };
 
+struct sensor_regulator {
+	struct regulator *vreg;
+	const char *name;
+	u32	min_uV;
+	u32	max_uV;
+};
+
+struct sensor_regulator mpu_vreg[] = {
+	{NULL, "vdd", 2100000, 3600000},
+	{NULL, "vlogic", 1800000, 1800000},
+};
+
+static int mpu3050_config_regulator(struct i2c_client *client, bool on)
+{
+	int rc = 0, i;
+	int num_reg = sizeof(mpu_vreg) / sizeof(struct sensor_regulator);
+
+	if (on) {
+		for (i = 0; i < num_reg; i++) {
+			mpu_vreg[i].vreg = regulator_get(&client->dev,
+						mpu_vreg[i].name);
+			if (IS_ERR(mpu_vreg[i].vreg)) {
+				rc = PTR_ERR(mpu_vreg[i].vreg);
+				pr_err("%s:regulator get failed rc=%d\n",
+						__func__, rc);
+				goto error_vdd;
+			}
+
+			if (regulator_count_voltages(mpu_vreg[i].vreg) > 0) {
+				rc = regulator_set_voltage(mpu_vreg[i].vreg,
+					mpu_vreg[i].min_uV, mpu_vreg[i].max_uV);
+				if (rc) {
+					pr_err("%s:set_voltage failed rc=%d\n",
+						__func__, rc);
+					regulator_put(mpu_vreg[i].vreg);
+					goto error_vdd;
+				}
+			}
+
+			rc = regulator_enable(mpu_vreg[i].vreg);
+			if (rc) {
+				pr_err("%s: regulator_enable failed rc =%d\n",
+						__func__,
+						rc);
+
+				if (regulator_count_voltages(
+					mpu_vreg[i].vreg) > 0) {
+					regulator_set_voltage(mpu_vreg[i].vreg,
+						0, mpu_vreg[i].max_uV);
+				}
+				regulator_put(mpu_vreg[i].vreg);
+				goto error_vdd;
+			}
+		}
+		return rc;
+	} else {
+		i = num_reg;
+	}
+error_vdd:
+	while (--i >= 0) {
+		if (regulator_count_voltages(mpu_vreg[i].vreg) > 0) {
+			regulator_set_voltage(mpu_vreg[i].vreg, 0,
+						mpu_vreg[i].max_uV);
+		}
+		regulator_disable(mpu_vreg[i].vreg);
+		regulator_put(mpu_vreg[i].vreg);
+	}
+	return rc;
+}
+
 /**
  *	mpu3050_xyz_read_reg	-	read the axes values
  *	@buffer: provide register addr and get register
@@ -179,11 +254,21 @@
 {
 	u8 value;
 
+	if (val) {
+		mpu3050_config_regulator(client, 1);
+		udelay(10);
+	}
+
 	value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
 	value = (value & ~MPU3050_PWR_MGM_MASK) |
 		(((val << MPU3050_PWR_MGM_POS) & MPU3050_PWR_MGM_MASK) ^
 		 MPU3050_PWR_MGM_MASK);
 	i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, value);
+
+	if (!val) {
+		udelay(10);
+		mpu3050_config_regulator(client, 0);
+	}
 }
 
 /**
@@ -210,6 +295,9 @@
 		pm_runtime_put(sensor->dev);
 		return error;
 	}
+	if (sensor->use_poll)
+		schedule_delayed_work(&sensor->input_work,
+			msecs_to_jiffies(MPU3050_DEFAULT_POLL_INTERVAL));
 
 	return 0;
 }
@@ -225,6 +313,9 @@
 {
 	struct mpu3050_sensor *sensor = input_get_drvdata(input);
 
+	if (sensor->use_poll)
+		cancel_delayed_work_sync(&sensor->input_work);
+
 	pm_runtime_put(sensor->dev);
 }
 
@@ -252,6 +343,33 @@
 }
 
 /**
+ *	mpu3050_input_work_fn -		polling work
+ *	@work: the work struct
+ *
+ *	Called by the work queue; read sensor data and generate an input
+ *	event
+ */
+static void mpu3050_input_work_fn(struct work_struct *work)
+{
+	struct mpu3050_sensor *sensor;
+	struct axis_data axis;
+
+	sensor = container_of((struct delayed_work *)work,
+				struct mpu3050_sensor, input_work);
+
+	mpu3050_read_xyz(sensor->client, &axis);
+
+	input_report_abs(sensor->idev, ABS_X, axis.x);
+	input_report_abs(sensor->idev, ABS_Y, axis.y);
+	input_report_abs(sensor->idev, ABS_Z, axis.z);
+	input_sync(sensor->idev);
+
+	if (sensor->use_poll)
+		schedule_delayed_work(&sensor->input_work,
+			msecs_to_jiffies(MPU3050_DEFAULT_POLL_INTERVAL));
+}
+
+/**
  *	mpu3050_hw_init	-	initialize hardware
  *	@sensor: the sensor
  *
@@ -325,6 +443,7 @@
 	sensor->client = client;
 	sensor->dev = &client->dev;
 	sensor->idev = idev;
+	sensor->platform_data = client->dev.platform_data;
 
 	mpu3050_set_power_mode(client, 1);
 	msleep(10);
@@ -365,14 +484,22 @@
 	if (error)
 		goto err_pm_set_suspended;
 
-	error = request_threaded_irq(client->irq,
+	if (client->irq == 0) {
+		INIT_DELAYED_WORK(&sensor->input_work, mpu3050_input_work_fn);
+		sensor->use_poll = 1;
+	} else {
+		sensor->use_poll = 0;
+
+		error = request_threaded_irq(client->irq,
 				     NULL, mpu3050_interrupt_thread,
 				     IRQF_TRIGGER_RISING,
 				     "mpu3050", sensor);
-	if (error) {
-		dev_err(&client->dev,
-			"can't get IRQ %d, error %d\n", client->irq, error);
-		goto err_pm_set_suspended;
+		if (error) {
+			dev_err(&client->dev,
+				"can't get IRQ %d, error %d\n",
+				client->irq, error);
+			goto err_pm_set_suspended;
+		}
 	}
 
 	error = input_register_device(idev);
@@ -387,7 +514,8 @@
 	return 0;
 
 err_free_irq:
-	free_irq(client->irq, sensor);
+	if (client->irq > 0)
+		free_irq(client->irq, sensor);
 err_pm_set_suspended:
 	pm_runtime_set_suspended(&client->dev);
 err_free_mem:
diff --git a/drivers/input/touchscreen/atmel_maxtouch.c b/drivers/input/touchscreen/atmel_maxtouch.c
index 52f1f4a..9bdeb51 100644
--- a/drivers/input/touchscreen/atmel_maxtouch.c
+++ b/drivers/input/touchscreen/atmel_maxtouch.c
@@ -2034,6 +2034,7 @@
 	mxt_debug(DEBUG_INFO, "maXTouch driver setting abs parameters\n");
 	
 	set_bit(BTN_TOUCH, input->keybit);
+	set_bit(INPUT_PROP_DIRECT, input->propbit);
 
 	/* Single touch */
 	input_set_abs_params(input, ABS_X, mxt->min_x_val,
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 7fe5498..23317d6 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -266,6 +266,9 @@
 #define MXT_X_INVERT		(1 << 1)
 #define MXT_Y_INVERT		(1 << 2)
 
+/* Touch suppression */
+#define MXT_TCHSUP_ACTIVE      (1 << 0)
+
 /* Touchscreen absolute values */
 #define MXT_MAX_AREA		0xff
 
@@ -343,6 +346,8 @@
 	u8 t9_min_reportid;
 	u8 t15_max_reportid;
 	u8 t15_min_reportid;
+	u8 t42_max_reportid;
+	u8 t42_min_reportid;
 	u8 cfg_version[MXT_CFG_VERSION_LEN];
 	int cfg_version_idx;
 	int t38_start_addr;
@@ -887,6 +892,25 @@
 	data->keyarray_old = data->keyarray_new;
 }
 
+static void mxt_release_all(struct mxt_data *data)
+{
+	int id;
+
+	for (id = 0; id < MXT_MAX_FINGER; id++)
+		if (data->finger[id].status)
+			data->finger[id].status = MXT_RELEASE;
+
+	mxt_input_report(data, 0);
+}
+
+static void mxt_handle_touch_supression(struct mxt_data *data, u8 status)
+{
+	dev_dbg(&data->client->dev, "touch suppression\n");
+	/* release all touches */
+	if (status & MXT_TCHSUP_ACTIVE)
+		mxt_release_all(data);
+}
+
 static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 {
 	struct mxt_data *data = dev_id;
@@ -921,6 +945,9 @@
 		else if (reportid >= data->t15_min_reportid &&
 					reportid <= data->t15_max_reportid)
 			mxt_handle_key_array(data, &message);
+		else if (reportid >= data->t42_min_reportid &&
+					reportid <= data->t42_max_reportid)
+			mxt_handle_touch_supression(data, message.message[0]);
 		else
 			mxt_dump_message(dev, &message);
 	} while (reportid != 0xff);
@@ -1283,6 +1310,7 @@
 	struct mxt_object *t7_object;
 	struct mxt_object *t9_object;
 	struct mxt_object *t15_object;
+	struct mxt_object *t42_object;
 	int error;
 
 	/* Store T7 and T9 locally, used in suspend/resume operations */
@@ -1322,6 +1350,16 @@
 		}
 	}
 
+	/* Store T42 min and max report ids */
+	t42_object = mxt_get_object(data, MXT_PROCI_TOUCHSUPPRESSION_T42);
+	if (!t42_object)
+		dev_dbg(&client->dev, "T42 object is not available\n");
+	else {
+		data->t42_max_reportid = t42_object->max_reportid;
+		data->t42_min_reportid = t42_object->max_reportid -
+					t42_object->num_report_ids + 1;
+	}
+
 	return 0;
 }
 
@@ -2258,6 +2296,7 @@
 	__set_bit(EV_ABS, input_dev->evbit);
 	__set_bit(EV_KEY, input_dev->evbit);
 	__set_bit(BTN_TOUCH, input_dev->keybit);
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
 
 	/* For single touch */
 	input_set_abs_params(input_dev, ABS_X,
diff --git a/drivers/input/touchscreen/cyttsp-i2c-qc.c b/drivers/input/touchscreen/cyttsp-i2c-qc.c
index e82dd13..5af4534 100644
--- a/drivers/input/touchscreen/cyttsp-i2c-qc.c
+++ b/drivers/input/touchscreen/cyttsp-i2c-qc.c
@@ -2510,6 +2510,8 @@
 	set_bit(EV_ABS, input_device->evbit);
 	set_bit(BTN_TOUCH, input_device->keybit);
 	set_bit(BTN_2, input_device->keybit);
+	set_bit(INPUT_PROP_DIRECT, input_device->propbit);
+
 	if (ts->platform_data->use_gestures)
 		set_bit(BTN_3, input_device->keybit);
 
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index c9905a4..ffeb8fe 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -445,6 +445,7 @@
 	__set_bit(EV_KEY, input_dev->evbit);
 	__set_bit(EV_ABS, input_dev->evbit);
 	__set_bit(BTN_TOUCH, input_dev->keybit);
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
 
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
 			     pdata->x_max, 0, 0);
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c
index 10d0b66..2ae9f28 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v2.c
@@ -23,6 +23,8 @@
 #include <linux/iommu.h>
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/sizes.h>
 
@@ -70,6 +72,7 @@
 	struct msm_priv *priv = domain->priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	int ret = 0;
 	int asid;
 
 	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
@@ -78,15 +81,21 @@
 		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
 		BUG_ON(!iommu_drvdata);
 
+
+		ret = __enable_clocks(iommu_drvdata);
+		if (ret)
+			goto fail;
+
 		asid = GET_CB_CONTEXTIDR_ASID(iommu_drvdata->base,
 					   ctx_drvdata->num);
 
 		SET_TLBIVA(iommu_drvdata->base, ctx_drvdata->num,
 			   asid | (va & CB_TLBIVA_VA));
 		mb();
+		__disable_clocks(iommu_drvdata);
 	}
-
-	return 0;
+fail:
+	return ret;
 }
 
 static int __flush_iotlb(struct iommu_domain *domain)
@@ -94,6 +103,7 @@
 	struct msm_priv *priv = domain->priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	int ret = 0;
 	int asid;
 
 	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
@@ -102,14 +112,56 @@
 		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
 		BUG_ON(!iommu_drvdata);
 
+		ret = __enable_clocks(iommu_drvdata);
+		if (ret)
+			goto fail;
+
 		asid = GET_CB_CONTEXTIDR_ASID(iommu_drvdata->base,
 					   ctx_drvdata->num);
 
 		SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num, asid);
 		mb();
+		__disable_clocks(iommu_drvdata);
 	}
 
-	return 0;
+fail:
+	return ret;
+}
+
+static void __reset_iommu(void __iomem *base)
+{
+	int i;
+
+	SET_ACR(base, 0);
+	SET_NSACR(base, 0);
+	SET_CR2(base, 0);
+	SET_NSCR2(base, 0);
+	SET_GFAR(base, 0);
+	SET_GFSRRESTORE(base, 0);
+	SET_TLBIALLNSNH(base, 0);
+	SET_PMCR(base, 0);
+	SET_SCR1(base, 0);
+	SET_SSDR_N(base, 0, 0);
+
+	for (i = 0; i < MAX_NUM_SMR; i++)
+		SET_SMR_VALID(base, i, 0);
+
+	mb();
+}
+
+static void __program_iommu(void __iomem *base)
+{
+	__reset_iommu(base);
+
+	SET_CR0_SMCFCFG(base, 1);
+	SET_CR0_USFCFG(base, 1);
+	SET_CR0_STALLD(base, 1);
+	SET_CR0_GCFGFIE(base, 1);
+	SET_CR0_GCFGFRE(base, 1);
+	SET_CR0_GFIE(base, 1);
+	SET_CR0_GFRE(base, 1);
+	SET_CR0_CLIENTPD(base, 0);
+	mb();	/* Make sure writes complete before returning */
 }
 
 static void __reset_context(void __iomem *base, int ctx)
@@ -129,11 +181,12 @@
 }
 
 static void __program_context(void __iomem *base, int ctx, int ncb,
-				phys_addr_t pgtable, int redirect)
+				phys_addr_t pgtable, int redirect,
+				u32 *sids, int len)
 {
 	unsigned int prrr, nmrr;
 	unsigned int pn;
-	int i, j, found;
+	int i, j, found, num = 0;
 
 	__reset_context(base, ctx);
 
@@ -172,6 +225,30 @@
 		SET_CB_TTBR0_RGN(base, ctx, 1);   /* WB, WA */
 	}
 
+	/* Program the M2V tables for this context */
+	for (i = 0; i < len / sizeof(*sids); i++) {
+		for (; num < MAX_NUM_SMR; num++)
+			if (GET_SMR_VALID(base, num) == 0)
+				break;
+		BUG_ON(num >= MAX_NUM_SMR);
+
+		SET_SMR_VALID(base, num, 1);
+		SET_SMR_MASK(base, num, 0);
+		SET_SMR_ID(base, num, sids[i]);
+
+		/* Set VMID = 0 */
+		SET_S2CR_N(base, num, 0);
+		SET_S2CR_CBNDX(base, num, ctx);
+		/* Set security bit override to be Non-secure */
+		SET_S2CR_NSCFG(base, sids[i], 3);
+
+		SET_CBAR_N(base, ctx, 0);
+		/* Stage 1 Context with Stage 2 bypass */
+		SET_CBAR_TYPE(base, ctx, 1);
+		/* Route page faults to the non-secure interrupt */
+		SET_CBAR_IRPTNDX(base, ctx, 1);
+	}
+
        /* Find if this page table is used elsewhere, and re-use ASID */
 	found = 0;
 	for (i = 0; i < ncb; i++)
@@ -244,13 +321,33 @@
 	mutex_unlock(&msm_iommu_lock);
 }
 
+static int msm_iommu_ctx_attached(struct device *dev)
+{
+	struct platform_device *pdev;
+	struct device_node *child;
+	struct msm_iommu_ctx_drvdata *ctx;
+
+	for_each_child_of_node(dev->of_node, child) {
+		pdev = of_find_device_by_node(child);
+
+		ctx = dev_get_drvdata(&pdev->dev);
+		if (ctx->attached_domain) {
+			of_node_put(child);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
 	struct msm_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	struct msm_iommu_ctx_drvdata *tmp_drvdata;
-	int ret = 0;
+	u32 sids[MAX_NUM_SMR];
+	int len = 0, ret;
 
 	mutex_lock(&msm_iommu_lock);
 
@@ -278,15 +375,26 @@
 			goto fail;
 		}
 
+	of_get_property(dev->of_node, "qcom,iommu-ctx-sids", &len);
+	BUG_ON(len >= sizeof(sids));
+	if (of_property_read_u32_array(dev->of_node, "qcom,iommu-ctx-sids",
+					sids, len / sizeof(*sids))) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
 	ret = __enable_clocks(iommu_drvdata);
 	if (ret)
 		goto fail;
 
+	if (!msm_iommu_ctx_attached(dev->parent))
+		__program_iommu(iommu_drvdata->base);
+
 	__program_context(iommu_drvdata->base, ctx_drvdata->num,
 		iommu_drvdata->ncb, __pa(priv->pt.fl_table),
-		priv->pt.redirect);
-
+		priv->pt.redirect, sids, len);
 	__disable_clocks(iommu_drvdata);
+
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ctx_drvdata->attached_domain = domain;
 
@@ -322,6 +430,7 @@
 
 	__reset_context(iommu_drvdata->base, ctx_drvdata->num);
 	__disable_clocks(iommu_drvdata);
+
 	list_del_init(&ctx_drvdata->attached_elm);
 	ctx_drvdata->attached_domain = NULL;
 
@@ -427,7 +536,7 @@
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	unsigned int par;
 	void __iomem *base;
-	phys_addr_t pa = 0;
+	phys_addr_t ret = 0;
 	int ctx;
 
 	mutex_lock(&msm_iommu_lock);
@@ -443,25 +552,33 @@
 	base = iommu_drvdata->base;
 	ctx = ctx_drvdata->num;
 
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret) {
+		ret = 0;	/* 0 indicates translation failed */
+		goto fail;
+	}
+
 	SET_ATS1PR(base, ctx, va & CB_ATS1PR_ADDR);
 	mb();
 	while (GET_CB_ATSR_ACTIVE(base, ctx))
 		cpu_relax();
 
 	par = GET_PAR(base, ctx);
+	__disable_clocks(iommu_drvdata);
+
 	if (par & CB_PAR_F) {
-		pa = 0;
+		ret = 0;
 	} else {
 		/* We are dealing with a supersection */
-		if (par & CB_PAR_SS)
-			pa = (par & 0xFF000000) | (va & 0x00FFFFFF);
+		if (ret & CB_PAR_SS)
+			ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
 		else /* Upper 20 bits from PAR, lower 12 from VA */
-			pa = (par & 0xFFFFF000) | (va & 0x00000FFF);
+			ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
 	}
 
 fail:
 	mutex_unlock(&msm_iommu_lock);
-	return pa;
+	return ret;
 }
 
 static int msm_iommu_domain_has_cap(struct iommu_domain *domain,
@@ -501,7 +618,7 @@
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	unsigned int fsr;
-	int ret = IRQ_NONE;
+	int ret;
 
 	mutex_lock(&msm_iommu_lock);
 
@@ -513,6 +630,12 @@
 	ctx_drvdata = dev_get_drvdata(&pdev->dev);
 	BUG_ON(!ctx_drvdata);
 
+	ret = __enable_clocks(drvdata);
+	if (ret) {
+		ret = IRQ_NONE;
+		goto fail;
+	}
+
 	fsr = GET_FSR(drvdata->base, ctx_drvdata->num);
 	if (fsr) {
 		if (!ctx_drvdata->attached_domain) {
@@ -537,6 +660,8 @@
 	} else
 		ret = IRQ_NONE;
 
+	__disable_clocks(drvdata);
+fail:
 	mutex_unlock(&msm_iommu_lock);
 	return ret;
 }
diff --git a/drivers/iommu/msm_iommu_dev-v2.c b/drivers/iommu/msm_iommu_dev-v2.c
index e690ada..d6858de 100644
--- a/drivers/iommu/msm_iommu_dev-v2.c
+++ b/drivers/iommu/msm_iommu_dev-v2.c
@@ -29,27 +29,6 @@
 #include <mach/iommu_hw-v2.h>
 #include <mach/iommu.h>
 
-static void msm_iommu_reset(void __iomem *base)
-{
-	int i;
-
-	SET_ACR(base, 0);
-	SET_NSACR(base, 0);
-	SET_CR2(base, 0);
-	SET_NSCR2(base, 0);
-	SET_GFAR(base, 0);
-	SET_GFSRRESTORE(base, 0);
-	SET_TLBIALLNSNH(base, 0);
-	SET_PMCR(base, 0);
-	SET_SCR1(base, 0);
-	SET_SSDR_N(base, 0, 0);
-
-	for (i = 0; i < MAX_NUM_SMR; i++)
-		SET_SMR_VALID(base, i, 0);
-
-	mb();
-}
-
 static int msm_iommu_parse_dt(struct platform_device *pdev,
 				struct msm_iommu_drvdata *drvdata)
 {
@@ -119,17 +98,6 @@
 	} else
 		drvdata->clk = NULL;
 
-	msm_iommu_reset(drvdata->base);
-
-	SET_CR0_SMCFCFG(drvdata->base, 1);
-	SET_CR0_USFCFG(drvdata->base, 1);
-	SET_CR0_STALLD(drvdata->base, 1);
-	SET_CR0_GCFGFIE(drvdata->base, 1);
-	SET_CR0_GCFGFRE(drvdata->base, 1);
-	SET_CR0_GFIE(drvdata->base, 1);
-	SET_CR0_GFRE(drvdata->base, 1);
-	SET_CR0_CLIENTPD(drvdata->base, 0);
-
 	ret = msm_iommu_parse_dt(pdev, drvdata);
 	if (ret)
 		goto fail_clk;
@@ -173,13 +141,10 @@
 }
 
 static int msm_iommu_ctx_parse_dt(struct platform_device *pdev,
-				struct msm_iommu_drvdata *drvdata,
 				struct msm_iommu_ctx_drvdata *ctx_drvdata)
 {
 	struct resource *r, rp;
-	u32 sids[MAX_NUM_SMR];
-	int num = 0;
-	int irq, i, ret, len = 0;
+	int irq, ret;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq > 0) {
@@ -212,53 +177,17 @@
 					&ctx_drvdata->name))
 		ctx_drvdata->name = dev_name(&pdev->dev);
 
-	of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-sids", &len);
-	BUG_ON(len >= sizeof(sids));
-	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-ctx-sids",
-					sids, len / sizeof(*sids)))
-		return -EINVAL;
-
-	/* Program the M2V tables for this context */
-	for (i = 0; i < len / sizeof(*sids); i++) {
-		for (; num < MAX_NUM_SMR; num++)
-			if (GET_SMR_VALID(drvdata->base, num) == 0)
-				break;
-		BUG_ON(num >= MAX_NUM_SMR);
-
-		SET_SMR_VALID(drvdata->base, num, 1);
-		SET_SMR_MASK(drvdata->base, num, 0);
-		SET_SMR_ID(drvdata->base, num, sids[i]);
-
-		/* Set VMID = 0 */
-		SET_S2CR_N(drvdata->base, num, 0);
-		SET_S2CR_CBNDX(drvdata->base, num, ctx_drvdata->num);
-		/* Set security bit override to be Non-secure */
-		SET_S2CR_NSCFG(drvdata->base, sids[i], 3);
-
-		SET_CBAR_N(drvdata->base, ctx_drvdata->num, 0);
-		/* Stage 1 Context with Stage 2 bypass */
-		SET_CBAR_TYPE(drvdata->base, ctx_drvdata->num, 1);
-		/* Route page faults to the non-secure interrupt */
-		SET_CBAR_IRPTNDX(drvdata->base, ctx_drvdata->num, 1);
-	}
-	mb();
-
 	return 0;
 }
 
 static int __devinit msm_iommu_ctx_probe(struct platform_device *pdev)
 {
-	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
 	int ret;
 
 	if (!pdev->dev.parent)
 		return -EINVAL;
 
-	drvdata = dev_get_drvdata(pdev->dev.parent);
-	if (!drvdata)
-		return -ENODEV;
-
 	ctx_drvdata = devm_kzalloc(&pdev->dev, sizeof(*ctx_drvdata),
 					GFP_KERNEL);
 	if (!ctx_drvdata)
@@ -268,27 +197,11 @@
 	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
 	platform_set_drvdata(pdev, ctx_drvdata);
 
-	ret = clk_prepare_enable(drvdata->pclk);
-	if (ret)
-		return ret;
-
-	if (drvdata->clk) {
-		ret = clk_prepare_enable(drvdata->clk);
-		if (ret) {
-			clk_disable_unprepare(drvdata->pclk);
-			return ret;
-		}
-	}
-
-	ret = msm_iommu_ctx_parse_dt(pdev, drvdata, ctx_drvdata);
+	ret = msm_iommu_ctx_parse_dt(pdev, ctx_drvdata);
 	if (!ret)
 		dev_info(&pdev->dev, "context %s using bank %d\n",
 				dev_name(&pdev->dev), ctx_drvdata->num);
 
-	if (drvdata->clk)
-		clk_disable_unprepare(drvdata->clk);
-	clk_disable_unprepare(drvdata->pclk);
-
 	return ret;
 }
 
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index c15609f..971cf10 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -120,6 +120,8 @@
 	/*PS repeatcount for PS Tx */
 	int ps_repeatcount;
 	int enable_optimized_srch_alg;
+	unsigned char spur_table_size;
+	struct fm_spur_data spur_data;
 };
 
 /**************************************************************************
@@ -147,6 +149,10 @@
 			enum radio_state_t state);
 static int tavarua_request_irq(struct tavarua_device *radio);
 static void start_pending_xfr(struct tavarua_device *radio);
+static int update_spur_table(struct tavarua_device *radio);
+static int xfr_rdwr_data(struct tavarua_device *radio, int op, int size,
+	unsigned long offset, unsigned char *buf);
+
 /* work function */
 static void read_int_stat(struct work_struct *work);
 
@@ -1025,6 +1031,35 @@
 			FMDBG("write PHY_TXGAIN is successful");
 			complete(&radio->sync_req_done);
 			break;
+		case (XFR_POKE_COMPLETE | LSH_DATA(ONE_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(TWO_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(THREE_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(FOUR_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(FIVE_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(SIX_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(SEVEN_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(EIGHT_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(NINE_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(TEN_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(ELEVEN_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(TWELVE_BYTE, 1)):
+		case (XFR_POKE_COMPLETE | LSH_DATA(THIRTEEN_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(ONE_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(TWO_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(THREE_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(FOUR_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(FIVE_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(SIX_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(SEVEN_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(EIGHT_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(NINE_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(TEN_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(ELEVEN_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(TWELVE_BYTE, 1)):
+		case (XFR_PEEK_COMPLETE | LSH_DATA(THIRTEEN_BYTE, 1)):
+			FMDBG("XFR interrupt for PEEK/POKE complete\n");
+			complete(&radio->sync_req_done);
+			break;
 		default:
 			FMDERR("UNKNOWN XFR = %d\n", xfr_status);
 		}
@@ -2158,6 +2193,7 @@
 	wait_for_completion(&radio->shutdown_done);
 	radio->handle_irq = 1;
 	radio->lp_mode = 1;
+	radio->spur_table_size = 0;
 	atomic_inc(&radio->users);
 	radio->marimba->mod_id = SLAVE_ID_BAHAMA;
 	flush_workqueue(radio->wqueue);
@@ -2481,6 +2517,135 @@
 
 	return retval;
 }
+
+static int update_spur_table(struct tavarua_device *radio)
+{
+	unsigned char xfr_buf[XFR_REG_NUM];
+	unsigned char size = 0, tbl_size = 0;
+	int index = 0, offset = 0, addr = 0x0, val = 0;
+	int retval = 0, temp = 0, cnt = 0, j = 0;
+
+	memset(xfr_buf, 0x0, XFR_REG_NUM);
+
+	/* Read the SPUR Table Size */
+	retval = xfr_rdwr_data(radio, XFR_READ, 1, SPUR_TABLE_ADDR, &tbl_size);
+	if (retval < 0) {
+		FMDERR("%s: Failed to read SPUR table size\n", __func__);
+		return retval;
+	}
+
+	/* Calculate the new SPUR Register address */
+	val = addr = (SPUR_TABLE_START_ADDR + (tbl_size * 3));
+
+	/* Save the SPUR Table length configured by user*/
+	temp = radio->spur_table_size;
+
+	/* COnfigure the new spur table length */
+	size = (radio->spur_table_size + tbl_size);
+	retval = xfr_rdwr_data(radio, XFR_WRITE, 1, SPUR_TABLE_ADDR, &size);
+	if (retval < 0) {
+		FMDERR("%s: Failed to configure SPUR table size\n", __func__);
+		return retval;
+	}
+
+	/* Program the spur table entries */
+	for (cnt = 0; cnt < (temp / 4); cnt++) {
+		offset  = 0;
+		for (j = 0; j < 4; j++) {
+			xfr_buf[offset++] = GET_FREQ(COMPUTE_SPUR(
+				radio->spur_data.freq[index]), 1);
+			xfr_buf[offset++] = GET_FREQ(COMPUTE_SPUR(
+				radio->spur_data.freq[index]), 0);
+			xfr_buf[offset++] =
+				radio->spur_data.rmssi[index];
+			index++;
+		}
+		retval = xfr_rdwr_data(radio, XFR_WRITE, (SPUR_DATA_SIZE * 4),
+			addr, xfr_buf);
+		if (retval < 0) {
+			FMDERR("%s: Failed to program SPUR frequencies\n",
+				__func__);
+			return retval;
+		}
+		addr += (SPUR_DATA_SIZE * 4);
+	}
+
+	/* Program the additional SPUR Frequencies */
+	temp = radio->spur_table_size;
+	temp = (temp % 4);
+	if (temp > 0) {
+		offset = 0;
+		for (j = 0; j < temp; j++) {
+			xfr_buf[offset++] = GET_FREQ(COMPUTE_SPUR(
+				radio->spur_data.freq[index]), 1);
+			xfr_buf[offset++] = GET_FREQ(COMPUTE_SPUR(
+				radio->spur_data.freq[index]), 0);
+			xfr_buf[offset++] =
+				radio->spur_data.rmssi[index];
+			index++;
+		}
+		size   = (temp * SPUR_DATA_SIZE);
+		retval = xfr_rdwr_data(radio, XFR_WRITE, size, addr, xfr_buf);
+		if (retval < 0) {
+			FMDERR("%s: Failed to program SPUR frequencies\n",
+				__func__);
+			return retval;
+		}
+	}
+
+	return retval;
+}
+
+static int xfr_rdwr_data(struct tavarua_device *radio, int op, int size,
+	unsigned long offset, unsigned char *buf) {
+
+	unsigned char xfr_buf[XFR_REG_NUM];
+	int retval = 0, temp = 0;
+
+	memset(xfr_buf, 0x0, XFR_REG_NUM);
+	temp = size;
+
+	xfr_buf[XFR_MODE_OFFSET]     = (size << 1);
+	xfr_buf[XFR_ADDR_MSB_OFFSET] = GET_FREQ(offset, 1);
+	xfr_buf[XFR_ADDR_LSB_OFFSET] = GET_FREQ(offset, 0);
+
+	if (op == XFR_READ) {
+		xfr_buf[XFR_MODE_OFFSET] |= (XFR_PEEK_MODE);
+		size = 3;
+	} else if (op == XFR_WRITE) {
+		xfr_buf[XFR_MODE_OFFSET] |= (XFR_POKE_MODE);
+		memcpy(&xfr_buf[XFR_DATA_OFFSET], buf, size);
+		size += 3;
+	}
+
+	retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, size);
+	if (retval < 0) {
+		FMDERR("%s: Failed to performXFR operation\n", __func__);
+		return retval;
+	}
+
+	size = temp;
+
+	/*Wait for the XFR interrupt */
+	init_completion(&radio->sync_req_done);
+	if (!wait_for_completion_timeout(&radio->sync_req_done,
+		msecs_to_jiffies(WAIT_TIMEOUT))) {
+		FMDERR("Timeout: No XFR interrupt");
+	}
+
+	if (op == XFR_READ) {
+		retval = tavarua_read_registers(radio, XFRDAT0, size);
+		if (retval < 0) {
+			FMDERR("%s: Failed to read the XFR data\n", __func__);
+			return retval;
+		}
+		if (buf != NULL)
+			memcpy(buf, &radio->registers[XFRDAT0], size);
+	}
+
+	return retval;
+}
+
 static int peek_MPX_DCC(struct tavarua_device *radio)
 {
 	int retval = 0;
@@ -3001,6 +3166,7 @@
 		}
 		/* check if off */
 		else if ((ctrl->value == FM_OFF) && radio->registers[RDCTRL]) {
+			radio->spur_table_size = 0;
 			FMDBG("%s: turning off...\n", __func__);
 			tavarua_write_register(radio, RDCTRL, ctrl->value);
 			/* flush the event and work queues */
@@ -3299,8 +3465,20 @@
 	case V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION:
 	case V4L2_CID_PRIVATE_SINR_THRESHOLD:
 	case V4L2_CID_PRIVATE_SINR_SAMPLES:
+	case V4L2_CID_PRIVATE_SPUR_SELECTION:
 		retval = 0;
 		break;
+	case V4L2_CID_PRIVATE_SPUR_FREQ:
+		radio->spur_data.freq[radio->spur_table_size] =
+			ctrl->value;
+		break;
+	case V4L2_CID_PRIVATE_SPUR_FREQ_RMSSI:
+		radio->spur_data.rmssi[radio->spur_table_size++] =
+			ctrl->value;
+		break;
+	case V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE:
+		retval = update_spur_table(radio);
+		break;
 	default:
 		retval = -EINVAL;
 	}
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 3416c91..d7dc67d 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -28,6 +28,7 @@
 	struct rc_dev *rcdev;
 	unsigned int gpio_nr;
 	bool active_low;
+	int can_sleep;
 };
 
 static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
@@ -37,7 +38,10 @@
 	int rc = 0;
 	enum raw_event_type type = IR_SPACE;
 
-	gval = gpio_get_value_cansleep(gpio_dev->gpio_nr);
+	if (gpio_dev->can_sleep)
+		gval = gpio_get_value_cansleep(gpio_dev->gpio_nr);
+	else
+		gval = gpio_get_value(gpio_dev->gpio_nr);
 
 	if (gval < 0)
 		goto err_get_value;
@@ -96,6 +100,9 @@
 	rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");
 	if (rc < 0)
 		goto err_gpio_request;
+
+	gpio_dev->can_sleep = gpio_cansleep(pdata->gpio_nr);
+
 	rc  = gpio_direction_input(pdata->gpio_nr);
 	if (rc < 0)
 		goto err_gpio_direction_input;
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 3c9431a..a3fe1c8 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -149,6 +149,10 @@
 			break;
 
 		data->state = STATE_TRAILER_SPACE;
+
+		if (data->is_nec_x)
+			goto rc_data;
+
 		return 0;
 
 	case STATE_TRAILER_SPACE:
@@ -157,7 +161,7 @@
 
 		if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
 			break;
-
+rc_data:
 		address     = bitrev8((data->bits >> 24) & 0xff);
 		not_address = bitrev8((data->bits >> 16) & 0xff);
 		command	    = bitrev8((data->bits >>  8) & 0xff);
diff --git a/drivers/media/rc/keymaps/rc-samsung-necx.c b/drivers/media/rc/keymaps/rc-samsung-necx.c
index 6cf837f..1a3d6be 100644
--- a/drivers/media/rc/keymaps/rc-samsung-necx.c
+++ b/drivers/media/rc/keymaps/rc-samsung-necx.c
@@ -32,7 +32,7 @@
 	{ 0x70707, KEY_VOLUMEUP},
 	{ 0x7070b, KEY_VOLUMEDOWN},
 	{ 0x70760, KEY_UP},
-	{ 0x70768, KEY_ENTER},		/* ok */
+	{ 0x70768, KEY_ENTER},
 	{ 0x70761, KEY_DOWN},
 	{ 0x70765, KEY_LEFT},
 	{ 0x70762, KEY_RIGHT},
@@ -44,15 +44,18 @@
 	{ 0x70748, KEY_FORWARD},
 	{ 0x7074a, KEY_PAUSE},
 	{ 0x70703, KEY_SLEEP},
-	{ 0x7076c, KEY_A},		/* search */
-	{ 0x70714, KEY_B},		/* camera */
-	{ 0x70715, KEY_C},
-	{ 0x70716, KEY_D},
+	{ 0x7076c, KEY_RED},
+	{ 0x70714, KEY_GREEN},
+	{ 0x70715, KEY_YELLOW},
+	{ 0x70716, KEY_BLUE},
 	{ 0x70758, KEY_BACK},
 	{ 0x7071a, KEY_MENU},
 	{ 0x7076b, KEY_LIST},
-	{ 0x70701, KEY_SCREENLOCK},
-	{ 0x7071f, KEY_HOME},
+	{ 0x70701, KEY_TV2},
+	{ 0x7071f, KEY_INFO},
+	{ 0x7071b, KEY_TV},
+	{ 0x7078b, KEY_AUX},
+	{ 0x7078c, KEY_MEDIA},
 
 };
 
diff --git a/drivers/media/rc/keymaps/rc-ue-rf4ce.c b/drivers/media/rc/keymaps/rc-ue-rf4ce.c
index 71c5505..ea982a8 100644
--- a/drivers/media/rc/keymaps/rc-ue-rf4ce.c
+++ b/drivers/media/rc/keymaps/rc-ue-rf4ce.c
@@ -25,7 +25,7 @@
 	{ 0x0d, KEY_EXIT },
 	{ 0x72, KEY_TV },
 	{ 0x73, KEY_VIDEO },
-	{ 0x74, KEY_COMPOSE },
+	{ 0x74, KEY_PC },
 	{ 0x71, KEY_AUX },
 	{ 0x45, KEY_STOP },
 	{ 0x0b, KEY_LIST },
@@ -43,18 +43,20 @@
 	{ 0x30, KEY_CHANNELUP },
 	{ 0x31, KEY_CHANNELDOWN },
 
-	{ 0x20, KEY_NUMERIC_0 },
-	{ 0x21, KEY_NUMERIC_1 },
-	{ 0x22, KEY_NUMERIC_2 },
-	{ 0x23, KEY_NUMERIC_3 },
-	{ 0x24, KEY_NUMERIC_4 },
-	{ 0x25, KEY_NUMERIC_5 },
-	{ 0x26, KEY_NUMERIC_6 },
-	{ 0x27, KEY_NUMERIC_7 },
-	{ 0x28, KEY_NUMERIC_8 },
-	{ 0x29, KEY_NUMERIC_9 },
-	{ 0x34, KEY_INSERT },
+	{ 0x20, KEY_0 },
+	{ 0x21, KEY_1 },
+	{ 0x22, KEY_2 },
+	{ 0x23, KEY_3 },
+	{ 0x24, KEY_4 },
+	{ 0x25, KEY_5 },
+	{ 0x26, KEY_6 },
+	{ 0x27, KEY_7 },
+	{ 0x28, KEY_8 },
+	{ 0x29, KEY_9 },
+	{ 0x34, KEY_TV2 },
 	{ 0x2b, KEY_ENTER },
+	{ 0x35, KEY_INFO },
+	{ 0x09, KEY_MENU },
 };
 
 static struct rc_map_list ue_rf4ce_map = {
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index 964218f..5ffc133 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -261,6 +261,16 @@
 	---help---
 	  Enable support for Video Pre-processing Engine
 
+config MSM_CAM_IRQ_ROUTER
+	bool "Enable MSM CAM IRQ Router"
+	depends on MSM_CAMERA
+	---help---
+	Enable IRQ Router for Camera. Depending on the
+	configuration, this module can handle the
+	interrupts from multiple camera hardware
+	cores and composite them into a single
+	interrupt to the MSM.
+
 config QUP_EXCLUSIVE_TO_CAMERA
 	bool "QUP exclusive to camera"
 	depends on MSM_CAMERA
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 67da5ea..431da2e 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -7,7 +7,6 @@
 obj-$(CONFIG_MSM_CAMERA) += io/
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/io
   EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
   EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
   EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
@@ -15,6 +14,7 @@
   obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
   obj-$(CONFIG_MSM_CAMERA) += server/ eeprom/ sensors/ actuators/ csi/
   obj-$(CONFIG_MSM_CAMERA) += msm_gesture.o
+  obj-$(CONFIG_MSM_CAM_IRQ_ROUTER) += msm_camirq_router.o
 else
   obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
 endif
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
index e5d5966..f7cb408 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/video/msm/csi/Makefile
@@ -1,6 +1,7 @@
 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
-obj-$(CONFIG_ARCH_MSM8X60) += msm_csic.o
-obj-$(CONFIG_ARCH_MSM7X30) += msm_csic.o
+obj-$(CONFIG_ARCH_MSM8960) += msm_csi2_register.o msm_csiphy.o msm_csid.o msm_ispif.o
+obj-$(CONFIG_ARCH_MSM7X27A) += msm_csic_register.o msm_csic.o
+obj-$(CONFIG_ARCH_MSM8X60) += msm_csic_register.o msm_csic.o
+obj-$(CONFIG_ARCH_MSM7X30) += msm_csic_register.o msm_csic.o
+
diff --git a/drivers/media/video/msm/csi/msm_csi2_register.c b/drivers/media/video/msm/csi/msm_csi2_register.c
new file mode 100644
index 0000000..7b85ded
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csi2_register.c
@@ -0,0 +1,67 @@
+/* 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/device.h>
+#include "msm.h"
+#include "msm_csi_register.h"
+
+int msm_csi_register_subdevs(struct msm_cam_media_controller *p_mctl,
+	int core_index,
+	int (*msm_mctl_subdev_match_core)(struct device *, void *))
+{
+	int rc = -ENODEV;
+	struct device_driver *driver;
+	struct device *dev;
+
+	/* 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;
+
+	p_mctl->csiphy_sdev = dev_get_drvdata(dev);
+
+	/* register csid subdev */
+	driver = driver_find(MSM_CSID_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;
+
+	p_mctl->csid_sdev = dev_get_drvdata(dev);
+
+	/* 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;
+
+	p_mctl->ispif_sdev = dev_get_drvdata(dev);
+	rc = 0;
+	return rc;
+out:
+	p_mctl->ispif_sdev = NULL;
+	return rc;
+}
+
diff --git a/drivers/media/video/msm/csi/msm_csi_register.h b/drivers/media/video/msm/csi/msm_csi_register.h
new file mode 100644
index 0000000..578b609
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csi_register.h
@@ -0,0 +1,16 @@
+/* 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.
+ *
+ */
+
+int msm_csi_register_subdevs(struct msm_cam_media_controller *p_mctl,
+	int core_index,
+	int (*msm_mctl_subdev_match_core)(struct device *, void *));
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index a217f9d..dbb4f32 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -388,6 +388,8 @@
 {
 	struct csic_device *new_csic_dev;
 	int rc = 0;
+	struct msm_cam_subdev_info sd_info;
+
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
 	new_csic_dev = kzalloc(sizeof(struct csic_device), GFP_KERNEL);
 	if (!new_csic_dev) {
@@ -455,8 +457,11 @@
 
 	iounmap(new_csic_dev->base);
 	new_csic_dev->base = NULL;
+	sd_info.sdev_type = CSIC_DEV;
+	sd_info.sd_index = pdev->id;
+	sd_info.irq_num = new_csic_dev->irq->start;
 	msm_cam_register_subdev_node(
-		&new_csic_dev->subdev, CSIC_DEV, pdev->id);
+		&new_csic_dev->subdev, &sd_info);
 
 	return 0;
 
diff --git a/drivers/media/video/msm/csi/msm_csic_register.c b/drivers/media/video/msm/csi/msm_csic_register.c
new file mode 100644
index 0000000..7ccaff2
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csic_register.c
@@ -0,0 +1,45 @@
+/* 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/device.h>
+#include "msm.h"
+#include "msm_csi_register.h"
+
+int msm_csi_register_subdevs(struct msm_cam_media_controller *p_mctl,
+	int core_index,
+	int (*msm_mctl_subdev_match_core)(struct device *, void *))
+{
+	int rc = -ENODEV;
+	struct device_driver *driver;
+	struct device *dev;
+
+	driver = driver_find(MSM_CSIC_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;
+
+	p_mctl->csic_sdev = dev_get_drvdata(dev);
+
+	rc = 0;
+	p_mctl->ispif_sdev = NULL;
+	return rc;
+
+out:
+	p_mctl->ispif_sdev = NULL;
+	return rc;
+}
+
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index bb2a1d4..1ab4e66 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -298,6 +298,8 @@
 static int __devinit csid_probe(struct platform_device *pdev)
 {
 	struct csid_device *new_csid_dev;
+	struct msm_cam_subdev_info sd_info;
+
 	int rc = 0;
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
 	new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
@@ -338,7 +340,10 @@
 	}
 
 	new_csid_dev->pdev = pdev;
-	msm_cam_register_subdev_node(&new_csid_dev->subdev, CSID_DEV, pdev->id);
+	sd_info.sdev_type = CSID_DEV;
+	sd_info.sd_index = pdev->id;
+	sd_info.irq_num = new_csid_dev->irq->start;
+	msm_cam_register_subdev_node(&new_csid_dev->subdev, &sd_info);
 	return 0;
 
 csid_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index e25660b..4693a8a 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -282,6 +282,8 @@
 {
 	struct csiphy_device *new_csiphy_dev;
 	int rc = 0;
+	struct msm_cam_subdev_info sd_info;
+
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
 	new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL);
 	if (!new_csiphy_dev) {
@@ -333,8 +335,11 @@
 	disable_irq(new_csiphy_dev->irq->start);
 
 	new_csiphy_dev->pdev = pdev;
+	sd_info.sdev_type = CSIPHY_DEV;
+	sd_info.sd_index = pdev->id;
+	sd_info.irq_num = new_csiphy_dev->irq->start;
 	msm_cam_register_subdev_node(
-		&new_csiphy_dev->subdev, CSIPHY_DEV, pdev->id);
+		&new_csiphy_dev->subdev, &sd_info);
 	return 0;
 
 csiphy_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index 23982dd..0f16bbf 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -571,16 +571,51 @@
 	}
 }
 
+static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
+{
+	long rc = 0;
+	struct ispif_cfg_data cdata;
+
+	if (copy_from_user(&cdata, (void *)arg, sizeof(struct ispif_cfg_data)))
+		return -EFAULT;
+	CDBG("%s cfgtype = %d\n", __func__, cdata.cfgtype);
+	switch (cdata.cfgtype) {
+	case ISPIF_INIT:
+		CDBG("%s csid_version = %x\n", __func__,
+			cdata.cfg.csid_version);
+		rc = msm_ispif_init(&cdata.cfg.csid_version);
+		break;
+	case ISPIF_SET_CFG:
+		CDBG("%s len = %d, intftype = %d,.cid_mask = %d, csid = %d\n",
+			__func__,
+			cdata.cfg.ispif_params.len,
+			cdata.cfg.ispif_params.params[0].intftype,
+			cdata.cfg.ispif_params.params[0].cid_mask,
+			cdata.cfg.ispif_params.params[0].csid);
+		rc = msm_ispif_config(&cdata.cfg.ispif_params);
+		break;
+
+	case ISPIF_SET_ON_FRAME_BOUNDARY:
+	case ISPIF_SET_OFF_FRAME_BOUNDARY:
+	case ISPIF_SET_OFF_IMMEDIATELY:
+		rc = msm_ispif_subdev_video_s_stream(sd, cdata.cfg.cmd);
+		break;
+	case ISPIF_RELEASE:
+		msm_ispif_release(sd);
+		break;
+	default:
+		break;
+	}
+
+	return rc;
+}
+
 static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd,
 								void *arg)
 {
 	switch (cmd) {
 	case VIDIOC_MSM_ISPIF_CFG:
-		return msm_ispif_config((struct msm_ispif_params_list *)arg);
-	case VIDIOC_MSM_ISPIF_INIT:
-		return msm_ispif_init((uint32_t *)arg);
-	case VIDIOC_MSM_ISPIF_RELEASE:
-		msm_ispif_release(sd);
+		return msm_ispif_cmd(sd, arg);
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -605,6 +640,8 @@
 static int __devinit ispif_probe(struct platform_device *pdev)
 {
 	int rc = 0;
+	struct msm_cam_subdev_info sd_info;
+
 	CDBG("%s\n", __func__);
 	ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
 	if (!ispif) {
@@ -652,7 +689,10 @@
 	}
 
 	ispif->pdev = pdev;
-	msm_cam_register_subdev_node(&ispif->subdev, ISPIF_DEV, pdev->id);
+	sd_info.sdev_type = ISPIF_DEV;
+	sd_info.sd_index = pdev->id;
+	sd_info.irq_num = ispif->irq->start;
+	msm_cam_register_subdev_node(&ispif->subdev, &sd_info);
 	return 0;
 
 ispif_no_mem:
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
index 8f1dd12..7b301ba 100644
--- a/drivers/media/video/msm/csi/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -43,25 +43,7 @@
 };
 
 #define VIDIOC_MSM_ISPIF_CFG \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_ispif_params)
-
-#define VIDIOC_MSM_ISPIF_INIT \
-	_IO('V', BASE_VIDIOC_PRIVATE + 2)
-
-#define VIDIOC_MSM_ISPIF_RELEASE \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct v4l2_subdev*)
-
-#define ISPIF_STREAM(intf, action) (((intf)<<ISPIF_S_STREAM_SHIFT)+(action))
-#define ISPIF_ON_FRAME_BOUNDARY	(0x01 << 0)
-#define ISPIF_OFF_FRAME_BOUNDARY    (0x01 << 1)
-#define ISPIF_OFF_IMMEDIATELY       (0x01 << 2)
-#define ISPIF_S_STREAM_SHIFT	4
-
-
-#define PIX_0 (0x01 << 0)
-#define RDI_0 (0x01 << 1)
-#define PIX_1 (0x01 << 2)
-#define RDI_1 (0x01 << 3)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 18, struct ispif_cfg_data*)
 
 void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num);
 
diff --git a/drivers/media/video/msm/flash.c b/drivers/media/video/msm/flash.c
index 7c4021d..54c59f8 100644
--- a/drivers/media/video/msm/flash.c
+++ b/drivers/media/video/msm/flash.c
@@ -17,15 +17,16 @@
 #include <linux/pwm.h>
 #include <linux/pmic8058-pwm.h>
 #include <linux/hrtimer.h>
-#include <linux/i2c.h>
 #include <linux/export.h>
 #include <mach/pmic.h>
 #include <mach/camera.h>
 #include <mach/gpio.h>
+#include "msm_camera_i2c.h"
 
 struct i2c_client *sx150x_client;
 struct timer_list timer_flash;
 static struct msm_camera_sensor_info *sensor_data;
+static struct msm_camera_i2c_client i2c_client;
 enum msm_cam_flash_stat{
 	MSM_CAM_FLASH_OFF,
 	MSM_CAM_FLASH_ON,
@@ -33,47 +34,6 @@
 
 static struct i2c_client *sc628a_client;
 
-static int32_t flash_i2c_txdata(struct i2c_client *client,
-		unsigned char *txdata, int length)
-{
-	struct i2c_msg msg[] = {
-		{
-			.addr = client->addr >> 1,
-			.flags = 0,
-			.len = length,
-			.buf = txdata,
-		},
-	};
-	if (i2c_transfer(client->adapter, msg, 1) < 0) {
-		CDBG("flash_i2c_txdata faild 0x%x\n", client->addr >> 1);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int32_t flash_i2c_write_b(struct i2c_client *client,
-	uint8_t baddr, uint8_t bdata)
-{
-	int32_t rc = -EFAULT;
-	unsigned char buf[2];
-	if (!client)
-		return  -ENOTSUPP;
-
-	memset(buf, 0, sizeof(buf));
-	buf[0] = baddr;
-	buf[1] = bdata;
-
-	rc = flash_i2c_txdata(client, buf, 2);
-	if (rc < 0) {
-		CDBG("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
-				baddr, bdata);
-	}
-	usleep_range(4000, 5000);
-
-	return rc;
-}
-
 static const struct i2c_device_id sc628a_i2c_id[] = {
 	{"sc628a", 0},
 	{ }
@@ -128,8 +88,10 @@
 	}
 
 	tps61310_client = client;
-
-	rc = flash_i2c_write_b(tps61310_client, 0x01, 0x00);
+	i2c_client.client = tps61310_client;
+	i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+	rc = msm_camera_i2c_write(&i2c_client, 0x01, 0x00,
+		MSM_CAMERA_I2C_BYTE_DATA);
 	if (rc < 0) {
 		tps61310_client = NULL;
 		goto probe_failure;
@@ -431,10 +393,18 @@
 		break;
 
 	case MSM_CAMERA_LED_OFF:
-		if (sc628a_client)
-			rc = flash_i2c_write_b(sc628a_client, 0x02, 0x00);
-		if (tps61310_client)
-			rc = flash_i2c_write_b(tps61310_client, 0x01, 0x00);
+		if (sc628a_client) {
+			i2c_client.client = sc628a_client;
+			i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+			rc = msm_camera_i2c_write(&i2c_client, 0x02, 0x00,
+				MSM_CAMERA_I2C_BYTE_DATA);
+		}
+		if (tps61310_client) {
+			i2c_client.client = tps61310_client;
+			i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+			rc = msm_camera_i2c_write(&i2c_client, 0x01, 0x00,
+				MSM_CAMERA_I2C_BYTE_DATA);
+		}
 		gpio_set_value_cansleep(external->led_en, 0);
 		gpio_set_value_cansleep(external->led_flash_en, 0);
 		break;
@@ -443,20 +413,36 @@
 		gpio_set_value_cansleep(external->led_en, 1);
 		gpio_set_value_cansleep(external->led_flash_en, 1);
 		usleep_range(2000, 3000);
-		if (sc628a_client)
-			rc = flash_i2c_write_b(sc628a_client, 0x02, 0x06);
-		if (tps61310_client)
-			rc = flash_i2c_write_b(tps61310_client, 0x01, 0x86);
+		if (sc628a_client) {
+			i2c_client.client = sc628a_client;
+			i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+			rc = msm_camera_i2c_write(&i2c_client, 0x02, 0x06,
+				MSM_CAMERA_I2C_BYTE_DATA);
+		}
+		if (tps61310_client) {
+			i2c_client.client = tps61310_client;
+			i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+			rc = msm_camera_i2c_write(&i2c_client, 0x01, 0x86,
+				MSM_CAMERA_I2C_BYTE_DATA);
+		}
 		break;
 
 	case MSM_CAMERA_LED_HIGH:
 		gpio_set_value_cansleep(external->led_en, 1);
 		gpio_set_value_cansleep(external->led_flash_en, 1);
 		usleep_range(2000, 3000);
-		if (sc628a_client)
-			rc = flash_i2c_write_b(sc628a_client, 0x02, 0x49);
-		if (tps61310_client)
-			rc = flash_i2c_write_b(tps61310_client, 0x01, 0x8B);
+		if (sc628a_client) {
+			i2c_client.client = sc628a_client;
+			i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+			rc = msm_camera_i2c_write(&i2c_client, 0x02, 0x49,
+				MSM_CAMERA_I2C_BYTE_DATA);
+		}
+		if (tps61310_client) {
+			i2c_client.client = tps61310_client;
+			i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+			rc = msm_camera_i2c_write(&i2c_client, 0x01, 0x8B,
+				MSM_CAMERA_I2C_BYTE_DATA);
+		}
 		break;
 
 	default:
diff --git a/drivers/media/video/msm/io/Makefile b/drivers/media/video/msm/io/Makefile
index 64df7fb..611eecd 100644
--- a/drivers/media/video/msm/io/Makefile
+++ b/drivers/media/video/msm/io/Makefile
@@ -1,9 +1,9 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
 
-obj-$(CONFIG_MSM_CAMERA)   += msm_camera_io_util.o
 EXTRA_CFLAGS += -Idrivers/media/video/msm
+obj-$(CONFIG_MSM_CAMERA)   += msm_camera_io_util.o msm_camera_i2c.o
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
-  obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_i2c_mux.o
+  obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c_mux.o
   obj-$(CONFIG_ARCH_MSM7X27A) += msm_io_7x27a_v4l2.o
   obj-$(CONFIG_ARCH_MSM8X60) += msm_io_vfe31_v4l2.o
   obj-$(CONFIG_ARCH_MSM7X30) += msm_io_vfe31_v4l2.o
diff --git a/drivers/media/video/msm/io/msm_io_vfe31.c b/drivers/media/video/msm/io/msm_io_vfe31.c
index 0c0c450..8c733a0 100644
--- a/drivers/media/video/msm/io/msm_io_vfe31.c
+++ b/drivers/media/video/msm/io/msm_io_vfe31.c
@@ -247,7 +247,7 @@
 	}
 
 	if (!IS_ERR(clk))
-		clk_enable(clk);
+		clk_prepare_enable(clk);
 	else
 		rc = -1;
 	return rc;
@@ -303,10 +303,11 @@
 	}
 
 	if (!IS_ERR(clk)) {
-		clk_disable(clk);
+		clk_disable_unprepare(clk);
 		clk_put(clk);
-	} else
+	} else {
 		rc = -1;
+	}
 
 	return rc;
 }
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index c3c09d4..d34b8e1 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1277,6 +1277,7 @@
 	struct msm_camera_sensor_info *sdata;
 	struct msm_cam_v4l2_device *pcam;
 	struct msm_sensor_ctrl_t *s_ctrl;
+	struct msm_cam_subdev_info sd_info;
 
 	D("%s for %s\n", __func__, sensor_sd->name);
 
@@ -1321,8 +1322,11 @@
 	}
 	msm_server_update_sensor_info(pcam, sdata);
 
+	sd_info.sdev_type = SENSOR_DEV;
+	sd_info.sd_index = vnode_count;
+	sd_info.irq_num = 0;
 	/* register the subdevice, must be done for callbacks */
-	rc = msm_cam_register_subdev_node(sensor_sd, SENSOR_DEV, vnode_count);
+	rc = msm_cam_register_subdev_node(sensor_sd, &sd_info);
 	if (rc < 0) {
 		D("%s sensor sub device register failed\n",
 			__func__);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 42330b4..d0322d1 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -58,14 +58,16 @@
 #define MSM_GEMINI_DRV_NAME "msm_gemini"
 #define MSM_MERCURY_DRV_NAME "msm_mercury"
 #define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
+#define MSM_IRQ_ROUTER_DRV_NAME "msm_cam_irq_router"
 
 #define MAX_NUM_CSIPHY_DEV 3
-#define MAX_NUM_CSID_DEV 3
+#define MAX_NUM_CSID_DEV 4
 #define MAX_NUM_CSIC_DEV 3
 #define MAX_NUM_ISPIF_DEV 1
 #define MAX_NUM_VFE_DEV 2
 #define MAX_NUM_AXI_DEV 2
 #define MAX_NUM_VPE_DEV 1
+#define MAX_NUM_JPEG_DEV 3
 
 enum msm_cam_subdev_type {
 	CSIPHY_DEV,
@@ -79,6 +81,7 @@
 	ACTUATOR_DEV,
 	EEPROM_DEV,
 	GESTURE_DEV,
+	IRQ_ROUTER_DEV,
 };
 
 /* msm queue management APIs*/
@@ -129,6 +132,7 @@
 
 struct msm_free_buf {
 	uint8_t num_planes;
+	int32_t image_mode;
 	uint32_t ch_paddr[VIDEO_MAX_PLANES];
 	uint32_t vb;
 };
@@ -146,13 +150,11 @@
 
 /* message id for v4l2_subdev_notify*/
 enum msm_camera_v4l2_subdev_notify {
-	NOTIFY_CID_CHANGE, /* arg = msm_camera_csid_params */
 	NOTIFY_ISP_MSG_EVT, /* arg = enum ISP_MESSAGE_ID */
 	NOTIFY_VFE_MSG_OUT, /* arg = struct isp_msg_output */
 	NOTIFY_VFE_MSG_STATS,  /* arg = struct isp_msg_stats */
 	NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */
 	NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */
-	NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
 	NOTIFY_PCLK_CHANGE, /* arg = pclk */
 	NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
 	NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
@@ -406,6 +408,15 @@
 	struct msm_mem_map_info mem_map;
 };
 
+struct msm_cam_subdev_info {
+	uint8_t sdev_type;
+	/* Subdev index. For eg: CSIPHY0, CSIPHY1 etc */
+	uint8_t sd_index;
+	/* This device/subdev's interrupt number, assigned
+	 * from the hardware document. */
+	uint8_t irq_num;
+};
+
 /* 2 for camera, 1 for gesture */
 #define MAX_NUM_ACTIVE_CAMERA 3
 
@@ -422,6 +433,68 @@
 	uint32_t handle;
 };
 
+struct msm_cam_server_irqmap_entry {
+	int irq_num;
+	int irq_idx;
+	uint8_t cam_hw_idx;
+	uint8_t is_composite;
+};
+
+struct intr_table_entry {
+	/* irq_num as understood by msm.
+	 * Unique for every camera hw core & target. Use a mapping function
+	 * to map this irq number to its equivalent index in camera side. */
+	int irq_num;
+	/* Camera hw core idx, in case of non-composite IRQs*/
+	uint8_t cam_hw_idx;
+	/* Camera hw core mask, in case of composite IRQs. */
+	uint32_t cam_hw_mask;
+	/* Each interrupt is mapped to an index, which is used
+	 * to add/delete entries into the lookup table. Both the information
+	 * are needed in the lookup table to avoid another subdev call into
+	 * the IRQ Router subdev to get the irq_idx in the interrupt context */
+	int irq_idx;
+	/* Is this irq composite? */
+	uint8_t is_composite;
+	/* IRQ Trigger type: TRIGGER_RAISING, TRIGGER_HIGH, etc. */
+	uint32_t irq_trigger_type;
+	/* If IRQ Router hw is present,
+	 * this field holds the number of camera hw core
+	 * which are bundled together in the above
+	 * interrupt. > 1 in case of composite irqs.
+	 * If IRQ Router hw is not present, this field should be set to 1. */
+	int num_hwcore;
+	/* Pointers to the subdevs composited in this
+	 * irq. If not composite, the 0th index stores the subdev to which
+	 * this irq needs to be dispatched to. */
+	struct v4l2_subdev *subdev_list[CAMERA_SS_IRQ_MAX];
+	/* Device requesting the irq. */
+	const char *dev_name;
+	/* subdev private data, if any */
+	void *data;
+};
+
+struct irqmgr_intr_lkup_table {
+	/* Individual(hw) interrupt lookup table:
+	 * This table is populated during initialization and doesnt
+	 * change, unless the IRQ Router has been configured
+	 * for composite IRQs. If the IRQ Router has been configured
+	 * for composite IRQs, the is_composite field of that IRQ will
+	 * be set to 1(default 0). And when there is an interrupt on
+	 * that line, the composite interrupt lookup table is used
+	 * for handling the interrupt. */
+	struct intr_table_entry ind_intr_tbl[CAMERA_SS_IRQ_MAX];
+
+	/* Composite interrupt lookup table:
+	 * This table can be dynamically modified based on the usecase.
+	 * If the usecase requires two or more HW core IRQs to be bundled
+	 * into a single composite IRQ, then this table is populated
+	 * accordingly. Also when this is done, the composite field
+	 * in the intr_lookup_table has to be updated to reflect that
+	 * the irq 'irq_num' will now  be triggered in composite mode. */
+	struct intr_table_entry comp_intr_tbl[CAMERA_SS_IRQ_MAX];
+};
+
 /* abstract camera server device for all sensor successfully probed*/
 struct msm_cam_server_dev {
 
@@ -467,9 +540,18 @@
 	struct v4l2_subdev *axi_device[MAX_NUM_AXI_DEV];
 	struct v4l2_subdev *vpe_device[MAX_NUM_VPE_DEV];
 	struct v4l2_subdev *gesture_device;
-};
+	struct v4l2_subdev *irqr_device;
 
-/* camera server related functions */
+	spinlock_t  intr_table_lock;
+	struct irqmgr_intr_lkup_table irq_lkup_table;
+	/* Stores the pointer to the subdev when the individual
+	 * subdevices register themselves with the server. This
+	 * will be used while dispatching composite irqs. The
+	 * cam_hw_idx will serve as the index into this array to
+	 * dispatch the irq to the corresponding subdev. */
+	struct v4l2_subdev *subdev_table[MSM_CAM_HW_MAX];
+	struct msm_cam_server_irqmap_entry hw_irqmap[CAMERA_SS_IRQ_MAX];
+};
 
 /* ISP related functions */
 void msm_isp_vfe_dev_init(struct v4l2_subdev *vd);
@@ -584,7 +666,7 @@
 					void __user *arg);
 void msm_release_ion_client(struct kref *ref);
 int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
-			enum msm_cam_subdev_type sdev_type, uint8_t index);
+	struct msm_cam_subdev_info *sd_info);
 int msm_server_open_client(int *p_qidx);
 int msm_server_send_ctrl(struct msm_ctrl_cmd *out, int ctrl_id);
 int msm_server_close_client(int idx);
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/video/msm/msm_camera.c
index 624fe9b..9f32bfe 100644
--- a/drivers/media/video/msm/msm_camera.c
+++ b/drivers/media/video/msm/msm_camera.c
@@ -36,6 +36,7 @@
 #include <linux/hrtimer.h>
 #include <linux/ion.h>
 
+#include <mach/cpuidle.h>
 DEFINE_MUTEX(ctrl_cmd_lock);
 
 #define CAMERA_STOP_VIDEO 58
@@ -3085,7 +3086,7 @@
 		msm_queue_drain(&sync->pict_q, list_pict);
 		msm_queue_drain(&sync->event_q, list_config);
 
-		wake_unlock(&sync->wake_lock);
+		pm_qos_update_request(&sync->idle_pm_qos, PM_QOS_DEFAULT_VALUE);
 		sync->apps_id = NULL;
 		sync->core_powered_on = 0;
 	}
@@ -3745,7 +3746,8 @@
 	sync->apps_id = apps_id;
 
 	if (!sync->core_powered_on && !is_controlnode) {
-		wake_lock(&sync->wake_lock);
+		pm_qos_update_request(&sync->idle_pm_qos,
+			msm_cpuidle_get_deep_idle_latency());
 
 		msm_camvfe_fn_init(&sync->vfefn, sync);
 		if (sync->vfefn.vfe_init) {
@@ -3959,11 +3961,12 @@
 	msm_queue_init(&sync->pict_q, "pict");
 	msm_queue_init(&sync->vpe_q, "vpe");
 
-	wake_lock_init(&sync->wake_lock, WAKE_LOCK_SUSPEND, "msm_camera");
+	pm_qos_add_request(&sync->idle_pm_qos, PM_QOS_CPU_DMA_LATENCY,
+					   PM_QOS_DEFAULT_VALUE);
 
 	rc = msm_camio_probe_on(pdev);
 	if (rc < 0) {
-		wake_lock_destroy(&sync->wake_lock);
+		pm_qos_remove_request(&sync->idle_pm_qos);
 		return rc;
 	}
 	rc = sensor_probe(sync->sdata, &sctrl);
@@ -3976,7 +3979,7 @@
 		pr_err("%s: failed to initialize %s\n",
 			__func__,
 			sync->sdata->sensor_name);
-		wake_lock_destroy(&sync->wake_lock);
+		pm_qos_remove_request(&sync->idle_pm_qos);
 		return rc;
 	}
 
@@ -3995,7 +3998,7 @@
 
 static int msm_sync_destroy(struct msm_sync *sync)
 {
-	wake_lock_destroy(&sync->wake_lock);
+	pm_qos_remove_request(&sync->idle_pm_qos);
 	return 0;
 }
 
diff --git a/drivers/media/video/msm/msm_camirq_router.c b/drivers/media/video/msm/msm_camirq_router.c
new file mode 100644
index 0000000..52dd175
--- /dev/null
+++ b/drivers/media/video/msm/msm_camirq_router.c
@@ -0,0 +1,266 @@
+/* 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/interrupt.h>
+#include <mach/irqs.h>
+#include <media/msm_isp.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include "msm.h"
+#include "server/msm_cam_server.h"
+#include "msm_camirq_router.h"
+
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define D(fmt, args...) pr_debug("msm: " fmt, ##args)
+#else
+#define D(fmt, args...) do {} while (0)
+#endif
+
+static void msm_irqrouter_update_irqmap_entry(
+	struct msm_cam_server_irqmap_entry *entry,
+	int is_composite, int irq_idx, int cam_hw_idx)
+{
+	int rc = 0;
+	entry->irq_idx = irq_idx;
+	entry->is_composite = is_composite;
+	entry->cam_hw_idx = cam_hw_idx;
+	rc = msm_cam_server_update_irqmap(entry);
+	if (rc < 0)
+		pr_err("%s Error updating irq %d information ",
+			__func__, irq_idx);
+}
+
+static void msm_irqrouter_send_default_irqmap(
+	struct irqrouter_ctrl_type *irqrouter_ctrl)
+{
+	struct msm_cam_server_irqmap_entry *irqmap =
+		&irqrouter_ctrl->def_hw_irqmap[0];
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_0],
+		0, CAMERA_SS_IRQ_0, MSM_CAM_HW_MICRO);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_1],
+		0, CAMERA_SS_IRQ_1, MSM_CAM_HW_CCI);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_2],
+		0, CAMERA_SS_IRQ_2, MSM_CAM_HW_CSI0);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_3],
+		0, CAMERA_SS_IRQ_3, MSM_CAM_HW_CSI1);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_4],
+		0, CAMERA_SS_IRQ_4, MSM_CAM_HW_CSI2);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_5],
+		0, CAMERA_SS_IRQ_5, MSM_CAM_HW_CSI3);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_6],
+		0, CAMERA_SS_IRQ_6, MSM_CAM_HW_ISPIF);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_7],
+		0, CAMERA_SS_IRQ_7, MSM_CAM_HW_CPP);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_8],
+		0, CAMERA_SS_IRQ_8, MSM_CAM_HW_VFE0);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_9],
+		0, CAMERA_SS_IRQ_9, MSM_CAM_HW_VFE1);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_10],
+		0, CAMERA_SS_IRQ_10, MSM_CAM_HW_JPEG0);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_11],
+		0, CAMERA_SS_IRQ_11, MSM_CAM_HW_JPEG1);
+
+	msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_12],
+		0, CAMERA_SS_IRQ_12, MSM_CAM_HW_JPEG2);
+}
+
+static int msm_irqrouter_open(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh)
+{
+	struct irqrouter_ctrl_type *irqrouter_ctrl = v4l2_get_subdevdata(sd);
+	/* Only one object of IRQ Router allowed. */
+	if (atomic_read(&irqrouter_ctrl->active) != 0) {
+		pr_err("%s IRQ router is already opened\n", __func__);
+		return -EINVAL;
+	}
+
+	D("%s E ", __func__);
+	atomic_inc(&irqrouter_ctrl->active);
+
+	return 0;
+}
+
+static int msm_irqrouter_close(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh)
+{
+	struct irqrouter_ctrl_type *irqrouter_ctrl = v4l2_get_subdevdata(sd);
+	if (atomic_read(&irqrouter_ctrl->active) == 0) {
+		pr_err("%s IRQ router is already closed\n", __func__);
+		return -EINVAL;
+	}
+	D("%s E ", __func__);
+	atomic_dec(&irqrouter_ctrl->active);
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops msm_irqrouter_internal_ops = {
+	.open = msm_irqrouter_open,
+	.close = msm_irqrouter_close,
+};
+
+long msm_irqrouter_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	struct irqrouter_ctrl_type *irqrouter_ctrl = v4l2_get_subdevdata(sd);
+	struct msm_camera_irq_cfg *irq_cfg;
+	struct intr_table_entry irq_req;
+	int rc = 0;
+
+	/* Handle all IRQ Router Subdev IOCTLs here.
+	 * Userspace sends the composite irq configuration.
+	 * IRQ Router subdev then configures the registers to group
+	 * together individual core hw irqs into a composite IRQ
+	 * to the MSM IRQ controller. It also registers them with
+	 * the irq manager in the camera server. */
+	switch (cmd) {
+	case MSM_IRQROUTER_CFG_COMPIRQ:
+		COPY_FROM_USER(rc, &irq_cfg, (void __user *)arg,
+			sizeof(struct msm_camera_irq_cfg));
+		if (rc) {
+			ERR_COPY_FROM_USER();
+			break;
+		}
+
+		if (!irq_cfg ||
+			(irq_cfg->irq_idx < CAMERA_SS_IRQ_0) ||
+			(irq_cfg->irq_idx >= CAMERA_SS_IRQ_MAX)) {
+			pr_err("%s Invalid input", __func__);
+			return -EINVAL;
+		} else {
+			irq_req.cam_hw_mask      = irq_cfg->cam_hw_mask;
+			irq_req.irq_idx          = irq_cfg->irq_idx;
+			irq_req.irq_num          =
+			irqrouter_ctrl->def_hw_irqmap[irq_cfg->irq_idx].irq_num;
+			irq_req.is_composite     = 1;
+			irq_req.irq_trigger_type = IRQF_TRIGGER_RISING;
+			irq_req.num_hwcore       = irq_cfg->num_hwcore;
+			irq_req.data             = NULL;
+			rc = msm_cam_server_request_irq(&irq_req);
+			if (rc < 0) {
+				pr_err("%s Error requesting comp irq %d ",
+					__func__, irq_req.irq_idx);
+				return rc;
+			}
+			irqrouter_ctrl->def_hw_irqmap
+				[irq_cfg->irq_idx].is_composite = 1;
+		}
+		break;
+	default:
+		pr_err("%s Invalid cmd %d ", __func__, cmd);
+		break;
+	}
+
+	return rc;
+}
+
+static const struct v4l2_subdev_core_ops msm_irqrouter_subdev_core_ops = {
+	.ioctl = msm_irqrouter_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_irqrouter_subdev_ops = {
+	.core = &msm_irqrouter_subdev_core_ops,
+};
+
+static int __devinit irqrouter_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	struct irqrouter_ctrl_type *irqrouter_ctrl;
+	struct msm_cam_subdev_info sd_info;
+
+	D("%s: device id = %d\n", __func__, pdev->id);
+
+	irqrouter_ctrl = kzalloc(sizeof(struct irqrouter_ctrl_type),
+				GFP_KERNEL);
+	if (!irqrouter_ctrl) {
+		pr_err("%s: not enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&irqrouter_ctrl->subdev, &msm_irqrouter_subdev_ops);
+	irqrouter_ctrl->subdev.internal_ops = &msm_irqrouter_internal_ops;
+	irqrouter_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(irqrouter_ctrl->subdev.name,
+			 sizeof(irqrouter_ctrl->subdev.name), "msm_irqrouter");
+	v4l2_set_subdevdata(&irqrouter_ctrl->subdev, irqrouter_ctrl);
+	irqrouter_ctrl->pdev = pdev;
+
+	msm_irqrouter_send_default_irqmap(irqrouter_ctrl);
+
+	media_entity_init(&irqrouter_ctrl->subdev.entity, 0, NULL, 0);
+	irqrouter_ctrl->subdev.entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+	irqrouter_ctrl->subdev.entity.group_id = IRQ_ROUTER_DEV;
+	irqrouter_ctrl->subdev.entity.name = pdev->name;
+
+	sd_info.sdev_type = IRQ_ROUTER_DEV;
+	sd_info.sd_index = 0;
+	sd_info.irq_num = 0;
+	/* Now register this subdev with the camera server. */
+	rc = msm_cam_register_subdev_node(&irqrouter_ctrl->subdev, &sd_info);
+	if (rc < 0) {
+		pr_err("%s Error registering irqr subdev %d", __func__, rc);
+		goto error;
+	}
+	irqrouter_ctrl->subdev.entity.revision =
+		irqrouter_ctrl->subdev.devnode->num;
+	atomic_set(&irqrouter_ctrl->active, 0);
+
+	platform_set_drvdata(pdev, &irqrouter_ctrl->subdev);
+
+	return rc;
+error:
+	kfree(irqrouter_ctrl);
+	return rc;
+}
+
+static int __exit irqrouter_exit(struct platform_device *pdev)
+{
+	kfree(irqrouter_ctrl);
+	return 0;
+}
+
+static struct platform_driver msm_irqrouter_driver = {
+	.probe = irqrouter_probe,
+	.remove = irqrouter_exit,
+	.driver = {
+		.name = MSM_IRQ_ROUTER_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_irqrouter_init_module(void)
+{
+	return platform_driver_register(&msm_irqrouter_driver);
+}
+
+static void __exit msm_irqrouter_exit_module(void)
+{
+	platform_driver_unregister(&msm_irqrouter_driver);
+}
+
+module_init(msm_irqrouter_init_module);
+module_exit(msm_irqrouter_exit_module);
+MODULE_DESCRIPTION("msm camera irq router");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_camirq_router.h b/drivers/media/video/msm/msm_camirq_router.h
new file mode 100644
index 0000000..2c9cb73
--- /dev/null
+++ b/drivers/media/video/msm/msm_camirq_router.h
@@ -0,0 +1,206 @@
+/* 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_CAM_IRQROUTER_H__
+#define __MSM_CAM_IRQROUTER_H__
+
+#include <linux/bitops.h>
+
+/* Camera SS common registers defines - Start */
+/* These registers are not directly related to
+ * IRQ Router, but are common to the Camera SS.
+ * IRQ Router registers dont have a unique base address
+ * in the memory mapped address space. It is offset from
+ * the Camera SS base address. So keep the common Camera
+ * SS registers also in the IRQ Router subdev for now. */
+
+/* READ ONLY: Camera Subsystem HW version */
+#define CAMSS_HW_VERSION			0x00000000
+
+/* Bits 4:0 of this register can be used to select a desired
+ * camera core test bus to drive the Camera_SS test bus output */
+#define CAMSS_TESTBUS_SEL			0x00000004
+
+/* Bits 4:0 of this register is used to allow either Microcontroller
+ * or the CCI drive the corresponding GPIO output.
+ * For eg: Setting bit 0 of this register allows Microcontroller to
+ * drive GPIO #0. Clearing the bit allows CCI to drive GPIO #0. */
+#define CAMSS_GPIO_MUX_SEL			0x00000008
+
+/* Bit 0 of this register is used to set the default AHB master
+ * for the AHB Arbiter. 0 - AHB Master 0, 1 - AHB Master 1*/
+#define CAMSS_AHB_ARB_CTL			0x0000000C
+
+/* READ ONLY */
+#define CAMSS_XPU2_STATUS			0x00000010
+
+/* Select the appropriate CSI clock for CSID Pixel pipes */
+#define CAMSS_CSI_PIX_CLK_MUX_SEL		0x00000020
+#define CAMSS_CSI_PIX_CLK_CGC_EN		0x00000024
+
+/* Select the appropriate CSI clock for CSID RDI pipes */
+#define CAMSS_CSI_RDI_CLK_MUX_SEL		0x00000028
+#define CAMSS_CSI_RDI_CLK_CGC_EN		0x0000002C
+
+/* Select the appropriate CSI clock for CSI Phy0 */
+#define CAMSS_CSI_PHY_0_CLK_MUX_SEL		0x00000030
+#define CAMSS_CSI_PHY_0_CLK_CGC_EN		0x00000034
+
+/* Select the appropriate CSI clock for CSI Phy1 */
+#define CAMSS_CSI_PHY_1_CLK_MUX_SEL		0x00000038
+#define CAMSS_CSI_PHY_1_CLK_CGC_EN		0x0000003C
+
+/* Select the appropriate CSI clock for CSI Phy2 */
+#define CAMSS_CSI_PHY_2_CLK_MUX_SEL		0x00000040
+#define CAMSS_CSI_PHY_2_CLK_CGC_EN		0x00000044
+/* Camera SS common registers defines - End */
+
+/* IRQ Router registers defines - Start */
+/* This register is used to reset the composite
+ * IRQ outputs of the Camera_SS IRQ Router */
+#define CAMSS_IRQ_COMPOSITE_RESET_CTRL		0x00000060
+
+/* By default, this 'allows' the interrupts from
+ * Micro to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_0		0x00000064
+
+/* By default, this 'allows' the interrupts from
+ * CCI to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_1		0x00000068
+
+/* By default, this 'allows' the interrupts from
+ * CSI_0 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_2		0x0000006C
+
+/* By default, this 'allows' the interrupts from
+ * CSI_1 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_3		0x00000070
+
+/* By default, this 'allows' the interrupts from
+ * CSI_2 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_4		0x00000074
+
+/* By default, this 'allows' the interrupts from
+ * CSI_3 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_5		0x00000078
+
+/* By default, this 'allows' the interrupts from
+ * ISPIF to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_6		0x0000007C
+
+/* By default, this 'allows' the interrupts from
+ * CPP to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_7		0x00000080
+
+/* By default, this 'allows' the interrupts from
+ * VFE_0 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_8		0x00000084
+
+/* By default, this 'allows' the interrupts from
+ * VFE_1 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_9		0x00000088
+
+/* By default, this 'allows' the interrupts from
+ * JPEG_0 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_10		0x0000008C
+
+/* By default, this 'allows' the interrupts from
+ * JPEG_1 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_11		0x00000090
+
+/* By default, this 'allows' the interrupts from
+ * JPEG_2 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_12		0x00000094
+
+/* The following IRQ_COMPOSITE_MICRO_MASK registers
+ * allow the interrupts from the individual hw
+ * cores to be composited into an IRQ for Micro. */
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_0	0x000000A4
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_1	0x000000A8
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_2	0x000000AC
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_3	0x000000B0
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_4	0x000000B4
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_5	0x000000B8
+/* IRQ Router register defines - End */
+
+/* Writing this mask will reset all the composite
+ * IRQs of the Camera_SS IRQ Router */
+#define CAMSS_IRQ_COMPOSITE_RESET_MASK		0x003F1FFF
+
+/* Use this to enable Micro IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_MICRO_IRQ_IN_COMPOSITE		BIT(0)
+/* Use this to enable CCI IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CCI_IRQ_IN_COMPOSITE		BIT(1)
+/* Use this to enable CSI0 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CSI0_IRQ_IN_COMPOSITE		BIT(2)
+/* Use this to enable CSI1 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CSI1_IRQ_IN_COMPOSITE		BIT(3)
+/* Use this to enable CSI2 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CSI2_IRQ_IN_COMPOSITE		BIT(4)
+/* Use this to enable CSI3 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CSI3_IRQ_IN_COMPOSITE		BIT(5)
+/* Use this to enable ISPIF IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_ISPIF_IRQ_IN_COMPOSITE		BIT(6)
+/* Use this to enable CPP IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CPP_IRQ_IN_COMPOSITE		BIT(7)
+/* Use this to enable VFE0 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_VFE0_IRQ_IN_COMPOSITE		BIT(8)
+/* Use this to enable VFE1 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_VFE1_IRQ_IN_COMPOSITE		BIT(9)
+/* Use this to enable JPEG0 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_JPEG0_IRQ_IN_COMPOSITE		BIT(10)
+/* Use this to enable JPEG1 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_JPEG1_IRQ_IN_COMPOSITE		BIT(11)
+/* Use this to enable JPEG2 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_JPEG2_IRQ_IN_COMPOSITE		BIT(12)
+
+struct irqrouter_ctrl_type {
+	/* v4l2 subdev */
+	struct v4l2_subdev subdev;
+	struct platform_device *pdev;
+
+	void __iomem *irqr_dev_base;
+
+	struct resource	*irqr_dev_mem;
+	struct resource *irqr_dev_io;
+	atomic_t active;
+	struct msm_cam_server_irqmap_entry def_hw_irqmap[CAMERA_SS_IRQ_MAX];
+};
+
+#endif /* __MSM_CAM_IRQROUTER_H__ */
diff --git a/drivers/media/video/msm/msm_gesture.c b/drivers/media/video/msm/msm_gesture.c
index 6b81d15..5777cb5 100644
--- a/drivers/media/video/msm/msm_gesture.c
+++ b/drivers/media/video/msm/msm_gesture.c
@@ -455,6 +455,8 @@
 	struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
 	struct v4l2_subdev *gesture_subdev =
 		kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	struct msm_cam_subdev_info sd_info;
+
 	D("%s\n", __func__);
 	if (!gesture_subdev) {
 		pr_err("%s: no enough memory\n", __func__);
@@ -475,7 +477,10 @@
 	/* events */
 	gesture_subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
 
-	msm_cam_register_subdev_node(gesture_subdev, GESTURE_DEV, 0);
+	sd_info.sdev_type = GESTURE_DEV;
+	sd_info.sd_index = 0;
+	sd_info.irq_num = 0;
+	msm_cam_register_subdev_node(gesture_subdev, &sd_info);
 
 	gesture_subdev->entity.revision = gesture_subdev->devnode->num;
 
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index c266b85..834c9b0 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -146,7 +146,7 @@
 
 static int msm_isp_notify_VFE_BUF_EVT(struct v4l2_subdev *sd, void *arg)
 {
-	int rc = -EINVAL, image_mode;
+	int rc = -EINVAL;
 	struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
 	struct msm_free_buf free_buf, temp_free_buf;
 	struct msm_camvfe_params vfe_params;
@@ -154,16 +154,22 @@
 	struct msm_cam_media_controller *pmctl =
 		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
-
-	int vfe_id = vdata->evt_msg.msg_id;
+	struct msm_frame_info *frame_info =
+		(struct msm_frame_info *)vdata->evt_msg.data;
+	uint32_t vfe_id, image_mode;
 	if (!pcam) {
 		pr_debug("%s pcam is null. return\n", __func__);
 		msm_isp_sync_free(vdata);
 		return rc;
 	}
-	/* Convert the vfe msg to the image mode */
-	image_mode = msm_isp_vfe_msg_to_img_mode(pmctl, vfe_id);
-	BUG_ON(image_mode < 0);
+	if (frame_info) {
+		vfe_id = frame_info->path;
+		image_mode = frame_info->image_mode;
+	} else {
+		vfe_id = vdata->evt_msg.msg_id;
+		image_mode = msm_isp_vfe_msg_to_img_mode(pmctl, vfe_id);
+	}
+
 	switch (vdata->type) {
 	case VFE_MSG_V32_START:
 	case VFE_MSG_V32_START_RECORDING:
@@ -302,45 +308,49 @@
 	}
 	case NOTIFY_VFE_MSG_OUT: {
 		uint8_t msgid;
+		int32_t image_mode = -1;
 		struct isp_msg_output *isp_output =
 				(struct isp_msg_output *)arg;
-		switch (isp_output->output_id) {
-		case MSG_ID_OUTPUT_P:
-			msgid = VFE_MSG_OUTPUT_P;
-			break;
-		case MSG_ID_OUTPUT_V:
-			msgid = VFE_MSG_OUTPUT_V;
-			break;
-		case MSG_ID_OUTPUT_T:
-			msgid = VFE_MSG_OUTPUT_T;
-			break;
-		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);
-			rc = -EINVAL;
-			break;
+		if (isp_output->buf.image_mode < 0) {
+			switch (isp_output->output_id) {
+			case MSG_ID_OUTPUT_P:
+				msgid = VFE_MSG_OUTPUT_P;
+				break;
+			case MSG_ID_OUTPUT_V:
+				msgid = VFE_MSG_OUTPUT_V;
+				break;
+			case MSG_ID_OUTPUT_T:
+				msgid = VFE_MSG_OUTPUT_T;
+				break;
+			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);
+				rc = -EINVAL;
+				break;
+			}
+			if (!rc)
+				image_mode =
+				msm_isp_vfe_msg_to_img_mode(pmctl, msgid);
+		} else {
+			image_mode = isp_output->buf.image_mode;
 		}
-
-		if (!rc) {
-			isp_event->isp_data.isp_msg.msg_id =
-				isp_output->output_id;
-			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);
-		}
+		isp_event->isp_data.isp_msg.msg_id =
+			isp_output->output_id;
+		isp_event->isp_data.isp_msg.frame_id =
+			isp_output->frameCounter;
+		buf = isp_output->buf;
+		BUG_ON(image_mode < 0);
+		msm_mctl_buf_done(pmctl, image_mode,
+			&buf, isp_output->frameCounter);
 		}
 		break;
 	case NOTIFY_VFE_MSG_COMP_STATS: {
@@ -661,6 +671,8 @@
 	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:
+	case CMD_AXI_START:
+	case CMD_AXI_STOP:
 		/* Dont need to pass buffer information.
 		 * subdev will get the buffer from media
 		 * controller free queue.
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index ed6c493..cdfad3b 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -39,6 +39,7 @@
 #include "msm_vpe.h"
 #include "msm_vfe32.h"
 #include "msm_camera_eeprom.h"
+#include "msm_csi_register.h"
 
 #ifdef CONFIG_MSM_CAMERA_DEBUG
 #define D(fmt, args...) pr_debug("msm_mctl: " fmt, ##args)
@@ -47,7 +48,6 @@
 #endif
 
 #define MSM_V4L2_SWFI_LATENCY 3
-
 /* VFE required buffer number for streaming */
 static struct msm_isp_color_fmt msm_isp_formats[] = {
 	{
@@ -162,6 +162,8 @@
 	info.mount_angle = sdata->sensor_platform_info->mount_angle;
 	info.actuator_enabled = sdata->actuator_info ? 1 : 0;
 	info.strobe_flash_enabled = sdata->strobe_flash_data ? 1 : 0;
+	info.ispif_supported = mctl->ispif_sdev ? 1 : 0;
+
 	/* copy back to user space */
 	if (copy_to_user((void *)arg,
 				&info,
@@ -400,6 +402,10 @@
 		else
 			rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
 		break;
+	case MSM_CAM_IOCTL_ISPIF_IO_CFG:
+		rc = v4l2_subdev_call(p_mctl->ispif_sdev,
+			core, ioctl, VIDIOC_MSM_ISPIF_CFG, argp);
+		break;
 	default:
 		/* ISP config*/
 		D("%s:%d: go to default. Calling msm_isp_config\n",
@@ -435,62 +441,12 @@
 		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
 	struct msm_camera_device_platform_data *pdata = sinfo->pdata;
 
-	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,
+	rc = msm_csi_register_subdevs(p_mctl, core_index,
 				msm_mctl_subdev_match_core);
-		if (!dev)
+
+	if (rc < 0)
 			goto out;
 
-		p_mctl->csiphy_sdev = dev_get_drvdata(dev);
-	}
-
-	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,
-				msm_mctl_subdev_match_core);
-		if (!dev)
-			goto out;
-
-		p_mctl->csic_sdev = dev_get_drvdata(dev);
-	}
-
-	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, (void *)core_index,
-				msm_mctl_subdev_match_core);
-		if (!dev)
-			goto out;
-
-		p_mctl->csid_sdev = dev_get_drvdata(dev);
-	}
-
-	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;
-
-		p_mctl->ispif_sdev = dev_get_drvdata(dev);
-	}
-
 	/* register vfe subdev */
 	driver = driver_find(MSM_VFE_DRV_NAME, &platform_bus_type);
 	if (!driver)
@@ -568,6 +524,7 @@
 	mutex_lock(&p_mctl->lock);
 	/* open sub devices - once only*/
 	if (!p_mctl->opencnt) {
+		struct msm_sensor_csi_info csi_info;
 		uint32_t csid_version;
 		wake_lock(&p_mctl->wake_lock);
 
@@ -594,7 +551,7 @@
 			goto act_power_up_failed;
 		}
 
-		if (camdev->is_csiphy) {
+		if (p_mctl->csiphy_sdev) {
 			rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
 				VIDIOC_MSM_CSIPHY_INIT, NULL);
 			if (rc < 0) {
@@ -604,7 +561,7 @@
 			}
 		}
 
-		if (camdev->is_csid) {
+		if (p_mctl->csid_sdev) {
 			rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
 				VIDIOC_MSM_CSID_INIT, &csid_version);
 			if (rc < 0) {
@@ -612,9 +569,10 @@
 					__func__, rc);
 				goto csid_init_failed;
 			}
+			csi_info.is_csic = 0;
 		}
 
-		if (camdev->is_csic) {
+		if (p_mctl->csic_sdev) {
 			rc = v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
 				VIDIOC_MSM_CSIC_INIT, &csid_version);
 			if (rc < 0) {
@@ -622,6 +580,16 @@
 					__func__, rc);
 				goto csic_init_failed;
 			}
+			csi_info.is_csic = 1;
+		}
+
+		csi_info.csid_version = csid_version;
+		rc = v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
+				VIDIOC_MSM_SENSOR_CSID_INFO, &csi_info);
+		if (rc < 0) {
+			pr_err("%s: sensor csi version failed %d\n",
+			__func__, rc);
+			goto msm_csi_version;
 		}
 
 		/* ISP first*/
@@ -655,15 +623,6 @@
 			}
 		}
 
-		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 ispif_init_failed;
-			}
-		}
 
 		pm_qos_add_request(&p_mctl->pm_qos_req_list,
 			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
@@ -679,11 +638,6 @@
 
 	return rc;
 
-ispif_init_failed:
-	if (camdev->is_vpe)
-		if (v4l2_subdev_call(p_mctl->vpe_sdev, core, ioctl,
-			VIDIOC_MSM_VPE_RELEASE, NULL) < 0)
-			pr_err("%s: vpe release failed %d\n", __func__, rc);
 vpe_init_failed:
 	if (p_mctl->axi_sdev)
 		if (v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
@@ -692,18 +646,19 @@
 axi_init_failed:
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
 		p_mctl->isp_sdev->isp_release(p_mctl, p_mctl->isp_sdev->sd);
+msm_csi_version:
 isp_open_failed:
-	if (camdev->is_csic)
+	if (p_mctl->csic_sdev)
 		if (v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
 			VIDIOC_MSM_CSIC_RELEASE, NULL) < 0)
 			pr_err("%s: csic release failed %d\n", __func__, rc);
 csic_init_failed:
-	if (camdev->is_csid)
+	if (p_mctl->csid_sdev)
 		if (v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
 			VIDIOC_MSM_CSID_RELEASE, NULL) < 0)
 			pr_err("%s: csid release failed %d\n", __func__, rc);
 csid_init_failed:
-	if (camdev->is_csiphy)
+	if (p_mctl->csiphy_sdev)
 		if (v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
 			VIDIOC_MSM_CSIPHY_RELEASE, NULL) < 0)
 			pr_err("%s: csiphy release failed %d\n", __func__, rc);
@@ -733,12 +688,7 @@
 	v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
 		VIDIOC_MSM_SENSOR_RELEASE, NULL);
 
-	if (camdev->is_ispif) {
-		v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
-			VIDIOC_MSM_ISPIF_RELEASE, NULL);
-	}
-
-	if (camdev->is_csic) {
+	if (p_mctl->csic_sdev) {
 		v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
 			VIDIOC_MSM_CSIC_RELEASE, NULL);
 	}
@@ -757,12 +707,12 @@
 		p_mctl->isp_sdev->isp_release(p_mctl,
 			p_mctl->isp_sdev->sd);
 
-	if (camdev->is_csid) {
+	if (p_mctl->csid_sdev) {
 		v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
 			VIDIOC_MSM_CSID_RELEASE, NULL);
 	}
 
-	if (camdev->is_csiphy) {
+	if (p_mctl->csiphy_sdev) {
 		v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
 			VIDIOC_MSM_CSIPHY_RELEASE, NULL);
 	}
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index a010817..885cd90 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -367,7 +367,7 @@
 
 static void vfe31_stop(void)
 {
-
+	uint8_t  axiBusyFlag = true;
 	unsigned long flags;
 
 	atomic_set(&vfe31_ctrl->vstate, 0);
@@ -397,52 +397,6 @@
 	 * at any time. stop camif immediately. */
 	msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
 		vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
-}
-
-void axi_start(void)
-{
-	switch (vfe31_ctrl->operation_mode) {
-	case VFE_OUTPUTS_PREVIEW:
-	case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
-		if (vfe31_ctrl->outpath.output_mode &
-			VFE31_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
-		} else if (vfe31_ctrl->outpath.output_mode &
-			VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
-		}
-		break;
-	default:
-		if (vfe31_ctrl->outpath.output_mode &
-			VFE31_OUTPUT_MODE_SECONDARY) {
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
-		} else if (vfe31_ctrl->outpath.output_mode &
-			VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
-			msm_camera_io_w(1, vfe31_ctrl->vfebase +
-			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch2]);
-		}
-		break;
-	}
-}
-
-void axi_stop(void)
-{
-	uint8_t  axiBusyFlag = true;
 	/* axi halt command. */
 	msm_camera_io_w(AXI_HALT,
 		vfe31_ctrl->vfebase + VFE_AXI_CMD);
@@ -466,15 +420,18 @@
 		vfe31_ctrl->vfebase + VFE_GLOBAL_RESET);
 }
 
-static void vfe31_subdev_notify(int id, int path)
+static void vfe31_subdev_notify(int id, int path, int image_mode)
 {
 	struct msm_vfe_resp rp;
+	struct msm_frame_info frame_info;
 	unsigned long flags;
 	spin_lock_irqsave(&vfe31_ctrl->sd_notify_lock, flags);
 	memset(&rp, 0, sizeof(struct msm_vfe_resp));
 	CDBG("vfe31_subdev_notify : msgId = %d\n", id);
 	rp.evt_msg.type   = MSM_CAMERA_MSG;
-	rp.evt_msg.msg_id = path;
+	frame_info.image_mode = image_mode;
+	frame_info.path = path;
+	rp.evt_msg.data = &frame_info;
 	rp.type	   = id;
 	v4l2_subdev_notify(&vfe31_ctrl->subdev, NOTIFY_VFE_BUF_EVT, &rp);
 	spin_unlock_irqrestore(&vfe31_ctrl->sd_notify_lock, flags);
@@ -488,10 +445,12 @@
 	ch_info = axi_cfg + V31_AXI_CFG_LEN;
 	vfe31_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
 	vfe31_ctrl->outpath.out0.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
-	vfe31_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+	vfe31_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info;
+	vfe31_ctrl->outpath.out0.image_mode = 0x0000FFFF & (*ch_info++ >> 16);
 	vfe31_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
 	vfe31_ctrl->outpath.out1.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
-	vfe31_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+	vfe31_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info;
+	vfe31_ctrl->outpath.out1.image_mode = 0x0000FFFF & (*ch_info++ >> 16);
 	vfe31_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
 	vfe31_ctrl->outpath.out2.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
 	vfe31_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
@@ -999,6 +958,43 @@
 	}
 	msm_camera_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
+	switch (vfe31_ctrl->operation_mode) {
+	case VFE_OUTPUTS_PREVIEW:
+	case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+		if (vfe31_ctrl->outpath.output_mode &
+			VFE31_OUTPUT_MODE_PRIMARY) {
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+		} else if (vfe31_ctrl->outpath.output_mode &
+			VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
+		}
+		break;
+	default:
+		if (vfe31_ctrl->outpath.output_mode &
+			VFE31_OUTPUT_MODE_SECONDARY) {
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+		} else if (vfe31_ctrl->outpath.output_mode &
+			VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+			msm_camera_io_w(1, vfe31_ctrl->vfebase +
+			vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch2]);
+		}
+		break;
+	}
 	msm_camio_bus_scale_cfg(
 		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	vfe31_start_common();
@@ -1177,7 +1173,14 @@
 {
 	struct vfe31_output_ch *outch = NULL;
 	struct msm_free_buf *b = NULL;
-	vfe31_subdev_notify(id, path);
+	uint32_t image_mode = 0;
+
+	if (path == VFE_MSG_OUTPUT_PRIMARY)
+		image_mode = vfe31_ctrl->outpath.out0.image_mode;
+	else
+		image_mode = vfe31_ctrl->outpath.out1.image_mode;
+
+	vfe31_subdev_notify(id, path, image_mode);
 	outch = vfe31_get_ch(path);
 	if (outch->free_buf.ch_paddr[0])
 		b = &outch->free_buf;
@@ -1187,7 +1190,14 @@
 {
 	struct vfe31_output_ch *outch = NULL;
 	int rc = 0;
-	vfe31_subdev_notify(id, path);
+	uint32_t image_mode = 0;
+
+	if (path == VFE_MSG_OUTPUT_PRIMARY)
+		image_mode = vfe31_ctrl->outpath.out0.image_mode;
+	else
+		image_mode = vfe31_ctrl->outpath.out1.image_mode;
+
+	vfe31_subdev_notify(id, path, image_mode);
 	outch = vfe31_get_ch(path);
 	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
 		/* Configure Preview Ping Pong */
@@ -2604,11 +2614,13 @@
 	}
 }
 static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
-	uint32_t ch0_paddr, uint32_t ch1_paddr, uint32_t ch2_paddr)
+	uint32_t ch0_paddr, uint32_t ch1_paddr,
+	uint32_t ch2_paddr, uint32_t image_mode)
 {
 	struct isp_msg_output msg;
 
 	msg.output_id		= msgid;
+	msg.buf.image_mode	= image_mode;
 	msg.buf.ch_paddr[0]	= ch0_paddr;
 	msg.buf.ch_paddr[1]	= ch1_paddr;
 	msg.buf.ch_paddr[2]	= ch2_paddr;
@@ -2690,7 +2702,8 @@
 
 		vfe_send_outmsg(&vfe31_ctrl->subdev,
 			MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
-			ch1_paddr, ch2_paddr);
+			ch1_paddr, ch2_paddr,
+			vfe31_ctrl->outpath.out0.image_mode);
 
 		if (vfe31_ctrl->liveshot_state == VFE_STATE_STOPPED)
 			vfe31_ctrl->liveshot_state = VFE_STATE_IDLE;
@@ -2762,7 +2775,8 @@
 
 		vfe_send_outmsg(&vfe31_ctrl->subdev,
 			MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
-			ch1_paddr, ch2_paddr);
+			ch1_paddr, ch2_paddr,
+			vfe31_ctrl->outpath.out1.image_mode);
 	} else {
 		vfe31_ctrl->outpath.out1.frame_drop_cnt++;
 		CDBG("path_irq_1 - no free buffer!\n");
@@ -3582,11 +3596,11 @@
 		break;
 
 	case CMD_AXI_START:
-		axi_start();
+		/* No need to decouple AXI/VFE for VFE3.1*/
 		break;
 
 	case CMD_AXI_STOP:
-		axi_stop();
+		/* No need to decouple AXI/VFE for VFE3.1*/
 		break;
 
 	default:
@@ -3830,7 +3844,10 @@
 static int __devinit vfe31_probe(struct platform_device *pdev)
 {
 	int rc = 0;
+	struct msm_cam_subdev_info sd_info;
+
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
+
 	vfe31_ctrl = kzalloc(sizeof(struct vfe31_ctrl_type), GFP_KERNEL);
 	if (!vfe31_ctrl) {
 		pr_err("%s: no enough memory\n", __func__);
@@ -3902,7 +3919,10 @@
 	disable_irq(vfe31_ctrl->vfeirq->start);
 
 	vfe31_ctrl->pdev = pdev;
-	msm_cam_register_subdev_node(&vfe31_ctrl->subdev, VFE_DEV, 0);
+	sd_info.sdev_type = VFE_DEV;
+	sd_info.sd_index = 0;
+	sd_info.irq_num = vfe31_ctrl->vfeirq->start;
+	msm_cam_register_subdev_node(&vfe31_ctrl->subdev, &sd_info);
 	return 0;
 
 vfe31_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.h b/drivers/media/video/msm/msm_vfe31_v4l2.h
index e94f286..739d157 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.h
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.h
@@ -695,7 +695,7 @@
 struct vfe31_output_ch {
 	struct list_head free_buf_queue;
 	spinlock_t free_buf_lock;
-	uint16_t output_fmt;
+	uint16_t image_mode;
 	int8_t ch0;
 	int8_t ch1;
 	int8_t ch2;
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 3611656..9382292 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -25,6 +25,7 @@
 #include <media/msm_isp.h>
 
 #include "msm.h"
+#include "msm_cam_server.h"
 #include "msm_vfe32.h"
 
 atomic_t irq_cnt;
@@ -389,16 +390,19 @@
 		vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
 }
 
-static void vfe32_subdev_notify(int id, int path,
+static void vfe32_subdev_notify(int id, int path, int image_mode,
 	struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl)
 {
 	struct msm_vfe_resp rp;
+	struct msm_frame_info frame_info;
 	unsigned long flags = 0;
 	spin_lock_irqsave(&share_ctrl->sd_notify_lock, flags);
 	CDBG("vfe32_subdev_notify : msgId = %d\n", id);
 	memset(&rp, 0, sizeof(struct msm_vfe_resp));
 	rp.evt_msg.type   = MSM_CAMERA_MSG;
-	rp.evt_msg.msg_id = path;
+	frame_info.image_mode = image_mode;
+	frame_info.path = path;
+	rp.evt_msg.data = &frame_info;
 	rp.type	   = id;
 	v4l2_subdev_notify(sd, NOTIFY_VFE_BUF_EVT, &rp);
 	spin_unlock_irqrestore(&share_ctrl->sd_notify_lock, flags);
@@ -415,11 +419,15 @@
 	axi_ctrl->share_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
 	axi_ctrl->share_ctrl->outpath.out0.ch1 =
 		0x0000FFFF & (*ch_info++ >> 16);
-	axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info;
+	axi_ctrl->share_ctrl->outpath.out0.image_mode =
+		0x0000FFFF & (*ch_info++ >> 16);
 	axi_ctrl->share_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
 	axi_ctrl->share_ctrl->outpath.out1.ch1 =
 		0x0000FFFF & (*ch_info++ >> 16);
-	axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+	axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info;
+	axi_ctrl->share_ctrl->outpath.out1.image_mode =
+		0x0000FFFF & (*ch_info++ >> 16);
 	axi_ctrl->share_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
 	axi_ctrl->share_ctrl->outpath.out2.ch1 =
 		0x0000FFFF & (*ch_info++ >> 16);
@@ -1239,7 +1247,14 @@
 {
 	struct vfe32_output_ch *outch = NULL;
 	struct msm_free_buf *b = NULL;
-	vfe32_subdev_notify(id, path,
+	uint32_t image_mode = 0;
+
+	if (path == VFE_MSG_OUTPUT_PRIMARY)
+		image_mode = axi_ctrl->share_ctrl->outpath.out0.image_mode;
+	else
+		image_mode = axi_ctrl->share_ctrl->outpath.out1.image_mode;
+
+	vfe32_subdev_notify(id, path, image_mode,
 		&axi_ctrl->subdev, axi_ctrl->share_ctrl);
 	outch = vfe32_get_ch(path, axi_ctrl->share_ctrl);
 	if (outch->free_buf.ch_paddr[0])
@@ -1251,7 +1266,13 @@
 {
 	struct vfe32_output_ch *outch = NULL;
 	int rc = 0;
-	vfe32_subdev_notify(id, path,
+	uint32_t image_mode = 0;
+	if (path == VFE_MSG_OUTPUT_PRIMARY)
+		image_mode = vfe32_ctrl->share_ctrl->outpath.out0.image_mode;
+	else
+		image_mode = vfe32_ctrl->share_ctrl->outpath.out1.image_mode;
+
+	vfe32_subdev_notify(id, path, image_mode,
 		&vfe32_ctrl->subdev, vfe32_ctrl->share_ctrl);
 	outch = vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
 	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
@@ -3163,11 +3184,13 @@
 
 static void vfe_send_outmsg(
 	struct axi_ctrl_t *axi_ctrl, uint8_t msgid,
-	uint32_t ch0_paddr, uint32_t ch1_paddr, uint32_t ch2_paddr)
+	uint32_t ch0_paddr, uint32_t ch1_paddr,
+	uint32_t ch2_paddr, uint32_t image_mode)
 {
 	struct isp_msg_output msg;
 
 	msg.output_id = msgid;
+	msg.buf.image_mode = image_mode;
 	msg.buf.ch_paddr[0]	= ch0_paddr;
 	msg.buf.ch_paddr[1]	= ch1_paddr;
 	msg.buf.ch_paddr[2]	= ch2_paddr;
@@ -3268,7 +3291,8 @@
 
 		vfe_send_outmsg(axi_ctrl,
 			MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
-			ch1_paddr, ch2_paddr);
+			ch1_paddr, ch2_paddr,
+			axi_ctrl->share_ctrl->outpath.out0.image_mode);
 
 		if (axi_ctrl->share_ctrl->liveshot_state == VFE_STATE_STOPPED)
 			axi_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
@@ -3348,7 +3372,9 @@
 
 		vfe_send_outmsg(axi_ctrl,
 			MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
-			ch1_paddr, ch2_paddr);
+			ch1_paddr, ch2_paddr,
+			axi_ctrl->share_ctrl->outpath.out1.image_mode);
+
 	} else {
 		axi_ctrl->share_ctrl->outpath.out1.frame_drop_cnt++;
 		CDBG("path_irq_1 - no free buffer!\n");
@@ -3954,6 +3980,17 @@
 	return IRQ_HANDLED;
 }
 
+int msm_axi_subdev_isr_routine(struct v4l2_subdev *sd,
+	u32 status, bool *handled)
+{
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	irqreturn_t ret;
+	pr_info("%s E ", __func__);
+	ret = vfe32_parse_irq(axi_ctrl->vfeirq->start, axi_ctrl);
+	*handled = TRUE;
+	return 0;
+}
+
 static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int subdev_cmd, void *arg)
 {
@@ -4653,6 +4690,7 @@
 
 static const struct v4l2_subdev_core_ops msm_axi_subdev_core_ops = {
 	.ioctl = msm_axi_subdev_ioctl,
+	.interrupt_service_routine = msm_axi_subdev_isr_routine,
 };
 
 static const struct v4l2_subdev_video_ops msm_axi_subdev_video_ops = {
@@ -4672,6 +4710,9 @@
 	struct axi_ctrl_t *axi_ctrl;
 	struct vfe32_ctrl_type *vfe32_ctrl;
 	struct vfe_share_ctrl_t *share_ctrl;
+	struct intr_table_entry irq_req;
+	struct msm_cam_subdev_info sd_info;
+
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
 
 	share_ctrl = kzalloc(sizeof(struct vfe_share_ctrl_t), GFP_KERNEL);
@@ -4707,7 +4748,11 @@
 			 sizeof(axi_ctrl->subdev.name), "axi");
 	v4l2_set_subdevdata(&axi_ctrl->subdev, axi_ctrl);
 	axi_ctrl->pdev = pdev;
-	msm_cam_register_subdev_node(&axi_ctrl->subdev, AXI_DEV, 0);
+
+	sd_info.sdev_type = AXI_DEV;
+	sd_info.sd_index = 0;
+	sd_info.irq_num = 0;
+	msm_cam_register_subdev_node(&axi_ctrl->subdev, &sd_info);
 
 	v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
 	vfe32_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
@@ -4740,23 +4785,49 @@
 		goto vfe32_no_resource;
 	}
 
-	rc = request_irq(axi_ctrl->vfeirq->start, vfe32_parse_irq,
-		IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
-	if (rc < 0) {
-		release_mem_region(axi_ctrl->vfemem->start,
-			resource_size(axi_ctrl->vfemem));
-		pr_err("%s: irq request fail\n", __func__);
-		rc = -EBUSY;
+	/* Request for this device irq from the camera server. If the
+	 * IRQ Router is present on this target, the interrupt will be
+	 * handled by the camera server and the interrupt service
+	 * routine called. If the request_irq call returns ENXIO, then
+	 * the IRQ Router hardware is not present on this target. We
+	 * have to request for the irq ourselves and register the
+	 * appropriate interrupt handler. */
+	irq_req.cam_hw_idx       = MSM_CAM_HW_VFE0;
+	irq_req.dev_name         = "vfe";
+	irq_req.irq_idx          = CAMERA_SS_IRQ_8;
+	irq_req.irq_num          = axi_ctrl->vfeirq->start;
+	irq_req.is_composite     = 0;
+	irq_req.irq_trigger_type = IRQF_TRIGGER_RISING;
+	irq_req.num_hwcore       = 1;
+	irq_req.subdev_list[0]   = &axi_ctrl->subdev;
+	irq_req.data             = (void *)axi_ctrl;
+	rc = msm_cam_server_request_irq(&irq_req);
+	if (rc == -ENXIO) {
+		/* IRQ Router hardware is not present on this hardware.
+		 * Request for the IRQ and register the interrupt handler. */
+		rc = request_irq(axi_ctrl->vfeirq->start, vfe32_parse_irq,
+			IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
+		if (rc < 0) {
+			release_mem_region(axi_ctrl->vfemem->start,
+				resource_size(axi_ctrl->vfemem));
+			pr_err("%s: irq request fail\n", __func__);
+			rc = -EBUSY;
+			goto vfe32_no_resource;
+		}
+		disable_irq(axi_ctrl->vfeirq->start);
+	} else if (rc < 0) {
+		pr_err("%s Error registering irq ", __func__);
 		goto vfe32_no_resource;
 	}
 
-	disable_irq(axi_ctrl->vfeirq->start);
-
 	tasklet_init(&axi_ctrl->vfe32_tasklet,
 		axi32_do_tasklet, (unsigned long)axi_ctrl);
 
 	vfe32_ctrl->pdev = pdev;
-	msm_cam_register_subdev_node(&vfe32_ctrl->subdev, VFE_DEV, 0);
+	sd_info.sdev_type = VFE_DEV;
+	sd_info.sd_index = 0;
+	sd_info.irq_num = axi_ctrl->vfeirq->start;
+	msm_cam_register_subdev_node(&vfe32_ctrl->subdev, &sd_info);
 	return 0;
 
 vfe32_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 086600a..d5da432 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -741,7 +741,7 @@
 struct vfe32_output_ch {
 	struct list_head free_buf_queue;
 	spinlock_t free_buf_lock;
-	uint16_t output_fmt;
+	uint16_t image_mode;
 	int8_t ch0;
 	int8_t ch1;
 	int8_t ch2;
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 135ad20..398621f 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -370,6 +370,7 @@
 	struct isp_msg_output msg;
 
 	msg.output_id = msgid;
+	msg.buf.image_mode = -1;
 	msg.buf.ch_paddr[0]     = ch0_paddr;
 	msg.buf.ch_paddr[1]     = ch1_paddr;
 	msg.frameCounter = vfe2x_ctrl->vfeFrameId;
@@ -859,6 +860,7 @@
 	CDBG("vfe2x_subdev_notify : msgId = %d\n", id);
 	rp.evt_msg.type   = MSM_CAMERA_MSG;
 	rp.evt_msg.msg_id = path;
+	rp.evt_msg.data = NULL;
 	rp.type	   = id;
 	v4l2_subdev_notify(&vfe2x_ctrl->subdev, NOTIFY_VFE_BUF_EVT, &rp);
 	spin_unlock_irqrestore(&vfe2x_ctrl->sd_notify_lock, flags);
@@ -1264,6 +1266,16 @@
 				vfestopped = 1;
 				spin_lock_irqsave(&vfe2x_ctrl->table_lock,
 						flags);
+				if (op_mode & SNAPSHOT_MASK_MODE) {
+					vfe2x_ctrl->stop_pending = 0;
+					vfe2x_send_isp_msg(vfe2x_ctrl,
+						msgs_map[MSG_STOP_ACK].
+						isp_id);
+					spin_unlock_irqrestore(
+							&vfe2x_ctrl->table_lock,
+							flags);
+					return 0;
+				}
 				if ((!list_empty(&vfe2x_ctrl->table_q)) ||
 						vfe2x_ctrl->tableack_pending) {
 					CDBG("stop pending\n");
@@ -1783,6 +1795,8 @@
 
 static int __devinit vfe2x_probe(struct platform_device *pdev)
 {
+	struct msm_cam_subdev_info sd_info;
+
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
 	vfe2x_ctrl = kzalloc(sizeof(struct vfe2x_ctrl_type), GFP_KERNEL);
 	if (!vfe2x_ctrl) {
@@ -1799,7 +1813,10 @@
 	platform_set_drvdata(pdev, &vfe2x_ctrl->subdev);
 
 	vfe2x_ctrl->pdev = pdev;
-	msm_cam_register_subdev_node(&vfe2x_ctrl->subdev, VFE_DEV, 0);
+	sd_info.sdev_type = VFE_DEV;
+	sd_info.sd_index = 0;
+	sd_info.irq_num = 0;
+	msm_cam_register_subdev_node(&vfe2x_ctrl->subdev, &sd_info);
 	return 0;
 }
 
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 54e9582..fb22cf9 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -970,6 +970,8 @@
 static int __devinit msm_vpe_probe(struct platform_device *pdev)
 {
 	int rc = 0;
+	struct msm_cam_subdev_info sd_info;
+
 	D("%s: device id = %d\n", __func__, pdev->id);
 	vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
 	if (!vpe_ctrl) {
@@ -1028,7 +1030,10 @@
 
 	atomic_set(&vpe_ctrl->active, 0);
 	vpe_ctrl->pdev = pdev;
-	msm_cam_register_subdev_node(&vpe_ctrl->subdev, VPE_DEV, pdev->id);
+	sd_info.sdev_type = VPE_DEV;
+	sd_info.sd_index = pdev->id;
+	sd_info.irq_num = vpe_ctrl->vpeirq->start;
+	msm_cam_register_subdev_node(&vpe_ctrl->subdev, &sd_info);
 	vpe_ctrl->subdev.entity.revision = vpe_ctrl->subdev.devnode->num;
 	msm_queue_init(&vpe_ctrl->eventData_q, "ackevents");
 
diff --git a/drivers/media/video/msm/msm_vpe1.c b/drivers/media/video/msm/msm_vpe1.c
index 4f97c43..df3630a 100644
--- a/drivers/media/video/msm/msm_vpe1.c
+++ b/drivers/media/video/msm/msm_vpe1.c
@@ -16,6 +16,7 @@
 #include <mach/irqs.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include "msm_vpe1.h"
 #include <linux/pm_qos.h>
 #include <linux/clk.h>
diff --git a/drivers/media/video/msm/mt9d112.c b/drivers/media/video/msm/mt9d112.c
index a7b5156..4dd0285 100644
--- a/drivers/media/video/msm/mt9d112.c
+++ b/drivers/media/video/msm/mt9d112.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
@@ -17,6 +17,7 @@
 #include <linux/i2c.h>
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
+#include <linux/module.h>
 #include <media/msm_camera.h>
 #include <mach/gpio.h>
 #include "mt9d112.h"
diff --git a/drivers/media/video/msm/mt9p012.h b/drivers/media/video/msm/mt9p012.h
index 0579813..3df98b7 100644
--- a/drivers/media/video/msm/mt9p012.h
+++ b/drivers/media/video/msm/mt9p012.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 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
@@ -15,6 +15,7 @@
 #define MT9T012_H
 
 #include <linux/types.h>
+#include <mach/board.h>
 
 extern struct mt9p012_reg mt9p012_regs;	/* from mt9p012_reg.c */
 
diff --git a/drivers/media/video/msm/mt9p012_km.h b/drivers/media/video/msm/mt9p012_km.h
index aefabd4..0feb331 100644
--- a/drivers/media/video/msm/mt9p012_km.h
+++ b/drivers/media/video/msm/mt9p012_km.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, 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
@@ -15,6 +15,7 @@
 #define MT9P012_KM_H
 
 #include <linux/types.h>
+#include <mach/board.h>
 
 extern struct mt9p012_km_reg mt9p012_km_regs;	/* from mt9p012_km_reg.c */
 
diff --git a/drivers/media/video/msm/mt9t013.c b/drivers/media/video/msm/mt9t013.c
index e1f6167..b4b5bdd 100644
--- a/drivers/media/video/msm/mt9t013.c
+++ b/drivers/media/video/msm/mt9t013.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 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
@@ -18,6 +18,7 @@
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <media/msm_camera.h>
 #include <mach/gpio.h>
 #include <mach/camera.h>
diff --git a/drivers/media/video/msm/mt9t013.h b/drivers/media/video/msm/mt9t013.h
index f6b7c28..6afcb2d 100644
--- a/drivers/media/video/msm/mt9t013.h
+++ b/drivers/media/video/msm/mt9t013.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 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
@@ -15,6 +15,7 @@
 #define MT9T013_H
 
 #include <linux/types.h>
+#include <mach/board.h>
 
 extern struct mt9t013_reg mt9t013_regs; /* from mt9t013_reg.c */
 
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index 7e41418..3d23337 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -277,6 +277,7 @@
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
 	.sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t imx074_regs = {
diff --git a/drivers/media/video/msm/sensors/imx091.c b/drivers/media/video/msm/sensors/imx091.c
index 70c3f6e..49442e9 100644
--- a/drivers/media/video/msm/sensors/imx091.c
+++ b/drivers/media/video/msm/sensors/imx091.c
@@ -304,6 +304,7 @@
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
 	.sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t imx091_regs = {
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 76981b0..8ab3963 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -246,9 +246,6 @@
 {
 	int32_t rc = 0;
 
-	v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
-		NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
-		PIX_0, ISPIF_OFF_IMMEDIATELY));
 	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
 	msleep(30);
 	if (update_type == MSM_SENSOR_REG_INIT) {
@@ -268,8 +265,6 @@
 			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 				NOTIFY_CSID_CFG,
 				&s_ctrl->curr_csi_params->csid_params);
-			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
-						NOTIFY_CID_CHANGE, NULL);
 			mb();
 			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 				NOTIFY_CSIPHY_CFG,
@@ -281,9 +276,6 @@
 		v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 			NOTIFY_PCLK_CHANGE, &s_ctrl->msm_sensor_reg->
 			output_settings[res].op_pixel_clk);
-		v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
-			NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
-			PIX_0, ISPIF_ON_FRAME_BOUNDARY));
 		s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
 		msleep(30);
 	}
@@ -303,7 +295,7 @@
 			s_ctrl->msm_sensor_reg->
 			output_settings[res].line_length_pclk;
 
-		if (s_ctrl->sensordata->pdata->is_csic ||
+		if (s_ctrl->is_csic ||
 			!s_ctrl->sensordata->csi_if)
 			rc = s_ctrl->func_tbl->sensor_csi_setting(s_ctrl,
 				MSM_SENSOR_UPDATE_PERIODIC, res);
@@ -330,7 +322,7 @@
 		s_ctrl->curr_res = MSM_SENSOR_INVALID_RES;
 		s_ctrl->cam_mode = mode;
 
-		if (s_ctrl->sensordata->pdata->is_csic ||
+		if (s_ctrl->is_csic ||
 			!s_ctrl->sensordata->csi_if)
 			rc = s_ctrl->func_tbl->sensor_csi_setting(s_ctrl,
 				MSM_SENSOR_REG_INIT, 0);
@@ -383,11 +375,32 @@
 		return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
 	case VIDIOC_MSM_SENSOR_RELEASE:
 		return msm_sensor_release(s_ctrl);
+	case VIDIOC_MSM_SENSOR_CSID_INFO: {
+		struct msm_sensor_csi_info *csi_info =
+			(struct msm_sensor_csi_info *)arg;
+		s_ctrl->csid_version = csi_info->csid_version;
+		s_ctrl->is_csic = csi_info->is_csic;
+		return 0;
+	}
 	default:
 		return -ENOIOCTLCMD;
 	}
 }
 
+int32_t msm_sensor_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
+		struct csi_lane_params_t *sensor_output_info)
+{
+	sensor_output_info->csi_lane_assign = s_ctrl->sensordata->
+		sensor_platform_info->csi_lane_params->csi_lane_assign;
+	sensor_output_info->csi_lane_mask = s_ctrl->sensordata->
+		sensor_platform_info->csi_lane_params->csi_lane_mask;
+	sensor_output_info->csi_if = s_ctrl->sensordata->csi_if;
+	sensor_output_info->csid_core = s_ctrl->sensordata->
+			pdata[0].csid_core;
+	sensor_output_info->csid_version = s_ctrl->csid_version;
+	return 0;
+}
+
 int32_t msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp)
 {
 	struct sensor_cfg_data cdata;
@@ -489,6 +502,37 @@
 				rc = -EFAULT;
 			break;
 
+		case CFG_START_STREAM:
+			if (s_ctrl->func_tbl->sensor_start_stream == NULL) {
+				rc = -EFAULT;
+				break;
+			}
+			s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
+			break;
+
+		case CFG_STOP_STREAM:
+			if (s_ctrl->func_tbl->sensor_stop_stream == NULL) {
+				rc = -EFAULT;
+				break;
+			}
+			s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
+			break;
+
+		case CFG_GET_CSI_PARAMS:
+			if (s_ctrl->func_tbl->sensor_get_csi_params == NULL) {
+				rc = -EFAULT;
+				break;
+			}
+			rc = s_ctrl->func_tbl->sensor_get_csi_params(
+				s_ctrl,
+				&cdata.cfg.csi_lane_params);
+
+			if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+				rc = -EFAULT;
+			break;
+
 		default:
 			rc = -EFAULT;
 			break;
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 7ade827..7697a79 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -137,6 +137,13 @@
 	int32_t (*sensor_match_id)(struct msm_sensor_ctrl_t *s_ctrl);
 	int (*sensor_adjust_frame_lines)
 		(struct msm_sensor_ctrl_t *s_ctrl, uint16_t res);
+	int32_t (*sensor_get_csi_params)(struct msm_sensor_ctrl_t *,
+		struct csi_lane_params_t *);
+};
+
+struct msm_sensor_csi_info {
+	uint32_t csid_version;
+	uint8_t is_csic;
 };
 
 struct msm_sensor_ctrl_t {
@@ -152,6 +159,8 @@
 	struct msm_sensor_reg_t *msm_sensor_reg;
 	struct msm_sensor_v4l2_ctrl_info_t *msm_sensor_v4l2_ctrl_info;
 	uint16_t num_v4l2_ctrl;
+	uint32_t csid_version;
+	uint8_t is_csic;
 
 	uint16_t curr_line_length_pclk;
 	uint16_t curr_frame_length_lines;
@@ -241,6 +250,9 @@
 long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int cmd, void *arg);
 
+int32_t msm_sensor_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
+		struct csi_lane_params_t *sensor_output_info);
+
 struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
 
 #if defined(CONFIG_OV5647)
@@ -253,4 +265,7 @@
 #define VIDIOC_MSM_SENSOR_RELEASE \
 	_IO('V', BASE_VIDIOC_PRIVATE + 11)
 
+#define VIDIOC_MSM_SENSOR_CSID_INFO\
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 12, struct msm_sensor_csi_info *)
+
 #endif
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
index e6e2d52..69a5498 100644
--- a/drivers/media/video/msm/sensors/mt9e013_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -472,6 +472,7 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t mt9e013_regs = {
diff --git a/drivers/media/video/msm/sensors/mt9m114_v4l2.c b/drivers/media/video/msm/sensors/mt9m114_v4l2.c
index 2184806..806bcc2 100644
--- a/drivers/media/video/msm/sensors/mt9m114_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9m114_v4l2.c
@@ -1268,6 +1268,7 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t mt9m114_regs = {
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index 40867fb..03f1af1 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.c
@@ -784,6 +784,7 @@
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
 	.sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t ov2720_regs = {
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index 9dfbf8d..eab0899 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -815,6 +815,7 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = ov5647_sensor_power_up,
 	.sensor_power_down = ov5647_sensor_power_down,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t ov5647_regs = {
diff --git a/drivers/media/video/msm/sensors/ov7692_v4l2.c b/drivers/media/video/msm/sensors/ov7692_v4l2.c
index 8c94e3b..a6af770 100644
--- a/drivers/media/video/msm/sensors/ov7692_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov7692_v4l2.c
@@ -909,6 +909,7 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = ov7692_sensor_power_up,
 	.sensor_power_down = ov7692_sensor_power_down,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t ov7692_regs = {
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/video/msm/sensors/ov9726_v4l2.c
index 61c693e..27a8b38 100644
--- a/drivers/media/video/msm/sensors/ov9726_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov9726_v4l2.c
@@ -236,6 +236,7 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t ov9726_regs = {
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index 1d7da0d..d7aeb74 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -653,6 +653,7 @@
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
 	.sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t s5k3l1yx_regs = {
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
index 2d25824..e90390e 100644
--- a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
+++ b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
@@ -487,6 +487,7 @@
 	.sensor_config = msm_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
 	.sensor_power_down = msm_sensor_power_down,
+	.sensor_get_csi_params = msm_sensor_get_csi_params,
 };
 
 static struct msm_sensor_reg_t s5k4e1_regs = {
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index cb59737..dfa7fbe 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1365,9 +1365,7 @@
 	struct msm_camera_device_platform_data *camdev;
 	uint8_t csid_core = 0;
 
-	if (notification == NOTIFY_CID_CHANGE ||
-		notification == NOTIFY_ISPIF_STREAM ||
-		notification == NOTIFY_PCLK_CHANGE ||
+	if (notification == NOTIFY_PCLK_CHANGE ||
 		notification == NOTIFY_CSIPHY_CFG ||
 		notification == NOTIFY_CSID_CFG ||
 		notification == NOTIFY_CSIC_CFG) {
@@ -1378,30 +1376,6 @@
 	}
 
 	switch (notification) {
-	case NOTIFY_CID_CHANGE:
-		/* reconfig the ISPIF*/
-		if (g_server_dev.ispif_device) {
-			struct msm_ispif_params_list ispif_params;
-			ispif_params.len = 1;
-			ispif_params.params[0].intftype = PIX0;
-			ispif_params.params[0].cid_mask = 0x0001;
-			ispif_params.params[0].csid = csid_core;
-
-			rc = v4l2_subdev_call(
-				g_server_dev.ispif_device, core, ioctl,
-				VIDIOC_MSM_ISPIF_CFG, &ispif_params);
-			if (rc < 0)
-				return;
-		}
-		break;
-	case NOTIFY_ISPIF_STREAM:
-		/* call ISPIF stream on/off */
-		rc = v4l2_subdev_call(g_server_dev.ispif_device, video,
-				s_stream, (int)arg);
-		if (rc < 0)
-			return;
-
-		break;
 	case NOTIFY_ISP_MSG_EVT:
 	case NOTIFY_VFE_MSG_OUT:
 	case NOTIFY_VFE_MSG_STATS:
@@ -1461,20 +1435,379 @@
 	}
 
 	return;
-}

-

-void msm_cam_release_subdev_node(struct video_device *vdev)

-{

-	struct v4l2_subdev *sd = video_get_drvdata(vdev);

-	sd->devnode = NULL;

-	kfree(vdev);

+}
+
+void msm_cam_release_subdev_node(struct video_device *vdev)
+{
+	struct v4l2_subdev *sd = video_get_drvdata(vdev);
+	sd->devnode = NULL;
+	kfree(vdev);
+}
+
+/* Helper function to get the irq_idx corresponding
+ * to the irq_num. */
+int get_irq_idx_from_irq_num(int irq_num)
+{
+	int i;
+	for (i = 0; i < CAMERA_SS_IRQ_MAX; i++)
+		if (irq_num == g_server_dev.hw_irqmap[i].irq_num)
+			return g_server_dev.hw_irqmap[i].irq_idx;
+
+	return -EINVAL;
+}
+
+static irqreturn_t msm_camera_server_parse_irq(int irq_num, void *data)
+{
+	unsigned long flags;
+	int irq_idx, i, rc;
+	u32 status = 0;
+	struct intr_table_entry *ind_irq_tbl;
+	struct intr_table_entry *comp_irq_tbl;
+	bool subdev_handled = 0;
+
+	irq_idx = get_irq_idx_from_irq_num(irq_num);
+	if (irq_idx < 0) {
+		pr_err("server_parse_irq: no clients for irq #%d. returning ",
+			irq_num);
+		return IRQ_HANDLED;
+	}
+
+	spin_lock_irqsave(&g_server_dev.intr_table_lock, flags);
+	ind_irq_tbl = &g_server_dev.irq_lkup_table.ind_intr_tbl[0];
+	comp_irq_tbl = &g_server_dev.irq_lkup_table.comp_intr_tbl[0];
+	if (ind_irq_tbl[irq_idx].is_composite) {
+		for (i = 0; i < comp_irq_tbl[irq_idx].num_hwcore; i++) {
+			if (comp_irq_tbl[irq_idx].subdev_list[i]) {
+				rc = v4l2_subdev_call(
+					comp_irq_tbl[irq_idx].subdev_list[i],
+					core, interrupt_service_routine,
+					status, &subdev_handled);
+				if ((rc < 0) || !subdev_handled) {
+					pr_err("server_parse_irq:Error\n"
+						"handling irq %d rc = %d",
+						irq_num, rc);
+					/* Dispatch the irq to the remaining
+					 * subdevs in the list. */
+					continue;
+				}
+			}
+		}
+	} else {
+		rc = v4l2_subdev_call(ind_irq_tbl[irq_idx].subdev_list[0],
+			core, interrupt_service_routine,
+			status, &subdev_handled);
+		if ((rc < 0) || !subdev_handled) {
+			pr_err("server_parse_irq: Error handling irq %d rc = %d",
+				irq_num, rc);
+			spin_unlock_irqrestore(&g_server_dev.intr_table_lock,
+				flags);
+			return IRQ_HANDLED;
+		}
+	}
+	spin_unlock_irqrestore(&g_server_dev.intr_table_lock, flags);
+	return IRQ_HANDLED;
+}
+
+/* Helper function to get the irq_idx corresponding
+ * to the camera hwcore. This function should _only_
+ * be invoked when the IRQ Router is configured
+ * non-composite mode. */
+int get_irq_idx_from_camhw_idx(int cam_hw_idx)
+{
+	int i;
+	for (i = 0; i < MSM_CAM_HW_MAX; i++)
+		if (cam_hw_idx == g_server_dev.hw_irqmap[i].cam_hw_idx)
+			return g_server_dev.hw_irqmap[i].irq_idx;
+
+	return -EINVAL;
+}
+
+static inline void update_compirq_subdev_info(
+	struct intr_table_entry *irq_entry,
+	uint32_t cam_hw_mask, uint8_t cam_hw_id,
+	int *num_hwcore)
+{
+	if (cam_hw_mask & (0x1 << cam_hw_id)) {
+		/* If the mask has been set for this cam hwcore
+		 * update the subdev ptr......*/
+		irq_entry->subdev_list[cam_hw_id] =
+			g_server_dev.subdev_table[cam_hw_id];
+		(*num_hwcore)++;
+	} else {
+		/*....else, just clear it, so that the irq will
+		 * not be dispatched to this hw. */
+		irq_entry->subdev_list[cam_hw_id] = NULL;
+	}
+}
+
+static int msm_server_update_composite_irq_info(
+	struct intr_table_entry *irq_req)
+{
+	int num_hwcore = 0, rc = 0;
+	struct intr_table_entry *comp_irq_tbl =
+		&g_server_dev.irq_lkup_table.comp_intr_tbl[0];
+
+	comp_irq_tbl[irq_req->irq_idx].is_composite = 1;
+	comp_irq_tbl[irq_req->irq_idx].irq_trigger_type =
+		irq_req->irq_trigger_type;
+	comp_irq_tbl[irq_req->irq_idx].num_hwcore = irq_req->num_hwcore;
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_MICRO, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_CCI, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_CSI0, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_CSI1, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_CSI2, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_CSI3, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_ISPIF, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_CPP, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_VFE0, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_VFE1, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_JPEG0, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_JPEG1, &num_hwcore);
+
+	update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+		irq_req->cam_hw_mask, MSM_CAM_HW_JPEG2, &num_hwcore);
+
+	if (num_hwcore != irq_req->num_hwcore) {
+		pr_warn("%s Mismatch!! requested cam hwcores: %d, Mask set %d",
+			__func__, irq_req->num_hwcore, num_hwcore);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+int msm_cam_server_request_irq(void *arg)
+{
+	unsigned long flags;
+	int rc = 0;
+	struct intr_table_entry *irq_req =  (struct intr_table_entry *)arg;
+	struct intr_table_entry *ind_irq_tbl =
+		&g_server_dev.irq_lkup_table.ind_intr_tbl[0];
+	struct intr_table_entry *comp_irq_tbl =
+		&g_server_dev.irq_lkup_table.comp_intr_tbl[0];
+
+	if (!irq_req || !irq_req->irq_num || !irq_req->num_hwcore) {
+		pr_err("%s Invalid input ", __func__);
+		return -EINVAL;
+	}
+
+	if (!g_server_dev.irqr_device) {
+		/* This either means, the current target does not
+		 * have a IRQ Router hw or the IRQ Router device is
+		 * not probed yet. The latter should not happen.
+		 * In any case, just return back without updating
+		 * the interrupt lookup table. */
+		pr_info("%s IRQ Router hw is not present. ", __func__);
+		return -ENXIO;
+	}
+
+	if (irq_req->is_composite) {
+		if (irq_req->irq_idx >= CAMERA_SS_IRQ_0 &&
+				irq_req->irq_idx < CAMERA_SS_IRQ_MAX) {
+			spin_lock_irqsave(&g_server_dev.intr_table_lock, flags);
+			/* Update the composite irq information into
+			 * the composite irq lookup table.... */
+			if (msm_server_update_composite_irq_info(irq_req)) {
+				pr_err("%s Invalid configuration", __func__);
+				spin_unlock_irqrestore(
+					&g_server_dev.intr_table_lock, flags);
+				return -EINVAL;
+			}
+			spin_unlock_irqrestore(&g_server_dev.intr_table_lock,
+				flags);
+			/*...and then update the corresponding entry
+			 * in the individual irq lookup table to indicate
+			 * that this IRQ is a composite irq and needs to be
+			 * sent to multiple subdevs. */
+			ind_irq_tbl[irq_req->irq_idx].is_composite = 1;
+			rc = request_irq(comp_irq_tbl[irq_req->irq_idx].irq_num,
+				msm_camera_server_parse_irq,
+				irq_req->irq_trigger_type,
+				ind_irq_tbl[irq_req->irq_idx].dev_name,
+				ind_irq_tbl[irq_req->irq_idx].data);
+			if (rc < 0) {
+				pr_err("%s: request_irq failed for %s\n",
+					__func__, irq_req->dev_name);
+				return -EBUSY;
+			}
+		} else {
+			pr_err("%s Invalid irq_idx %d ",
+				__func__, irq_req->irq_idx);
+			return -EINVAL;
+		}
+	} else {
+		if (irq_req->cam_hw_idx >= MSM_CAM_HW_MICRO &&
+				irq_req->cam_hw_idx < MSM_CAM_HW_MAX) {
+			/* Update the irq information into
+			 * the individual irq lookup table.... */
+			irq_req->irq_idx =
+				get_irq_idx_from_camhw_idx(irq_req->cam_hw_idx);
+			if (irq_req->cam_hw_idx < 0) {
+				pr_err("%s Invalid hw index %d ", __func__,
+					irq_req->cam_hw_idx);
+				return -EINVAL;
+			}
+			spin_lock_irqsave(&g_server_dev.intr_table_lock, flags);
+			/* Make sure the composite irq is not configured for
+			 * this IRQ already. */
+			BUG_ON(ind_irq_tbl[irq_req->irq_idx].is_composite);
+
+			ind_irq_tbl[irq_req->irq_idx] = *irq_req;
+			/* irq_num is stored inside the server's hw_irqmap
+			 * during the device subdevice registration. */
+			ind_irq_tbl[irq_req->irq_idx].irq_num =
+			g_server_dev.hw_irqmap[irq_req->irq_idx].irq_num;
+
+			/*...and clear the corresponding entry in the
+			 * compsoite irq lookup table to indicate that this
+			 * IRQ will only be dispatched to single subdev. */
+			memset(&comp_irq_tbl[irq_req->irq_idx], 0,
+					sizeof(struct intr_table_entry));
+			D("%s Saving Entry %d %d %d %p",
+			__func__,
+			ind_irq_tbl[irq_req->cam_hw_idx].irq_num,
+			ind_irq_tbl[irq_req->cam_hw_idx].cam_hw_idx,
+			ind_irq_tbl[irq_req->cam_hw_idx].is_composite,
+			ind_irq_tbl[irq_req->cam_hw_idx].subdev_list[0]);
+
+			spin_unlock_irqrestore(&g_server_dev.intr_table_lock,
+				flags);
+
+			rc = request_irq(ind_irq_tbl[irq_req->irq_idx].irq_num,
+				msm_camera_server_parse_irq,
+				irq_req->irq_trigger_type,
+				ind_irq_tbl[irq_req->irq_idx].dev_name,
+				ind_irq_tbl[irq_req->irq_idx].data);
+			if (rc < 0) {
+				pr_err("%s: request_irq failed for %s\n",
+					__func__, irq_req->dev_name);
+				return -EBUSY;
+			}
+		} else {
+			pr_err("%s Invalid hw index %d ", __func__,
+				irq_req->cam_hw_idx);
+			return -EINVAL;
+		}
+	}
+	D("%s Successfully requested for IRQ for device %s ", __func__,
+		irq_req->dev_name);
+	return rc;
+}
+
+int msm_cam_server_update_irqmap(
+	struct msm_cam_server_irqmap_entry *irqmap_entry)
+{
+	if (!irqmap_entry || (irqmap_entry->irq_idx < CAMERA_SS_IRQ_0 ||
+		irqmap_entry->irq_idx >= CAMERA_SS_IRQ_MAX)) {
+		pr_err("%s Invalid irqmap entry ", __func__);
+		return -EINVAL;
+	}
+	g_server_dev.hw_irqmap[irqmap_entry->irq_idx] = *irqmap_entry;
+	return 0;
+}
+
+static int msm_cam_server_register_subdev(struct v4l2_device *v4l2_dev,
+	struct v4l2_subdev *sd)
+{
+	int rc = 0;
+	struct video_device *vdev;
+
+	if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) {
+		pr_err("%s Invalid input ", __func__);
+		return -EINVAL;
+	}
+
+	rc = v4l2_device_register_subdev(v4l2_dev, sd);
+	if (rc < 0) {
+		pr_err("%s v4l2 subdev register failed for %s ret = %d",
+			__func__, sd->name, rc);
+		return rc;
+	}
+
+	/* Register a device node for every subdev marked with the
+	 * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
+	 */
+	if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
+		return rc;
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev) {
+		pr_err("%s Not enough memory ", __func__);
+		rc = -ENOMEM;
+		goto clean_up;
+	}
+
+	video_set_drvdata(vdev, sd);
+	strlcpy(vdev->name, sd->name, sizeof(vdev->name));
+	vdev->v4l2_dev = v4l2_dev;
+	vdev->fops = &v4l2_subdev_fops;
+	vdev->release = msm_cam_release_subdev_node;
+	rc = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+						  sd->owner);
+	if (rc < 0) {
+		pr_err("%s Error registering video device %s", __func__,
+			sd->name);
+		kfree(vdev);
+		goto clean_up;
+	}
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	sd->entity.info.v4l.major = VIDEO_MAJOR;
+	sd->entity.info.v4l.minor = vdev->minor;
+#endif
+	sd->devnode = vdev;
+	return 0;
+
+clean_up:
+	if (sd->devnode)
+		video_unregister_device(sd->devnode);
+	return rc;
+}
+
+static int msm_cam_server_fill_sdev_irqnum(int cam_hw_idx,
+	int irq_num)
+{
+	int rc = 0, irq_idx;
+	irq_idx = get_irq_idx_from_camhw_idx(cam_hw_idx);
+	if (irq_idx < 0) {
+		pr_err("%s Invalid cam_hw_idx %d ", __func__, cam_hw_idx);
+		rc = -EINVAL;
+	} else {
+		g_server_dev.hw_irqmap[irq_idx].irq_num = irq_num;
+	}
+	return rc;
 }
 
 int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
-	enum msm_cam_subdev_type sdev_type, uint8_t index)
+	struct msm_cam_subdev_info *sd_info)
 {
-	struct video_device *vdev;
-	int err = 0;
+	int err = 0, cam_hw_idx;
+	uint8_t sdev_type, index;
+
+	sdev_type = sd_info->sdev_type;
+	index     = sd_info->sd_index;
 
 	switch (sdev_type) {
 	case CSIPHY_DEV:
@@ -1492,7 +1825,13 @@
 			err = -EINVAL;
 			break;
 		}
+		cam_hw_idx = MSM_CAM_HW_CSI0 + index;
 		g_server_dev.csid_device[index] = sd;
+		if (g_server_dev.irqr_device) {
+			g_server_dev.subdev_table[cam_hw_idx] = sd;
+			err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
+				sd_info->irq_num);
+		}
 		break;
 
 	case CSIC_DEV:
@@ -1506,6 +1845,11 @@
 
 	case ISPIF_DEV:
 		g_server_dev.ispif_device = sd;
+		if (g_server_dev.irqr_device) {
+			g_server_dev.subdev_table[cam_hw_idx] = sd;
+			err = msm_cam_server_fill_sdev_irqnum(MSM_CAM_HW_ISPIF,
+				sd_info->irq_num);
+		}
 		break;
 
 	case VFE_DEV:
@@ -1514,7 +1858,13 @@
 			err = -EINVAL;
 			break;
 		}
+		cam_hw_idx = MSM_CAM_HW_VFE0 + index;
 		g_server_dev.vfe_device[index] = sd;
+		if (g_server_dev.irqr_device) {
+			g_server_dev.subdev_table[cam_hw_idx] = sd;
+			err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
+				sd_info->irq_num);
+		}
 		break;
 
 	case VPE_DEV:
@@ -1538,6 +1888,9 @@
 	case GESTURE_DEV:
 		g_server_dev.gesture_device = sd;
 		break;
+	case IRQ_ROUTER_DEV:
+		g_server_dev.irqr_device = sd;
+		break;
 	default:
 		break;
 	}
@@ -1545,49 +1898,11 @@
 	if (err < 0)
 		return err;
 
-	err = v4l2_device_register_subdev(&g_server_dev.v4l2_dev, sd);
-	if (err < 0) {
-		pr_err("%s v4l2 subdev register failed for %d ret = %d",
-			__func__, sdev_type, err);
-		return err;
-	}
-
-	/* Register a device node for every subdev marked with the
-	 * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
-	 */
-	if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
-		return err;
-
-	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);

-	if (!vdev) {

-		err = -ENOMEM;

-		goto clean_up;

-	}

-

-	video_set_drvdata(vdev, sd);

-	strlcpy(vdev->name, sd->name, sizeof(vdev->name));
-	vdev->v4l2_dev = &g_server_dev.v4l2_dev;
-	vdev->fops = &v4l2_subdev_fops;
-	vdev->release = msm_cam_release_subdev_node;

-	err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
-						  sd->owner);
-	if (err < 0) {

-		kfree(vdev);

-		goto clean_up;

-	}

-#if defined(CONFIG_MEDIA_CONTROLLER)
-	sd->entity.info.v4l.major = VIDEO_MAJOR;

-	sd->entity.info.v4l.minor = vdev->minor;

-#endif
-	sd->devnode = vdev;

-	return 0;
-

-clean_up:

-	if (sd->devnode)

-		video_unregister_device(sd->devnode);

-	return err;

+	err = msm_cam_server_register_subdev(&g_server_dev.v4l2_dev, sd);
+	return err;
 }
 
+
 static int msm_setup_server_dev(struct platform_device *pdev)
 {
 	int rc = -ENODEV, i;
@@ -1630,6 +1945,9 @@
 
 	mutex_init(&g_server_dev.server_lock);
 	mutex_init(&g_server_dev.server_queue_lock);
+	spin_lock_init(&g_server_dev.intr_table_lock);
+	memset(&g_server_dev.irq_lkup_table, 0,
+			sizeof(struct irqmgr_intr_lkup_table));
 	g_server_dev.pcam_active = NULL;
 	g_server_dev.camera_info.num_cameras = 0;
 	atomic_set(&g_server_dev.number_pcam_active, 0);
@@ -1786,16 +2104,20 @@
 
 	struct v4l2_event v4l2_evt;
 	struct msm_isp_event_ctrl *isp_event;
-	isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
-	if (!isp_event) {
-		pr_err("%s Insufficient memory. return", __func__);
-		return -ENOMEM;
-	}
+	void *ctrlcmd_data;
+
 	event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
 	if (!event_qcmd) {
 		pr_err("%s Insufficient memory. return", __func__);
-		kfree(isp_event);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto event_qcmd_alloc_fail;
+	}
+
+	isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
+	if (!isp_event) {
+		pr_err("%s Insufficient memory. return", __func__);
+		rc = -ENOMEM;
+		goto isp_event_alloc_fail;
 	}
 
 	D("%s\n", __func__);
@@ -1808,12 +2130,23 @@
 	server_dev->server_queue[out->queue_idx].evt_id =
 		server_dev->server_evt_id;
 	v4l2_evt.type = V4L2_EVENT_PRIVATE_START + ctrl_id;
+	v4l2_evt.id = 0;
 	v4l2_evt.u.data[0] = out->queue_idx;
 	/* setup event object to transfer the command; */
 	isp_event->resptype = MSM_CAM_RESP_V4L2;
 	isp_event->isp_data.ctrl = *out;
 	isp_event->isp_data.ctrl.evt_id = server_dev->server_evt_id;
 
+	if (out->value != NULL && out->length != 0) {
+		ctrlcmd_data = kzalloc(out->length, GFP_KERNEL);
+		if (!ctrlcmd_data) {
+			rc = -ENOMEM;
+			goto ctrlcmd_alloc_fail;
+		}
+		memcpy(ctrlcmd_data, out->value, out->length);
+		isp_event->isp_data.ctrl.value = ctrlcmd_data;
+	}
+
 	atomic_set(&event_qcmd->on_heap, 1);
 	event_qcmd->command = isp_event;
 
@@ -1837,7 +2170,8 @@
 		if (!rc)
 			rc = -ETIMEDOUT;
 		if (rc < 0) {
-			kfree(isp_event);
+			if (++server_dev->server_evt_id == 0)
+				server_dev->server_evt_id++;
 			pr_err("%s: wait_event error %d\n", __func__, rc);
 			return rc;
 		}
@@ -1858,7 +2192,6 @@
 
 	kfree(ctrlcmd);
 	free_qcmd(rcmd);
-	kfree(isp_event);
 	D("%s: rc %d\n", __func__, rc);
 	/* rc is the time elapsed. */
 	if (rc >= 0) {
@@ -1871,6 +2204,13 @@
 			rc = -EINVAL;
 	}
 	return rc;
+
+ctrlcmd_alloc_fail:
+	kfree(isp_event);
+isp_event_alloc_fail:
+	kfree(event_qcmd);
+event_qcmd_alloc_fail:
+	return rc;
 }
 
 int msm_server_close_client(int idx)
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index 677feaa..8a02d32 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -61,5 +61,7 @@
 	struct v4l2_event_subscription *sub);
 int msm_server_get_crop(struct msm_cam_v4l2_device *pcam,
 	int idx, struct v4l2_crop *crop);
-
+int msm_cam_server_request_irq(void *arg);
+int msm_cam_server_update_irqmap(
+	struct msm_cam_server_irqmap_entry *entry);
 #endif /* _MSM_CAM_SERVER_H */
diff --git a/drivers/media/video/msm/sn12m0pz.c b/drivers/media/video/msm/sn12m0pz.c
index 2eabb3c..c39e97f 100644
--- a/drivers/media/video/msm/sn12m0pz.c
+++ b/drivers/media/video/msm/sn12m0pz.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/uaccess.h>
 #include <linux/miscdevice.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <media/msm_camera.h>
 #include <mach/gpio.h>
 #include <mach/camera.h>
diff --git a/drivers/media/video/msm/vx6953.c b/drivers/media/video/msm/vx6953.c
index 3b8f14c..f933a76 100644
--- a/drivers/media/video/msm/vx6953.c
+++ b/drivers/media/video/msm/vx6953.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
@@ -16,6 +16,7 @@
 #include <linux/i2c.h>
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
+#include <linux/module.h>
 #include <media/msm_camera.h>
 #include <mach/gpio.h>
 #include <mach/camera.h>
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 1c646dd..6cd9e6b 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -28,6 +28,7 @@
 #include "msm_smem.h"
 
 #define BASE_DEVICE_NUMBER 32
+#define MAX_EVENTS 30
 
 struct msm_vidc_drv *vidc_driver;
 
@@ -215,21 +216,20 @@
 	int rc;
 	struct buffer_info *bi;
 	struct v4l2_buffer buffer_info;
+	struct v4l2_plane plane;
 	v4l2_inst = get_v4l2_inst(file, NULL);
 	if (b->count == 0) {
 		list_for_each_safe(ptr, next, &v4l2_inst->registered_bufs) {
 			bi = list_entry(ptr, struct buffer_info, list);
 			if (bi->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 				buffer_info.type = bi->type;
-				buffer_info.m.planes[0].reserved[0] =
-					bi->fd;
-				buffer_info.m.planes[0].reserved[1] =
-					bi->buff_off;
-				buffer_info.m.planes[0].length = bi->size;
-				buffer_info.m.planes[0].m.userptr =
-					bi->uvaddr;
+				plane.reserved[0] = bi->fd;
+				plane.reserved[1] = bi->buff_off;
+				plane.length = bi->size;
+				plane.m.userptr = bi->uvaddr;
+				buffer_info.m.planes = &plane;
 				buffer_info.length = 1;
-				pr_err("Releasing buffer: %d, %d, %d\n",
+				pr_info("Releasing buffer: %d, %d, %d\n",
 				buffer_info.m.planes[0].reserved[0],
 				buffer_info.m.planes[0].reserved[1],
 				buffer_info.m.planes[0].length);
@@ -359,9 +359,7 @@
 				struct v4l2_event_subscription *sub)
 {
 	int rc = 0;
-	if (sub->type == V4L2_EVENT_ALL)
-		sub->type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
-	rc = v4l2_event_subscribe(fh, sub, 0);
+	rc = v4l2_event_subscribe(fh, sub, MAX_EVENTS);
 	return rc;
 }
 
@@ -445,7 +443,7 @@
 	INIT_LIST_HEAD(&core->instances);
 	mutex_init(&core->sync_lock);
 	spin_lock_init(&core->lock);
-	core->base_addr = 0x34f00000;
+	core->base_addr = 0x14f00000;
 	core->state = VIDC_CORE_UNINIT;
 	for (i = SYS_MSG_INDEX(SYS_MSG_START);
 		i <= SYS_MSG_INDEX(SYS_MSG_END); i++) {
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index ed99d35..ec93628 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -348,7 +348,7 @@
 	{
 		.id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
 		.name = "H.264 Loop Filter Mode",
-		.type = V4L2_CTRL_TYPE_INTEGER,
+		.type = V4L2_CTRL_TYPE_MENU,
 		.minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
 		.maximum = L_MODE,
 		.default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
@@ -375,7 +375,9 @@
 
 static u32 get_frame_size_compressed(int plane, u32 height, u32 width)
 {
-	return ((height + 31) & (~31)) * ((width + 31) & (~31)) * 3/2;
+	int sz = ((height + 31) & (~31)) * ((width + 31) & (~31)) * 3/2;
+	sz = (sz + 4095) & (~4095);
+	return sz;
 }
 
 static struct hal_quantization
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index a11f817..11fbcf4 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -186,7 +186,7 @@
 void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 				unsigned long size, int write)
 {
-	return NULL;
+	return (void *)0xdeadbeef;
 }
 
 void vidc_put_userptr(void *buf_priv)
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 52f1dca..9b617aa 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -183,21 +183,9 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct video_device *vdev;
-	struct v4l2_event dqevent;
-	struct msm_vidc_core *core;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
-		core = inst->core;
-		if (inst->session_type == MSM_VIDC_ENCODER)
-			vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
-		else
-			vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
-		dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
-		dqevent.u.data[0] = (uint8_t)MSM_VIDC_OPEN_DONE;
-		v4l2_event_queue(vdev, &dqevent);
-		return;
 	} else {
 		pr_err("Failed to get valid response for session init\n");
 	}
@@ -207,24 +195,17 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct video_device *vdev;
 	struct v4l2_event dqevent;
 	struct msm_vidc_cb_event *event_notify;
-	struct msm_vidc_core *core;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
-		core = inst->core;
-		if (inst->session_type == MSM_VIDC_ENCODER)
-			vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
-		else
-			vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
-		dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
-		dqevent.u.data[0] = (uint8_t)MSM_VIDC_DECODER_EVENT_CHANGE;
+		dqevent.type = V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED;
+		dqevent.id = 0;
 		event_notify = (struct msm_vidc_cb_event *) response->data;
 		inst->reconfig_height = event_notify->height;
 		inst->reconfig_width = event_notify->width;
 		inst->in_reconfig = true;
-		v4l2_event_queue(vdev, &dqevent);
+		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 		return;
 	} else {
 		pr_err("Failed to get valid response for event_change\n");
@@ -262,20 +243,9 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct video_device *vdev;
-	struct v4l2_event dqevent;
-	struct msm_vidc_core *core;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
-		core = inst->core;
-		if (inst->session_type == MSM_VIDC_ENCODER)
-			vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
-		else
-			vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
-		dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
-		dqevent.u.data[0] = (uint8_t)MSM_VIDC_START_DONE;
-		v4l2_event_queue(vdev, &dqevent);
 	} else {
 		pr_err("Failed to get valid response for start\n");
 	}
@@ -285,20 +255,9 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct video_device *vdev;
-	struct v4l2_event dqevent;
-	struct msm_vidc_core *core;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
-		core = inst->core;
-		if (inst->session_type == MSM_VIDC_ENCODER)
-			vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
-		else
-			vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
-		dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
-		dqevent.u.data[0] = (uint8_t)MSM_VIDC_STOP_DONE;
-		v4l2_event_queue(vdev, &dqevent);
 	} else {
 		pr_err("Failed to get valid response for stop\n");
 	}
@@ -320,19 +279,12 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct video_device *vdev;
 	struct v4l2_event dqevent;
-	struct msm_vidc_core *core;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
-		core = inst->core;
-		if (inst->session_type == MSM_VIDC_ENCODER)
-			vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
-		else
-			vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
-		dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
-		dqevent.u.data[0] = (uint8_t)MSM_VIDC_DECODER_FLUSH_DONE;
-		v4l2_event_queue(vdev, &dqevent);
+		dqevent.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
+		dqevent.id = 0;
+		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 	} else {
 		pr_err("Failed to get valid response for flush\n");
 	}
@@ -343,20 +295,13 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct video_device *vdev;
 	struct v4l2_event dqevent;
-	struct msm_vidc_core *core;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
-		core = inst->core;
-		if (inst->session_type == MSM_VIDC_ENCODER)
-			vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
-		else
-			vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
-		dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
-		dqevent.u.data[0] = (uint8_t)MSM_VIDC_CLOSE_DONE;
-		v4l2_event_queue(vdev, &dqevent);
+		dqevent.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
+		dqevent.id = 0;
+		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 	} else {
 		pr_err("Failed to get valid response for session close\n");
 	}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index fb1ab58..fb8fbc4 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -75,11 +75,6 @@
 	MSM_VIDC_CORE_UNINIT,
 };
 
-enum vidc_resposes_id {
-	MSM_VIDC_DECODER_FLUSH_DONE = 0x11,
-	MSM_VIDC_DECODER_EVENT_CHANGE,
-};
-
 struct buf_info {
 	struct list_head list;
 	struct vb2_buffer *buf;
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 1f33c2c..13a319d9 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -84,8 +84,8 @@
 	{
 		struct hfi_cmd_session_release_buffer_packet *pkt =
 			(struct hfi_cmd_session_release_buffer_packet *)packet;
-		if ((pkt->buffer_type == HAL_BUFFER_OUTPUT) ||
-			(pkt->buffer_type == HAL_BUFFER_OUTPUT2)) {
+		if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
+			(pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
 			struct hfi_buffer_info *buff;
 			buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
 			buff->buffer_addr -= HFI_VIRTIO_FW_BIAS;
@@ -824,8 +824,7 @@
 	}
 
 	HAL_MSG_INFO("IN func: %s, with property id: %d", __func__, ptype);
-	pkt->size = sizeof(struct hfi_cmd_session_set_property_packet)
-		- sizeof(u32);
+	pkt->size = sizeof(struct hfi_cmd_session_set_property_packet);
 	pkt->packet_type = HFI_CMD_SESSION_SET_PROPERTY;
 	pkt->session_id = (u32) session;
 	pkt->num_properties = 1;
diff --git a/drivers/media/video/msm_vidc/vidc_hal.h b/drivers/media/video/msm_vidc/vidc_hal.h
index 166ed0d..15441f4 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.h
+++ b/drivers/media/video/msm_vidc/vidc_hal.h
@@ -1153,7 +1153,7 @@
 	enum HFI_COMMAND packet_type;
 	u32 session_id;
 	u32 num_properties;
-	u32 rg_property_data[1];
+	u32 rg_property_data[0];
 };
 
 struct hfi_cmd_session_get_property_packet {
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 9719307..db0dbc2 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -32,6 +32,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
 #include <linux/regulator/consumer.h>
 #include <mach/clk.h>
 #include <linux/clk.h>
@@ -58,6 +59,228 @@
 			printk(KERN_DEBUG "VCAP: " fmt, ## arg);	\
 	} while (0)
 
+int vcap_reg_powerup(struct vcap_dev *dev)
+{
+	dev->fs_vcap = regulator_get(NULL, "fs_vcap");
+	if (IS_ERR(dev->fs_vcap)) {
+		pr_err("%s: Regulator FS_VCAP get failed %ld\n", __func__,
+			PTR_ERR(dev->fs_vcap));
+		dev->fs_vcap = NULL;
+		return -EINVAL;
+	} else if (regulator_enable(dev->fs_vcap)) {
+		pr_err("%s: Regulator FS_VCAP enable failed\n", __func__);
+		regulator_put(dev->fs_vcap);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+void vcap_reg_powerdown(struct vcap_dev *dev)
+{
+	if (dev->fs_vcap == NULL)
+		return;
+	regulator_disable(dev->fs_vcap);
+	regulator_put(dev->fs_vcap);
+	dev->fs_vcap = NULL;
+	return;
+}
+
+int config_gpios(int on, struct vcap_platform_data *pdata)
+{
+	int i, ret;
+	int num_gpios = pdata->num_gpios;
+	unsigned *gpios = pdata->gpios;
+
+	dprintk(4, "GPIO config start\n");
+	if (on) {
+		for (i = 0; i < num_gpios; i++) {
+			ret = gpio_request(gpios[i], "vcap:vc");
+			if (ret) {
+				pr_err("VCAP: failed at GPIO %d to request\n",
+						gpios[i]);
+				goto gpio_failed;
+			}
+			ret = gpio_direction_input(gpios[i]);
+			if (ret) {
+				pr_err("VCAP: failed at GPIO %d to set to input\n",
+					gpios[i]);
+				i++;
+				goto gpio_failed;
+			}
+		}
+	} else {
+		for (i = 0; i < num_gpios; i++)
+			gpio_free(gpios[i]);
+	}
+	dprintk(4, "GPIO config exit\n");
+	return 0;
+gpio_failed:
+	for (i--; i >= 0; i--)
+		gpio_free(gpios[i]);
+	return -EINVAL;
+}
+
+int vcap_clk_powerup(struct vcap_dev *dev, struct device *ddev,
+		unsigned long rate)
+{
+	int ret = 0;
+
+	dev->vcap_clk = clk_get(ddev, "core_clk");
+	if (IS_ERR(dev->vcap_clk)) {
+		dev->vcap_clk = NULL;
+		pr_err("%s: Could not clk_get core_clk\n", __func__);
+		clk_put(dev->vcap_clk);
+		dev->vcap_clk = NULL;
+		return -EINVAL;
+	}
+
+	clk_prepare(dev->vcap_clk);
+	ret = clk_enable(dev->vcap_clk);
+	if (ret) {
+		pr_err("%s: Failed core clk_enable %d\n", __func__, ret);
+		goto fail_vcap_clk_unprep;
+	}
+
+	rate = clk_round_rate(dev->vcap_clk, rate);
+	if (rate < 0) {
+		pr_err("%s: Failed core rnd_rate\n", __func__);
+		goto fail_vcap_clk;
+	}
+	ret = clk_set_rate(dev->vcap_clk, rate);
+	if (ret < 0) {
+		pr_err("%s: Failed core set_rate %d\n", __func__, ret);
+		goto fail_vcap_clk;
+	}
+
+	dev->vcap_npl_clk = clk_get(ddev, "vcap_npl_clk");
+	if (IS_ERR(dev->vcap_npl_clk)) {
+		dev->vcap_npl_clk = NULL;
+		pr_err("%s: Could not clk_get npl\n", __func__);
+		clk_put(dev->vcap_npl_clk);
+		dev->vcap_npl_clk = NULL;
+		goto fail_vcap_clk;
+	}
+
+	clk_prepare(dev->vcap_npl_clk);
+	ret = clk_enable(dev->vcap_npl_clk);
+	if (ret) {
+		pr_err("%s:Failed npl clk_enable %d\n", __func__, ret);
+		goto fail_vcap_npl_clk_unprep;
+	}
+
+	dev->vcap_p_clk = clk_get(ddev, "iface_clk");
+	if (IS_ERR(dev->vcap_p_clk)) {
+		dev->vcap_p_clk = NULL;
+		pr_err("%s: Could not clk_get pix(AHB)\n", __func__);
+		clk_put(dev->vcap_p_clk);
+		dev->vcap_p_clk = NULL;
+		goto fail_vcap_npl_clk;
+	}
+
+	clk_prepare(dev->vcap_p_clk);
+	ret = clk_enable(dev->vcap_p_clk);
+	if (ret) {
+		pr_err("%s: Failed pix(AHB) clk_enable %d\n", __func__, ret);
+		goto fail_vcap_p_clk_unprep;
+	}
+	return 0;
+
+fail_vcap_p_clk_unprep:
+	clk_unprepare(dev->vcap_p_clk);
+	clk_put(dev->vcap_p_clk);
+	dev->vcap_p_clk = NULL;
+
+fail_vcap_npl_clk:
+	clk_disable(dev->vcap_npl_clk);
+fail_vcap_npl_clk_unprep:
+	clk_unprepare(dev->vcap_npl_clk);
+	clk_put(dev->vcap_npl_clk);
+	dev->vcap_npl_clk = NULL;
+
+fail_vcap_clk:
+	clk_disable(dev->vcap_clk);
+fail_vcap_clk_unprep:
+	clk_unprepare(dev->vcap_clk);
+	clk_put(dev->vcap_clk);
+	dev->vcap_clk = NULL;
+	return -EINVAL;
+}
+
+void vcap_clk_powerdown(struct vcap_dev *dev)
+{
+	if (dev->vcap_p_clk != NULL) {
+		clk_disable(dev->vcap_p_clk);
+		clk_unprepare(dev->vcap_p_clk);
+		clk_put(dev->vcap_p_clk);
+		dev->vcap_p_clk = NULL;
+	}
+
+	if (dev->vcap_npl_clk != NULL) {
+		clk_disable(dev->vcap_npl_clk);
+		clk_unprepare(dev->vcap_npl_clk);
+		clk_put(dev->vcap_npl_clk);
+		dev->vcap_npl_clk = NULL;
+	}
+
+	if (dev->vcap_clk != NULL) {
+		clk_disable(dev->vcap_clk);
+		clk_unprepare(dev->vcap_clk);
+		clk_put(dev->vcap_clk);
+		dev->vcap_clk = NULL;
+	}
+}
+
+int vcap_get_bus_client_handle(struct vcap_dev *dev)
+{
+	struct msm_bus_scale_pdata *vcap_axi_client_pdata =
+			dev->vcap_pdata->bus_client_pdata;
+	dev->bus_client_handle =
+			msm_bus_scale_register_client(vcap_axi_client_pdata);
+
+	return 0;
+}
+
+int vcap_enable(struct vcap_dev *dev, struct device *ddev,
+		unsigned long rate)
+{
+	int rc;
+
+	rc = vcap_reg_powerup(dev);
+	if (rc < 0)
+		goto reg_failed;
+	rc = vcap_clk_powerup(dev, ddev, rate);
+	if (rc < 0)
+		goto clk_failed;
+	rc = vcap_get_bus_client_handle(dev);
+	if (rc < 0)
+		goto bus_r_failed;
+	rc = config_gpios(1, dev->vcap_pdata);
+	if (rc < 0)
+		goto gpio_failed;
+	return 0;
+
+gpio_failed:
+	msm_bus_scale_unregister_client(dev->bus_client_handle);
+	dev->bus_client_handle = 0;
+bus_r_failed:
+	vcap_clk_powerdown(dev);
+clk_failed:
+	vcap_reg_powerdown(dev);
+reg_failed:
+	return rc;
+}
+
+int vcap_disable(struct vcap_dev *dev)
+{
+	config_gpios(0, dev->vcap_pdata);
+
+	msm_bus_scale_unregister_client(dev->bus_client_handle);
+	dev->bus_client_handle = 0;
+	vcap_clk_powerdown(dev);
+	vcap_reg_powerdown(dev);
+	return 0;
+}
+
 enum vcap_op_mode determine_mode(struct vcap_client_data *cd)
 {
 	if (cd->set_cap == 1 && cd->set_vp_o == 0 &&
@@ -502,7 +725,7 @@
 	int size;
 	struct vcap_priv_fmt *priv_fmt;
 	struct v4l2_format_vc_ext *vc_format;
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
 
 	priv_fmt = (struct vcap_priv_fmt *) f->fmt.raw_data;
 
@@ -511,8 +734,6 @@
 		vc_format = (struct v4l2_format_vc_ext *) &priv_fmt->u.timing;
 		c_data->vc_format = *vc_format;
 
-		config_vc_format(c_data);
-
 		size = (c_data->vc_format.hactive_end -
 			c_data->vc_format.hactive_start);
 
@@ -525,11 +746,9 @@
 		size *= (c_data->vc_format.vactive_end -
 			c_data->vc_format.vactive_start);
 		priv_fmt->u.timing.sizeimage = size;
-		vcap_ctrl->vc_client = c_data;
 		c_data->set_cap = true;
 		break;
 	case VP_IN_TYPE:
-		vcap_ctrl->vp_client = c_data;
 		c_data->vp_in_fmt.width = priv_fmt->u.pix.width;
 		c_data->vp_in_fmt.height = priv_fmt->u.pix.height;
 		c_data->vp_in_fmt.pixfmt = priv_fmt->u.pix.pixelformat;
@@ -546,7 +765,6 @@
 		c_data->set_decode = true;
 		break;
 	case VP_OUT_TYPE:
-		vcap_ctrl->vp_client = c_data;
 		c_data->vp_out_fmt.width = priv_fmt->u.pix.width;
 		c_data->vp_out_fmt.height = priv_fmt->u.pix.height;
 		c_data->vp_out_fmt.pixfmt = priv_fmt->u.pix.pixelformat;
@@ -572,7 +790,7 @@
 static int vidioc_reqbufs(struct file *file, void *priv,
 			  struct v4l2_requestbuffers *rb)
 {
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
 	int rc;
 
 	dprintk(3, "In Req Buf %08x\n", (unsigned int)rb->type);
@@ -631,7 +849,7 @@
 
 static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
 {
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
 
 	switch (p->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -645,7 +863,7 @@
 
 static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 {
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
 	struct vb2_buffer *vb;
 	struct vb2_queue *q;
 	int rc;
@@ -706,7 +924,7 @@
 
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 {
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
 	int rc;
 
 	dprintk(3, "In DQ Buf %08x\n", (unsigned int)p->type);
@@ -764,10 +982,33 @@
 	return 0;
 }
 
+int request_bus_bw(struct vcap_dev *dev, unsigned long rate)
+{
+	struct msm_bus_paths *bus_vectors;
+	int idx, length;
+	bus_vectors = dev->vcap_pdata->bus_client_pdata->usecase;
+	length = dev->vcap_pdata->bus_client_pdata->num_usecases;
+	idx = 0;
+	do {
+		if (rate <= bus_vectors[idx].vectors[0].ab)
+			break;
+		idx++;
+	} while (idx < length);
+	if (idx == length) {
+		pr_err("VCAP: Defaulting to highest BW request\n");
+		idx--;
+	}
+	msm_bus_scale_client_update_request(dev->bus_client_handle, idx);
+	return 0;
+}
+
 static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
+	struct vcap_dev *dev = c_data->dev;
+	unsigned long flags;
 	int rc;
+	unsigned long rate;
 
 	dprintk(3, "In Stream ON\n");
 	if (determine_mode(c_data) != c_data->op_mode) {
@@ -777,25 +1018,97 @@
 
 	switch (c_data->op_mode) {
 	case VC_VCAP_OP:
+		spin_lock_irqsave(&dev->dev_slock, flags);
+		if (dev->vc_resource) {
+			pr_err("VCAP Err: %s: VC resource taken", __func__);
+			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			return -EBUSY;
+		}
+		dev->vc_resource = 1;
+		spin_unlock_irqrestore(&dev->dev_slock, flags);
+
 		c_data->dev->vc_client = c_data;
+
+		if (!c_data->vc_format.clk_freq) {
+			rc = -EINVAL;
+			goto free_res;
+		}
+
+		rate = c_data->vc_format.clk_freq;
+		rate = clk_round_rate(dev->vcap_clk, rate);
+		if (rate <= 0) {
+			pr_err("%s: Failed core rnd_rate\n", __func__);
+			rc = -EINVAL;
+			goto free_res;
+		}
+		rc = clk_set_rate(dev->vcap_clk, rate);
+		if (rc < 0)
+			goto free_res;
+
+		rate = (c_data->vc_format.hactive_end -
+			c_data->vc_format.hactive_start);
+
+		if (c_data->vc_format.color_space)
+			rate *= 3;
+		else
+			rate *= 2;
+
+		rate *= (c_data->vc_format.vactive_end -
+			c_data->vc_format.vactive_start);
+		rate *= c_data->vc_format.frame_rate;
+		if (rate == 0)
+			goto free_res;
+
+		rc = request_bus_bw(dev, rate);
+		if (rc < 0)
+			goto free_res;
+
 		config_vc_format(c_data);
-		return vb2_streamon(&c_data->vc_vidq, i);
+		rc = vb2_streamon(&c_data->vc_vidq, i);
+		if (rc < 0)
+			goto free_res;
+		break;
 	case VP_VCAP_OP:
+		spin_lock_irqsave(&dev->dev_slock, flags);
+		if (dev->vp_resource) {
+			pr_err("VCAP Err: %s: VP resource taken", __func__);
+			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			return -EBUSY;
+		}
+		dev->vp_resource = 1;
+		spin_unlock_irqrestore(&dev->dev_slock, flags);
+		c_data->dev->vp_client = c_data;
+
+		rate = 160000000;
+		rate = clk_round_rate(dev->vcap_clk, rate);
+		if (rate <= 0) {
+			pr_err("%s: Failed core rnd_rate\n", __func__);
+			rc = -EINVAL;
+			goto free_res;
+		}
+		rc = clk_set_rate(dev->vcap_clk, rate);
+		if (rc < 0)
+			goto free_res;
+
+		rate = c_data->vp_out_fmt.width *
+			c_data->vp_out_fmt.height * 240;
+		rc = request_bus_bw(dev, rate);
+		if (rc < 0)
+			goto free_res;
+
 		rc = streamon_validate_q(&c_data->vp_in_vidq);
 		if (rc < 0)
-			return rc;
+			goto free_res;
 		rc = streamon_validate_q(&c_data->vp_out_vidq);
 		if (rc < 0)
-			return rc;
-
-		c_data->dev->vp_client = c_data;
+			goto free_res;
 
 		rc = config_vp_format(c_data);
 		if (rc < 0)
-			return rc;
+			goto free_res;
 		rc = init_motion_buf(c_data);
 		if (rc < 0)
-			return rc;
+			goto free_res;
 		if (c_data->vid_vp_action.nr_enabled) {
 			rc = init_nr_buf(c_data);
 			if (rc < 0)
@@ -803,6 +1116,7 @@
 		}
 
 		c_data->vid_vp_action.vp_state = VP_FRAME1;
+		c_data->streaming = 1;
 
 		rc = vb2_streamon(&c_data->vp_in_vidq,
 				V4L2_BUF_TYPE_INTERLACED_IN_DECODER);
@@ -813,39 +1127,85 @@
 				V4L2_BUF_TYPE_VIDEO_OUTPUT);
 		if (rc < 0)
 			goto s_on_deinit_nr_buf;
-		return rc;
+		break;
 	case VC_AND_VP_VCAP_OP:
+		spin_lock_irqsave(&dev->dev_slock, flags);
+		if (dev->vc_resource || dev->vp_resource) {
+			pr_err("VCAP Err: %s: VC/VP resource taken",
+				__func__);
+			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			return -EBUSY;
+		}
+		dev->vc_resource = 1;
+		dev->vp_resource = 1;
+		spin_unlock_irqrestore(&dev->dev_slock, flags);
+		c_data->dev->vc_client = c_data;
+		c_data->dev->vp_client = c_data;
+
+		if (!c_data->vc_format.clk_freq) {
+			rc = -EINVAL;
+			goto free_res;
+		}
+
+		rate = c_data->vc_format.clk_freq;
+		rate = clk_round_rate(dev->vcap_clk, rate);
+		if (rate <= 0) {
+			pr_err("%s: Failed core rnd_rate\n", __func__);
+			rc = -EINVAL;
+			goto free_res;
+		}
+		rc = clk_set_rate(dev->vcap_clk, rate);
+		if (rc < 0)
+			goto free_res;
+
+		rate = (c_data->vc_format.hactive_end -
+			c_data->vc_format.hactive_start);
+
+		if (c_data->vc_format.color_space)
+			rate *= 3;
+		else
+			rate *= 2;
+
+		rate *= (c_data->vc_format.vactive_end -
+			c_data->vc_format.vactive_start);
+		rate *= c_data->vc_format.frame_rate;
+		rate *= 2;
+		if (rate == 0)
+			goto free_res;
+
+		rc = request_bus_bw(dev, rate);
+		if (rc < 0)
+			goto free_res;
+
 		rc = streamon_validate_q(&c_data->vc_vidq);
 		if (rc < 0)
 			return rc;
 		rc = streamon_validate_q(&c_data->vp_in_vidq);
 		if (rc < 0)
-			return rc;
+			goto free_res;
 		rc = streamon_validate_q(&c_data->vp_out_vidq);
 		if (rc < 0)
-			return rc;
-
-		c_data->dev->vc_client = c_data;
-		c_data->dev->vp_client = c_data;
-		c_data->dev->vc_to_vp_work.cd = c_data;
+			goto free_res;
 
 		rc = config_vc_format(c_data);
 		if (rc < 0)
-			return rc;
+			goto free_res;
 		rc = config_vp_format(c_data);
 		if (rc < 0)
-			return rc;
+			goto free_res;
 		rc = init_motion_buf(c_data);
 		if (rc < 0)
-			return rc;
+			goto free_res;
+
 		if (c_data->vid_vp_action.nr_enabled) {
 			rc = init_nr_buf(c_data);
 			if (rc < 0)
 				goto s_on_deinit_m_buf;
 		}
-		c_data->streaming = 1;
 
+		c_data->dev->vc_to_vp_work.cd = c_data;
 		c_data->vid_vp_action.vp_state = VP_FRAME1;
+		c_data->streaming = 1;
 
 		/* These stream on calls should not fail */
 		rc = vb2_streamon(&c_data->vc_vidq,
@@ -862,7 +1222,7 @@
 				V4L2_BUF_TYPE_VIDEO_OUTPUT);
 		if (rc < 0)
 			goto s_on_deinit_nr_buf;
-		return rc;
+		break;
 	default:
 		pr_err("VCAP Error: %s: Operation Mode type", __func__);
 		return -ENOTRECOVERABLE;
@@ -874,6 +1234,21 @@
 		deinit_nr_buf(c_data);
 s_on_deinit_m_buf:
 	deinit_motion_buf(c_data);
+free_res:
+	spin_lock_irqsave(&dev->dev_slock, flags);
+	if (c_data->op_mode == VC_VCAP_OP) {
+		dev->vc_resource = 0;
+		c_data->dev->vc_client = NULL;
+	} else if (c_data->op_mode == VP_VCAP_OP) {
+		dev->vp_resource = 0;
+		c_data->dev->vp_client = NULL;
+	} else if (c_data->op_mode == VC_AND_VP_VCAP_OP) {
+		c_data->dev->vc_client = NULL;
+		c_data->dev->vp_client = NULL;
+		dev->vc_resource = 0;
+		dev->vp_resource = 0;
+	}
+	spin_unlock_irqrestore(&dev->dev_slock, flags);
 	return rc;
 }
 
@@ -893,22 +1268,51 @@
 
 static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 {
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
+	struct vcap_dev *dev = c_data->dev;
+	unsigned long flags;
 	int rc;
 
 	switch (c_data->op_mode) {
 	case VC_VCAP_OP:
+		if (c_data != dev->vc_client) {
+			pr_err("VCAP Err: %s: VC held by other client",
+				__func__);
+			return -EBUSY;
+		}
+		spin_lock_irqsave(&dev->dev_slock, flags);
+		if (!dev->vc_resource) {
+			pr_err("VCAP Err: %s: VC res not acquired", __func__);
+			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			return -EBUSY;
+		}
+		dev->vc_resource = 0;
+		spin_unlock_irqrestore(&dev->dev_slock, flags);
 		rc = vb2_streamoff(&c_data->vc_vidq, i);
 		if (rc >= 0)
 			atomic_set(&c_data->dev->vc_enabled, 0);
 		return rc;
 	case VP_VCAP_OP:
+		if (c_data != dev->vp_client) {
+			pr_err("VCAP Err: %s: VP held by other client",
+				__func__);
+			return -EBUSY;
+		}
+		spin_lock_irqsave(&dev->dev_slock, flags);
+		if (!dev->vp_resource) {
+			pr_err("VCAP Err: %s: VP res not acquired", __func__);
+			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			return -EBUSY;
+		}
+		dev->vp_resource = 0;
+		spin_unlock_irqrestore(&dev->dev_slock, flags);
 		rc = streamoff_validate_q(&c_data->vp_in_vidq);
 		if (rc < 0)
 			return rc;
 		rc = streamoff_validate_q(&c_data->vp_out_vidq);
 		if (rc < 0)
 			return rc;
+		c_data->streaming = 0;
 
 		/* These stream on calls should not fail */
 		rc = vb2_streamoff(&c_data->vp_in_vidq,
@@ -927,6 +1331,21 @@
 		atomic_set(&c_data->dev->vp_enabled, 0);
 		return rc;
 	case VC_AND_VP_VCAP_OP:
+		if (c_data != dev->vp_client || c_data != dev->vc_client) {
+			pr_err("VCAP Err: %s: VC/VP held by other client",
+				__func__);
+			return -EBUSY;
+		}
+		spin_lock_irqsave(&dev->dev_slock, flags);
+		if (!(dev->vc_resource || dev->vp_resource)) {
+			pr_err("VCAP Err: %s: VC or VP res not acquired",
+				__func__);
+			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			return -EBUSY;
+		}
+		dev->vc_resource = 0;
+		dev->vp_resource = 0;
+		spin_unlock_irqrestore(&dev->dev_slock, flags);
 		rc = streamoff_validate_q(&c_data->vc_vidq);
 		if (rc < 0)
 			return rc;
@@ -967,6 +1386,36 @@
 	return 0;
 }
 
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+			struct v4l2_event_subscription *sub)
+{
+	int rc;
+	if (sub->type == V4L2_EVENT_ALL) {
+		sub->type = V4L2_EVENT_PRIVATE_START +
+				VCAP_GENERIC_NOTIFY_EVENT;
+		sub->id = 0;
+		do {
+			rc = v4l2_event_subscribe(fh, sub, 16);
+			if (rc < 0) {
+				sub->type = V4L2_EVENT_ALL;
+				v4l2_event_unsubscribe(fh, sub);
+				return rc;
+			}
+			sub->type++;
+		} while (sub->type !=
+			V4L2_EVENT_PRIVATE_START + VCAP_MAX_NOTIFY_EVENT);
+	} else {
+		rc = v4l2_event_subscribe(fh, sub, 16);
+	}
+	return rc;
+}
+
+static int vidioc_unsubscribe_event(struct v4l2_fh *fh,
+			struct v4l2_event_subscription *sub)
+{
+	return v4l2_event_unsubscribe(fh, sub);
+}
+
 /* VCAP fops */
 static void *vcap_ops_get_userptr(void *alloc_ctx, unsigned long vaddr,
 					unsigned long size, int write)
@@ -995,6 +1444,7 @@
 	struct vcap_dev *dev = video_drvdata(file);
 	struct vcap_client_data *c_data;
 	struct vb2_queue *q;
+	unsigned long flags;
 	int ret;
 	c_data = kzalloc(sizeof(*c_data), GFP_KERNEL);
 	if (!dev)
@@ -1047,10 +1497,29 @@
 	INIT_LIST_HEAD(&c_data->vid_vc_action.active);
 	INIT_LIST_HEAD(&c_data->vid_vp_action.in_active);
 	INIT_LIST_HEAD(&c_data->vid_vp_action.out_active);
-	file->private_data = c_data;
 
+	v4l2_fh_init(&c_data->vfh, dev->vfd);
+	v4l2_fh_add(&c_data->vfh);
+
+	spin_lock_irqsave(&dev->dev_slock, flags);
+	atomic_inc(&dev->open_clients);
+	ret = atomic_read(&dev->open_clients);
+	spin_unlock_irqrestore(&dev->dev_slock, flags);
+	if (ret == 1) {
+		ret = vcap_enable(dev, dev->ddev, 54860000);
+		if (ret < 0) {
+			pr_err("Err: %s: Power on vcap failed", __func__);
+			goto vcap_power_failed;
+		}
+	}
+
+	file->private_data = &c_data->vfh;
 	return 0;
 
+vcap_power_failed:
+	v4l2_fh_del(&c_data->vfh);
+	v4l2_fh_exit(&c_data->vfh);
+	vb2_queue_release(&c_data->vp_out_vidq);
 vp_out_q_failed:
 	vb2_queue_release(&c_data->vp_in_vidq);
 vp_in_q_failed:
@@ -1062,12 +1531,29 @@
 
 static int vcap_close(struct file *file)
 {
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_dev *dev = video_drvdata(file);
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
+	unsigned long flags;
+	int ret;
+
+	if (c_data == NULL)
+		return 0;
+
+	spin_lock_irqsave(&dev->dev_slock, flags);
+	atomic_dec(&dev->open_clients);
+	ret = atomic_read(&dev->open_clients);
+	spin_unlock_irqrestore(&dev->dev_slock, flags);
+	if (ret == 0)
+		vcap_disable(dev);
+	v4l2_fh_del(&c_data->vfh);
+	v4l2_fh_exit(&c_data->vfh);
 	vb2_queue_release(&c_data->vp_out_vidq);
 	vb2_queue_release(&c_data->vp_in_vidq);
 	vb2_queue_release(&c_data->vc_vidq);
-	c_data->dev->vc_client = NULL;
-	c_data->dev->vp_client = NULL;
+	if (c_data->dev->vc_client == c_data)
+		c_data->dev->vc_client = NULL;
+	if (c_data->dev->vp_client == c_data)
+		c_data->dev->vp_client = NULL;
 	kfree(c_data);
 	return 0;
 }
@@ -1103,29 +1589,35 @@
 static unsigned int vcap_poll(struct file *file,
 				  struct poll_table_struct *wait)
 {
-	struct vcap_client_data *c_data = file->private_data;
+	struct vcap_client_data *c_data = to_client_data(file->private_data);
 	struct vb2_queue *q;
 	unsigned int mask = 0;
 
+	dprintk(1, "Enter slect/poll\n");
+
 	switch (c_data->op_mode) {
 	case VC_VCAP_OP:
 		q = &c_data->vc_vidq;
-		return vb2_poll(q, file, wait);
+		mask = vb2_poll(q, file, wait);
+		break;
 	case VP_VCAP_OP:
 		q = &c_data->vp_in_vidq;
 		mask = poll_work(q, file, wait, 0);
 		q = &c_data->vp_out_vidq;
 		mask |= poll_work(q, file, wait, 1);
-		return mask;
+		break;
 	case VC_AND_VP_VCAP_OP:
 		q = &c_data->vp_out_vidq;
 		mask = poll_work(q, file, wait, 0);
-		return mask;
+		break;
 	default:
 		pr_err("VCAP Error: %s: Unknown operation mode", __func__);
 		return POLLERR;
 	}
-	return 0;
+	if (v4l2_event_pending(&c_data->vfh))
+		mask |= POLLPRI;
+	poll_wait(file, &(c_data->vfh.wait), wait);
+	return mask;
 }
 /* V4L2 and video device structures */
 
@@ -1153,6 +1645,9 @@
 	.vidioc_dqbuf         = vidioc_dqbuf,
 	.vidioc_streamon      = vidioc_streamon,
 	.vidioc_streamoff     = vidioc_streamoff,
+
+	.vidioc_subscribe_event = vidioc_subscribe_event,
+	.vidioc_unsubscribe_event = vidioc_unsubscribe_event,
 };
 
 static struct video_device vcap_template = {
@@ -1162,220 +1657,6 @@
 	.release	= video_device_release,
 };
 
-int vcap_reg_powerup(struct vcap_dev *dev)
-{
-	dev->fs_vcap = regulator_get(NULL, "fs_vcap");
-	if (IS_ERR(dev->fs_vcap)) {
-		pr_err("%s: Regulator FS_VCAP get failed %ld\n", __func__,
-			PTR_ERR(dev->fs_vcap));
-		dev->fs_vcap = NULL;
-		return -EINVAL;
-	} else if (regulator_enable(dev->fs_vcap)) {
-		pr_err("%s: Regulator FS_VCAP enable failed\n", __func__);
-		regulator_put(dev->fs_vcap);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-void vcap_reg_powerdown(struct vcap_dev *dev)
-{
-	if (dev->fs_vcap == NULL)
-		return;
-	regulator_disable(dev->fs_vcap);
-	regulator_put(dev->fs_vcap);
-	dev->fs_vcap = NULL;
-	return;
-}
-
-int config_gpios(int on, struct vcap_platform_data *pdata)
-{
-	int i, ret;
-	int num_gpios = pdata->num_gpios;
-	unsigned *gpios = pdata->gpios;
-
-	if (on) {
-		for (i = 0; i < num_gpios; i++) {
-			ret = gpio_request(gpios[i], "vcap:vc");
-			if (ret) {
-				pr_err("VCAP: failed at GPIO %d to request\n",
-						gpios[i]);
-				goto gpio_failed;
-			}
-			ret = gpio_direction_input(gpios[i]);
-			if (ret) {
-				pr_err("VCAP: failed at GPIO %d to set to input\n",
-					gpios[i]);
-				i++;
-				goto gpio_failed;
-			}
-		}
-	} else {
-		for (i = 0; i < num_gpios; i++)
-			gpio_free(gpios[i]);
-	}
-	dprintk(2, "GPIO config done\n");
-	return 0;
-gpio_failed:
-	for (i--; i >= 0; i--)
-		gpio_free(gpios[i]);
-	return -EINVAL;
-}
-
-int vcap_clk_powerup(struct vcap_dev *dev, struct device *ddev)
-{
-	int ret = 0;
-
-	dev->vcap_clk = clk_get(ddev, "core_clk");
-	if (IS_ERR(dev->vcap_clk)) {
-		dev->vcap_clk = NULL;
-		pr_err("%s: Could not clk_get core_clk\n", __func__);
-		clk_put(dev->vcap_clk);
-		dev->vcap_clk = NULL;
-		return -EINVAL;
-	}
-
-	clk_prepare(dev->vcap_clk);
-	ret = clk_enable(dev->vcap_clk);
-	if (ret) {
-		pr_err("%s: Failed core clk_enable %d\n", __func__, ret);
-		goto fail_vcap_clk_unprep;
-	}
-
-	clk_set_rate(dev->vcap_clk, 160000000);
-	if (ret) {
-		pr_err("%s: Failed core set_rate %d\n", __func__, ret);
-		goto fail_vcap_clk;
-	}
-
-	dev->vcap_npl_clk = clk_get(ddev, "vcap_npl_clk");
-	if (IS_ERR(dev->vcap_npl_clk)) {
-		dev->vcap_npl_clk = NULL;
-		pr_err("%s: Could not clk_get npl\n", __func__);
-		clk_put(dev->vcap_npl_clk);
-		dev->vcap_npl_clk = NULL;
-		goto fail_vcap_clk;
-	}
-
-	clk_prepare(dev->vcap_npl_clk);
-	ret = clk_enable(dev->vcap_npl_clk);
-	if (ret) {
-		pr_err("%s:Failed npl clk_enable %d\n", __func__, ret);
-		goto fail_vcap_npl_clk_unprep;
-	}
-
-	dev->vcap_p_clk = clk_get(ddev, "iface_clk");
-	if (IS_ERR(dev->vcap_p_clk)) {
-		dev->vcap_p_clk = NULL;
-		pr_err("%s: Could not clk_get pix(AHB)\n", __func__);
-		clk_put(dev->vcap_p_clk);
-		dev->vcap_p_clk = NULL;
-		goto fail_vcap_npl_clk;
-	}
-
-	clk_prepare(dev->vcap_p_clk);
-	ret = clk_enable(dev->vcap_p_clk);
-	if (ret) {
-		pr_err("%s: Failed pix(AHB) clk_enable %d\n", __func__, ret);
-		goto fail_vcap_p_clk_unprep;
-	}
-	return 0;
-
-fail_vcap_p_clk_unprep:
-	clk_unprepare(dev->vcap_p_clk);
-	clk_put(dev->vcap_p_clk);
-	dev->vcap_p_clk = NULL;
-
-fail_vcap_npl_clk:
-	clk_disable(dev->vcap_npl_clk);
-fail_vcap_npl_clk_unprep:
-	clk_unprepare(dev->vcap_npl_clk);
-	clk_put(dev->vcap_npl_clk);
-	dev->vcap_npl_clk = NULL;
-
-fail_vcap_clk:
-	clk_disable(dev->vcap_clk);
-fail_vcap_clk_unprep:
-	clk_unprepare(dev->vcap_clk);
-	clk_put(dev->vcap_clk);
-	dev->vcap_clk = NULL;
-	return -EINVAL;
-}
-
-void vcap_clk_powerdown(struct vcap_dev *dev)
-{
-	if (dev->vcap_p_clk != NULL) {
-		clk_disable(dev->vcap_p_clk);
-		clk_unprepare(dev->vcap_p_clk);
-		clk_put(dev->vcap_p_clk);
-		dev->vcap_p_clk = NULL;
-	}
-
-	if (dev->vcap_npl_clk != NULL) {
-		clk_disable(dev->vcap_npl_clk);
-		clk_unprepare(dev->vcap_npl_clk);
-		clk_put(dev->vcap_npl_clk);
-		dev->vcap_npl_clk = NULL;
-	}
-
-	if (dev->vcap_clk != NULL) {
-		clk_disable(dev->vcap_clk);
-		clk_unprepare(dev->vcap_clk);
-		clk_put(dev->vcap_clk);
-		dev->vcap_clk = NULL;
-	}
-}
-
-int vcap_get_bus_client_handle(struct vcap_dev *dev)
-{
-	struct msm_bus_scale_pdata *vcap_axi_client_pdata =
-			dev->vcap_pdata->bus_client_pdata;
-	dev->bus_client_handle =
-			msm_bus_scale_register_client(vcap_axi_client_pdata);
-
-	return 0;
-}
-
-int vcap_enable(struct vcap_dev *dev, struct device *ddev)
-{
-	int rc;
-
-	rc = vcap_reg_powerup(dev);
-	if (rc < 0)
-		goto reg_failed;
-	rc = vcap_clk_powerup(dev, ddev);
-	if (rc < 0)
-		goto clk_failed;
-	rc = vcap_get_bus_client_handle(dev);
-	if (rc < 0)
-		goto bus_r_failed;
-	config_gpios(1, dev->vcap_pdata);
-	if (rc < 0)
-		goto gpio_failed;
-	return 0;
-
-gpio_failed:
-	msm_bus_scale_unregister_client(dev->bus_client_handle);
-	dev->bus_client_handle = 0;
-bus_r_failed:
-	vcap_clk_powerdown(dev);
-clk_failed:
-	vcap_reg_powerdown(dev);
-reg_failed:
-	return rc;
-}
-
-int vcap_disable(struct vcap_dev *dev)
-{
-	config_gpios(0, dev->vcap_pdata);
-
-	msm_bus_scale_unregister_client(dev->bus_client_handle);
-	dev->bus_client_handle = 0;
-	vcap_clk_powerdown(dev);
-	vcap_reg_powerdown(dev);
-	return 0;
-}
-
 static irqreturn_t vcap_vp_handler(int irq_num, void *data)
 {
 	return vp_handler(vcap_ctrl);
@@ -1465,10 +1746,10 @@
 	if (ret)
 		goto free_resource;
 
-	ret = vcap_enable(dev, &pdev->dev);
+	ret = vcap_enable(dev, &pdev->dev, 54860000);
 	if (ret)
 		goto unreg_dev;
-	msm_bus_scale_client_update_request(dev->bus_client_handle, 3);
+	msm_bus_scale_client_update_request(dev->bus_client_handle, 0);
 
 	ret = detect_vc(dev);
 
@@ -1504,6 +1785,10 @@
 
 	atomic_set(&dev->vc_enabled, 0);
 	atomic_set(&dev->vp_enabled, 0);
+	atomic_set(&dev->open_clients, 0);
+	dev->ddev = &pdev->dev;
+	spin_lock_init(&dev->dev_slock);
+	vcap_disable(dev);
 
 	dprintk(1, "Exit probe succesfully");
 	return 0;
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 2c4a243..ad0718e 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -22,6 +22,7 @@
 #include <mach/clk.h>
 #include <linux/clk.h>
 
+#include <media/v4l2-event.h>
 #include <media/vcap_v4l2.h>
 #include <media/vcap_fmt.h>
 #include "vcap_vc.h"
@@ -113,14 +114,40 @@
 	struct vcap_buffer *buf;
 	struct vb2_buffer *vb = NULL;
 	struct vcap_client_data *c_data;
-
+	struct v4l2_event v4l2_evt;
 
 	irq = readl_relaxed(VCAP_VC_INT_STATUS);
 
 	dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
 
-	vc_buf_status = irq & VC_BUFFER_WRITTEN;
+	v4l2_evt.id = 0;
+	if (irq & 0x8000200) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VC_PIX_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
+	if (irq & 0x40000200) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VC_LINE_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
+	if (irq & 0x20000200) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VC_VSYNC_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
+	if (irq & 0x00000800) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VC_NPL_OFLOW_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
+	if (irq & 0x00000400) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VC_LBUF_OFLOW_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
 
+	vc_buf_status = irq & VC_BUFFER_WRITTEN;
 	dprintk(1, "Done buf status = %d\n", vc_buf_status);
 
 	if (vc_buf_status == VC_NO_BUF) {
@@ -139,8 +166,11 @@
 	spin_lock(&dev->vc_client->cap_slock);
 	if (list_empty(&dev->vc_client->vid_vc_action.active)) {
 		/* Just leave we have no new queued buffers */
-		writel_relaxed(irq, VCAP_VC_INT_CLEAR);
 		spin_unlock(&dev->vc_client->cap_slock);
+		writel_relaxed(irq, VCAP_VC_INT_CLEAR);
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VC_BUF_OVERWRITE_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
 		dprintk(1, "We have no more avilable buffers\n");
 		return IRQ_HANDLED;
 	}
@@ -166,6 +196,9 @@
 		spin_lock(&dev->vc_client->cap_slock);
 		if (list_empty(&dev->vc_client->vid_vc_action.active)) {
 			spin_unlock(&dev->vc_client->cap_slock);
+			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+				VCAP_VC_BUF_OVERWRITE_EVENT;
+			v4l2_event_queue(dev->vfd, &v4l2_evt);
 			writel_relaxed(irq, VCAP_VC_INT_CLEAR);
 			return IRQ_HANDLED;
 		}
@@ -187,8 +220,11 @@
 		spin_lock(&dev->vc_client->cap_slock);
 		vb = &dev->vc_client->vid_vc_action.buf2->vb;
 		if (list_empty(&dev->vc_client->vid_vc_action.active)) {
-			writel_relaxed(irq, VCAP_VC_INT_CLEAR);
 			spin_unlock(&dev->vc_client->cap_slock);
+			writel_relaxed(irq, VCAP_VC_INT_CLEAR);
+			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+				VCAP_VC_BUF_OVERWRITE_EVENT;
+			v4l2_event_queue(dev->vfd, &v4l2_evt);
 			return IRQ_HANDLED;
 		}
 		buf = list_entry(dev->vc_client->vid_vc_action.active.next,
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index f8dfdc1..1b503ba 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -20,6 +20,7 @@
 #include <mach/clk.h>
 #include <linux/clk.h>
 
+#include <media/v4l2-event.h>
 #include <media/vcap_v4l2.h>
 #include <media/vcap_fmt.h>
 #include "vcap_vp.h"
@@ -254,13 +255,35 @@
 {
 	struct vcap_client_data *c_data;
 	struct vp_action *vp_act;
+	struct v4l2_event v4l2_evt;
 	uint32_t irq;
 	int rc;
 
 	irq = readl_relaxed(VCAP_VP_INT_STATUS);
 
+	if (irq & 0x02000000) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VP_REG_R_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
+	if (irq & 0x01000000) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VC_LINE_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
+	if (irq & 0x00020000) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VP_IN_HEIGHT_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
+	if (irq & 0x00010000) {
+		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+			VCAP_VP_IN_WIDTH_ERR_EVENT;
+		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	}
+
 	dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
-	if (!irq & VP_PIC_DONE) {
+	if (!(irq & VP_PIC_DONE)) {
 		writel_relaxed(irq, VCAP_VP_INT_CLEAR);
 		pr_err("VP IRQ shows some error\n");
 		return IRQ_HANDLED;
@@ -530,7 +553,7 @@
 			chroma_fmt << 11 | 0x2 << 4, VCAP_VP_IN_CONFIG);
 
 	chroma_fmt = 0;
-	if (c_data->vp_in_fmt.pixfmt == V4L2_PIX_FMT_NV16)
+	if (c_data->vp_out_fmt.pixfmt == V4L2_PIX_FMT_NV16)
 		chroma_fmt = 1;
 
 	writel_relaxed((c_data->vp_in_fmt.width / 16) << 20 |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f4e7fda..8c392fc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1043,6 +1043,18 @@
           read/write capability to registers which are part of the
           WCD9310 core and gives the ability to use the WCD9310 codec.
 
+config WCD9320_CODEC
+	tristate "WCD9320 Codec"
+	select SLIMBUS
+	select MFD_CORE
+	help
+	  Enables the WCD9xxx codec core driver. The core driver provides
+	  read/write capability to registers which are part of the
+	  WCD9320 core and gives the ability to use the WCD9320 codec.
+	  The WCD9320 codec support either I2C/I2S or Slimbus for
+	  control and data exchnage with master processor.
+
+
 config MFD_RC5T583
 	bool "Ricoh RC5T583 Power Management system device"
 	depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 099e45f..07552c8 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -80,6 +80,8 @@
 
 obj-$(CONFIG_WCD9310_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
 obj-$(CONFIG_WCD9304_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
+obj-$(CONFIG_WCD9320_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
+
 
 ifeq ($(CONFIG_SA1100_ASSABET),y)
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-assabet.o
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index 4271a2a..8fef786 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -36,6 +36,9 @@
 #define REG_SPK_BASE		0x253
 #define REG_SPK_REGISTERS	3
 
+#define REG_TEMP_ALARM_CTRL	0x01B
+#define REG_TEMP_ALARM_PWM	0x09B
+
 #define PM8038_VERSION_MASK	0xFFF0
 #define PM8038_VERSION_VALUE	0x09F0
 #define PM8038_REVISION_MASK	0x000F
@@ -300,6 +303,30 @@
 	.pdata_size	= sizeof("pm8038-dbg"),
 };
 
+static const struct resource thermal_alarm_cell_resources[] __devinitconst = {
+	SINGLE_IRQ_RESOURCE("pm8038_tempstat_irq", PM8038_TEMPSTAT_IRQ),
+	SINGLE_IRQ_RESOURCE("pm8038_overtemp_irq", PM8038_OVERTEMP_IRQ),
+};
+
+static struct pm8xxx_tm_core_data thermal_alarm_cdata = {
+	.adc_channel			= CHANNEL_DIE_TEMP,
+	.adc_type			= PM8XXX_TM_ADC_PM8XXX_ADC,
+	.reg_addr_temp_alarm_ctrl	= REG_TEMP_ALARM_CTRL,
+	.reg_addr_temp_alarm_pwm	= REG_TEMP_ALARM_PWM,
+	.tm_name			= "pm8038_tz",
+	.irq_name_temp_stat		= "pm8038_tempstat_irq",
+	.irq_name_over_temp		= "pm8038_overtemp_irq",
+};
+
+static struct mfd_cell thermal_alarm_cell __devinitdata = {
+	.name		= PM8XXX_TM_DEV_NAME,
+	.id		= -1,
+	.resources	= thermal_alarm_cell_resources,
+	.num_resources	= ARRAY_SIZE(thermal_alarm_cell_resources),
+	.platform_data	= &thermal_alarm_cdata,
+	.pdata_size	= sizeof(struct pm8xxx_tm_core_data),
+};
+
 static struct pm8xxx_vreg regulator_data[] = {
 	/*   name	     pc_name	    ctrl   test   hpm_min */
 	NLDO1200("8038_l1",		    0x0AE, 0x0AF, LDO_1200),
@@ -606,6 +633,14 @@
 			goto bail;
 		}
 	}
+
+	ret = mfd_add_devices(pmic->dev, 0, &thermal_alarm_cell, 1, NULL,
+				irq_base);
+	if (ret) {
+		pr_err("Failed to add thermal alarm subdevice ret=%d\n", ret);
+		goto bail;
+	}
+
 	return 0;
 bail:
 	if (pmic->irq_chip) {
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 705a57b..889c416 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -472,6 +472,12 @@
 		grph = rx[idx].grph;
 	}
 
+	/* slim_disconnect_port */
+	ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
+	if (ret < 0) {
+		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+				__func__, ret);
+	}
 	/* slim_control_ch (REMOVE) */
 	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
 	if (ret < 0) {
@@ -510,6 +516,12 @@
 		sph[i] = tx[idx].sph;
 		grph = tx[idx].grph;
 	}
+	/* slim_disconnect_port */
+	ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
+	if (ret < 0) {
+		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+				__func__, ret);
+	}
 	/* slim_control_ch (REMOVE) */
 	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
 	if (ret < 0) {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1c2f018..3c28447 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -628,14 +628,6 @@
 	  PMIC8058. Driver interface to program registers of the ADC over
 	  AMUX channels, devices on programmable MPP's and xotherm.
 
-config TZCOM
-	tristate "Trustzone Communicator driver"
-	default n
-	help
-	  Provides a communication interface between userspace and
-	  TrustZone Operating Environment (TZBSP) using Secure Channel
-	  Manager (SCM) interface.
-
 config QSEECOM
 	tristate "Qualcomm Secure Execution Communicator driver"
 	help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b628976..be3d0a0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -69,6 +69,5 @@
 obj-$(CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN) \
 	+= msm_migrate_pages.o
 obj-$(CONFIG_PMIC8058_XOADC) += pmic8058-xoadc.o
-obj-$(CONFIG_TZCOM) += tzcom.o
 obj-$(CONFIG_QSEECOM) += qseecom.o
 obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 4c92ee5..d5afe8d 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1717,19 +1717,22 @@
 	}
 
 	/* register client for bus scaling */
-	qseecom_platform_support = (struct msm_bus_scale_pdata *)
-					pdev->dev.platform_data;
-	qsee_perf_client = msm_bus_scale_register_client(
-					qseecom_platform_support);
-	if (!qsee_perf_client) {
-		pr_err("Unable to register bus client\n");
-	} else {
-		qseecom_bus_clk = clk_get(class_dev, "bus_clk");
-		if (IS_ERR(qseecom_bus_clk)) {
-			qseecom_bus_clk = NULL;
-		} else if (qseecom_bus_clk != NULL) {
-			pr_debug("Enabled DFAB clock");
-			clk_set_rate(qseecom_bus_clk, 64000000);
+	if (!pdev->dev.of_node) {
+		qseecom_platform_support = (struct msm_bus_scale_pdata *)
+						pdev->dev.platform_data;
+		qsee_perf_client = msm_bus_scale_register_client(
+						qseecom_platform_support);
+
+		if (!qsee_perf_client) {
+			pr_err("Unable to register bus client\n");
+		} else {
+			qseecom_bus_clk = clk_get(class_dev, "bus_clk");
+			if (IS_ERR(qseecom_bus_clk)) {
+				qseecom_bus_clk = NULL;
+			} else if (qseecom_bus_clk != NULL) {
+				pr_debug("Enabled DFAB clock");
+				clk_set_rate(qseecom_bus_clk, 64000000);
+			}
 		}
 	}
 	return 0;
@@ -1750,12 +1753,20 @@
 	return 0;
 };
 
+static struct of_device_id qseecom_match[] = {
+	{
+		.compatible = "qcom,qseecom",
+	},
+	{}
+};
+
 static struct platform_driver qseecom_plat_driver = {
 	.probe = qseecom_probe,
 	.remove = qseecom_remove,
 	.driver = {
 		.name = "qseecom",
 		.owner = THIS_MODULE,
+		.of_match_table = qseecom_match,
 	},
 };
 
diff --git a/drivers/misc/tzcom.c b/drivers/misc/tzcom.c
deleted file mode 100644
index 3b943c8..0000000
--- a/drivers/misc/tzcom.c
+++ /dev/null
@@ -1,1248 +0,0 @@
-/* Qualcomm TrustZone communicator driver
- *
- * 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.
- */
-
-#define KMSG_COMPONENT "TZCOM"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <linux/cdev.h>
-#include <linux/uaccess.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/android_pmem.h>
-#include <linux/io.h>
-#include <linux/ion.h>
-#include <linux/tzcom.h>
-#include <linux/clk.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
-#include <mach/socinfo.h>
-#include "tzcomi.h"
-
-#define TZCOM_DEV "tzcom"
-
-#define TZSCHEDULER_CMD_ID 1 /* CMD id of the trustzone scheduler */
-
-#undef PDEBUG
-#define PDEBUG(fmt, args...) pr_debug("%s(%i, %s): " fmt "\n", \
-		__func__, current->pid, current->comm, ## args)
-
-#undef PERR
-#define PERR(fmt, args...) pr_err("%s(%i, %s): " fmt "\n", \
-		__func__, current->pid, current->comm, ## args)
-
-#undef PWARN
-#define PWARN(fmt, args...) pr_warning("%s(%i, %s): " fmt "\n", \
-		__func__, current->pid, current->comm, ## args)
-
-
-static uint32_t tzcom_perf_client;
-static struct class *driver_class;
-static dev_t tzcom_device_no;
-static struct cdev tzcom_cdev;
-struct ion_client *ion_clnt;
-static u8 *sb_in_virt;
-static s32 sb_in_phys;
-static size_t sb_in_length = 20 * SZ_1K;
-static u8 *sb_out_virt;
-static s32 sb_out_phys;
-static size_t sb_out_length = 20 * SZ_1K;
-
-static void *pil;
-
-static atomic_t svc_instance_ctr = ATOMIC_INIT(0);
-static DEFINE_MUTEX(sb_in_lock);
-static DEFINE_MUTEX(sb_out_lock);
-static DEFINE_MUTEX(send_cmd_lock);
-static DEFINE_MUTEX(tzcom_bw_mutex);
-static int tzcom_bw_count;
-static struct clk *tzcom_bus_clk;
-struct tzcom_callback_list {
-	struct list_head      list;
-	struct tzcom_callback callback;
-};
-
-struct tzcom_registered_svc_list {
-	struct list_head                 list;
-	struct tzcom_register_svc_op_req svc;
-	wait_queue_head_t                next_cmd_wq;
-	int                              next_cmd_flag;
-};
-
-struct tzcom_data_t {
-	struct list_head  callback_list_head;
-	struct mutex      callback_list_lock;
-	struct list_head  registered_svc_list_head;
-	spinlock_t        registered_svc_list_lock;
-	wait_queue_head_t cont_cmd_wq;
-	int               cont_cmd_flag;
-	u32               handled_cmd_svc_instance_id;
-	int               abort;
-	wait_queue_head_t abort_wq;
-	atomic_t          ioctl_count;
-};
-
-static int tzcom_enable_bus_scaling(void)
-{
-	int ret = 0;
-	if (!tzcom_perf_client)
-		return -EINVAL;
-
-	if (IS_ERR_OR_NULL(tzcom_bus_clk))
-		return -EINVAL;
-
-	mutex_lock(&tzcom_bw_mutex);
-	if (!tzcom_bw_count) {
-		ret = msm_bus_scale_client_update_request(
-				tzcom_perf_client, 1);
-		if (ret) {
-			pr_err("Bandwidth request failed (%d)\n", ret);
-		} else {
-			ret = clk_enable(tzcom_bus_clk);
-			if (ret)
-				pr_err("Clock enable failed\n");
-		}
-	}
-	if (ret)
-		msm_bus_scale_client_update_request(tzcom_perf_client, 0);
-	else
-		tzcom_bw_count++;
-	mutex_unlock(&tzcom_bw_mutex);
-	return ret;
-}
-
-static void tzcom_disable_bus_scaling(void)
-{
-	if (!tzcom_perf_client)
-		return ;
-
-	if (IS_ERR_OR_NULL(tzcom_bus_clk))
-		return ;
-
-	mutex_lock(&tzcom_bw_mutex);
-	if (tzcom_bw_count > 0)
-		if (tzcom_bw_count-- == 1) {
-			msm_bus_scale_client_update_request(tzcom_perf_client,
-								0);
-			clk_disable(tzcom_bus_clk);
-		}
-	mutex_unlock(&tzcom_bw_mutex);
-}
-
-static int tzcom_scm_call(const void *cmd_buf, size_t cmd_len,
-		void *resp_buf, size_t resp_len)
-{
-	return scm_call(SCM_SVC_TZSCHEDULER, TZSCHEDULER_CMD_ID,
-			cmd_buf, cmd_len, resp_buf, resp_len);
-}
-
-static s32 tzcom_virt_to_phys(u8 *virt)
-{
-	if (virt >= sb_in_virt &&
-			virt < (sb_in_virt + sb_in_length)) {
-		return sb_in_phys + (virt - sb_in_virt);
-	} else if (virt >= sb_out_virt &&
-			virt < (sb_out_virt + sb_out_length)) {
-		return sb_out_phys + (virt - sb_out_virt);
-	} else {
-		return virt_to_phys(virt);
-	}
-}
-
-static u8 *tzcom_phys_to_virt(s32 phys)
-{
-	if (phys >= sb_in_phys &&
-			phys < (sb_in_phys + sb_in_length)) {
-		return sb_in_virt + (phys - sb_in_phys);
-	} else if (phys >= sb_out_phys &&
-			phys < (sb_out_phys + sb_out_length)) {
-		return sb_out_virt + (phys - sb_out_phys);
-	} else {
-		return phys_to_virt(phys);
-	}
-}
-
-static int __tzcom_is_svc_unique(struct tzcom_data_t *data,
-		struct tzcom_register_svc_op_req svc)
-{
-	struct tzcom_registered_svc_list *ptr;
-	int unique = 1;
-	unsigned long flags;
-
-	spin_lock_irqsave(&data->registered_svc_list_lock, flags);
-	list_for_each_entry(ptr, &data->registered_svc_list_head, list) {
-		if (ptr->svc.svc_id == svc.svc_id) {
-			PERR("Service id: %u is already registered",
-					ptr->svc.svc_id);
-			unique = 0;
-			break;
-		} else if (svc.cmd_id_low >= ptr->svc.cmd_id_low &&
-				svc.cmd_id_low <= ptr->svc.cmd_id_high) {
-			PERR("Cmd id low falls in the range of another"
-					"registered service");
-			unique = 0;
-			break;
-		} else if (svc.cmd_id_high >= ptr->svc.cmd_id_low &&
-				svc.cmd_id_high <= ptr->svc.cmd_id_high) {
-			PERR("Cmd id high falls in the range of another"
-					"registered service");
-			unique = 0;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-	return unique;
-}
-
-static int tzcom_register_service(struct tzcom_data_t *data, void __user *argp)
-{
-	int ret;
-	unsigned long flags;
-	struct tzcom_register_svc_op_req rcvd_svc;
-	struct tzcom_registered_svc_list *new_entry;
-
-	ret = copy_from_user(&rcvd_svc, argp, sizeof(rcvd_svc));
-
-	if (ret) {
-		PERR("copy_from_user failed");
-		return ret;
-	}
-
-	PDEBUG("svc_id: %u, cmd_id_low: %u, cmd_id_high: %u",
-			rcvd_svc.svc_id, rcvd_svc.cmd_id_low,
-			rcvd_svc.cmd_id_high);
-	if (!__tzcom_is_svc_unique(data, rcvd_svc)) {
-		PERR("Provided service is not unique");
-		return -EINVAL;
-	}
-
-	rcvd_svc.instance_id = atomic_inc_return(&svc_instance_ctr);
-
-	ret = copy_to_user(argp, &rcvd_svc, sizeof(rcvd_svc));
-	if (ret) {
-		PERR("copy_to_user failed");
-		return ret;
-	}
-
-	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
-	if (!new_entry) {
-		PERR("kmalloc failed");
-		return -ENOMEM;
-	}
-	memcpy(&new_entry->svc, &rcvd_svc, sizeof(rcvd_svc));
-	new_entry->next_cmd_flag = 0;
-	init_waitqueue_head(&new_entry->next_cmd_wq);
-
-	spin_lock_irqsave(&data->registered_svc_list_lock, flags);
-	list_add_tail(&new_entry->list, &data->registered_svc_list_head);
-	spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-
-
-	return ret;
-}
-
-static int tzcom_unregister_service(struct tzcom_data_t *data,
-		void __user *argp)
-{
-	int ret = 0;
-	unsigned long flags;
-	struct tzcom_unregister_svc_op_req req;
-	struct tzcom_registered_svc_list *ptr, *next;
-	ret = copy_from_user(&req, argp, sizeof(req));
-	if (ret) {
-		PERR("copy_from_user failed");
-		return ret;
-	}
-
-	spin_lock_irqsave(&data->registered_svc_list_lock, flags);
-	list_for_each_entry_safe(ptr, next, &data->registered_svc_list_head,
-			list) {
-		if (req.svc_id == ptr->svc.svc_id &&
-				req.instance_id == ptr->svc.instance_id) {
-			wake_up_all(&ptr->next_cmd_wq);
-			list_del(&ptr->list);
-			kfree(ptr);
-			spin_unlock_irqrestore(&data->registered_svc_list_lock,
-					flags);
-			return 0;
-		}
-	}
-	spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-
-	return -EINVAL;
-}
-
-static int __tzcom_is_cont_cmd(struct tzcom_data_t *data)
-{
-	int ret;
-	ret = (data->cont_cmd_flag != 0);
-	return ret || data->abort;
-}
-
-/**
- *   +---------+                              +-----+       +-----------------+
- *   |  TZCOM  |                              | SCM |       | TZCOM_SCHEDULER |
- *   +----+----+                              +--+--+       +--------+--------+
- *        |                                      |                   |
- *        |        scm_call                      |                   |
- *        |------------------------------------->|                   |
- *        |  cmd_buf = struct tzcom_command {    |                   |
- *        |              cmd_type,               |------------------>|
- * +------+------------- sb_in_cmd_addr,         |                   |
- * |      |              sb_in_cmd_len           |                   |
- * |      |            }                         |                   |
- * |      |   resp_buf = struct tzcom_response { |                   |
- * |                         cmd_status,         |                   |
- * |             +---------- sb_in_rsp_addr,     |                   |
- * |             |           sb_in_rsp_len       |<------------------|
- * |             |         }
- * |             |                            struct tzcom_callback {---------+
- * |             |                                uint32_t cmd_id;            |
- * |             |                                uint32_t sb_out_cb_data_len;|
- * |             +---------------+                uint32_t sb_out_cb_data_off;|
- * |                             |            }                               |
- * |    _________________________|_______________________________             |
- * |    +-----------------------+| +----------------------+                   |
- * +--->+ copy from req.cmd_buf |+>| copy to req.resp_buf |                   |
- *      +-----------------------+  +----------------------+                   |
- *      _________________________________________________________             |
- *                               INPUT SHARED BUFFER                          |
- *   +------------------------------------------------------------------------+
- *   |  _________________________________________________________
- *   |  +---------------------------------------------+
- *   +->| cmd_id | data_len | data_off |   data...    |
- *      +---------------------------------------------+
- *                                     |<------------>|copy to next_cmd.req_buf
- *      _________________________________________________________
- *                              OUTPUT SHARED BUFFER
- */
-static int __tzcom_send_cmd(struct tzcom_data_t *data,
-			struct tzcom_send_cmd_op_req *req)
-{
-	int ret = 0;
-	unsigned long flags;
-	u32 reqd_len_sb_in = 0;
-	u32 reqd_len_sb_out = 0;
-	struct tzcom_command cmd;
-	struct tzcom_response resp;
-	struct tzcom_callback *next_callback;
-	void *cb_data = NULL;
-	struct tzcom_callback_list *new_entry;
-	struct tzcom_callback *cb;
-	size_t new_entry_len = 0;
-	struct tzcom_registered_svc_list *ptr_svc;
-
-	if (req->cmd_buf == NULL || req->resp_buf == NULL) {
-		PERR("cmd buffer or response buffer is null");
-		return -EINVAL;
-	}
-
-	if (req->cmd_len <= 0 || req->resp_len <= 0 ||
-		req->cmd_len > sb_in_length || req->resp_len > sb_in_length) {
-		PERR("cmd buffer length or "
-				"response buffer length not valid");
-		return -EINVAL;
-	}
-	PDEBUG("received cmd_req.req: 0x%p",
-				req->cmd_buf);
-	PDEBUG("received cmd_req.rsp size: %u, ptr: 0x%p",
-			req->resp_len,
-			req->resp_buf);
-
-	reqd_len_sb_in = req->cmd_len + req->resp_len;
-	if (reqd_len_sb_in > sb_in_length) {
-		PDEBUG("Not enough memory to fit cmd_buf and "
-				"resp_buf. Required: %u, Available: %u",
-				reqd_len_sb_in, sb_in_length);
-		return -ENOMEM;
-	}
-
-	/* Copy req->cmd_buf to SB in and set
-	 * req->resp_buf to SB in + cmd_len
-	 */
-	mutex_lock(&sb_in_lock);
-	PDEBUG("Before memcpy on sb_in");
-	memcpy(sb_in_virt, req->cmd_buf, req->cmd_len);
-	PDEBUG("After memcpy on sb_in");
-
-	/* cmd_type will always be a new here */
-	cmd.cmd_type = TZ_SCHED_CMD_NEW;
-	cmd.sb_in_cmd_addr = (u8 *) tzcom_virt_to_phys(sb_in_virt);
-	cmd.sb_in_cmd_len = req->cmd_len;
-
-	resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
-	resp.sb_in_rsp_addr = (u8 *) tzcom_virt_to_phys(sb_in_virt +
-			req->cmd_len);
-	resp.sb_in_rsp_len = req->resp_len;
-
-	PDEBUG("before call tzcom_scm_call, cmd_id = : %u", req->cmd_id);
-	PDEBUG("before call tzcom_scm_call, sizeof(cmd) = : %u", sizeof(cmd));
-
-	ret = tzcom_scm_call((const void *) &cmd, sizeof(cmd),
-			&resp, sizeof(resp));
-	mutex_unlock(&sb_in_lock);
-
-	if (ret) {
-		PERR("tzcom_scm_call failed with err: %d", ret);
-		return ret;
-	}
-
-	while (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
-		/*
-		 * If cmd is incomplete, get the callback cmd out from SB out
-		 * and put it on the list
-		 */
-		PDEBUG("cmd_status is incomplete.");
-		next_callback = (struct tzcom_callback *)sb_out_virt;
-
-		mutex_lock(&sb_out_lock);
-		reqd_len_sb_out = sizeof(*next_callback)
-					+ next_callback->sb_out_cb_data_len;
-		if (reqd_len_sb_out > sb_out_length ||
-			reqd_len_sb_out < sizeof(*next_callback) ||
-			next_callback->sb_out_cb_data_len > sb_out_length) {
-			PERR("Incorrect callback data length"
-					" Required: %u, Available: %u, Min: %u",
-					reqd_len_sb_out, sb_out_length,
-					sizeof(*next_callback));
-			mutex_unlock(&sb_out_lock);
-			return -ENOMEM;
-		}
-
-		/* Assumption is cb_data_off is sizeof(tzcom_callback) */
-		new_entry_len = sizeof(*new_entry)
-					+ next_callback->sb_out_cb_data_len;
-		new_entry = kmalloc(new_entry_len, GFP_KERNEL);
-		if (!new_entry) {
-			PERR("kmalloc failed");
-			mutex_unlock(&sb_out_lock);
-			return -ENOMEM;
-		}
-
-		cb = &new_entry->callback;
-		cb->cmd_id = next_callback->cmd_id;
-		cb->sb_out_cb_data_len = next_callback->sb_out_cb_data_len;
-		cb->sb_out_cb_data_off = sizeof(*cb);
-
-		cb_data = (u8 *)next_callback
-				+ next_callback->sb_out_cb_data_off;
-		memcpy((u8 *)cb + cb->sb_out_cb_data_off, cb_data,
-				next_callback->sb_out_cb_data_len);
-		mutex_unlock(&sb_out_lock);
-
-		mutex_lock(&data->callback_list_lock);
-		list_add_tail(&new_entry->list, &data->callback_list_head);
-		mutex_unlock(&data->callback_list_lock);
-
-		/*
-		 * We don't know which service can handle the command. so we
-		 * wake up all blocking services and let them figure out if
-		 * they can handle the given command.
-		 */
-		spin_lock_irqsave(&data->registered_svc_list_lock, flags);
-		list_for_each_entry(ptr_svc,
-				&data->registered_svc_list_head, list) {
-			ptr_svc->next_cmd_flag = 1;
-			wake_up_interruptible(&ptr_svc->next_cmd_wq);
-		}
-		spin_unlock_irqrestore(&data->registered_svc_list_lock,
-				flags);
-
-		PDEBUG("waking up next_cmd_wq and "
-				"waiting for cont_cmd_wq");
-		if (wait_event_interruptible(data->cont_cmd_wq,
-				__tzcom_is_cont_cmd(data))) {
-			PWARN("Interrupted: exiting send_cmd loop");
-			return -ERESTARTSYS;
-		}
-
-		if (data->abort) {
-			PERR("Aborting driver");
-			return -ENODEV;
-		}
-		data->cont_cmd_flag = 0;
-		cmd.cmd_type = TZ_SCHED_CMD_PENDING;
-		mutex_lock(&sb_in_lock);
-		ret = tzcom_scm_call((const void *) &cmd, sizeof(cmd), &resp,
-				sizeof(resp));
-		mutex_unlock(&sb_in_lock);
-		if (ret) {
-			PERR("tzcom_scm_call failed with err: %d", ret);
-			return ret;
-		}
-	}
-
-	mutex_lock(&sb_in_lock);
-	resp.sb_in_rsp_addr = sb_in_virt + cmd.sb_in_cmd_len;
-	resp.sb_in_rsp_len = req->resp_len;
-	memcpy(req->resp_buf, resp.sb_in_rsp_addr, resp.sb_in_rsp_len);
-	/* Zero out memory for security purpose */
-	memset(sb_in_virt, 0, reqd_len_sb_in);
-	mutex_unlock(&sb_in_lock);
-
-	return ret;
-}
-
-
-static int tzcom_send_cmd(struct tzcom_data_t *data, void __user *argp)
-{
-	int ret = 0;
-	struct tzcom_send_cmd_op_req req;
-
-	ret = copy_from_user(&req, argp, sizeof(req));
-	if (ret) {
-		PERR("copy_from_user failed");
-		return ret;
-	}
-	ret = __tzcom_send_cmd(data, &req);
-	if (ret)
-		return ret;
-
-	PDEBUG("sending cmd_req->rsp "
-			"size: %u, ptr: 0x%p", req.resp_len,
-			req.resp_buf);
-	ret = copy_to_user(argp, &req, sizeof(req));
-	if (ret) {
-		PDEBUG("copy_to_user failed");
-		return ret;
-	}
-	return ret;
-}
-
-static int __tzcom_send_cmd_req_clean_up(
-			struct tzcom_send_cmd_fd_op_req *req)
-{
-	char *field;
-	uint32_t *update;
-	int ret = 0;
-	int i = 0;
-
-	for (i = 0; i < MAX_ION_FD; i++) {
-		if (req->ifd_data[i].fd != 0) {
-			field = (char *)req->cmd_buf +
-					req->ifd_data[i].cmd_buf_offset;
-			update = (uint32_t *) field;
-			*update = 0;
-		}
-	}
-	return ret;
-}
-
-static int __tzcom_update_with_phy_addr(
-			struct tzcom_send_cmd_fd_op_req *req)
-{
-	struct ion_handle *ihandle;
-	char *field;
-	uint32_t *update;
-	ion_phys_addr_t pa;
-	int ret = 0;
-	int i = 0;
-	uint32_t length;
-
-	for (i = 0; i < MAX_ION_FD; i++) {
-		if (req->ifd_data[i].fd != 0) {
-			/* Get the handle of the shared fd */
-			ihandle = ion_import_fd(ion_clnt, req->ifd_data[i].fd);
-			if (ihandle == NULL) {
-				PERR("Ion client can't retrieve the handle\n");
-				return -ENOMEM;
-			}
-			field = (char *) req->cmd_buf +
-						req->ifd_data[i].cmd_buf_offset;
-			update = (uint32_t *) field;
-
-			/* Populate the cmd data structure with the phys_addr */
-			ret = ion_phys(ion_clnt, ihandle, &pa, &length);
-			if (ret)
-				return -ENOMEM;
-
-			*update = (uint32_t)pa;
-			ion_free(ion_clnt, ihandle);
-		}
-	}
-	return ret;
-}
-
-static int tzcom_send_cmd_with_fd(struct tzcom_data_t *data,
-					void __user *argp)
-{
-	int ret = 0;
-	struct tzcom_send_cmd_fd_op_req req;
-	struct tzcom_send_cmd_op_req send_cmd_req;
-
-	ret = copy_from_user(&req, argp, sizeof(req));
-	if (ret) {
-		PERR("copy_from_user failed");
-		return ret;
-	}
-
-	send_cmd_req.cmd_id = req.cmd_id;
-	send_cmd_req.cmd_buf = req.cmd_buf;
-	send_cmd_req.cmd_len = req.cmd_len;
-	send_cmd_req.resp_buf = req.resp_buf;
-	send_cmd_req.resp_len = req.resp_len;
-
-	ret = __tzcom_update_with_phy_addr(&req);
-	if (ret)
-		return ret;
-	ret = __tzcom_send_cmd(data, &send_cmd_req);
-	__tzcom_send_cmd_req_clean_up(&req);
-
-	if (ret)
-		return ret;
-
-	PDEBUG("sending cmd_req->rsp "
-			"size: %u, ptr: 0x%p", req.resp_len,
-			req.resp_buf);
-	ret = copy_to_user(argp, &req, sizeof(req));
-	if (ret) {
-		PDEBUG("copy_to_user failed");
-		return ret;
-	}
-	return ret;
-}
-
-static struct tzcom_registered_svc_list *__tzcom_find_svc(
-		struct tzcom_data_t *data,
-		uint32_t instance_id)
-{
-	struct tzcom_registered_svc_list *entry;
-	unsigned long flags;
-
-	spin_lock_irqsave(&data->registered_svc_list_lock, flags);
-	list_for_each_entry(entry,
-			&data->registered_svc_list_head, list) {
-		if (entry->svc.instance_id == instance_id)
-			break;
-	}
-	spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-
-	return entry;
-}
-
-static int __tzcom_copy_cmd(struct tzcom_data_t *data,
-		struct tzcom_next_cmd_op_req *req,
-		struct tzcom_registered_svc_list *ptr_svc)
-{
-	int found = 0;
-	int ret = -EAGAIN;
-	struct tzcom_callback_list *entry, *next;
-	struct tzcom_callback *cb;
-
-	PDEBUG("In here");
-	mutex_lock(&data->callback_list_lock);
-	PDEBUG("Before looping through cmd and svc lists.");
-	list_for_each_entry_safe(entry, next, &data->callback_list_head, list) {
-		cb = &entry->callback;
-		if (req->svc_id == ptr_svc->svc.svc_id &&
-			req->instance_id == ptr_svc->svc.instance_id &&
-			cb->cmd_id >= ptr_svc->svc.cmd_id_low &&
-			cb->cmd_id <= ptr_svc->svc.cmd_id_high) {
-			PDEBUG("Found matching entry");
-			found = 1;
-			if (cb->sb_out_cb_data_len <= req->req_len) {
-				PDEBUG("copying cmd buffer %p to req "
-					"buffer %p, length: %u",
-					(u8 *)cb + cb->sb_out_cb_data_off,
-					req->req_buf, cb->sb_out_cb_data_len);
-				req->cmd_id = cb->cmd_id;
-				ret = copy_to_user(req->req_buf,
-					(u8 *)cb + cb->sb_out_cb_data_off,
-					cb->sb_out_cb_data_len);
-				if (ret) {
-					PERR("copy_to_user failed");
-					break;
-				}
-				list_del(&entry->list);
-				kfree(entry);
-				ret = 0;
-			} else {
-				PERR("callback data buffer is "
-					"larger than provided buffer."
-					"Required: %u, Provided: %u",
-					cb->sb_out_cb_data_len,
-					req->req_len);
-				ret = -ENOMEM;
-			}
-			break;
-		}
-	}
-	PDEBUG("After looping through cmd and svc lists.");
-	mutex_unlock(&data->callback_list_lock);
-	return ret;
-}
-
-static int __tzcom_is_next_cmd(struct tzcom_data_t *data,
-		struct tzcom_registered_svc_list *svc)
-{
-	int ret;
-	ret = (svc->next_cmd_flag != 0);
-	return ret || data->abort;
-}
-
-static int tzcom_read_next_cmd(struct tzcom_data_t *data, void __user *argp)
-{
-	int ret = 0;
-	struct tzcom_next_cmd_op_req req;
-	struct tzcom_registered_svc_list *this_svc;
-
-	ret = copy_from_user(&req, argp, sizeof(req));
-	if (ret) {
-		PERR("copy_from_user failed");
-		return ret;
-	}
-
-	if (req.instance_id > atomic_read(&svc_instance_ctr)) {
-		PERR("Invalid instance_id for the request");
-		return -EINVAL;
-	}
-
-	if (!req.req_buf || req.req_len == 0) {
-		PERR("Invalid request buffer or buffer length");
-		return -EINVAL;
-	}
-
-	PDEBUG("Before next_cmd loop");
-	this_svc = __tzcom_find_svc(data, req.instance_id);
-
-	while (1) {
-		PDEBUG("Before wait_event next_cmd.");
-		if (wait_event_interruptible(this_svc->next_cmd_wq,
-				__tzcom_is_next_cmd(data, this_svc))) {
-			PWARN("Interrupted: exiting wait_next_cmd loop");
-			/* woken up for different reason */
-			return -ERESTARTSYS;
-		}
-
-		if (data->abort) {
-			PERR("Aborting driver");
-			return -ENODEV;
-		}
-		PDEBUG("After wait_event next_cmd.");
-		this_svc->next_cmd_flag = 0;
-
-		ret = __tzcom_copy_cmd(data, &req, this_svc);
-		if (ret == 0) {
-			PDEBUG("Successfully found svc for cmd");
-			data->handled_cmd_svc_instance_id = req.instance_id;
-			break;
-		} else if (ret == -ENOMEM) {
-			PERR("Not enough memory");
-			return ret;
-		}
-	}
-	ret = copy_to_user(argp, &req, sizeof(req));
-	if (ret) {
-		PERR("copy_to_user failed");
-		return ret;
-	}
-	PDEBUG("copy_to_user is done.");
-	return ret;
-}
-
-static int tzcom_cont_cmd(struct tzcom_data_t *data, void __user *argp)
-{
-	int ret = 0;
-	struct tzcom_cont_cmd_op_req req;
-	ret = copy_from_user(&req, argp, sizeof(req));
-	if (ret) {
-		PERR("copy_from_user failed");
-		return ret;
-	}
-
-	/*
-	 * Only the svc instance that handled the cmd (in read_next_cmd method)
-	 * can call continue cmd
-	 */
-	if (data->handled_cmd_svc_instance_id != req.instance_id) {
-		PWARN("Only the service instance that handled the last "
-				"callback can continue cmd. "
-				"Expected: %u, Received: %u",
-				data->handled_cmd_svc_instance_id,
-				req.instance_id);
-		return -EINVAL;
-	}
-
-	if (req.resp_buf) {
-		mutex_lock(&sb_out_lock);
-		memcpy(sb_out_virt, req.resp_buf, req.resp_len);
-		mutex_unlock(&sb_out_lock);
-	}
-
-	data->cont_cmd_flag = 1;
-	wake_up_interruptible(&data->cont_cmd_wq);
-	return ret;
-}
-
-static int tzcom_abort(struct tzcom_data_t *data)
-{
-	int ret = 0;
-	unsigned long flags;
-	struct tzcom_registered_svc_list *lsvc, *nsvc;
-	if (data->abort) {
-		PERR("Already aborting");
-		return -EINVAL;
-	}
-
-	data->abort = 1;
-
-	PDEBUG("Waking up cont_cmd_wq");
-	wake_up_all(&data->cont_cmd_wq);
-
-	spin_lock_irqsave(&data->registered_svc_list_lock, flags);
-	PDEBUG("Before waking up service wait queues");
-	list_for_each_entry_safe(lsvc, nsvc,
-			&data->registered_svc_list_head, list) {
-		wake_up_all(&lsvc->next_cmd_wq);
-	}
-	spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-
-	PDEBUG("ioctl_count before loop: %d", atomic_read(&data->ioctl_count));
-	while (atomic_read(&data->ioctl_count) > 0) {
-		if (wait_event_interruptible(data->abort_wq,
-				atomic_read(&data->ioctl_count) <= 0)) {
-			PERR("Interrupted from abort");
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	return ret;
-}
-
-static long tzcom_ioctl(struct file *file, unsigned cmd,
-		unsigned long arg)
-{
-	int ret = 0;
-	struct tzcom_data_t *tzcom_data = file->private_data;
-	void __user *argp = (void __user *) arg;
-	PDEBUG("enter tzcom_ioctl()");
-	if (tzcom_data->abort) {
-		PERR("Aborting tzcom driver");
-		return -ENODEV;
-	}
-
-	switch (cmd) {
-	case TZCOM_IOCTL_REGISTER_SERVICE_REQ: {
-		PDEBUG("ioctl register_service_req()");
-		atomic_inc(&tzcom_data->ioctl_count);
-		ret = tzcom_register_service(tzcom_data, argp);
-		atomic_dec(&tzcom_data->ioctl_count);
-		wake_up_interruptible(&tzcom_data->abort_wq);
-		if (ret)
-			PERR("failed tzcom_register_service: %d", ret);
-		break;
-	}
-	case TZCOM_IOCTL_UNREGISTER_SERVICE_REQ: {
-		PDEBUG("ioctl unregister_service_req()");
-		atomic_inc(&tzcom_data->ioctl_count);
-		ret = tzcom_unregister_service(tzcom_data, argp);
-		atomic_dec(&tzcom_data->ioctl_count);
-		wake_up_interruptible(&tzcom_data->abort_wq);
-		if (ret)
-			PERR("failed tzcom_unregister_service: %d", ret);
-		break;
-	}
-	case TZCOM_IOCTL_SEND_CMD_REQ: {
-		PDEBUG("ioctl send_cmd_req()");
-		/* Only one client allowed here at a time */
-		mutex_lock(&send_cmd_lock);
-		atomic_inc(&tzcom_data->ioctl_count);
-		ret = tzcom_send_cmd(tzcom_data, argp);
-		atomic_dec(&tzcom_data->ioctl_count);
-		wake_up_interruptible(&tzcom_data->abort_wq);
-		mutex_unlock(&send_cmd_lock);
-		if (ret)
-			PERR("failed tzcom_send_cmd: %d", ret);
-		break;
-	}
-	case TZCOM_IOCTL_SEND_CMD_FD_REQ: {
-		PDEBUG("ioctl send_cmd_req()");
-		/* Only one client allowed here at a time */
-		mutex_lock(&send_cmd_lock);
-		atomic_inc(&tzcom_data->ioctl_count);
-		ret = tzcom_send_cmd_with_fd(tzcom_data, argp);
-		atomic_dec(&tzcom_data->ioctl_count);
-		wake_up_interruptible(&tzcom_data->abort_wq);
-		mutex_unlock(&send_cmd_lock);
-		if (ret)
-			PERR("failed tzcom_send_cmd: %d", ret);
-		break;
-	}
-	case TZCOM_IOCTL_READ_NEXT_CMD_REQ: {
-		PDEBUG("ioctl read_next_cmd_req()");
-		atomic_inc(&tzcom_data->ioctl_count);
-		ret = tzcom_read_next_cmd(tzcom_data, argp);
-		atomic_dec(&tzcom_data->ioctl_count);
-		wake_up_interruptible(&tzcom_data->abort_wq);
-		if (ret)
-			PERR("failed tzcom_read_next: %d", ret);
-		break;
-	}
-	case TZCOM_IOCTL_CONTINUE_CMD_REQ: {
-		PDEBUG("ioctl continue_cmd_req()");
-		atomic_inc(&tzcom_data->ioctl_count);
-		ret = tzcom_cont_cmd(tzcom_data, argp);
-		atomic_dec(&tzcom_data->ioctl_count);
-		wake_up_interruptible(&tzcom_data->abort_wq);
-		if (ret)
-			PERR("failed tzcom_cont_cmd: %d", ret);
-		break;
-	}
-	case TZCOM_IOCTL_ABORT_REQ: {
-		PDEBUG("ioctl abort_req()");
-		ret = tzcom_abort(tzcom_data);
-		if (ret)
-			PERR("failed tzcom_abort: %d", ret);
-		break;
-	}
-	default:
-		return -EINVAL;
-	}
-	return ret;
-}
-
-static int tzcom_open(struct inode *inode, struct file *file)
-{
-	int ret;
-	long pil_error;
-	struct tz_pr_init_sb_req_s sb_out_init_req;
-	struct tz_pr_init_sb_rsp_s sb_out_init_rsp;
-	void *rsp_addr_virt;
-	struct tzcom_command cmd;
-	struct tzcom_response resp;
-	struct tzcom_data_t *tzcom_data;
-
-	PDEBUG("In here");
-
-	ret = tzcom_enable_bus_scaling();
-
-	if (pil == NULL) {
-		pil = pil_get("tzapps");
-		if (IS_ERR(pil)) {
-			PERR("Playready PIL image load failed");
-			pil_error = PTR_ERR(pil);
-			pil = NULL;
-			return pil_error;
-		}
-		PDEBUG("tzapps image loaded successfully");
-	}
-
-	sb_out_init_req.pr_cmd = TZ_SCHED_CMD_ID_INIT_SB_OUT;
-	sb_out_init_req.sb_len = sb_out_length;
-	sb_out_init_req.sb_ptr = tzcom_virt_to_phys(sb_out_virt);
-	PDEBUG("sb_out_init_req { pr_cmd: %d, sb_len: %u, "
-			"sb_ptr (phys): 0x%x }",
-			sb_out_init_req.pr_cmd,
-			sb_out_init_req.sb_len,
-			sb_out_init_req.sb_ptr);
-
-	mutex_lock(&sb_in_lock);
-	PDEBUG("Before memcpy on sb_in");
-	memcpy(sb_in_virt, &sb_out_init_req, sizeof(sb_out_init_req));
-	PDEBUG("After memcpy on sb_in");
-
-	/* It will always be a new cmd from this method */
-	cmd.cmd_type = TZ_SCHED_CMD_NEW;
-	cmd.sb_in_cmd_addr = (u8 *) tzcom_virt_to_phys(sb_in_virt);
-	cmd.sb_in_cmd_len = sizeof(sb_out_init_req);
-	PDEBUG("tzcom_command { cmd_type: %u, sb_in_cmd_addr: %p, "
-			"sb_in_cmd_len: %u }",
-			cmd.cmd_type, cmd.sb_in_cmd_addr, cmd.sb_in_cmd_len);
-
-	resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
-
-	PDEBUG("Before scm_call for sb_init");
-	ret = tzcom_scm_call(&cmd, sizeof(cmd), &resp, sizeof(resp));
-	if (ret) {
-		PERR("tzcom_scm_call failed with err: %d", ret);
-		return ret;
-	}
-	PDEBUG("After scm_call for sb_init");
-
-	PDEBUG("tzcom_response after scm cmd_status: %u", resp.cmd_status);
-	if (resp.cmd_status == TZ_SCHED_STATUS_COMPLETE) {
-		resp.sb_in_rsp_addr = (u8 *)cmd.sb_in_cmd_addr +
-				cmd.sb_in_cmd_len;
-		resp.sb_in_rsp_len = sizeof(sb_out_init_rsp);
-		PDEBUG("tzcom_response sb_in_rsp_addr: %p, sb_in_rsp_len: %u",
-				resp.sb_in_rsp_addr, resp.sb_in_rsp_len);
-		rsp_addr_virt = tzcom_phys_to_virt((unsigned long)
-				resp.sb_in_rsp_addr);
-		PDEBUG("Received response phys: %p, virt: %p",
-				resp.sb_in_rsp_addr, rsp_addr_virt);
-		memcpy(&sb_out_init_rsp, rsp_addr_virt, resp.sb_in_rsp_len);
-	} else {
-		PERR("Error with SB initialization");
-		mutex_unlock(&sb_in_lock);
-		return -EPERM;
-	}
-	mutex_unlock(&sb_in_lock);
-
-	PDEBUG("sb_out_init_rsp { pr_cmd: %d, ret: %d }",
-			sb_out_init_rsp.pr_cmd, sb_out_init_rsp.ret);
-
-	if (sb_out_init_rsp.ret) {
-		PERR("sb_out_init_req failed: %d", sb_out_init_rsp.ret);
-		return -EPERM;
-	}
-
-	tzcom_data = kmalloc(sizeof(*tzcom_data), GFP_KERNEL);
-	if (!tzcom_data) {
-		PERR("kmalloc failed");
-		return -ENOMEM;
-	}
-	file->private_data = tzcom_data;
-
-	INIT_LIST_HEAD(&tzcom_data->callback_list_head);
-	mutex_init(&tzcom_data->callback_list_lock);
-
-	INIT_LIST_HEAD(&tzcom_data->registered_svc_list_head);
-	spin_lock_init(&tzcom_data->registered_svc_list_lock);
-
-	init_waitqueue_head(&tzcom_data->cont_cmd_wq);
-	tzcom_data->cont_cmd_flag = 0;
-	tzcom_data->handled_cmd_svc_instance_id = 0;
-	tzcom_data->abort = 0;
-	init_waitqueue_head(&tzcom_data->abort_wq);
-	atomic_set(&tzcom_data->ioctl_count, 0);
-	return 0;
-}
-
-static int tzcom_release(struct inode *inode, struct file *file)
-{
-	struct tzcom_data_t *tzcom_data = file->private_data;
-	struct tzcom_callback_list *lcb, *ncb;
-	struct tzcom_registered_svc_list *lsvc, *nsvc;
-	unsigned long flags;
-	PDEBUG("In here");
-
-	if (!tzcom_data->abort) {
-		PDEBUG("Calling abort");
-		tzcom_abort(tzcom_data);
-	}
-
-	PDEBUG("Before removing callback list");
-	mutex_lock(&tzcom_data->callback_list_lock);
-	list_for_each_entry_safe(lcb, ncb,
-			&tzcom_data->callback_list_head, list) {
-		list_del(&lcb->list);
-		kfree(lcb);
-	}
-	mutex_unlock(&tzcom_data->callback_list_lock);
-	PDEBUG("After removing callback list");
-
-	PDEBUG("Before removing svc list");
-	spin_lock_irqsave(&tzcom_data->registered_svc_list_lock, flags);
-	list_for_each_entry_safe(lsvc, nsvc,
-			&tzcom_data->registered_svc_list_head, list) {
-		list_del(&lsvc->list);
-		kfree(lsvc);
-	}
-	spin_unlock_irqrestore(&tzcom_data->registered_svc_list_lock, flags);
-	PDEBUG("After removing svc list");
-	if (pil != NULL) {
-		pil_put(pil);
-		pil = NULL;
-	}
-	PDEBUG("Freeing tzcom data");
-	kfree(tzcom_data);
-	tzcom_disable_bus_scaling();
-	return 0;
-}
-
-static struct msm_bus_paths tzcom_bw_table[] = {
-	{
-		.vectors = (struct msm_bus_vectors[]){
-			{
-				.src = MSM_BUS_MASTER_SPS,
-				.dst = MSM_BUS_SLAVE_EBI_CH0,
-			},
-		},
-		.num_paths = 1,
-	},
-	{
-		.vectors = (struct msm_bus_vectors[]){
-			{
-				.src = MSM_BUS_MASTER_SPS,
-				.dst = MSM_BUS_SLAVE_EBI_CH0,
-				.ib = (492 * 8) * 1000000UL,
-				.ab = (492 * 8) *  100000UL,
-			},
-		},
-		.num_paths = 1,
-	},
-
-};
-
-static struct msm_bus_scale_pdata tzcom_bus_pdata = {
-	.usecase = tzcom_bw_table,
-	.num_usecases = ARRAY_SIZE(tzcom_bw_table),
-	.name = "tzcom",
-};
-static const struct file_operations tzcom_fops = {
-		.owner = THIS_MODULE,
-		.unlocked_ioctl = tzcom_ioctl,
-		.open = tzcom_open,
-		.release = tzcom_release
-};
-
-static int __init tzcom_init(void)
-{
-	int rc;
-	struct device *class_dev;
-
-	PDEBUG("Hello tzcom");
-
-	rc = alloc_chrdev_region(&tzcom_device_no, 0, 1, TZCOM_DEV);
-	if (rc < 0) {
-		PERR("alloc_chrdev_region failed %d", rc);
-		return rc;
-	}
-
-	driver_class = class_create(THIS_MODULE, TZCOM_DEV);
-	if (IS_ERR(driver_class)) {
-		rc = -ENOMEM;
-		PERR("class_create failed %d", rc);
-		goto unregister_chrdev_region;
-	}
-
-	class_dev = device_create(driver_class, NULL, tzcom_device_no, NULL,
-			TZCOM_DEV);
-	if (!class_dev) {
-		PERR("class_device_create failed %d", rc);
-		rc = -ENOMEM;
-		goto class_destroy;
-	}
-
-	cdev_init(&tzcom_cdev, &tzcom_fops);
-	tzcom_cdev.owner = THIS_MODULE;
-
-	rc = cdev_add(&tzcom_cdev, MKDEV(MAJOR(tzcom_device_no), 0), 1);
-	if (rc < 0) {
-		PERR("cdev_add failed %d", rc);
-		goto class_device_destroy;
-	}
-
-	sb_in_phys = pmem_kalloc(sb_in_length, PMEM_MEMTYPE_EBI1 |
-			PMEM_ALIGNMENT_4K);
-	if (IS_ERR((void *)sb_in_phys)) {
-		PERR("could not allocte in kernel pmem buffers for sb_in");
-		sb_in_phys = 0;
-		rc = -ENOMEM;
-		goto class_device_destroy;
-	}
-	PDEBUG("physical_addr for sb_in: 0x%x", sb_in_phys);
-
-	sb_in_virt = (u8 *) ioremap((unsigned long)sb_in_phys,
-			sb_in_length);
-	if (!sb_in_virt) {
-		PERR("Shared buffer IN allocation failed.");
-		rc = -ENOMEM;
-		goto class_device_destroy;
-	}
-	PDEBUG("sb_in virt address: %p, phys address: 0x%x",
-			sb_in_virt, tzcom_virt_to_phys(sb_in_virt));
-
-	sb_out_phys = pmem_kalloc(sb_out_length, PMEM_MEMTYPE_EBI1 |
-			PMEM_ALIGNMENT_4K);
-	if (IS_ERR((void *)sb_out_phys)) {
-		PERR("could not allocte in kernel pmem buffers for sb_out");
-		sb_out_phys = 0;
-		rc = -ENOMEM;
-		goto class_device_destroy;
-	}
-	PDEBUG("physical_addr for sb_out: 0x%x", sb_out_phys);
-
-	sb_out_virt = (u8 *) ioremap((unsigned long)sb_out_phys,
-			sb_out_length);
-	if (!sb_out_virt) {
-		PERR("Shared buffer OUT allocation failed.");
-		rc = -ENOMEM;
-		goto class_device_destroy;
-	}
-	PDEBUG("sb_out virt address: %p, phys address: 0x%x",
-			sb_out_virt, tzcom_virt_to_phys(sb_out_virt));
-	ion_clnt = msm_ion_client_create(0x03, "tzcom");
-	/* Initialized in tzcom_open */
-	pil = NULL;
-
-	tzcom_perf_client = msm_bus_scale_register_client(
-					&tzcom_bus_pdata);
-	if (!tzcom_perf_client)
-		pr_err("Unable to register bus client");
-
-	tzcom_bus_clk = clk_get(class_dev, "bus_clk");
-	if (IS_ERR(tzcom_bus_clk)) {
-		tzcom_bus_clk = NULL;
-	} else  if (tzcom_bus_clk != NULL) {
-		pr_debug("Enabled DFAB clock\n");
-		clk_set_rate(tzcom_bus_clk, 64000000);
-	}
-	return 0;
-
-class_device_destroy:
-	if (sb_in_virt)
-		iounmap(sb_in_virt);
-	if (sb_in_phys)
-		pmem_kfree(sb_in_phys);
-	if (sb_out_virt)
-		iounmap(sb_out_virt);
-	if (sb_out_phys)
-		pmem_kfree(sb_out_phys);
-	device_destroy(driver_class, tzcom_device_no);
-class_destroy:
-	class_destroy(driver_class);
-unregister_chrdev_region:
-	unregister_chrdev_region(tzcom_device_no, 1);
-	return rc;
-}
-
-static void __exit tzcom_exit(void)
-{
-	PDEBUG("Goodbye tzcom");
-	if (sb_in_virt)
-		iounmap(sb_in_virt);
-	if (sb_in_phys)
-		pmem_kfree(sb_in_phys);
-	if (sb_out_virt)
-		iounmap(sb_out_virt);
-	if (sb_out_phys)
-		pmem_kfree(sb_out_phys);
-	if (pil != NULL) {
-		pil_put(pil);
-		pil = NULL;
-	}
-	clk_put(tzcom_bus_clk);
-	device_destroy(driver_class, tzcom_device_no);
-	class_destroy(driver_class);
-	unregister_chrdev_region(tzcom_device_no, 1);
-	ion_client_destroy(ion_clnt);
-}
-
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Sachin Shah <sachins@codeaurora.org>");
-MODULE_DESCRIPTION("Qualcomm TrustZone Communicator");
-MODULE_VERSION("1.00");
-
-module_init(tzcom_init);
-module_exit(tzcom_exit);
diff --git a/drivers/misc/tzcomi.h b/drivers/misc/tzcomi.h
deleted file mode 100644
index 33634cf..0000000
--- a/drivers/misc/tzcomi.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Qualcomm TrustZone communicator driver
- *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __TZCOMI_H_
-#define __TZCOMI_H_
-
-#include <linux/types.h>
-
-enum tz_sched_cmd_id {
-	TZ_SCHED_CMD_ID_INVALID      = 0,
-	TZ_SCHED_CMD_ID_INIT_SB_OUT,    /**< Initialize the shared buffer */
-	TZ_SCHED_CMD_ID_INIT_SB_LOG,    /**< Initialize the logging shared buf */
-	TZ_SCHED_CMD_ID_UNKNOWN         = 0x7FFFFFFE,
-	TZ_SCHED_CMD_ID_MAX             = 0x7FFFFFFF
-};
-
-enum tz_sched_cmd_type {
-	TZ_SCHED_CMD_INVALID = 0,
-	TZ_SCHED_CMD_NEW,      /** New TZ Scheduler Command */
-	TZ_SCHED_CMD_PENDING,  /** Pending cmd...sched will restore stack */
-	TZ_SCHED_CMD_COMPLETE, /** TZ sched command is complete */
-	TZ_SCHED_CMD_MAX     = 0x7FFFFFFF
-};
-
-enum tz_sched_cmd_status {
-	TZ_SCHED_STATUS_INCOMPLETE = 0,
-	TZ_SCHED_STATUS_COMPLETE,
-	TZ_SCHED_STATUS_MAX  = 0x7FFFFFFF
-};
-
-/** Command structure for initializing shared buffers (SB_OUT
-    and SB_LOG)
-*/
-__packed struct tz_pr_init_sb_req_s {
-	/** First 4 bytes should always be command id
-	 * from enum tz_sched_cmd_id */
-	uint32_t                  pr_cmd;
-	/** Pointer to the physical location of sb_out buffer */
-	uint32_t                  sb_ptr;
-	/** length of shared buffer */
-	uint32_t                  sb_len;
-};
-
-
-__packed struct tz_pr_init_sb_rsp_s {
-	/** First 4 bytes should always be command id
-	 * from enum tz_sched_cmd_id */
-	uint32_t                  pr_cmd;
-	/** Return code, 0 for success, Approp error code otherwise */
-	int32_t                   ret;
-};
-
-
-/**
- * struct tzcom_command - tzcom command buffer
- * @cmd_type: value from enum tz_sched_cmd_type
- * @sb_in_cmd_addr: points to physical location of command
- *                buffer
- * @sb_in_cmd_len: length of command buffer
- */
-__packed struct tzcom_command {
-	uint32_t               cmd_type;
-	uint8_t                *sb_in_cmd_addr;
-	uint32_t               sb_in_cmd_len;
-};
-
-/**
- * struct tzcom_response - tzcom response buffer
- * @cmd_status: value from enum tz_sched_cmd_status
- * @sb_in_rsp_addr: points to physical location of response
- *                buffer
- * @sb_in_rsp_len: length of command response
- */
-__packed struct tzcom_response {
-	uint32_t                 cmd_status;
-	uint8_t                  *sb_in_rsp_addr;
-	uint32_t                 sb_in_rsp_len;
-};
-
-/**
- * struct tzcom_callback - tzcom callback buffer
- * @cmd_id: command to run in registered service
- * @sb_out_rsp_addr: points to physical location of response
- *                buffer
- * @sb_in_cmd_len: length of command response
- *
- * A callback buffer would be laid out in sb_out as follows:
- *
- *     --------------------- <--- struct tzcom_callback
- *     | callback header   |
- *     --------------------- <--- tzcom_callback.sb_out_cb_data_off
- *     | callback data     |
- *     ---------------------
- */
-__packed struct tzcom_callback {
-	uint32_t cmd_id;
-	uint32_t sb_out_cb_data_len;
-	uint32_t sb_out_cb_data_off;
-};
-
-#endif /* __TZCOMI_H_ */
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 2558c96..1331aa4 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1382,6 +1382,7 @@
 		if (mq->num_of_potential_packed_wr_reqs >
 				mq->num_wr_reqs_to_start_packing)
 			mq->wr_packing_enabled = true;
+		mq->num_of_potential_packed_wr_reqs = 0;
 		return;
 	}
 
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index a21b39d..b5ffe94 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1455,7 +1455,15 @@
 		err = mmc_poweroff_notify(host, MMC_PW_OFF_NOTIFY_SHORT);
 	} else {
 		if (mmc_card_can_sleep(host))
-			err = mmc_card_sleep(host);
+			/*
+			 * If sleep command has error it doesn't mean host
+			 * cannot suspend, but a deeper low power state
+			 * transition for the card has failed. Ignore
+			 * sleep errors so that the suspend is not aborted.
+			 * In error case, mmc_resume() takes care of
+			 * complete intialization of the card.
+			 */
+			mmc_card_sleep(host);
 		else if (!mmc_host_is_spi(host))
 			mmc_deselect_cards(host);
 	}
@@ -1512,7 +1520,7 @@
 	if (card && card->ext_csd.rev >= 3) {
 		err = mmc_card_sleepawake(host, 1);
 		if (err < 0)
-			pr_debug("%s: Error %d while putting card into sleep",
+			pr_warn("%s: Error %d while putting card into sleep",
 				 mmc_hostname(host), err);
 	}
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e84d87b..e9ccbc7 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2877,13 +2877,14 @@
 	DBG(host, "ios->clock = %u\n", ios->clock);
 	spin_lock_irqsave(&host->lock, flags);
 	if (!host->sdcc_irq_disabled) {
-		spin_unlock_irqrestore(&host->lock, flags);
-		disable_irq(host->core_irqres->start);
-		spin_lock_irqsave(&host->lock, flags);
+		disable_irq_nosync(host->core_irqres->start);
 		host->sdcc_irq_disabled = 1;
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
 
+	/* Make sure sdcc core irq is synchronized */
+	synchronize_irq(host->core_irqres->start);
+
 	pwr = msmsdcc_setup_pwr(host, ios);
 
 	spin_lock_irqsave(&host->lock, flags);
@@ -4939,9 +4940,10 @@
 	mmc->f_min = msmsdcc_get_min_sup_clk_rate(host);
 	mmc->f_max = msmsdcc_get_max_sup_clk_rate(host);
 	mmc->ocr_avail = plat->ocr_mask;
+	mmc->clkgate_delay = MSM_MMC_CLK_GATE_DELAY;
+
 	mmc->pm_caps |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
 	mmc->caps |= plat->mmc_bus_width;
-
 	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
 	mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
 
@@ -5403,6 +5405,49 @@
 #endif
 
 #ifdef CONFIG_PM
+#ifdef CONFIG_MMC_CLKGATE
+static inline void msmsdcc_gate_clock(struct msmsdcc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+	unsigned long flags;
+
+	mmc_host_clk_hold(mmc);
+	spin_lock_irqsave(&mmc->clk_lock, flags);
+	mmc->clk_old = mmc->ios.clock;
+	mmc->ios.clock = 0;
+	mmc->clk_gated = true;
+	spin_unlock_irqrestore(&mmc->clk_lock, flags);
+	mmc_set_ios(mmc);
+	mmc_host_clk_release(mmc);
+}
+
+static inline void msmsdcc_ungate_clock(struct msmsdcc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	mmc_host_clk_hold(mmc);
+	mmc->ios.clock = host->clk_rate;
+	mmc_set_ios(mmc);
+	mmc_host_clk_release(mmc);
+}
+#else
+static inline void msmsdcc_gate_clock(struct msmsdcc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	mmc->ios.clock = 0;
+	mmc_set_ios(mmc);
+}
+
+static inline void msmsdcc_ungate_clock(struct msmsdcc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	mmc->ios.clock = host->clk_rate;
+	mmc_set_ios(mmc);
+}
+#endif
+
 static int
 msmsdcc_runtime_suspend(struct device *dev)
 {
@@ -5449,21 +5494,12 @@
 			spin_unlock_irqrestore(&host->lock, flags);
 			if (mmc->card && mmc_card_sdio(mmc->card) &&
 				mmc->ios.clock) {
-#ifdef CONFIG_MMC_CLKGATE
 				/*
 				 * If SDIO function driver doesn't want
 				 * to power off the card, atleast turn off
 				 * clocks to allow deep sleep (TCXO shutdown).
 				 */
-				mmc_host_clk_hold(mmc);
-				spin_lock_irqsave(&mmc->clk_lock, flags);
-				mmc->clk_old = mmc->ios.clock;
-				mmc->ios.clock = 0;
-				mmc->clk_gated = true;
-				spin_unlock_irqrestore(&mmc->clk_lock, flags);
-				mmc_set_ios(mmc);
-				mmc_host_clk_release(mmc);
-#endif
+				msmsdcc_gate_clock(host);
 			}
 		}
 		host->sdcc_suspending = 0;
@@ -5492,10 +5528,7 @@
 	if (mmc) {
 		if (mmc->card && mmc_card_sdio(mmc->card) &&
 				mmc_card_keep_power(mmc)) {
-			mmc_host_clk_hold(mmc);
-			mmc->ios.clock = host->clk_rate;
-			mmc_set_ios(mmc);
-			mmc_host_clk_release(mmc);
+			msmsdcc_ungate_clock(host);
 		}
 
 		mmc_resume_host(mmc);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 2222337..5531f06 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -212,10 +212,10 @@
 #define NR_SG		128
 
 #define MSM_MMC_IDLE_TIMEOUT	5000 /* msecs */
+#define MSM_MMC_CLK_GATE_DELAY	200 /* msecs */
 
 /* Set the request timeout to 10secs */
 #define MSM_MMC_REQ_TIMEOUT	10000 /* msecs */
-#define MSM_MMC_DISABLE_TIMEOUT        200 /* msecs */
 
 /*
  * Controller HW limitations
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 23ba900..c2085c9 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -174,6 +174,8 @@
 			goto resubmit_int_urb;
 		}
 
+		usb_mark_last_busy(udev);
+
 		if (!dev->resp_available) {
 			dev->resp_available = true;
 			wake_up(&dev->open_wait_queue);
@@ -261,6 +263,7 @@
 
 resubmit_int_urb:
 	/*re-submit int urb to check response available*/
+	usb_mark_last_busy(udev);
 	status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
 	if (status)
 		dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
@@ -796,6 +799,7 @@
 			 dev->intbuf, wMaxPacketSize,
 			 notification_available_cb, dev, interval);
 
+	usb_mark_last_busy(udev);
 	return rmnet_usb_ctrl_start_rx(dev);
 }
 
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 2183ee6..9e1e252 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -99,7 +99,7 @@
 
 	dev = (struct rmnet_ctrl_dev *)unet->data[1];
 	if (!dev) {
-		dev_err(&unet->udev->dev, "%s: ctrl device not found\n",
+		dev_err(&iface->dev, "%s: ctrl device not found\n",
 				__func__);
 		retval = -ENODEV;
 		goto fail;
@@ -118,7 +118,7 @@
 		}
 		/*  TBD : do we need to set/clear usbnet->udev->reset_resume*/
 		} else
-		dev_dbg(&unet->udev->dev,
+		dev_dbg(&iface->dev,
 			"%s: device is busy can not suspend\n", __func__);
 
 fail:
@@ -141,8 +141,7 @@
 
 	dev = (struct rmnet_ctrl_dev *)unet->data[1];
 	if (!dev) {
-		dev_err(&unet->udev->dev, "%s: ctrl device not found\n",
-				__func__);
+		dev_err(&iface->dev, "%s: ctrl device not found\n", __func__);
 		retval = -ENODEV;
 		goto fail;
 	}
@@ -164,17 +163,15 @@
 	struct usb_host_endpoint	*bulk_in = NULL;
 	struct usb_host_endpoint	*bulk_out = NULL;
 	struct usb_host_endpoint	*int_in = NULL;
-	struct usb_device		*udev;
 	int				status = 0;
 	int				i;
 	int				numends;
 
-	udev = interface_to_usbdev(iface);
 	numends = iface->cur_altsetting->desc.bNumEndpoints;
 	for (i = 0; i < numends; i++) {
 		endpoint = iface->cur_altsetting->endpoint + i;
 		if (!endpoint) {
-			dev_err(&udev->dev, "%s: invalid endpoint %u\n",
+			dev_err(&iface->dev, "%s: invalid endpoint %u\n",
 				__func__, i);
 			status = -EINVAL;
 			goto out;
@@ -188,7 +185,7 @@
 	}
 
 	if (!bulk_in || !bulk_out || !int_in) {
-		dev_err(&udev->dev, "%s: invalid endpoints\n", __func__);
+		dev_err(&iface->dev, "%s: invalid endpoints\n", __func__);
 		status = -EINVAL;
 		goto out;
 	}
@@ -394,7 +391,7 @@
 		break;
 
 	default:
-		dev_err(&unet->udev->dev, "[%s] error: "
+		dev_err(&unet->intf->dev, "[%s] error: "
 			"rmnet_ioct called for unsupported cmd[%d]",
 			dev->name, cmd);
 		return -EINVAL;
@@ -507,16 +504,15 @@
 		const struct usb_device_id *prod)
 {
 	struct usbnet		*unet;
-	struct usb_device	*udev;
 	struct driver_info	*info;
+	struct usb_device	*udev;
 	unsigned int		iface_num;
 	static int		first_rmnet_iface_num = -EINVAL;
 	int			status = 0;
 
-	udev = interface_to_usbdev(iface);
 	iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
 	if (iface->num_altsetting != 1) {
-		dev_err(&udev->dev, "%s invalid num_altsetting %u\n",
+		dev_err(&iface->dev, "%s invalid num_altsetting %u\n",
 			__func__, iface->num_altsetting);
 		status = -EINVAL;
 		goto out;
@@ -528,7 +524,7 @@
 
 	status = usbnet_probe(iface, prod);
 	if (status < 0) {
-		dev_err(&udev->dev, "usbnet_probe failed %d\n", status);
+		dev_err(&iface->dev, "usbnet_probe failed %d\n", status);
 		goto out;
 	}
 	unet = usb_get_intfdata(iface);
@@ -558,10 +554,19 @@
 
 	status = rmnet_usb_data_debugfs_init(unet);
 	if (status)
-		dev_dbg(&udev->dev, "mode debugfs file is not available\n");
+		dev_dbg(&iface->dev, "mode debugfs file is not available\n");
+
+	udev = unet->udev;
 
 	/* allow modem to wake up suspended system */
 	device_set_wakeup_enable(&udev->dev, 1);
+
+	/* set default autosuspend timeout for modem and roothub */
+	if (udev->parent && !udev->parent->parent) {
+		pm_runtime_set_autosuspend_delay(&udev->dev, 1000);
+		pm_runtime_set_autosuspend_delay(&udev->parent->dev, 200);
+	}
+
 out:
 	return status;
 }
@@ -569,23 +574,20 @@
 static void rmnet_usb_disconnect(struct usb_interface *intf)
 {
 	struct usbnet		*unet;
-	struct usb_device	*udev;
 	struct rmnet_ctrl_dev	*dev;
 
-	udev = interface_to_usbdev(intf);
-	device_set_wakeup_enable(&udev->dev, 0);
-
 	unet = usb_get_intfdata(intf);
 	if (!unet) {
-		dev_err(&udev->dev, "%s:data device not found\n", __func__);
+		dev_err(&intf->dev, "%s:data device not found\n", __func__);
 		return;
 	}
 
+	device_set_wakeup_enable(&unet->udev->dev, 0);
 	rmnet_usb_data_debugfs_cleanup(unet);
 
 	dev = (struct rmnet_ctrl_dev *)unet->data[1];
 	if (!dev) {
-		dev_err(&udev->dev, "%s:ctrl device not found\n", __func__);
+		dev_err(&intf->dev, "%s:ctrl device not found\n", __func__);
 		return;
 	}
 	unet->data[0] = 0;
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 23efb00..15e7f3f 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -13,7 +13,8 @@
 config SPS
 	bool "SPS support"
 	depends on (HAS_IOMEM && (ARCH_MSM8960 || ARCH_MSM8X60 \
-			|| ARCH_APQ8064 || ARCH_MSM9615 || ARCH_MSMCOPPER))
+			|| ARCH_APQ8064 || ARCH_MSM9615 \
+			|| ARCH_MSM9625 || ARCH_MSMCOPPER))
 	select GENERIC_ALLOCATOR
 	default n
 	help
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index fbaea09..1329f6c 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -79,6 +79,8 @@
  */
 static struct sps_drv *sps;
 
+u32 d_type;
+
 static void sps_device_de_init(void);
 
 #ifdef CONFIG_DEBUG_FS
@@ -1443,11 +1445,6 @@
 {
 	SPS_DBG("sps:%s.", __func__);
 
-	if (h == NULL) {
-		SPS_ERR("sps:%s:pipe is NULL.\n", __func__);
-		return SPS_ERROR;
-	}
-
 	if (sps == NULL)
 		return -ENODEV;
 
@@ -1461,6 +1458,11 @@
 		return SPS_ERROR;
 	}
 
+	if (h == NULL)
+		SPS_DBG("sps:allocate pipe memory before setup pipe");
+	else
+		SPS_DBG("sps:allocate pipe memory for pipe %d", h->pipe_index);
+
 	mem_buffer->phys_base = sps_mem_alloc_io(mem_buffer->size);
 	if (mem_buffer->phys_base == SPS_ADDR_INVALID) {
 		SPS_ERR("sps:invalid address of allocated memory");
@@ -1481,16 +1483,16 @@
 {
 	SPS_DBG("sps:%s.", __func__);
 
-	if (h == NULL) {
-		SPS_ERR("sps:%s:pipe is NULL.\n", __func__);
-		return SPS_ERROR;
-	}
-
 	if (mem_buffer == NULL || mem_buffer->phys_base == SPS_ADDR_INVALID) {
 		SPS_ERR("sps:invalid memory to free");
 		return SPS_ERROR;
 	}
 
+	if (h == NULL)
+		SPS_DBG("sps:free pipe memory.");
+	else
+		SPS_DBG("sps:free pipe memory for pipe %d.", h->pipe_index);
+
 	sps_mem_free_io(mem_buffer->phys_base, mem_buffer->size);
 
 	return 0;
@@ -1928,13 +1930,20 @@
 
 	if (of_property_read_u32((&pdev->dev)->of_node,
 				"qcom,bam-dma-res-pipes",
-				&sps->bamdma_restricted_pipes)) {
-		SPS_ERR("sps:Fail to get restricted bamdma pipes.\n");
-		return -EINVAL;
-	} else
+				&sps->bamdma_restricted_pipes))
+		SPS_DBG("sps:No restricted bamdma pipes on this target.\n");
+	else
 		SPS_DBG("sps:bamdma_restricted_pipes=0x%x.",
 			sps->bamdma_restricted_pipes);
 
+	if (of_property_read_u32((&pdev->dev)->of_node,
+				"qcom,device-type",
+				&d_type)) {
+		d_type = 1;
+		SPS_DBG("sps:default device type.\n");
+	} else
+		SPS_DBG("sps:device type is %d.", d_type);
+
 	resource  = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (resource) {
 		sps->bamdma_bam_phys_base = resource->start;
@@ -1959,6 +1968,16 @@
 		return -ENODEV;
 	}
 
+	resource = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (resource) {
+		sps->pipemem_phys_base = resource->start;
+		sps->pipemem_size = resource_size(resource);
+		SPS_DBG("sps:pipemem.base=0x%x,size=0x%x.",
+			sps->pipemem_phys_base,
+			sps->pipemem_size);
+	} else
+		SPS_DBG("sps:No pipe memory on this target.\n");
+
 	resource  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (resource) {
 		sps->bamdma_irq = resource->start;
@@ -1985,6 +2004,7 @@
 		} else
 			SPS_DBG("sps:get data from device tree.");
 	} else {
+		d_type = 0;
 		if (get_platform_data(pdev)) {
 			SPS_ERR("sps:Fail to get platform data.");
 			return -ENODEV;
@@ -2008,17 +2028,18 @@
 		goto device_create_err;
 	}
 
-	sps->dfab_clk = clk_get(sps->dev, "dfab_clk");
-	if (IS_ERR(sps->dfab_clk)) {
-		SPS_ERR("sps:fail to get dfab_clk.");
-		goto clk_err;
-	} else {
-		ret = clk_set_rate(sps->dfab_clk, 64000000);
-		if (ret) {
-			SPS_ERR("sps:failed to set dfab_clk rate. "
-					"ret=%d", ret);
-			clk_put(sps->dfab_clk);
+	if (!d_type) {
+		sps->dfab_clk = clk_get(sps->dev, "dfab_clk");
+		if (IS_ERR(sps->dfab_clk)) {
+			SPS_ERR("sps:fail to get dfab_clk.");
 			goto clk_err;
+		} else {
+			ret = clk_set_rate(sps->dfab_clk, 64000000);
+			if (ret) {
+				SPS_ERR("sps:failed to set dfab_clk rate.");
+				clk_put(sps->dfab_clk);
+				goto clk_err;
+			}
 		}
 	}
 
@@ -2047,22 +2068,26 @@
 		}
 	}
 
-	ret = clk_prepare_enable(sps->dfab_clk);
-	if (ret) {
-		SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
-		goto clk_err;
+	if (!d_type) {
+		ret = clk_prepare_enable(sps->dfab_clk);
+		if (ret) {
+			SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
+			goto clk_err;
+		}
 	}
 #endif
 	ret = sps_device_init();
 	if (ret) {
 		SPS_ERR("sps:sps_device_init err.");
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
-		clk_disable_unprepare(sps->dfab_clk);
+		if (!d_type)
+			clk_disable_unprepare(sps->dfab_clk);
 #endif
 		goto sps_device_init_err;
 	}
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
-	clk_disable_unprepare(sps->dfab_clk);
+	if (!d_type)
+		clk_disable_unprepare(sps->dfab_clk);
 #endif
 	sps->is_ready = true;
 
@@ -2089,7 +2114,8 @@
 	class_destroy(sps->dev_class);
 	sps_device_de_init();
 
-	clk_put(sps->dfab_clk);
+	if (!d_type)
+		clk_put(sps->dfab_clk);
 	clk_put(sps->pmem_clk);
 	clk_put(sps->bamdma_clk);
 
diff --git a/drivers/platform/msm/sps/sps_mem.c b/drivers/platform/msm/sps/sps_mem.c
index 1b19b12..fa22f1c 100644
--- a/drivers/platform/msm/sps/sps_mem.c
+++ b/drivers/platform/msm/sps/sps_mem.c
@@ -104,31 +104,30 @@
  */
 int sps_mem_init(u32 pipemem_phys_base, u32 pipemem_size)
 {
-#ifndef CONFIG_SPS_SUPPORT_NDP_BAM
 	int res;
-#endif
+
 	/* 2^8=128. The desc-fifo and data-fifo minimal allocation. */
 	int min_alloc_order = 8;
 
-#ifndef CONFIG_SPS_SUPPORT_NDP_BAM
-	iomem_phys = pipemem_phys_base;
-	iomem_size = pipemem_size;
+	if ((d_type == 0) || (d_type == 2)) {
+		iomem_phys = pipemem_phys_base;
+		iomem_size = pipemem_size;
 
-	if (iomem_phys == 0) {
-		SPS_ERR("sps:Invalid Pipe-Mem address");
-		return SPS_ERROR;
-	} else {
-		iomem_virt = ioremap(iomem_phys, iomem_size);
-		if (!iomem_virt) {
-			SPS_ERR("sps:Failed to IO map pipe memory.\n");
-			return -ENOMEM;
+		if (iomem_phys == 0) {
+			SPS_ERR("sps:Invalid Pipe-Mem address");
+			return SPS_ERROR;
+		} else {
+			iomem_virt = ioremap(iomem_phys, iomem_size);
+			if (!iomem_virt) {
+				SPS_ERR("sps:Failed to IO map pipe memory.\n");
+				return -ENOMEM;
+			}
 		}
-	}
 
-	iomem_offset = 0;
-	SPS_DBG("sps:sps_mem_init.iomem_phys=0x%x,iomem_virt=0x%x.",
-		iomem_phys, (u32) iomem_virt);
-#endif
+		iomem_offset = 0;
+		SPS_DBG("sps:sps_mem_init.iomem_phys=0x%x,iomem_virt=0x%x.",
+			iomem_phys, (u32) iomem_virt);
+	}
 
 	pool = gen_pool_create(min_alloc_order, nid);
 
@@ -137,11 +136,11 @@
 		return -ENOMEM;
 	}
 
-#ifndef CONFIG_SPS_SUPPORT_NDP_BAM
-	res = gen_pool_add(pool, (u32) iomem_virt, iomem_size, nid);
-	if (res)
-		return res;
-#endif
+	if ((d_type == 0) || (d_type == 2)) {
+		res = gen_pool_add(pool, (u32) iomem_virt, iomem_size, nid);
+		if (res)
+			return res;
+	}
 
 	return 0;
 }
diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h
index e8ab832..5a141ca 100644
--- a/drivers/platform/msm/sps/spsi.h
+++ b/drivers/platform/msm/sps/spsi.h
@@ -40,6 +40,8 @@
 /* "Clear" value for the connection parameter struct */
 #define SPSRM_CLEAR     0xcccccccc
 
+extern u32 d_type;
+
 #ifdef CONFIG_DEBUG_FS
 extern u8 debugfs_record_enabled;
 extern u8 logging_option;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index b0439bc..73c042d 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -100,8 +100,6 @@
 	struct sf_lut		*rbatt_sf_lut;
 	int			delta_rbatt_mohm;
 	struct work_struct	calib_hkadc_work;
-	struct delayed_work	calib_ccadc_work;
-	unsigned int		calib_delay_ms;
 	unsigned int		revision;
 	unsigned int		xoadc_v0625_usb_present;
 	unsigned int		xoadc_v0625_usb_absent;
@@ -1604,18 +1602,6 @@
 	schedule_work(&the_chip->calib_hkadc_work);
 }
 
-static void calibrate_ccadc_work(struct work_struct *work)
-{
-	struct pm8921_bms_chip *chip = container_of(work,
-				struct pm8921_bms_chip, calib_ccadc_work.work);
-
-	pm8xxx_calib_ccadc();
-	calib_hkadc(chip);
-	schedule_delayed_work(&chip->calib_ccadc_work,
-			round_jiffies_relative(msecs_to_jiffies
-			(chip->calib_delay_ms)));
-}
-
 int pm8921_bms_get_vsense_avg(int *result)
 {
 	int rc = -EINVAL;
@@ -2601,7 +2587,6 @@
 	chip->r_sense = pdata->r_sense;
 	chip->i_test = pdata->i_test;
 	chip->v_failure = pdata->v_failure;
-	chip->calib_delay_ms = pdata->calib_delay_ms;
 	chip->max_voltage_uv = pdata->max_voltage_uv;
 	chip->batt_type = pdata->battery_type;
 	chip->rconn_mohm = pdata->rconn_mohm;
@@ -2655,11 +2640,6 @@
 	}
 	check_initial_ocv(chip);
 
-	INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
-	/* begin calibration only on chips > 2.0 */
-	if (chip->revision >= PM8XXX_REVISION_8921_2p0)
-		schedule_delayed_work(&chip->calib_ccadc_work, 0);
-
 	/* initial hkadc calibration */
 	schedule_work(&chip->calib_hkadc_work);
 	/* enable the vbatt reading interrupts for scheduling hkadc calib */
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index c983389..a1561f0 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -3308,6 +3308,9 @@
 	int rc;
 	int vdd_safe;
 
+	/* forcing 19p2mhz before accessing any charger registers */
+	pm8921_chg_force_19p2mhz_clk(chip);
+
 	rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
 					BOOT_DONE_BIT, BOOT_DONE_BIT);
 	if (rc) {
@@ -3501,8 +3504,6 @@
 	/* 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)
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index ce72a5b..ef31575 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -70,8 +70,10 @@
 	u16			ccadc_offset;
 	int			ccadc_gain_uv;
 	unsigned int		revision;
+	unsigned int		calib_delay_ms;
 	int			eoc_irq;
 	int			r_sense;
+	struct delayed_work	calib_ccadc_work;
 };
 
 static struct pm8xxx_ccadc_chip *the_chip;
@@ -334,6 +336,11 @@
 	u16 result;
 	int i, rc;
 
+	if (!the_chip) {
+		pr_err("chip not initialized\n");
+		return;
+	}
+
 	rc = pm8xxx_readb(the_chip->dev->parent,
 					ADC_ARB_SECP_CNTRL, &sec_cntrl);
 	if (rc < 0) {
@@ -473,6 +480,17 @@
 }
 EXPORT_SYMBOL(pm8xxx_calib_ccadc);
 
+static void calibrate_ccadc_work(struct work_struct *work)
+{
+	struct pm8xxx_ccadc_chip *chip = container_of(work,
+			struct pm8xxx_ccadc_chip, calib_ccadc_work.work);
+
+	pm8xxx_calib_ccadc();
+	schedule_delayed_work(&chip->calib_ccadc_work,
+			round_jiffies_relative(msecs_to_jiffies
+			(chip->calib_delay_ms)));
+}
+
 static irqreturn_t pm8921_bms_ccadc_eoc_handler(int irq, void *data)
 {
 	u8 data_msb, data_lsb;
@@ -671,6 +689,7 @@
 	chip->revision = pm8xxx_get_revision(chip->dev->parent);
 	chip->eoc_irq = res->start;
 	chip->r_sense = pdata->r_sense;
+	chip->calib_delay_ms = pdata->calib_delay_ms;
 
 	calib_ccadc_read_offset_and_gain(chip,
 					&chip->ccadc_gain_uv,
@@ -682,6 +701,10 @@
 		pr_err("failed to request %d irq rc= %d\n", chip->eoc_irq, rc);
 		goto free_chip;
 	}
+
+	INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
+	schedule_delayed_work(&chip->calib_ccadc_work, 0);
+
 	disable_irq_nosync(chip->eoc_irq);
 
 	platform_set_drvdata(pdev, chip);
diff --git a/drivers/power/smb349.c b/drivers/power/smb349.c
index 4c07285..ffc92d5 100644
--- a/drivers/power/smb349.c
+++ b/drivers/power/smb349.c
@@ -86,11 +86,11 @@
 
 	int			en_n_gpio;
 	int			chg_susp_gpio;
-	struct dentry			*dent;
-	spinlock_t			lock;
-	struct work_struct			hwinit_work;
+	struct dentry		*dent;
+	spinlock_t		lock;
 
-	struct power_supply			dc_psy;
+	struct work_struct	chg_work;
+	struct power_supply	dc_psy;
 };
 
 struct chg_ma_limit_entry {
@@ -244,7 +244,7 @@
 {
 	int addr = (int)data;
 	int ret;
-	u8 temp;
+	u8 temp = 0;
 
 	ret = smb349_read_reg(the_smb349_chg->client, addr, &temp);
 	if (ret) {
@@ -445,16 +445,17 @@
 static int smb349_stop_charging(struct smb349_struct *smb349_chg)
 {
 	unsigned long flags;
-
-	if (smb349_chg->charging)
-		gpio_set_value_cansleep(smb349_chg->en_n_gpio, 0);
+	int rc = 0;
 
 	spin_lock_irqsave(&smb349_chg->lock, flags);
 	pr_debug("stop charging %d\n", smb349_chg->charging);
 	smb349_chg->charging = 0;
 	spin_unlock_irqrestore(&smb349_chg->lock, flags);
-	power_supply_changed(&smb349_chg->dc_psy);
-	return 0;
+
+	if (smb349_chg->charging)
+		rc = schedule_work(&smb349_chg->chg_work);
+
+	return rc;
 }
 
 static int smb349_start_charging(struct smb349_struct *smb349_chg)
@@ -463,21 +464,14 @@
 	int rc;
 
 	rc = 0;
-	if (!smb349_chg->charging) {
-		gpio_set_value_cansleep(smb349_chg->en_n_gpio, 1);
-		/*
-		 * Write non-default values, charger chip reloads from
-		 * non-volatile memory if it was in suspend mode
-		 *
-		 */
-		rc = schedule_work(&smb349_chg->hwinit_work);
-	}
-
 	spin_lock_irqsave(&smb349_chg->lock, flags);
 	pr_debug("start charging %d\n", smb349_chg->charging);
 	smb349_chg->charging = 1;
 	spin_unlock_irqrestore(&smb349_chg->lock, flags);
-	power_supply_changed(&smb349_chg->dc_psy);
+
+	if (!smb349_chg->charging)
+		rc = schedule_work(&smb349_chg->chg_work);
+
 	return rc;
 }
 
@@ -522,15 +516,25 @@
 	return 0;
 }
 
-static void hwinit_worker(struct work_struct *work)
+static void chg_worker(struct work_struct *work)
 {
-	int ret;
 	struct smb349_struct *smb349_chg = container_of(work,
-				struct smb349_struct, hwinit_work);
+				struct smb349_struct, chg_work);
+	int ret = 0;
 
-	ret = smb349_hwinit(smb349_chg);
+	gpio_set_value_cansleep(smb349_chg->en_n_gpio, smb349_chg->charging);
+
+	/*
+	 * Write non-default values, charger chip reloads from
+	 * non-volatile memory if it was in suspend mode
+	 *
+	 */
+	if (smb349_chg->charging)
+		ret = smb349_hwinit(smb349_chg);
 	if (ret)
 		pr_err("Failed to re-initilaze registers\n");
+
+	power_supply_changed(&smb349_chg->dc_psy);
 }
 
 static int __devinit smb349_init_ext_chg(struct smb349_struct *smb349_chg)
@@ -614,7 +618,7 @@
 	the_smb349_chg = smb349_chg;
 
 	create_debugfs_entries(smb349_chg);
-	INIT_WORK(&smb349_chg->hwinit_work, hwinit_worker);
+	INIT_WORK(&smb349_chg->chg_work, chg_worker);
 
 	pr_info("OK connector present = %d\n", smb349_chg->present);
 	return 0;
@@ -634,7 +638,7 @@
 	const struct smb349_platform_data *pdata;
 	struct smb349_struct *smb349_chg = i2c_get_clientdata(client);
 
-	flush_work(&smb349_chg->hwinit_work);
+	flush_work(&smb349_chg->chg_work);
 	pdata = client->dev.platform_data;
 	power_supply_unregister(&smb349_chg->dc_psy);
 	gpio_free(pdata->en_n_gpio);
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 65bcb08..d03b4b4 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -78,6 +78,11 @@
 			pr_info(x);  \
 } while (0)
 
+#define SMUX_PWR(x...) do {                              \
+	if (smux_debug_mask & MSM_SMUX_POWER_INFO) \
+			pr_info(x);  \
+} while (0)
+
 #define SMUX_LOG_PKT_RX(pkt) do { \
 	if (smux_debug_mask & MSM_SMUX_PKT) \
 			smux_log_pkt(pkt, 1); \
@@ -448,6 +453,7 @@
 		pkt =  list_first_entry(&smux.power_queue,
 						struct smux_pkt_t,
 						list);
+		list_del(&pkt->list);
 		SMUX_DBG("%s: emptying power queue pkt=%p\n",
 				__func__, pkt);
 		smux_free_pkt(pkt);
@@ -1005,7 +1011,6 @@
 	pkt->hdr.cmd = SMUX_CMD_BYTE;
 	pkt->hdr.flags = ch;
 	pkt->hdr.lcid = SMUX_BROADCAST_LCID;
-	pkt->hdr.flags = ch;
 
 	list_add_tail(&pkt->list, &smux.power_queue);
 	queue_work(smux_tx_wq, &smux_tx_work);
@@ -1601,7 +1606,7 @@
 		/* local sleep request ack */
 		if (smux.power_state == SMUX_PWR_TURNING_OFF) {
 			/* Power-down complete, turn off UART */
-			SMUX_DBG("%s: Power %d->%d\n", __func__,
+			SMUX_PWR("%s: Power %d->%d\n", __func__,
 					smux.power_state, SMUX_PWR_OFF_FLUSH);
 			smux.power_state = SMUX_PWR_OFF_FLUSH;
 			queue_work(smux_tx_wq, &smux_inactivity_work);
@@ -1625,7 +1630,7 @@
 			|| smux.power_state == SMUX_PWR_TURNING_OFF) {
 			ack_pkt = smux_alloc_pkt();
 			if (ack_pkt) {
-				SMUX_DBG("%s: Power %d->%d\n", __func__,
+				SMUX_PWR("%s: Power %d->%d\n", __func__,
 						smux.power_state,
 						SMUX_PWR_TURNING_OFF_FLUSH);
 
@@ -1658,24 +1663,44 @@
  */
 static int smux_dispatch_rx_pkt(struct smux_pkt_t *pkt)
 {
-	int ret;
+	int ret = -ENXIO;
 
 	SMUX_LOG_PKT_RX(pkt);
 
 	switch (pkt->hdr.cmd) {
 	case SMUX_CMD_OPEN_LCH:
+		if (smux_assert_lch_id(pkt->hdr.lcid)) {
+			pr_err("%s: invalid channel id %d\n",
+					__func__, pkt->hdr.lcid);
+			break;
+		}
 		ret = smux_handle_rx_open_cmd(pkt);
 		break;
 
 	case SMUX_CMD_DATA:
+		if (smux_assert_lch_id(pkt->hdr.lcid)) {
+			pr_err("%s: invalid channel id %d\n",
+					__func__, pkt->hdr.lcid);
+			break;
+		}
 		ret = smux_handle_rx_data_cmd(pkt);
 		break;
 
 	case SMUX_CMD_CLOSE_LCH:
+		if (smux_assert_lch_id(pkt->hdr.lcid)) {
+			pr_err("%s: invalid channel id %d\n",
+					__func__, pkt->hdr.lcid);
+			break;
+		}
 		ret = smux_handle_rx_close_cmd(pkt);
 		break;
 
 	case SMUX_CMD_STATUS:
+		if (smux_assert_lch_id(pkt->hdr.lcid)) {
+			pr_err("%s: invalid channel id %d\n",
+					__func__, pkt->hdr.lcid);
+			break;
+		}
 		ret = smux_handle_rx_status_cmd(pkt);
 		break;
 
@@ -1705,7 +1730,6 @@
 static int smux_deserialize(unsigned char *data, int len)
 {
 	struct smux_pkt_t recv;
-	uint8_t lcid;
 
 	smux_init_pkt(&recv);
 
@@ -1720,12 +1744,6 @@
 		return -EINVAL;
 	}
 
-	lcid = recv.hdr.lcid;
-	if (smux_assert_lch_id(lcid)) {
-		pr_err("%s: invalid channel id %d\n", __func__, lcid);
-		return -ENXIO;
-	}
-
 	if (recv.hdr.payload_len)
 		recv.payload = data + sizeof(struct smux_hdr_t);
 
@@ -1743,7 +1761,7 @@
 	if (smux.power_state == SMUX_PWR_OFF
 		|| smux.power_state == SMUX_PWR_TURNING_ON) {
 		/* wakeup system */
-		SMUX_DBG("%s: Power %d->%d\n", __func__,
+		SMUX_PWR("%s: Power %d->%d\n", __func__,
 				smux.power_state, SMUX_PWR_ON);
 		smux.power_state = SMUX_PWR_ON;
 		queue_work(smux_tx_wq, &smux_wakeup_work);
@@ -1767,7 +1785,7 @@
 	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
 	if (smux.power_state == SMUX_PWR_TURNING_ON) {
 		/* received response to wakeup request */
-		SMUX_DBG("%s: Power %d->%d\n", __func__,
+		SMUX_PWR("%s: Power %d->%d\n", __func__,
 				smux.power_state, SMUX_PWR_ON);
 		smux.power_state = SMUX_PWR_ON;
 		queue_work(smux_tx_wq, &smux_tx_work);
@@ -2201,7 +2219,7 @@
 				/* start power-down sequence */
 				pkt = smux_alloc_pkt();
 				if (pkt) {
-					SMUX_DBG("%s: Power %d->%d\n", __func__,
+					SMUX_PWR("%s: Power %d->%d\n", __func__,
 						smux.power_state,
 						SMUX_PWR_TURNING_OFF);
 					smux.power_state = SMUX_PWR_TURNING_OFF;
@@ -2228,9 +2246,9 @@
 
 	if (smux.power_state == SMUX_PWR_OFF_FLUSH) {
 		/* ready to power-down the UART */
-		smux.power_state = SMUX_PWR_OFF;
-		SMUX_DBG("%s: Power %d->%d\n", __func__,
+		SMUX_PWR("%s: Power %d->%d\n", __func__,
 				smux.power_state, SMUX_PWR_OFF);
+		smux.power_state = SMUX_PWR_OFF;
 
 		/* if data is pending, schedule a new wakeup */
 		if (!list_empty(&smux.lch_tx_ready_list) ||
@@ -2455,7 +2473,7 @@
 			   !list_empty(&smux.power_queue)) {
 				/* data to transmit, do wakeup */
 				smux.pwr_wakeup_delay_us = 1;
-				SMUX_DBG("%s: Power %d->%d\n", __func__,
+				SMUX_PWR("%s: Power %d->%d\n", __func__,
 						smux.power_state,
 						SMUX_PWR_TURNING_ON);
 				smux.power_state = SMUX_PWR_TURNING_ON;
@@ -2492,7 +2510,7 @@
 			if (smux.power_state == SMUX_PWR_TURNING_OFF_FLUSH &&
 				pkt->hdr.cmd == SMUX_CMD_PWR_CTL &&
 				(pkt->hdr.flags & SMUX_CMD_PWR_CTL_ACK)) {
-				SMUX_DBG("%s: Power %d->%d\n", __func__,
+				SMUX_PWR("%s: Power %d->%d\n", __func__,
 						smux.power_state,
 						SMUX_PWR_OFF_FLUSH);
 				smux.power_state = SMUX_PWR_OFF_FLUSH;
@@ -3106,24 +3124,39 @@
 	unsigned long flags;
 	int power_off_uart = 0;
 
-	if (code != SUBSYS_AFTER_SHUTDOWN)
+	if (code == SUBSYS_BEFORE_SHUTDOWN) {
+		SMUX_DBG("%s: ssr - before shutdown\n", __func__);
+		mutex_lock(&smux.mutex_lha0);
+		smux.in_reset = 1;
+		mutex_unlock(&smux.mutex_lha0);
 		return NOTIFY_DONE;
+	} else if (code != SUBSYS_AFTER_SHUTDOWN) {
+		return NOTIFY_DONE;
+	}
+	SMUX_DBG("%s: ssr - after shutdown\n", __func__);
 
 	/* Cleanup channels */
+	mutex_lock(&smux.mutex_lha0);
 	smux_lch_purge();
+	if (smux.tty)
+		tty_driver_flush_buffer(smux.tty);
 
 	/* Power-down UART */
 	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
 	if (smux.power_state != SMUX_PWR_OFF) {
-		SMUX_DBG("%s: SSR - turning off UART\n", __func__);
+		SMUX_PWR("%s: SSR - turning off UART\n", __func__);
 		smux.power_state = SMUX_PWR_OFF;
 		power_off_uart = 1;
 	}
+	smux.powerdown_enabled = 0;
 	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 
 	if (power_off_uart)
 		smux_uart_power_off();
 
+	smux.in_reset = 0;
+	mutex_unlock(&smux.mutex_lha0);
+
 	return NOTIFY_DONE;
 }
 
@@ -3173,7 +3206,7 @@
 	/* power-down the UART if we are idle */
 	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
 	if (smux.power_state == SMUX_PWR_OFF) {
-		SMUX_DBG("%s: powering off uart\n", __func__);
+		SMUX_PWR("%s: powering off uart\n", __func__);
 		smux.power_state = SMUX_PWR_OFF_FLUSH;
 		spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 		queue_work(smux_tx_wq, &smux_inactivity_work);
@@ -3227,6 +3260,7 @@
 	if (smux.power_state == SMUX_PWR_OFF)
 		power_up_uart = 1;
 	smux.power_state = SMUX_PWR_OFF;
+	smux.powerdown_enabled = 0;
 	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 
 	if (power_up_uart)
@@ -3371,7 +3405,7 @@
 		return ret;
 	}
 
-	subsys_notif_register_notifier("qsc", &ssr_notifier);
+	subsys_notif_register_notifier("external_modem", &ssr_notifier);
 
 	ret = lch_init();
 	if (ret != 0) {
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 4a65177..5735534 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -628,8 +628,8 @@
 		break;
 	}
 
-	/* Set timeout to be ~100x the character transmit time */
-	msm_hsl_port->tx_timeout = 1000000000 / baud;
+	/* Set timeout to be ~600x the character transmit time */
+	msm_hsl_port->tx_timeout = (1000000000 / baud) * 6;
 
 	vid = msm_hsl_port->ver_id;
 	msm_hsl_write(port, baud_code, regmap[vid][UARTDM_CSR]);
diff --git a/drivers/tty/smux_loopback.c b/drivers/tty/smux_loopback.c
index bf6d50b..c4374bb 100644
--- a/drivers/tty/smux_loopback.c
+++ b/drivers/tty/smux_loopback.c
@@ -174,13 +174,15 @@
 		}
 
 		lcid = pkt->hdr.lcid;
-		if (smux_assert_lch_id(lcid)) {
-			pr_err("%s: invalid channel id %d\n", __func__, lcid);
-			return;
-		}
 
 		switch (pkt->hdr.cmd) {
 		case SMUX_CMD_OPEN_LCH:
+			if (smux_assert_lch_id(lcid)) {
+				pr_err("%s: invalid channel id %d\n",
+						__func__, lcid);
+				break;
+			}
+
 			if (pkt->hdr.flags & SMUX_CMD_OPEN_ACK)
 				break;
 
@@ -207,6 +209,12 @@
 			break;
 
 		case SMUX_CMD_CLOSE_LCH:
+			if (smux_assert_lch_id(lcid)) {
+				pr_err("%s: invalid channel id %d\n",
+						__func__, lcid);
+				break;
+			}
+
 			if (pkt->hdr.flags == SMUX_CMD_CLOSE_ACK)
 				break;
 
@@ -232,6 +240,12 @@
 			break;
 
 		case SMUX_CMD_DATA:
+			if (smux_assert_lch_id(lcid)) {
+				pr_err("%s: invalid channel id %d\n",
+						__func__, lcid);
+				break;
+			}
+
 			/* Echo back received data */
 			smux_init_pkt(&reply_pkt);
 			reply_pkt.hdr.lcid = lcid;
@@ -245,6 +259,12 @@
 			break;
 
 		case SMUX_CMD_STATUS:
+			if (smux_assert_lch_id(lcid)) {
+				pr_err("%s: invalid channel id %d\n",
+						__func__, lcid);
+				break;
+			}
+
 			/* Echo back received status */
 			smux_init_pkt(&reply_pkt);
 			reply_pkt.hdr.lcid = lcid;
@@ -260,7 +280,7 @@
 		case SMUX_CMD_PWR_CTL:
 			/* reply with ack */
 			smux_init_pkt(&reply_pkt);
-			reply_pkt.hdr.lcid = lcid;
+			reply_pkt.hdr.lcid = SMUX_BROADCAST_LCID;
 			reply_pkt.hdr.cmd = SMUX_CMD_PWR_CTL;
 			reply_pkt.hdr.flags = SMUX_CMD_PWR_CTL_ACK;
 			reply_pkt.hdr.payload_len = 0;
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index d8f741f..742beef 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -3,7 +3,6 @@
 	depends on (USB && USB_GADGET)
 	select USB_OTG_UTILS
 	select USB_GADGET_DUALSPEED
-	select USB_GADGET_SUPERSPEED
 	select USB_XHCI_PLATFORM
 	help
 	  Say Y or M here if your system has a Dual Role SuperSpeed
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 81ce143..5a79cae 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -82,6 +82,12 @@
 
 #define DBM_MAX_EPS		4
 
+/* DBM TRB configurations */
+#define DBM_TRB_BIT		0x80000000
+#define DBM_TRB_DATA_SRC	0x40000000
+#define DBM_TRB_DMA		0x20000000
+#define DBM_TRB_EP_NUM(ep)	(ep<<24)
+
 struct dwc3_msm_req_complete {
 	struct list_head list_item;
 	struct usb_request *req;
@@ -507,19 +513,12 @@
 */
 static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 {
-	struct dwc3_trb_hw *trb_hw;
-	struct dwc3_trb_hw *trb_link_hw;
-	struct dwc3_trb trb;
+	struct dwc3_trb *trb;
+	struct dwc3_trb *trb_link;
 	struct dwc3_gadget_ep_cmd_params params;
 	u32 cmd;
 	int ret = 0;
 
-	if ((req->request.udc_priv & MSM_IS_FINITE_TRANSFER) &&
-	    (req->request.length > 0)) {
-		/* Map the request to a DMA. */
-		dwc3_map_buffer_to_dma(req);
-	}
-
 	/* We push the request to the dep->req_queued list to indicate that
 	 * this request is issued with start transfer. The request will be out
 	 * from this list in 2 cases. The first is that the transfer will be
@@ -531,31 +530,26 @@
 	list_add_tail(&req->list, &dep->req_queued);
 
 	/* First, prepare a normal TRB, point to the fake buffer */
-	trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+	trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
 	dep->free_slot++;
-	memset(&trb, 0, sizeof(trb));
+	memset(trb, 0, sizeof(*trb));
 
-	req->trb = trb_hw;
-
-	trb.bplh = req->request.dma;
-	trb.lst = 0;
-	trb.trbctl = DWC3_TRBCTL_NORMAL;
-	trb.length = req->request.length;
-	trb.hwo = true;
-
-	dwc3_trb_to_hw(&trb, trb_hw);
-	req->trb_dma = dep->trb_pool_dma;
+	req->trb = trb;
+	req->trb_dma = dwc3_trb_dma_offset(dep, trb);
+	trb->bph = DBM_TRB_BIT | DBM_TRB_DATA_SRC |
+		   DBM_TRB_DMA | DBM_TRB_EP_NUM(dep->number);
+	trb->size = DWC3_TRB_SIZE_LENGTH(req->request.length);
+	trb->ctrl = DWC3_TRBCTL_NORMAL | DWC3_TRB_CTRL_HWO | DWC3_TRB_CTRL_CHN;
 
 	/* Second, prepare a Link TRB that points to the first TRB*/
-	trb_link_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+	trb_link = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
 	dep->free_slot++;
-	memset(&trb, 0, sizeof(trb));
 
-	trb.bplh = dep->trb_pool_dma;
-	trb.trbctl = DWC3_TRBCTL_LINK_TRB;
-	trb.hwo = true;
-
-	dwc3_trb_to_hw(&trb, trb_link_hw);
+	trb_link->bpl = lower_32_bits(req->trb_dma);
+	trb_link->bph = DBM_TRB_BIT | DBM_TRB_DATA_SRC |
+			DBM_TRB_DMA | DBM_TRB_EP_NUM(dep->number);
+	trb_link->size = 0;
+	trb_link->ctrl = DWC3_TRBCTL_LINK_TRB | DWC3_TRB_CTRL_HWO;
 
 	/*
 	 * Now start the transfer
@@ -570,7 +564,6 @@
 			"%s: failed to send STARTTRANSFER command\n",
 			__func__);
 
-		dwc3_unmap_buffer_from_dma(req);
 		list_del(&req->list);
 		return ret;
 	}
@@ -1115,7 +1108,7 @@
 		goto disable_hs_ldo;
 	}
 
-	dwc3 = platform_device_alloc("dwc3-msm", -1);
+	dwc3 = platform_device_alloc("dwc3", -1);
 	if (!dwc3) {
 		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
 		ret = -ENODEV;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5255fe9..a988c43 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -313,7 +313,7 @@
 	} while (1);
 }
 
-static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
+dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
 		struct dwc3_trb *trb)
 {
 	u32		offset = (char *) trb - (char *) dep->trb_pool;
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index a860008..662682e 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -111,6 +111,8 @@
 int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
 int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
 		unsigned cmd, struct dwc3_gadget_ep_cmd_params *params);
+dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
+		struct dwc3_trb *trb);
 
 /**
  * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 14b07e5..95f11c1 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -506,6 +506,32 @@
 	  dynamically linked module called "ci13xxx_msm_hsic" and force all
 	  gadget drivers to also be dynamically linked.
 
+config USB_DWC3_MSM
+	tristate "DesignWare USB3.0 (DRD) Controller for MSM"
+	depends on ARCH_MSM
+	select USB_DWC3
+	select USB_GADGET_DUALSPEED
+	select USB_GADGET_SELECTED
+	help
+	  The DesignWare USB3.0 controller is a SuperSpeed USB3.0 Controller
+	  integrated into the Qualcomm MSM chipset series, supporting host,
+	  device and otg modes of operation. For more information please
+	  refer to http://www.qualcomm.com/chipsets.
+
+config USB_DWC3_OMAP
+	tristate "DesignWare USB3.0 (DRD) Controller for OMAP"
+	depends on ARCH_OMAP
+	select USB_DWC3
+	select USB_GADGET_DUALSPEED
+	select USB_GADGET_SUPERSPEED
+	select USB_GADGET_SELECTED
+	help
+	  DesignWare USB3.0 controller is a SuperSpeed USB3.0 Controller
+	  which can be configured for peripheral-only, host-only, hub-only
+	  and Dual-Role operation. This Controller was first integrated into
+	  the OMAP5 series of processors. More information about the OMAP5
+	  version of this controller, refer to http://www.ti.com/omap5.
+
 #
 # LAST -- dummy/emulated controller
 #
@@ -556,8 +582,15 @@
 
 # Selected by UDC drivers that support super-speed opperation
 config USB_GADGET_SUPERSPEED
-	bool
+	bool "Operate as superspeed"
+	depends on USB_GADGET
 	depends on USB_GADGET_DUALSPEED
+	default n
+	help
+	 When a superspeed peripheral controller is selected
+	 (for example DesignWare USB3.0 controller), use this flag to
+	 indicate if the device should operate in superspeed(=y)
+	 or not.
 
 #
 # USB Gadget Drivers
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index eefe95f..be8e6aa 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -1546,7 +1546,9 @@
 {									\
 	if (size >= sizeof(buffer))					\
 		return -EINVAL;						\
-	return strlcpy(buffer, buf, sizeof(buffer));			\
+	strlcpy(buffer, buf, sizeof(buffer));				\
+	strim(buffer);							\
+	return size;							\
 }									\
 static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
 
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 1cbaa8e..e3c1216 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -56,7 +56,7 @@
 
 	if (_udc_ctxt.wake_irq && _udc_ctxt.wake_irq_state) {
 		disable_irq_wake(_udc_ctxt.wake_irq);
-		disable_irq(_udc_ctxt.wake_irq);
+		disable_irq_nosync(_udc_ctxt.wake_irq);
 		_udc_ctxt.wake_irq_state = false;
 	}
 }
@@ -134,7 +134,7 @@
 	dev_dbg(&pdev->dev, "_udc_ctxt.gpio_irq = %d and irq = %d\n",
 			_udc_ctxt.wake_gpio, wake_irq);
 	ret = request_irq(wake_irq, ci13xxx_msm_resume_irq,
-		IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "usb resume", NULL);
+		IRQF_TRIGGER_RISING | IRQF_ONESHOT, "usb resume", NULL);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "could not register USB_RESUME IRQ.\n");
 		goto gpio_free;
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
index 39d4720..30b45eb 100644
--- a/drivers/usb/gadget/ci13xxx_msm_hsic.c
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -30,16 +30,16 @@
 #include <mach/clk.h>
 #include <mach/msm_iomap.h>
 #include <mach/msm_xo.h>
+#include <mach/rpm-regulator.h>
 
 #include "ci13xxx_udc.c"
 
 #define MSM_USB_BASE	(mhsic->regs)
 
 #define ULPI_IO_TIMEOUT_USEC			(10 * 1000)
-#define USB_PHY_VDD_DIG_VOL_SUSP_MIN	500000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_NONE		0 /*uV */
 #define USB_PHY_VDD_DIG_VOL_MIN			1045000 /* uV */
 #define USB_PHY_VDD_DIG_VOL_MAX			1320000 /* uV */
-#define USB_PHY_VDD_DIG_LOAD			49360	/* uA */
 #define LINK_RESET_TIMEOUT_USEC			(250 * 1000)
 #define PHY_SUSPEND_TIMEOUT_USEC		(500 * 1000)
 #define PHY_RESUME_TIMEOUT_USEC			(100 * 1000)
@@ -66,38 +66,56 @@
 	struct workqueue_struct *wq;
 	struct work_struct	suspend_w;
 	struct msm_hsic_peripheral_platform_data *pdata;
+	enum usb_vdd_type	vdd_type;
+};
+
+static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
+		{   /* VDD_CX CORNER Voting */
+			[VDD_NONE]	= RPM_VREG_CORNER_NONE,
+			[VDD_MIN]	= RPM_VREG_CORNER_NOMINAL,
+			[VDD_MAX]	= RPM_VREG_CORNER_HIGH,
+		},
+		{   /* VDD_CX Voltage Voting */
+			[VDD_NONE]	= USB_PHY_VDD_DIG_VOL_NONE,
+			[VDD_MIN]	= USB_PHY_VDD_DIG_VOL_MIN,
+			[VDD_MAX]	= USB_PHY_VDD_DIG_VOL_MAX,
+		},
 };
 
 static int msm_hsic_init_vddcx(struct msm_hsic_per *mhsic, int init)
 {
 	int ret = 0;
+	int none_vol, min_vol, max_vol;
+
+	if (!mhsic->hsic_vddcx) {
+		mhsic->vdd_type = VDDCX_CORNER;
+		mhsic->hsic_vddcx = devm_regulator_get(mhsic->dev,
+			"hsic_vdd_dig");
+		if (IS_ERR(mhsic->hsic_vddcx)) {
+			mhsic->hsic_vddcx = devm_regulator_get(mhsic->dev,
+				"HSIC_VDDCX");
+			if (IS_ERR(mhsic->hsic_vddcx)) {
+				dev_err(mhsic->dev, "unable to get hsic vddcx\n");
+				return PTR_ERR(mhsic->hsic_vddcx);
+			}
+			mhsic->vdd_type = VDDCX;
+		}
+	}
+
+	none_vol = vdd_val[mhsic->vdd_type][VDD_NONE];
+	min_vol = vdd_val[mhsic->vdd_type][VDD_MIN];
+	max_vol = vdd_val[mhsic->vdd_type][VDD_MAX];
 
 	if (!init)
 		goto disable_reg;
 
-	mhsic->hsic_vddcx = regulator_get(mhsic->dev, "HSIC_VDDCX");
-	if (IS_ERR(mhsic->hsic_vddcx)) {
-		dev_err(mhsic->dev, "unable to get hsic vddcx\n");
-		return PTR_ERR(mhsic->hsic_vddcx);
-	}
-
-	ret = regulator_set_voltage(mhsic->hsic_vddcx,
-			USB_PHY_VDD_DIG_VOL_MIN,
-			USB_PHY_VDD_DIG_VOL_MAX);
+	ret = regulator_set_voltage(mhsic->hsic_vddcx, min_vol, max_vol);
 	if (ret) {
 		dev_err(mhsic->dev, "unable to set the voltage"
 				"for hsic vddcx\n");
 		goto reg_set_voltage_err;
 	}
 
-	ret = regulator_set_optimum_mode(mhsic->hsic_vddcx,
-				USB_PHY_VDD_DIG_LOAD);
-	if (ret < 0) {
-		pr_err("%s: Unable to set optimum mode of the regulator:"
-					"VDDCX\n", __func__);
-		goto reg_optimum_mode_err;
-	}
-
 	ret = regulator_enable(mhsic->hsic_vddcx);
 	if (ret) {
 		dev_err(mhsic->dev, "unable to enable hsic vddcx\n");
@@ -109,12 +127,8 @@
 disable_reg:
 	regulator_disable(mhsic->hsic_vddcx);
 reg_enable_err:
-	regulator_set_optimum_mode(mhsic->hsic_vddcx, 0);
-reg_optimum_mode_err:
-	regulator_set_voltage(mhsic->hsic_vddcx, 0,
-				USB_PHY_VDD_DIG_VOL_MIN);
+	regulator_set_voltage(mhsic->hsic_vddcx, none_vol, max_vol);
 reg_set_voltage_err:
-	regulator_put(mhsic->hsic_vddcx);
 
 	return ret;
 
@@ -323,6 +337,7 @@
 {
 	int cnt = 0, ret;
 	u32 val;
+	int none_vol, max_vol;
 
 	if (atomic_read(&mhsic->in_lpm)) {
 		dev_dbg(mhsic->dev, "%s called while in lpm\n", __func__);
@@ -378,11 +393,12 @@
 		dev_err(mhsic->dev, "%s failed to devote for TCXO %d\n"
 				, __func__, ret);
 
-	ret = regulator_set_voltage(mhsic->hsic_vddcx,
-				USB_PHY_VDD_DIG_VOL_SUSP_MIN,
-				USB_PHY_VDD_DIG_VOL_MAX);
+	none_vol = vdd_val[mhsic->vdd_type][VDD_NONE];
+	max_vol = vdd_val[mhsic->vdd_type][VDD_MAX];
+
+	ret = regulator_set_voltage(mhsic->hsic_vddcx, none_vol, max_vol);
 	if (ret < 0)
-		dev_err(mhsic->dev, "unable to set vddcx voltage: min:0.5v max:1.32v\n");
+		dev_err(mhsic->dev, "unable to set vddcx voltage for VDD MIN\n");
 
 	if (device_may_wakeup(mhsic->dev))
 		enable_irq_wake(mhsic->irq);
@@ -400,6 +416,7 @@
 {
 	int cnt = 0, ret;
 	unsigned temp;
+	int min_vol, max_vol;
 
 	if (!atomic_read(&mhsic->in_lpm)) {
 		dev_dbg(mhsic->dev, "%s called while not in lpm\n", __func__);
@@ -407,12 +424,14 @@
 	}
 
 	wake_lock(&mhsic->wlock);
-	ret = regulator_set_voltage(mhsic->hsic_vddcx,
-				USB_PHY_VDD_DIG_VOL_MIN,
-				USB_PHY_VDD_DIG_VOL_MAX);
+
+	min_vol = vdd_val[mhsic->vdd_type][VDD_MIN];
+	max_vol = vdd_val[mhsic->vdd_type][VDD_MAX];
+
+	ret = regulator_set_voltage(mhsic->hsic_vddcx, min_vol, max_vol);
 	if (ret < 0)
 		dev_err(mhsic->dev,
-				"unable to set vddcx voltage: min:1.045v max:1.32v\n");
+			"unable to set nominal vddcx voltage (no VDD MIN)\n");
 
 	ret = msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_ON);
 	if (ret)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index fb86874..8cdc2e9 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1720,6 +1720,7 @@
 			if (!mReq->req.no_interrupt)
 				mReq->ptr->token |= MSM_ETD_IOC;
 		}
+		mReq->req.dma = 0;
 	}
 
 	mReq->ptr->page[0]  = mReq->req.dma;
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 9e3301f..62955c2 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -690,6 +690,14 @@
 		usb_ep_disable(link->in_ep);
 		usb_ep_disable(link->out_ep);
 		if (netif_carrier_ok(net)) {
+			if (config_ep_by_speed(dev->gadget, &link->func,
+					       link->in_ep) ||
+			    config_ep_by_speed(dev->gadget, &link->func,
+					       link->out_ep)) {
+				link->in_ep->desc = NULL;
+				link->out_ep->desc = NULL;
+				return -EINVAL;
+			}
 			DBG(dev, "host still using in/out endpoints\n");
 			usb_ep_enable(link->in_ep);
 			usb_ep_enable(link->out_ep);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 5cc70e0..caf86ca 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -313,7 +313,7 @@
 	if (!ehci->susp_sof_bug)
 		ehci_halt(ehci); /* turn off now-idle HC */
 
-	hcd->state = HC_STATE_SUSPENDED;
+	ehci->rh_state = EHCI_RH_SUSPENDED;
 
 	if (ehci->reclaim)
 		end_unlink_async(ehci);
@@ -562,6 +562,10 @@
 	unsigned long	flags;
 	u32		ppcd = 0;
 
+	/* if !USB_SUSPEND, root hub timers won't get shut down ... */
+	if (ehci->rh_state != EHCI_RH_RUNNING)
+		return 0;
+
 	/* init status to no-changes */
 	buf [0] = 0;
 	ports = HCS_N_PORTS (ehci->hcs_params);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 5ed16cc..a6b7dee 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -30,16 +30,19 @@
 #include <linux/wakelock.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
-#include <mach/msm_bus.h>
 
 #include <linux/usb/msm_hsusb_hw.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/gpio.h>
+#include <linux/spinlock.h>
+
+#include <mach/msm_bus.h>
 #include <mach/clk.h>
 #include <mach/msm_iomap.h>
 #include <mach/msm_xo.h>
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
+#include <mach/rpm-regulator.h>
 
 #define MSM_USB_BASE (hcd->regs)
 
@@ -62,6 +65,7 @@
 	atomic_t		pm_usage_cnt;
 	uint32_t		bus_perf_client;
 	uint32_t		wakeup_int_cnt;
+	enum usb_vdd_type	vdd_type;
 };
 
 static bool debug_bus_voting_enabled = true;
@@ -254,43 +258,59 @@
 
 #define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
 
-#define USB_PHY_VDD_DIG_VOL_SUSP_MIN	500000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_NONE	0 /*uV */
 #define USB_PHY_VDD_DIG_VOL_MIN		1000000 /* uV */
 #define USB_PHY_VDD_DIG_VOL_MAX		1320000 /* uV */
-#define USB_PHY_VDD_DIG_LOAD		49360	/* uA */
 
 #define HSIC_DBG1_REG		0x38
 
+static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
+		{   /* VDD_CX CORNER Voting */
+			[VDD_NONE]	= RPM_VREG_CORNER_NONE,
+			[VDD_MIN]	= RPM_VREG_CORNER_NOMINAL,
+			[VDD_MAX]	= RPM_VREG_CORNER_HIGH,
+		},
+		{   /* VDD_CX Voltage Voting */
+			[VDD_NONE]	= USB_PHY_VDD_DIG_VOL_NONE,
+			[VDD_MIN]	= USB_PHY_VDD_DIG_VOL_MIN,
+			[VDD_MAX]	= USB_PHY_VDD_DIG_VOL_MAX,
+		},
+};
+
 static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
 {
 	int ret = 0;
+	int none_vol, min_vol, max_vol;
+
+	if (!mehci->hsic_vddcx) {
+		mehci->vdd_type = VDDCX_CORNER;
+		mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
+			"hsic_vdd_dig");
+		if (IS_ERR(mehci->hsic_vddcx)) {
+			mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
+				"HSIC_VDDCX");
+			if (IS_ERR(mehci->hsic_vddcx)) {
+				dev_err(mehci->dev, "unable to get hsic vddcx\n");
+				return PTR_ERR(mehci->hsic_vddcx);
+			}
+			mehci->vdd_type = VDDCX;
+		}
+	}
+
+	none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
+	min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
+	max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
 
 	if (!init)
 		goto disable_reg;
 
-	mehci->hsic_vddcx = devm_regulator_get(mehci->dev, "HSIC_VDDCX");
-	if (IS_ERR(mehci->hsic_vddcx)) {
-		dev_err(mehci->dev, "unable to get hsic vddcx\n");
-		return PTR_ERR(mehci->hsic_vddcx);
-	}
-
-	ret = regulator_set_voltage(mehci->hsic_vddcx,
-			USB_PHY_VDD_DIG_VOL_MIN,
-			USB_PHY_VDD_DIG_VOL_MAX);
+	ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
 	if (ret) {
 		dev_err(mehci->dev, "unable to set the voltage"
 				"for hsic vddcx\n");
 		return ret;
 	}
 
-	ret = regulator_set_optimum_mode(mehci->hsic_vddcx,
-				USB_PHY_VDD_DIG_LOAD);
-	if (ret < 0) {
-		pr_err("%s: Unable to set optimum mode of the regulator:"
-					"VDDCX\n", __func__);
-		goto reg_optimum_mode_err;
-	}
-
 	ret = regulator_enable(mehci->hsic_vddcx);
 	if (ret) {
 		dev_err(mehci->dev, "unable to enable hsic vddcx\n");
@@ -302,10 +322,8 @@
 disable_reg:
 	regulator_disable(mehci->hsic_vddcx);
 reg_enable_err:
-	regulator_set_optimum_mode(mehci->hsic_vddcx, 0);
-reg_optimum_mode_err:
-	regulator_set_voltage(mehci->hsic_vddcx, 0,
-				USB_PHY_VDD_DIG_VOL_MIN);
+	regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
+
 	return ret;
 
 }
@@ -528,6 +546,7 @@
 	struct usb_hcd *hcd = hsic_to_hcd(mehci);
 	int cnt = 0, ret;
 	u32 val;
+	int none_vol, max_vol;
 
 	if (atomic_read(&mehci->in_lpm)) {
 		dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
@@ -593,11 +612,12 @@
 	clk_disable_unprepare(mehci->cal_clk);
 	clk_disable_unprepare(mehci->ahb_clk);
 
-	ret = regulator_set_voltage(mehci->hsic_vddcx,
-				USB_PHY_VDD_DIG_VOL_SUSP_MIN,
-				USB_PHY_VDD_DIG_VOL_MAX);
+	none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
+	max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
+
+	ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
 	if (ret < 0)
-		dev_err(mehci->dev, "unable to set vddcx voltage: min:0.5v max:1.3v\n");
+		dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
 
 	if (mehci->bus_perf_client && debug_bus_voting_enabled) {
 		ret = msm_bus_scale_client_update_request(
@@ -626,6 +646,7 @@
 	struct usb_hcd *hcd = hsic_to_hcd(mehci);
 	int cnt = 0, ret;
 	unsigned temp;
+	int min_vol, max_vol;
 
 	if (!atomic_read(&mehci->in_lpm)) {
 		dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
@@ -648,11 +669,12 @@
 				   "bus bandwidth %d\n", __func__, ret);
 	}
 
-	ret = regulator_set_voltage(mehci->hsic_vddcx,
-				USB_PHY_VDD_DIG_VOL_MIN,
-				USB_PHY_VDD_DIG_VOL_MAX);
+	min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
+	max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
+
+	ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
 	if (ret < 0)
-		dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
+		dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
 
 	clk_prepare_enable(mehci->core_clk);
 	clk_prepare_enable(mehci->phy_clk);
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 96e5a90..8b762a2 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -11,6 +11,9 @@
  * GNU General Public License for more details.
  */
 
+/* add additional information to our printk's */
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -18,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/kref.h>
 #include <linux/platform_device.h>
+#include <linux/ratelimit.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/debugfs.h>
@@ -50,26 +54,37 @@
 	struct diag_bridge	*dev = __dev;
 
 	if (!dev) {
-		err("dev is null");
+		pr_err("dev is null");
 		return -ENODEV;
 	}
 
 	dev->ops = ops;
 	dev->err = 0;
 
+	kref_get(&dev->kref);
+
 	return 0;
 }
 EXPORT_SYMBOL(diag_bridge_open);
 
+static void diag_bridge_delete(struct kref *kref)
+{
+	struct diag_bridge *dev = container_of(kref, struct diag_bridge, kref);
+
+	usb_put_dev(dev->udev);
+	__dev = 0;
+	kfree(dev);
+}
+
 void diag_bridge_close(void)
 {
 	struct diag_bridge	*dev = __dev;
 
-	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+	dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
 
 	usb_kill_anchored_urbs(&dev->submitted);
-
 	dev->ops = 0;
+	kref_put(&dev->kref, diag_bridge_delete);
 }
 EXPORT_SYMBOL(diag_bridge_close);
 
@@ -78,13 +93,14 @@
 	struct diag_bridge	*dev = urb->context;
 	struct diag_bridge_ops	*cbs = dev->ops;
 
-	dev_dbg(&dev->udev->dev, "%s: status:%d actual:%d\n", __func__,
+	dev_dbg(&dev->ifc->dev, "%s: status:%d actual:%d\n", __func__,
 			urb->status, urb->actual_length);
 
 	if (urb->status == -EPROTO) {
-		dev_err(&dev->udev->dev, "%s: proto error\n", __func__);
-		/* save error so that subsequent read/write returns ESHUTDOWN */
+		dev_err(&dev->ifc->dev, "%s: proto error\n", __func__);
+		/* save error so that subsequent read/write returns ENODEV */
 		dev->err = urb->status;
+		kref_put(&dev->kref, diag_bridge_delete);
 		return;
 	}
 
@@ -96,6 +112,7 @@
 
 	dev->bytes_to_host += urb->actual_length;
 	dev->pending_reads--;
+	kref_put(&dev->kref, diag_bridge_delete);
 }
 
 int diag_bridge_read(char *data, int size)
@@ -105,33 +122,40 @@
 	struct diag_bridge	*dev = __dev;
 	int			ret;
 
-	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+	pr_debug("reading %d bytes", size);
 
-	if (!size) {
-		dev_err(&dev->udev->dev, "invalid size:%d\n", size);
-		return -EINVAL;
+	if (!dev || !dev->ifc) {
+		pr_err("device is disconnected");
+		return -ENODEV;
 	}
 
-	if (!dev->ifc) {
-		dev_err(&dev->udev->dev, "device is disconnected\n");
+	if (!dev->ops) {
+		pr_err("bridge is not open");
 		return -ENODEV;
 	}
 
+	if (!size) {
+		dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
+		return -EINVAL;
+	}
+
 	/* if there was a previous unrecoverable error, just quit */
 	if (dev->err)
-		return -ESHUTDOWN;
+		return -ENODEV;
+
+	kref_get(&dev->kref);
 
 	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
-		dev_err(&dev->udev->dev, "unable to allocate urb\n");
-		return -ENOMEM;
+		dev_err(&dev->ifc->dev, "unable to allocate urb\n");
+		ret = -ENOMEM;
+		goto error;
 	}
 
 	ret = usb_autopm_get_interface(dev->ifc);
-	if (ret < 0) {
-		dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret);
-		usb_free_urb(urb);
-		return ret;
+	if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
+		pr_err_ratelimited("read: autopm_get failed:%d", ret);
+		goto free_error;
 	}
 
 	pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr);
@@ -142,18 +166,18 @@
 
 	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret) {
-		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+		pr_err_ratelimited("submitting urb failed err:%d", ret);
 		dev->pending_reads--;
 		usb_unanchor_urb(urb);
-		usb_free_urb(urb);
-		usb_autopm_put_interface(dev->ifc);
-		return ret;
 	}
-
 	usb_autopm_put_interface(dev->ifc);
-	usb_free_urb(urb);
 
-	return 0;
+free_error:
+	usb_free_urb(urb);
+error:
+	if (ret) /* otherwise this is done in the completion handler */
+		kref_put(&dev->kref, diag_bridge_delete);
+	return ret;
 }
 EXPORT_SYMBOL(diag_bridge_read);
 
@@ -162,14 +186,15 @@
 	struct diag_bridge	*dev = urb->context;
 	struct diag_bridge_ops	*cbs = dev->ops;
 
-	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+	dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
 
 	usb_autopm_put_interface_async(dev->ifc);
 
 	if (urb->status == -EPROTO) {
-		dev_err(&dev->udev->dev, "%s: proto error\n", __func__);
-		/* save error so that subsequent read/write returns ESHUTDOWN */
+		dev_err(&dev->ifc->dev, "%s: proto error\n", __func__);
+		/* save error so that subsequent read/write returns ENODEV */
 		dev->err = urb->status;
+		kref_put(&dev->kref, diag_bridge_delete);
 		return;
 	}
 
@@ -181,6 +206,7 @@
 
 	dev->bytes_to_mdm += urb->actual_length;
 	dev->pending_writes--;
+	kref_put(&dev->kref, diag_bridge_delete);
 }
 
 int diag_bridge_write(char *data, int size)
@@ -190,33 +216,40 @@
 	struct diag_bridge	*dev = __dev;
 	int			ret;
 
-	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+	pr_debug("writing %d bytes", size);
 
-	if (!size) {
-		dev_err(&dev->udev->dev, "invalid size:%d\n", size);
-		return -EINVAL;
+	if (!dev || !dev->ifc) {
+		pr_err("device is disconnected");
+		return -ENODEV;
 	}
 
-	if (!dev->ifc) {
-		dev_err(&dev->udev->dev, "device is disconnected\n");
+	if (!dev->ops) {
+		pr_err("bridge is not open");
 		return -ENODEV;
 	}
 
+	if (!size) {
+		dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
+		return -EINVAL;
+	}
+
 	/* if there was a previous unrecoverable error, just quit */
 	if (dev->err)
-		return -ESHUTDOWN;
+		return -ENODEV;
+
+	kref_get(&dev->kref);
 
 	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
-		err("unable to allocate urb");
-		return -ENOMEM;
+		dev_err(&dev->ifc->dev, "unable to allocate urb\n");
+		ret = -ENOMEM;
+		goto error;
 	}
 
 	ret = usb_autopm_get_interface(dev->ifc);
-	if (ret < 0) {
-		dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret);
-		usb_free_urb(urb);
-		return ret;
+	if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
+		pr_err_ratelimited("write: autopm_get failed:%d", ret);
+		goto free_error;
 	}
 
 	pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr);
@@ -227,30 +260,22 @@
 
 	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret) {
-		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+		pr_err_ratelimited("submitting urb failed err:%d", ret);
 		dev->pending_writes--;
 		usb_unanchor_urb(urb);
-		usb_free_urb(urb);
 		usb_autopm_put_interface(dev->ifc);
-		return ret;
+		goto free_error;
 	}
 
+free_error:
 	usb_free_urb(urb);
-
-	return 0;
+error:
+	if (ret) /* otherwise this is done in the completion handler */
+		kref_put(&dev->kref, diag_bridge_delete);
+	return ret;
 }
 EXPORT_SYMBOL(diag_bridge_write);
 
-static void diag_bridge_delete(struct kref *kref)
-{
-	struct diag_bridge *dev =
-		container_of(kref, struct diag_bridge, kref);
-
-	usb_put_dev(dev->udev);
-	__dev = 0;
-	kfree(dev);
-}
-
 #if defined(CONFIG_DEBUG_FS)
 #define DEBUG_BUF_SIZE	512
 static ssize_t diag_read_stats(struct file *file, char __user *ubuf,
@@ -260,6 +285,9 @@
 	char			*buf;
 	int			ret;
 
+	if (!dev)
+		return -ENODEV;
+
 	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
@@ -286,8 +314,10 @@
 {
 	struct diag_bridge	*dev = __dev;
 
-	dev->bytes_to_host = dev->bytes_to_mdm = 0;
-	dev->pending_reads = dev->pending_writes = 0;
+	if (dev) {
+		dev->bytes_to_host = dev->bytes_to_mdm = 0;
+		dev->pending_reads = dev->pending_writes = 0;
+	}
 
 	return count;
 }
@@ -334,7 +364,7 @@
 	int				ret = -ENOMEM;
 	__u8				ifc_num;
 
-	dbg("%s: id:%lu", __func__, id->driver_info);
+	pr_debug("id:%lu", id->driver_info);
 
 	ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
 
@@ -344,12 +374,12 @@
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
-		pr_err("%s: unable to allocate dev\n", __func__);
+		pr_err("unable to allocate dev");
 		return -ENOMEM;
 	}
 	dev->pdev = platform_device_alloc("diag_bridge", -1);
 	if (!dev->pdev) {
-		pr_err("%s: unable to allocate platform device\n", __func__);
+		pr_err("unable to allocate platform device");
 		kfree(dev);
 		return -ENOMEM;
 	}
@@ -372,7 +402,7 @@
 	}
 
 	if (!(dev->in_epAddr && dev->out_epAddr)) {
-		err("could not find bulk in and bulk out endpoints");
+		pr_err("could not find bulk in and bulk out endpoints");
 		ret = -ENODEV;
 		goto error;
 	}
@@ -381,7 +411,7 @@
 	diag_bridge_debugfs_init();
 	platform_device_add(dev->pdev);
 
-	dev_dbg(&dev->udev->dev, "%s: complete\n", __func__);
+	dev_dbg(&dev->ifc->dev, "%s: complete\n", __func__);
 
 	return 0;
 
@@ -396,9 +426,10 @@
 {
 	struct diag_bridge	*dev = usb_get_intfdata(ifc);
 
-	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+	dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
 
-	platform_device_del(dev->pdev);
+	platform_device_unregister(dev->pdev);
+	dev->ifc = NULL;
 	diag_bridge_debugfs_cleanup();
 	kref_put(&dev->kref, diag_bridge_delete);
 	usb_set_intfdata(ifc, NULL);
@@ -413,7 +444,7 @@
 	if (cbs && cbs->suspend) {
 		ret = cbs->suspend(cbs->ctxt);
 		if (ret) {
-			dev_dbg(&dev->udev->dev,
+			dev_dbg(&dev->ifc->dev,
 				"%s: diag veto'd suspend\n", __func__);
 			return ret;
 		}
@@ -467,7 +498,7 @@
 
 	ret = usb_register(&diag_bridge_driver);
 	if (ret) {
-		err("%s: unable to register diag driver", __func__);
+		pr_err("unable to register diag driver");
 		return ret;
 	}
 
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 49591cd..e685233 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -128,12 +128,10 @@
 static void resp_avail_cb(struct urb *urb)
 {
 	struct ctrl_bridge	*dev = urb->context;
-	struct usb_device	*udev;
 	int			status = 0;
 	int			resubmit_urb = 1;
 	struct bridge		*brdg = dev->brdg;
 
-	udev = interface_to_usbdev(dev->intf);
 	switch (urb->status) {
 	case 0:
 		/*success*/
@@ -154,7 +152,7 @@
 	/*resubmit*/
 	case -EOVERFLOW:
 	default:
-		dev_dbg(&udev->dev, "%s: non zero urb status = %d\n",
+		dev_dbg(&dev->intf->dev, "%s: non zero urb status = %d\n",
 			__func__, urb->status);
 	}
 
@@ -163,7 +161,7 @@
 		usb_anchor_urb(dev->inturb, &dev->tx_submitted);
 		status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
 		if (status) {
-			dev_err(&udev->dev,
+			dev_err(&dev->intf->dev,
 				"%s: Error re-submitting Int URB %d\n",
 				__func__, status);
 			usb_unanchor_urb(dev->inturb);
@@ -175,14 +173,11 @@
 {
 	int				status;
 	struct usb_cdc_notification	*ctrl;
-	struct usb_device		*udev;
 	struct ctrl_bridge		*dev = urb->context;
 	struct bridge			*brdg = dev->brdg;
 	unsigned int			ctrl_bits;
 	unsigned char			*data;
 
-	udev = interface_to_usbdev(dev->intf);
-
 	switch (urb->status) {
 	case 0:
 		/*success*/
@@ -194,7 +189,8 @@
 		 /* unplug */
 		 return;
 	case -EPIPE:
-		dev_err(&udev->dev, "%s: stall on int endpoint\n", __func__);
+		dev_err(&dev->intf->dev,
+			"%s: stall on int endpoint\n", __func__);
 		/* TBD : halt to be cleared in work */
 	case -EOVERFLOW:
 	default:
@@ -209,8 +205,8 @@
 	switch (ctrl->bNotificationType) {
 	case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
 		dev->resp_avail++;
-		usb_fill_control_urb(dev->readurb, udev,
-					usb_rcvctrlpipe(udev, 0),
+		usb_fill_control_urb(dev->readurb, dev->udev,
+					usb_rcvctrlpipe(dev->udev, 0),
 					(unsigned char *)dev->in_ctlreq,
 					dev->readbuf,
 					DEFAULT_READ_URB_LENGTH,
@@ -219,7 +215,7 @@
 		usb_anchor_urb(dev->readurb, &dev->tx_submitted);
 		status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
 		if (status) {
-			dev_err(&udev->dev,
+			dev_err(&dev->intf->dev,
 				"%s: Error submitting Read URB %d\n",
 				__func__, status);
 			usb_unanchor_urb(dev->readurb);
@@ -227,19 +223,19 @@
 		}
 		return;
 	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
-		dev_dbg(&udev->dev, "%s network\n", ctrl->wValue ?
+		dev_dbg(&dev->intf->dev, "%s network\n", ctrl->wValue ?
 					"connected to" : "disconnected from");
 		break;
 	case USB_CDC_NOTIFY_SERIAL_STATE:
 		dev->notify_ser_state++;
 		ctrl_bits = get_unaligned_le16(data);
-		dev_dbg(&udev->dev, "serial state: %d\n", ctrl_bits);
+		dev_dbg(&dev->intf->dev, "serial state: %d\n", ctrl_bits);
 		dev->cbits_tohost = ctrl_bits;
 		if (brdg && brdg->ops.send_cbits)
 			brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
 		break;
 	default:
-		dev_err(&udev->dev, "%s: unknown notification %d received:"
+		dev_err(&dev->intf->dev, "%s: unknown notification %d received:"
 			"index %d len %d data0 %d data1 %d",
 			__func__, ctrl->bNotificationType, ctrl->wIndex,
 			ctrl->wLength, data[0], data[1]);
@@ -249,7 +245,7 @@
 	usb_anchor_urb(urb, &dev->tx_submitted);
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
-		dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n",
+		dev_err(&dev->intf->dev, "%s: Error re-submitting Int URB %d\n",
 		__func__, status);
 		usb_unanchor_urb(urb);
 	}
@@ -260,7 +256,7 @@
 	int	retval = 0;
 
 	if (!dev->inturb) {
-		dev_err(&dev->udev->dev, "%s: inturb is NULL\n", __func__);
+		dev_err(&dev->intf->dev, "%s: inturb is NULL\n", __func__);
 		return -ENODEV;
 	}
 
@@ -268,7 +264,7 @@
 		usb_anchor_urb(dev->inturb, &dev->tx_submitted);
 		retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
 		if (retval < 0) {
-			dev_err(&dev->udev->dev,
+			dev_err(&dev->intf->dev,
 				"%s error submitting int urb %d\n",
 				__func__, retval);
 			usb_unanchor_urb(dev->inturb);
@@ -321,7 +317,7 @@
 	if (!dev || !dev->brdg)
 		return;
 
-	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+	dev_dbg(&dev->intf->dev, "%s:\n", __func__);
 
 	ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
 	usb_unlink_anchored_urbs(&dev->tx_submitted);
@@ -350,7 +346,6 @@
 	int			result;
 	struct urb		*writeurb;
 	struct usb_ctrlrequest	*out_ctlreq;
-	struct usb_device	*udev;
 	struct ctrl_bridge	*dev;
 
 	if (id >= MAX_BRIDGE_DEVICES) {
@@ -365,14 +360,12 @@
 		goto free_data;
 	}
 
-	udev = interface_to_usbdev(dev->intf);
-
-	dev_dbg(&udev->dev, "%s:[id]:%u: write (%d bytes)\n",
+	dev_dbg(&dev->intf->dev, "%s:[id]:%u: write (%d bytes)\n",
 		__func__, id, size);
 
 	writeurb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!writeurb) {
-		dev_err(&udev->dev, "%s: error allocating read urb\n",
+		dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
 			__func__);
 		result = -ENOMEM;
 		goto free_data;
@@ -380,7 +373,7 @@
 
 	out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_ATOMIC);
 	if (!out_ctlreq) {
-		dev_err(&udev->dev,
+		dev_err(&dev->intf->dev,
 			"%s: error allocating setup packet buffer\n",
 			__func__);
 		result = -ENOMEM;
@@ -403,15 +396,15 @@
 		dev->intf->cur_altsetting->desc.bInterfaceNumber;
 	out_ctlreq->wLength = cpu_to_le16(size);
 
-	usb_fill_control_urb(writeurb, udev,
-				 usb_sndctrlpipe(udev, 0),
+	usb_fill_control_urb(writeurb, dev->udev,
+				 usb_sndctrlpipe(dev->udev, 0),
 				 (unsigned char *)out_ctlreq,
 				 (void *)data, size,
 				 ctrl_write_callback, dev);
 
 	result = usb_autopm_get_interface_async(dev->intf);
 	if (result < 0) {
-		dev_err(&udev->dev, "%s: unable to resume interface: %d\n",
+		dev_err(&dev->intf->dev, "%s: unable to resume interface: %d\n",
 			__func__, result);
 
 		/*
@@ -430,7 +423,7 @@
 	usb_anchor_urb(writeurb, &dev->tx_submitted);
 	result = usb_submit_urb(writeurb, GFP_ATOMIC);
 	if (result < 0) {
-		dev_err(&udev->dev, "%s: submit URB error %d\n",
+		dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
 			__func__, result);
 		usb_autopm_put_interface_async(dev->intf);
 		goto unanchor_urb;
@@ -614,14 +607,14 @@
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
-		dev_err(&udev->dev, "%s: unable to allocate dev\n",
+		dev_err(&ifc->dev, "%s: unable to allocate dev\n",
 			__func__);
 		return -ENOMEM;
 	}
 	dev->pdev = platform_device_alloc(ctrl_bridge_names[id], id);
 	if (!dev->pdev) {
-		dev_err(&dev->udev->dev,
-			"%s: unable to allocate platform device\n", __func__);
+		dev_err(&ifc->dev, "%s: unable to allocate platform device\n",
+			__func__);
 		retval = -ENOMEM;
 		goto nomem;
 	}
@@ -639,7 +632,7 @@
 
 	dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->inturb) {
-		dev_err(&udev->dev, "%s: error allocating int urb\n", __func__);
+		dev_err(&ifc->dev, "%s: error allocating int urb\n", __func__);
 		retval = -ENOMEM;
 		goto pdev_del;
 	}
@@ -648,7 +641,7 @@
 
 	dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
 	if (!dev->intbuf) {
-		dev_err(&udev->dev, "%s: error allocating int buffer\n",
+		dev_err(&ifc->dev, "%s: error allocating int buffer\n",
 			__func__);
 		retval = -ENOMEM;
 		goto free_inturb;
@@ -663,7 +656,7 @@
 
 	dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->readurb) {
-		dev_err(&udev->dev, "%s: error allocating read urb\n",
+		dev_err(&ifc->dev, "%s: error allocating read urb\n",
 			__func__);
 		retval = -ENOMEM;
 		goto free_intbuf;
@@ -671,7 +664,7 @@
 
 	dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
 	if (!dev->readbuf) {
-		dev_err(&udev->dev, "%s: error allocating read buffer\n",
+		dev_err(&ifc->dev, "%s: error allocating read buffer\n",
 			__func__);
 		retval = -ENOMEM;
 		goto free_rurb;
@@ -679,8 +672,7 @@
 
 	dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
 	if (!dev->in_ctlreq) {
-		dev_err(&udev->dev,
-			"%s:error allocating setup packet buffer\n",
+		dev_err(&ifc->dev, "%s:error allocating setup packet buffer\n",
 			__func__);
 		retval = -ENOMEM;
 		goto free_rbuf;
@@ -711,7 +703,7 @@
 free_inturb:
 	usb_free_urb(dev->inturb);
 pdev_del:
-	platform_device_del(dev->pdev);
+	platform_device_unregister(dev->pdev);
 nomem:
 	kfree(dev);
 
@@ -722,9 +714,9 @@
 {
 	struct ctrl_bridge	*dev = __dev[id];
 
-	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+	dev_dbg(&dev->intf->dev, "%s:\n", __func__);
 
-	platform_device_del(dev->pdev);
+	platform_device_unregister(dev->pdev);
 
 	kfree(dev->in_ctlreq);
 	kfree(dev->readbuf);
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index 6ee3204..db2f40a 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -208,7 +208,7 @@
 	/*do not resubmit*/
 	case -EPIPE:
 		set_bit(RX_HALT, &dev->flags);
-		dev_err(&dev->udev->dev, "%s: epout halted\n", __func__);
+		dev_err(&dev->intf->dev, "%s: epout halted\n", __func__);
 		schedule_work(&dev->kevent);
 		/* FALLTHROUGH */
 	case -ESHUTDOWN:
@@ -309,7 +309,7 @@
 		return -ENODEV;
 	}
 
-	dev_dbg(&dev->udev->dev, "%s: dev:%p\n", __func__, dev);
+	dev_dbg(&dev->intf->dev, "%s: dev:%p\n", __func__, dev);
 
 	dev->brdg = brdg;
 	dev->err = 0;
@@ -341,7 +341,7 @@
 	if (!dev || !dev->brdg)
 		return;
 
-	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+	dev_dbg(&dev->intf->dev, "%s:\n", __func__);
 
 	usb_unlink_anchored_urbs(&dev->tx_active);
 	usb_unlink_anchored_urbs(&dev->rx_active);
@@ -370,7 +370,7 @@
 
 		status = usb_autopm_get_interface(dev->intf);
 		if (status < 0) {
-			dev_err(&dev->udev->dev,
+			dev_err(&dev->intf->dev,
 				"can't acquire interface, status %d\n", status);
 			return;
 		}
@@ -378,7 +378,7 @@
 		status = usb_clear_halt(dev->udev, dev->bulk_out);
 		usb_autopm_put_interface(dev->intf);
 		if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
-			dev_err(&dev->udev->dev,
+			dev_err(&dev->intf->dev,
 				"can't clear tx halt, status %d\n", status);
 		else
 			clear_bit(TX_HALT, &dev->flags);
@@ -389,7 +389,7 @@
 
 		status = usb_autopm_get_interface(dev->intf);
 		if (status < 0) {
-			dev_err(&dev->udev->dev,
+			dev_err(&dev->intf->dev,
 				"can't acquire interface, status %d\n", status);
 			return;
 		}
@@ -397,7 +397,7 @@
 		status = usb_clear_halt(dev->udev, dev->bulk_in);
 		usb_autopm_put_interface(dev->intf);
 		if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
-			dev_err(&dev->udev->dev,
+			dev_err(&dev->intf->dev,
 				"can't clear rx halt, status %d\n", status);
 		else {
 			clear_bit(RX_HALT, &dev->flags);
@@ -426,7 +426,7 @@
 		break;
 	case -EPIPE:
 		set_bit(TX_HALT, &dev->flags);
-		dev_err(&dev->udev->dev, "%s: epout halted\n", __func__);
+		dev_err(&dev->intf->dev, "%s: epout halted\n", __func__);
 		schedule_work(&dev->kevent);
 		/* FALLTHROUGH */
 	case -ESHUTDOWN:
@@ -474,17 +474,17 @@
 	if (!brdg)
 		return -ENODEV;
 
-	dev_dbg(&dev->udev->dev, "%s: write (%d bytes)\n", __func__, skb->len);
+	dev_dbg(&dev->intf->dev, "%s: write (%d bytes)\n", __func__, skb->len);
 
 	result = usb_autopm_get_interface(dev->intf);
 	if (result < 0) {
-		dev_err(&dev->udev->dev, "%s: resume failure\n", __func__);
+		dev_err(&dev->intf->dev, "%s: resume failure\n", __func__);
 		goto pm_error;
 	}
 
 	txurb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!txurb) {
-		dev_err(&dev->udev->dev, "%s: error allocating read urb\n",
+		dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
 			__func__);
 		result = -ENOMEM;
 		goto error;
@@ -512,13 +512,13 @@
 	if (result < 0) {
 		usb_unanchor_urb(txurb);
 		atomic_dec(&dev->pending_txurbs);
-		dev_err(&dev->udev->dev, "%s: submit URB error %d\n",
+		dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
 			__func__, result);
 		goto free_urb;
 	}
 
 	dev->to_modem++;
-	dev_dbg(&dev->udev->dev, "%s: pending_txurbs: %u\n", __func__, pending);
+	dev_dbg(&dev->intf->dev, "%s: pending_txurbs: %u\n", __func__, pending);
 
 	/* flow control: last urb submitted but return -EBUSY */
 	if (fctrl_support && pending > fctrl_en_thld) {
@@ -918,17 +918,17 @@
 		return -EINVAL;
 	}
 
-	udev = interface_to_usbdev(iface);
-	usb_get_dev(udev);
-
 	if (!test_bit(iface_num, &id->driver_info))
 		return -ENODEV;
 
+	udev = interface_to_usbdev(iface);
+	usb_get_dev(udev);
+
 	numends = iface->cur_altsetting->desc.bNumEndpoints;
 	for (i = 0; i < numends; i++) {
 		endpoint = iface->cur_altsetting->endpoint + i;
 		if (!endpoint) {
-			dev_err(&udev->dev, "%s: invalid endpoint %u\n",
+			dev_err(&iface->dev, "%s: invalid endpoint %u\n",
 					__func__, i);
 			status = -EINVAL;
 			goto out;
@@ -943,20 +943,20 @@
 	}
 
 	if (!bulk_in || !bulk_out || !int_in) {
-		dev_err(&udev->dev, "%s: invalid endpoints\n", __func__);
+		dev_err(&iface->dev, "%s: invalid endpoints\n", __func__);
 		status = -EINVAL;
 		goto out;
 	}
 
 	status = data_bridge_probe(iface, bulk_in, bulk_out, ch_id);
 	if (status < 0) {
-		dev_err(&udev->dev, "data_bridge_probe failed %d\n", status);
+		dev_err(&iface->dev, "data_bridge_probe failed %d\n", status);
 		goto out;
 	}
 
 	status = ctrl_bridge_probe(iface, int_in, ch_id);
 	if (status < 0) {
-		dev_err(&udev->dev, "ctrl_bridge_probe failed %d\n", status);
+		dev_err(&iface->dev, "ctrl_bridge_probe failed %d\n", status);
 		goto free_data_bridge;
 	}
 
@@ -965,7 +965,7 @@
 	return 0;
 
 free_data_bridge:
-	platform_device_del(__dev[ch_id]->pdev);
+	platform_device_unregister(__dev[ch_id]->pdev);
 	usb_set_intfdata(iface, NULL);
 	kfree(__dev[ch_id]);
 	__dev[ch_id] = NULL;
@@ -989,7 +989,7 @@
 
 	ch_id--;
 	ctrl_bridge_disconnect(ch_id);
-	platform_device_del(dev->pdev);
+	platform_device_unregister(dev->pdev);
 	usb_set_intfdata(intf, NULL);
 	__dev[ch_id] = NULL;
 
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 61fbac0..c0f9346 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -87,13 +87,6 @@
 #endif
 }
 
-enum usb_vdd_value {
-	VDD_NONE = 0,
-	VDD_MIN,
-	VDD_MAX,
-	VDD_VAL_MAX,
-};
-
 static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
 		{  /* VDD_CX CORNER Voting */
 			[VDD_NONE]	= RPM_VREG_CORNER_NONE,
diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
index de8d490..9811a82 100644
--- a/drivers/usb/serial/usb-wwan.h
+++ b/drivers/usb/serial/usb-wwan.h
@@ -53,6 +53,7 @@
 	u8 *out_buffer[N_OUT_URB];
 	unsigned long out_busy;	/* Bit vector of URBs in use */
 	int opened;
+	struct usb_anchor submitted;
 	struct usb_anchor delayed;
 
 	/* Settings for the port */
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 519af39..0c58554 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -252,10 +252,12 @@
 		} else {
 			intfdata->in_flight++;
 			spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+			usb_anchor_urb(this_urb, &portdata->submitted);
 			err = usb_submit_urb(this_urb, GFP_ATOMIC);
 			if (err) {
 				dbg("usb_submit_urb %p (write bulk) failed "
 				    "(%d)", this_urb, err);
+				usb_unanchor_urb(this_urb);
 				clear_bit(i, &portdata->out_busy);
 				spin_lock_irqsave(&intfdata->susp_lock, flags);
 				intfdata->in_flight--;
@@ -281,6 +283,7 @@
 {
 	int err;
 	int endpoint;
+	struct usb_wwan_port_private *portdata;
 	struct usb_serial_port *port;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
@@ -290,6 +293,7 @@
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 	port = urb->context;
+	portdata = usb_get_serial_port_data(port);
 
 	if (status) {
 		dbg("%s: nonzero status: %d on endpoint %02x.",
@@ -308,8 +312,10 @@
 
 		/* Resubmit urb so we continue receiving */
 		if (status != -ESHUTDOWN) {
+			usb_anchor_urb(urb, &portdata->submitted);
 			err = usb_submit_urb(urb, GFP_ATOMIC);
 			if (err) {
+				usb_unanchor_urb(urb);
 				if (err != -EPERM) {
 					printk(KERN_ERR "%s: resubmit read urb failed. "
 						"(%d)", __func__, err);
@@ -418,8 +424,10 @@
 		urb = portdata->in_urbs[i];
 		if (!urb)
 			continue;
+		usb_anchor_urb(urb, &portdata->submitted);
 		err = usb_submit_urb(urb, GFP_KERNEL);
 		if (err) {
+			usb_unanchor_urb(urb);
 			dbg("%s: submit urb %d failed (%d) %d",
 			    __func__, i, err, urb->transfer_buffer_length);
 		}
@@ -551,6 +559,7 @@
 			return 1;
 		}
 		init_usb_anchor(&portdata->delayed);
+		init_usb_anchor(&portdata->submitted);
 
 		for (j = 0; j < N_IN_URB; j++) {
 			buffer = kmalloc(IN_BUFLEN, GFP_KERNEL);
@@ -590,7 +599,7 @@
 
 static void stop_read_write_urbs(struct usb_serial *serial)
 {
-	int i, j;
+	int i;
 	struct usb_serial_port *port;
 	struct usb_wwan_port_private *portdata;
 
@@ -598,10 +607,7 @@
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		portdata = usb_get_serial_port_data(port);
-		for (j = 0; j < N_IN_URB; j++)
-			usb_kill_urb(portdata->in_urbs[j]);
-		for (j = 0; j < N_OUT_URB; j++)
-			usb_kill_urb(portdata->out_urbs[j]);
+		usb_kill_anchored_urbs(&portdata->submitted);
 	}
 }
 
@@ -694,10 +700,12 @@
 	portdata = usb_get_serial_port_data(port);
 	data = port->serial->private;
 	while ((urb = usb_get_from_anchor(&portdata->delayed))) {
+		usb_anchor_urb(urb, &portdata->submitted);
 		err = usb_submit_urb(urb, GFP_ATOMIC);
 		if (!err) {
 			data->in_flight++;
 		} else {
+			usb_unanchor_urb(urb);
 			/* we have to throw away the rest */
 			do {
 				unbusy_queued_urb(urb, portdata);
@@ -736,33 +744,32 @@
 
 	spin_lock_irq(&intfdata->susp_lock);
 	intfdata->suspended = 0;
-	spin_unlock_irq(&intfdata->susp_lock);
-
 	for (i = 0; i < serial->num_ports; i++) {
 		/* walk all ports */
 		port = serial->port[i];
 		portdata = usb_get_serial_port_data(port);
 
 		/* skip closed ports */
-		spin_lock_irq(&intfdata->susp_lock);
-		if (!portdata->opened) {
-			spin_unlock_irq(&intfdata->susp_lock);
+		if (!portdata->opened)
 			continue;
-		}
 
 		for (j = 0; j < N_IN_URB; j++) {
 			urb = portdata->in_urbs[j];
+			usb_anchor_urb(urb, &portdata->submitted);
 			err = usb_submit_urb(urb, GFP_ATOMIC);
 			if (err < 0) {
 				err("%s: Error %d for bulk URB %d",
 				    __func__, err, i);
+				usb_unanchor_urb(urb);
+				intfdata->suspended = 1;
 				spin_unlock_irq(&intfdata->susp_lock);
 				goto err_out;
 			}
 		}
 		play_delayed(port);
-		spin_unlock_irq(&intfdata->susp_lock);
 	}
+	spin_unlock_irq(&intfdata->susp_lock);
+
 err_out:
 	return err;
 }
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index 7777154..7e078ab 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -84,6 +84,16 @@
 	  Support for MSM MDP HW revision 4.0
 	  Say Y here if this is msm7x30 variant platform.
 
+config FB_MSM_MDSS
+	bool "MDSS HW"
+	---help---
+	The Mobile Display Sub System (MDSS) driver supports devices which
+	contain MDSS hardware block.
+
+	The MDSS driver implements frame buffer interface to provide access to
+	the display hardware and provide a way for users to display graphics
+	on connected display panels.
+
 config FB_MSM_MDP_NONE
 	bool "MDP HW None"
 	---help---
@@ -936,4 +946,8 @@
 	default n
 	---help---
 	  Support for EBI2 panel auto detect
+
+if FB_MSM_MDSS
+	source "drivers/video/msm/mdss/Kconfig"
+endif
 endif
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index e4a0948..a0f9e02 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -1,10 +1,12 @@
+ifeq ($(CONFIG_FB_MSM_MDSS),y)
+obj-y += mdss/
+else
 obj-y := msm_fb.o
 
 obj-$(CONFIG_FB_MSM_LOGO) += logo.o
 obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
 
 ifeq ($(CONFIG_FB_MSM_MDP_HW),y)
-
 # MDP
 obj-y += mdp.o
 
@@ -182,15 +184,15 @@
 obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_wfd_writeback_panel.o
 obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_wfd_writeback.o
 obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_overlay_writeback.o
-
-obj-$(CONFIG_MSM_VIDC_1080P) += vidc/
-obj-$(CONFIG_MSM_VIDC_720P) += vidc/
 else
 obj-$(CONFIG_FB_MSM_EBI2) += ebi2_host.o
 obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
 obj-y += msm_fb_panel.o
 obj-$(CONFIG_FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL) += ebi2_epson_s1d_qvga.o
 endif
+endif
 
+obj-$(CONFIG_MSM_VIDC_1080P) += vidc/
+obj-$(CONFIG_MSM_VIDC_720P) += vidc/
 clean:
 	rm *.o .*cmd
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index a372016..03243ac 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -809,7 +809,6 @@
 			if (!external_common_state->
 					disp_mode_list.num_of_elements)
 				hdmi_msm_read_edid();
-			hdmi_msm_turn_on();
 		}
 	} else {
 		hdmi_msm_state->hpd_cable_chg_detected = FALSE;
@@ -824,16 +823,14 @@
 		DEV_INFO("Hdmi state switch to %d: %s\n",
 			external_common_state->sdev.state,  __func__);
 		if (hpd_state) {
+			/* Build EDID table */
 			hdmi_msm_read_edid();
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 			hdmi_msm_state->reauth = FALSE ;
 #endif
-			/* Build EDID table */
-			hdmi_msm_turn_on();
 			DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
 			kobject_uevent(external_common_state->uevent_kobj,
 				KOBJ_ONLINE);
-			hdmi_msm_hdcp_enable();
 #ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 			/* Send Audio for HDMI Compliance Cases*/
 			envp[0] = "HDCP_STATE=PASS";
@@ -1312,7 +1309,8 @@
 
 	/* HDMI_CTRL */
 	HDMI_OUTP(0x0000, reg_val);
-	DEV_DBG("HDMI Core: %s\n", power_on ? "Enable" : "Disable");
+	DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
+			power_on ? "Enable" : "Disable", reg_val);
 }
 
 static void msm_hdmi_init_ddc(void)
@@ -4105,7 +4103,6 @@
 
 static void hdmi_msm_turn_on(void)
 {
-	uint32 hpd_ctrl;
 	uint32 audio_pkt_ctrl, audio_cfg;
 	/*
 	 * Number of wait iterations for QDSP to disable Audio Engine
@@ -4128,6 +4125,7 @@
 		msleep(20);
 	}
 
+	hdmi_msm_set_mode(FALSE);
 	mutex_lock(&hdcp_auth_state_mutex);
 	hdmi_msm_reset_core();
 	mutex_unlock(&hdcp_auth_state_mutex);
@@ -4147,14 +4145,7 @@
 #endif
 	hdmi_msm_spd_infoframe_packetsetup();
 
-	/* set timeout to 4.1ms (max) for hardware debounce */
-	hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
-
-	/* Toggle HPD circuit to trigger HPD sense */
-	HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
-	HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
-
-	/* Setup HPD IRQ */
+	/* Set IRQ for HPD */
 	HDMI_OUTP(0x0254, 4 | (external_common_state->hpd_state ? 0 : 2));
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
@@ -4231,22 +4222,24 @@
 
 static void hdmi_msm_hpd_off(void)
 {
+	int rc = 0;
+
 	if (!hdmi_msm_state->hpd_initialized) {
 		DEV_DBG("%s: HPD is already OFF, returning\n", __func__);
 		return;
 	}
 
-	DEV_DBG("%s: (timer, clk, 5V, core, IRQ off)\n", __func__);
+	DEV_DBG("%s: (timer, 5V, IRQ off)\n", __func__);
 	del_timer(&hdmi_msm_state->hpd_state_timer);
 	disable_irq(hdmi_msm_state->irq);
 
 	hdmi_msm_set_mode(FALSE);
-	hdmi_msm_state->hpd_initialized = FALSE;
-	hdmi_msm_powerdown_phy();
-	hdmi_msm_state->pd->cec_power(0);
 	hdmi_msm_state->pd->enable_5v(0);
-	hdmi_msm_state->pd->core_power(0, 1);
 	hdmi_msm_clk(0);
+	rc = hdmi_msm_state->pd->gpio_config(0);
+	if (rc != 0)
+		DEV_INFO("%s: Failed to disable GPIOs. Error=%d\n",
+				__func__, rc);
 	hdmi_msm_state->hpd_initialized = FALSE;
 }
 
@@ -4262,40 +4255,56 @@
 {
 	static int phy_reset_done;
 	uint32 hpd_ctrl;
+	int rc = 0;
 
 	if (hdmi_msm_state->hpd_initialized) {
-		DEV_DBG("%s: HPD is already ON, returning\n", __func__);
-		return 0;
+		DEV_DBG("%s: HPD is already ON\n", __func__);
+	} else {
+		rc = hdmi_msm_state->pd->gpio_config(1);
+		if (rc) {
+			DEV_ERR("%s: Failed to enable GPIOs. Error=%d\n",
+					__func__, rc);
+			goto error1;
+		}
+
+		rc = hdmi_msm_clk(1);
+		if (rc) {
+			DEV_ERR("%s: Failed to enable clocks. Error=%d\n",
+					__func__, rc);
+			goto error2;
+		}
+
+		rc = hdmi_msm_state->pd->enable_5v(1);
+		if (rc) {
+			DEV_ERR("%s: Failed to enable 5V regulator. Error=%d\n",
+					__func__, rc);
+			goto error3;
+		}
+		hdmi_msm_dump_regs("HDMI-INIT: ");
+
+		hdmi_msm_set_mode(FALSE);
+		if (!phy_reset_done) {
+			hdmi_phy_reset();
+			phy_reset_done = 1;
+		}
+		hdmi_msm_set_mode(TRUE);
+
+		/* HDMI_USEC_REFTIMER[0x0208] */
+		HDMI_OUTP(0x0208, 0x0001001B);
+
+		/* set timeout to 4.1ms (max) for hardware debounce */
+		hpd_ctrl = HDMI_INP(0x0258) | 0x1FFF;
+
+		/* Toggle HPD circuit to trigger HPD sense */
+		HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
+		HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
+
+		hdmi_msm_state->hpd_initialized = TRUE;
+
+		/* Check HPD State */
+		enable_irq(hdmi_msm_state->irq);
 	}
 
-	hdmi_msm_clk(1);
-	hdmi_msm_state->pd->core_power(1, 1);
-	hdmi_msm_state->pd->enable_5v(1);
-	hdmi_msm_state->pd->cec_power(1);
-	hdmi_msm_dump_regs("HDMI-INIT: ");
-	hdmi_msm_set_mode(FALSE);
-
-	if (!phy_reset_done) {
-		hdmi_phy_reset();
-		phy_reset_done = 1;
-	}
-
-	/* HDMI_USEC_REFTIMER[0x0208] */
-	HDMI_OUTP(0x0208, 0x0001001B);
-
-	/* Check HPD State */
-	enable_irq(hdmi_msm_state->irq);
-
-	/* set timeout to 4.1ms (max) for hardware debounce */
-	hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
-
-	/* Toggle HPD circuit to trigger HPD sense */
-	HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
-	HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
-
-	DEV_DBG("%s: (clk, 5V, core, IRQ on) <trigger:%s>\n", __func__,
-		trigger_handler ? "true" : "false");
-
 	if (trigger_handler) {
 		/* Set HPD state machine: ensure at least 2 readouts */
 		mutex_lock(&hdmi_msm_state_mutex);
@@ -4310,24 +4319,33 @@
 			jiffies + HZ/2);
 	}
 
-	hdmi_msm_state->hpd_initialized = TRUE;
-
-	hdmi_msm_set_mode(TRUE);
-
+	DEV_DBG("%s: (IRQ, 5V on) <trigger:%s>\n", __func__,
+		trigger_handler ? "true" : "false");
 	return 0;
+
+error3:
+	hdmi_msm_clk(0);
+error2:
+	hdmi_msm_state->pd->gpio_config(0);
+error1:
+	return rc;
 }
 
 static int hdmi_msm_power_ctrl(boolean enable)
 {
-	if (!external_common_state->hpd_feature_on)
+	int rc = 0;
+	if (!hdmi_prim_display && !external_common_state->hpd_feature_on)
 		return 0;
 
-	if (enable)
-		hdmi_msm_hpd_on(true);
-	else
+	if (enable) {
+		DEV_DBG("%s: Turning HPD ciruitry on\n", __func__);
+		rc = hdmi_msm_hpd_on(true);
+	} else {
+		DEV_DBG("%s: Turning HPD ciruitry off\n", __func__);
 		hdmi_msm_hpd_off();
+	}
 
-	return 0;
+	return rc;
 }
 
 static int hdmi_msm_power_on(struct platform_device *pdev)
@@ -4351,22 +4369,15 @@
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 	changed = hdmi_common_get_video_format_from_drv_data(mfd);
-	if (!external_common_state->hpd_feature_on || mfd->ref_cnt) {
-		int rc = hdmi_msm_hpd_on(true);
-		DEV_INFO("HPD: panel power without 'hpd' feature on\n");
-		if (rc) {
-			DEV_WARN("HPD: activation failed: rc=%d\n", rc);
-			return rc;
-		}
-	}
 	hdmi_msm_audio_info_setup(TRUE, 0, 0, 0, FALSE);
 
 	mutex_lock(&external_common_state_hpd_mutex);
 	hdmi_msm_state->panel_power_on = TRUE;
-	if ((external_common_state->hpd_state && !hdmi_msm_is_power_on())
-		|| changed) {
+	if (external_common_state->hpd_state && hdmi_msm_is_power_on()) {
+		DEV_DBG("%s: Turning HDMI on\n", __func__);
 		mutex_unlock(&external_common_state_hpd_mutex);
 		hdmi_msm_turn_on();
+		hdmi_msm_hdcp_enable();
 	} else
 		mutex_unlock(&external_common_state_hpd_mutex);
 
@@ -4386,8 +4397,6 @@
  */
 static int hdmi_msm_power_off(struct platform_device *pdev)
 {
-	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
-
 	if (!hdmi_msm_state->hdmi_app_clk)
 		return -ENODEV;
 
@@ -4407,15 +4416,7 @@
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 	hdcp_deauthenticate();
 #endif
-	hdmi_msm_hpd_off();
 	hdmi_msm_powerdown_phy();
-	hdmi_msm_dump_regs("HDMI-OFF: ");
-	hdmi_msm_hpd_on(true);
-
-	mutex_lock(&external_common_state_hpd_mutex);
-	if (!external_common_state->hpd_feature_on || mfd->ref_cnt)
-		hdmi_msm_hpd_off();
-	mutex_unlock(&external_common_state_hpd_mutex);
 
 	hdmi_msm_state->panel_power_on = FALSE;
 	return 0;
@@ -4530,7 +4531,6 @@
 	hdmi_msm_state->hpd_state_timer.data = (uint32)NULL;
 
 	hdmi_msm_state->hpd_state_timer.expires = 0xffffffffL;
-	add_timer(&hdmi_msm_state->hpd_state_timer);
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 	init_timer(&hdmi_msm_state->hdcp_timer);
@@ -4561,11 +4561,10 @@
 	} else
 		DEV_ERR("Init FAILED: failed to add fb device\n");
 
-	DEV_INFO("HDMI HPD: ON\n");
-
 	rc = hdmi_msm_hpd_on(true);
 	if (rc)
 		goto error;
+	DEV_INFO("HDMI HPD: ON\n");
 
 	if (hdmi_msm_has_hdcp()) {
 		/* Don't Set Encryption in case of non HDCP builds */
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index ca5d2c6..cad6e02 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -88,6 +88,7 @@
 struct workqueue_struct *mdp_vsync_wq;	/*mdp vsync wq */
 
 struct workqueue_struct *mdp_hist_wq;	/*mdp histogram wq */
+bool mdp_pp_initialized = FALSE;
 
 static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
 static struct delayed_work mdp_pipe_ctrl_worker;
@@ -219,10 +220,28 @@
 	mutex_unlock(&mdp_hist_lut_list_mutex);
 }
 
-static int mdp_hist_lut_init(void)
+static int mdp_hist_lut_destroy(void)
 {
 	struct mdp_hist_lut_mgmt *temp;
 	struct list_head *pos, *q;
+
+	mutex_lock(&mdp_hist_lut_list_mutex);
+	list_for_each_safe(pos, q, &mdp_hist_lut_list) {
+		temp = list_entry(pos, struct mdp_hist_lut_mgmt, list);
+		list_del(pos);
+		kfree(temp);
+	}
+	mutex_unlock(&mdp_hist_lut_list_mutex);
+	return 0;
+}
+
+static int mdp_hist_lut_init(void)
+{
+	struct mdp_hist_lut_mgmt *temp;
+
+	if (mdp_pp_initialized)
+		return -EEXIST;
+
 	INIT_LIST_HEAD(&mdp_hist_lut_list);
 
 	if (mdp_rev >= MDP_REV_30) {
@@ -253,13 +272,7 @@
 	return 0;
 
 exit_list:
-	mutex_lock(&mdp_hist_lut_list_mutex);
-	list_for_each_safe(pos, q, &mdp_hist_lut_list) {
-		temp = list_entry(pos, struct mdp_hist_lut_mgmt, list);
-		list_del(pos);
-		kfree(temp);
-	}
-	mutex_unlock(&mdp_hist_lut_list_mutex);
+	mdp_hist_lut_destroy();
 exit:
 	pr_err("Failed initializing histogram LUT memory\n");
 	return -ENOMEM;
@@ -682,10 +695,30 @@
 	kfree(mgmt->c0);
 }
 
+static int mdp_histogram_destroy(void)
+{
+	struct mdp_hist_mgmt *temp;
+	int i;
+
+	for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+		temp = mdp_hist_mgmt_array[i];
+		if (!temp)
+			continue;
+		mdp_hist_del_mgmt(temp);
+		kfree(temp);
+		mdp_hist_mgmt_array[i] = NULL;
+	}
+	return 0;
+}
+
 static int mdp_histogram_init(void)
 {
 	struct mdp_hist_mgmt *temp;
 	int i, ret;
+
+	if (mdp_pp_initialized)
+		return -EEXIST;
+
 	mdp_hist_wq = alloc_workqueue("mdp_hist_wq",
 					WQ_NON_REENTRANT | WQ_UNBOUND, 0);
 
@@ -731,14 +764,7 @@
 	return 0;
 
 exit_list:
-	for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
-		temp = mdp_hist_mgmt_array[i];
-		if (!temp)
-			continue;
-		mdp_hist_del_mgmt(temp);
-		kfree(temp);
-		mdp_hist_mgmt_array[i] = NULL;
-	}
+	mdp_histogram_destroy();
 exit:
 	return -ENOMEM;
 }
@@ -888,6 +914,7 @@
 		goto error;
 	}
 
+	mutex_lock(&mgmt->mdp_do_hist_mutex);
 	mutex_lock(&mgmt->mdp_hist_mutex);
 	if (mgmt->mdp_is_hist_start == TRUE) {
 		pr_err("%s histogram already started\n", __func__);
@@ -907,6 +934,7 @@
 
 error_lock:
 	mutex_unlock(&mgmt->mdp_hist_mutex);
+	mutex_unlock(&mgmt->mdp_do_hist_mutex);
 error:
 	return ret;
 }
@@ -923,6 +951,7 @@
 		goto error;
 	}
 
+	mutex_lock(&mgmt->mdp_do_hist_mutex);
 	mutex_lock(&mgmt->mdp_hist_mutex);
 	if (mgmt->mdp_is_hist_start == FALSE) {
 		pr_err("%s histogram already stopped\n", __func__);
@@ -943,10 +972,12 @@
 
 	mutex_unlock(&mgmt->mdp_hist_mutex);
 	cancel_work_sync(&mgmt->mdp_histogram_worker);
+	mutex_unlock(&mgmt->mdp_do_hist_mutex);
 	return ret;
 
 error_lock:
 	mutex_unlock(&mgmt->mdp_hist_mutex);
+	mutex_unlock(&mgmt->mdp_do_hist_mutex);
 error:
 	return ret;
 }
@@ -1068,21 +1099,31 @@
 		goto error;
 	}
 
-	switch (mgmt->block) {
-	case MDP_BLOCK_DMA_P:
-	case MDP_BLOCK_DMA_S:
-		ret = _mdp_histogram_read_dma_data(mgmt);
-		break;
-	case MDP_BLOCK_VG_1:
-	case MDP_BLOCK_VG_2:
-		ret = _mdp_histogram_read_vg_data(mgmt);
-		break;
-	default:
-		pr_err("%s, invalid MDP block = %d\n", __func__, mgmt->block);
+	if (mgmt->hist == NULL) {
+		if ((mgmt->mdp_is_hist_init == TRUE) &&
+			((!completion_done(&mgmt->mdp_hist_comp)) &&
+			waitqueue_active(&mgmt->mdp_hist_comp.wait)))
+			pr_err("mgmt->hist invalid NULL\n");
 		ret = -EINVAL;
-		goto error;
 	}
 
+	if (!ret) {
+		switch (mgmt->block) {
+		case MDP_BLOCK_DMA_P:
+		case MDP_BLOCK_DMA_S:
+			ret = _mdp_histogram_read_dma_data(mgmt);
+			break;
+		case MDP_BLOCK_VG_1:
+		case MDP_BLOCK_VG_2:
+			ret = _mdp_histogram_read_vg_data(mgmt);
+			break;
+		default:
+			pr_err("%s, invalid MDP block = %d\n", __func__,
+								mgmt->block);
+			ret = -EINVAL;
+			goto error;
+		}
+	}
 	/*
 	 * if read was triggered by an underrun or failed copying,
 	 * don't wake up readers
@@ -1142,11 +1183,13 @@
 	return ret;
 }
 
+#define MDP_HISTOGRAM_TIMEOUT_MS	84 /*5 Frames*/
 static int mdp_do_histogram(struct fb_info *info,
 					struct mdp_histogram_data *hist)
 {
 	struct mdp_hist_mgmt *mgmt = NULL;
 	int ret = 0;
+	unsigned long timeout = (MDP_HISTOGRAM_TIMEOUT_MS * HZ) / 1000;
 
 	ret = mdp_histogram_block2mgmt(hist->block, &mgmt);
 	if (ret) {
@@ -1191,9 +1234,17 @@
 	mgmt->hist = hist;
 	mutex_unlock(&mgmt->mdp_hist_mutex);
 
-	if (wait_for_completion_killable(&mgmt->mdp_hist_comp)) {
-		pr_err("%s(): histogram bin collection killed", __func__);
-		ret = -EINVAL;
+	ret = wait_for_completion_killable_timeout(&mgmt->mdp_hist_comp,
+								timeout);
+	if (ret <= 0) {
+		if (!ret) {
+			mgmt->hist = NULL;
+			ret = -ETIMEDOUT;
+			pr_debug("%s: bin collection timedout", __func__);
+		} else {
+			mgmt->hist = NULL;
+			pr_debug("%s: bin collection interrupted", __func__);
+		}
 		goto error;
 	}
 
@@ -1573,16 +1624,7 @@
 		__mdp_histogram_kickoff(mgmt);
 
 	if (isr & INTR_HIST_DONE) {
-		if ((waitqueue_active(&mgmt->mdp_hist_comp.wait))
-			 && (mgmt->hist != NULL)) {
-			if (!queue_work(mdp_hist_wq,
-						&mgmt->mdp_histogram_worker)) {
-				pr_err("%s %d- can't queue hist_read\n",
-							 __func__, mgmt->block);
-			}
-		} else {
-			__mdp_histogram_reset(mgmt);
-		}
+		queue_work(mdp_hist_wq, &mgmt->mdp_histogram_worker);
 	}
 }
 
@@ -2255,6 +2297,7 @@
 	/* initialize Post Processing data*/
 	mdp_hist_lut_init();
 	mdp_histogram_init();
+	mdp_pp_initialized = TRUE;
 
 	/* add panel data */
 	if (platform_device_add_data
@@ -2656,6 +2699,12 @@
 {
 	if (footswitch != NULL)
 		regulator_put(footswitch);
+
+	/*free post processing memory*/
+	mdp_histogram_destroy();
+	mdp_hist_lut_destroy();
+	mdp_pp_initialized = FALSE;
+
 	iounmap(msm_mdp_base);
 	pm_runtime_disable(&pdev->dev);
 #ifdef CONFIG_MSM_BUS_SCALING
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 511edb6..e60b24e 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -836,5 +836,12 @@
 	unsigned long srcp0_addr, unsigned long srcp0_size,
 	unsigned long srcp1_addr, unsigned long srcp1_size);
 
+#ifdef CONFIG_FB_MSM_DTV
 void mdp_vid_quant_set(void);
+#else
+static inline void mdp_vid_quant_set(void)
+{
+	/* empty */
+}
+#endif
 #endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 16fede1..1557eed 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -446,6 +446,7 @@
 			struct mdp4_overlay_pipe *pipe);
 void mdp4_dma_e_done_dtv(void);
 void mdp4_overlay_dtv_wait4vsync(void);
+void mdp4_dtv_base_swap(struct mdp4_overlay_pipe *pipe);
 #else
 static inline void mdp4_overlay_dtv_start(void)
 {
@@ -488,6 +489,10 @@
 {
 	return;
 }
+static inline void mdp4_dtv_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+	/* empty */
+}
 #endif
 
 void mdp4_dtv_set_black_screen(void);
@@ -505,7 +510,6 @@
 			struct mdp4_overlay_pipe *pipe);
 int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe);
-void mdp4_dtv_base_swap(struct mdp4_overlay_pipe *pipe);
 void mdp4_dtv_overlay(struct msm_fb_data_type *mfd);
 int mdp4_dtv_on(struct platform_device *pdev);
 int mdp4_dtv_off(struct platform_device *pdev);
diff --git a/drivers/video/msm/mdp4_dtv.c b/drivers/video/msm/mdp4_dtv.c
index f0353bd..bd0ce2f 100644
--- a/drivers/video/msm/mdp4_dtv.c
+++ b/drivers/video/msm/mdp4_dtv.c
@@ -137,6 +137,12 @@
 		clk_prepare_enable(ebi1_clk);
 	}
 #endif
+
+	if (dtv_pdata && dtv_pdata->lcdc_power_save)
+		dtv_pdata->lcdc_power_save(1);
+	if (dtv_pdata && dtv_pdata->lcdc_gpio_config)
+		ret = dtv_pdata->lcdc_gpio_config(1);
+
 	mfd = platform_get_drvdata(pdev);
 
 	ret = clk_set_rate(tv_src_clk, mfd->fbi->var.pixclock);
@@ -158,11 +164,6 @@
 	if (mdp_tv_clk)
 		clk_prepare_enable(mdp_tv_clk);
 
-	if (dtv_pdata && dtv_pdata->lcdc_power_save)
-		dtv_pdata->lcdc_power_save(1);
-	if (dtv_pdata && dtv_pdata->lcdc_gpio_config)
-		ret = dtv_pdata->lcdc_gpio_config(1);
-
 	ret = panel_next_on(pdev);
 	return ret;
 }
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index aa1795f..9174bc5 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -239,15 +239,8 @@
 
 	mdp_footswitch_ctrl(TRUE);
 	mdp4_overlay_panel_mode(MDP4_MIXER1, MDP4_PANEL_DTV);
-
-	/* Allocate dtv_pipe at dtv_on*/
-	if (dtv_pipe == NULL) {
-		if (mdp4_overlay_dtv_set(mfd, NULL)) {
-			pr_warn("%s: dtv_pipe is NULL, dtv_set failed\n",
-				__func__);
-			return -EINVAL;
-		}
-	}
+	if (dtv_pipe != NULL)
+		ret = mdp4_dtv_start(mfd);
 
 	ret = panel_next_on(pdev);
 	if (ret != 0)
@@ -676,10 +669,12 @@
 	if (!change)
 		return;
 
-	mdp4_overlay_dtv_wait4dmae(mfd);
+	if (dtv_enabled) {
+		mdp4_overlay_dtv_wait4dmae(mfd);
+		MDP_OUTP(MDP_BASE + DTV_BASE, 0);	/* stop dtv */
+		msleep(20);
+	}
 
-	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 */
@@ -706,6 +701,14 @@
 		return;
 	}
 	mutex_lock(&mfd->dma->ov_mutex);
+	if (dtv_pipe == NULL) {
+		if (mdp4_overlay_dtv_set(mfd, NULL)) {
+			pr_warn("%s: dtv_pipe == NULL\n", __func__);
+			mutex_unlock(&mfd->dma->ov_mutex);
+			return;
+		}
+	}
+
 	pipe = dtv_pipe;
 
 	if (hdmi_prim_display && (pipe->pipe_used == 0 ||
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 8410592..fd6d365 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -551,9 +551,12 @@
 	if (!change)
 		return;
 
-	mdp4_overlay_lcdc_wait4event(mfd, INTR_DMA_P_DONE);
-	MDP_OUTP(MDP_BASE + LCDC_BASE, 0);	/* stop lcdc */
-	msleep(20);
+	if (lcdc_enabled) {
+		mdp4_overlay_lcdc_wait4event(mfd, INTR_DMA_P_DONE);
+		MDP_OUTP(MDP_BASE + LCDC_BASE, 0);	/* stop lcdc */
+		msleep(20);
+	}
+
 	mdp4_overlayproc_cfg(lcdc_pipe);
 	mdp4_overlay_dmap_xy(lcdc_pipe);
 	if (lcdc_pipe->blt_addr) {
diff --git a/drivers/video/msm/mdss/Kconfig b/drivers/video/msm/mdss/Kconfig
new file mode 100644
index 0000000..30351a3
--- /dev/null
+++ b/drivers/video/msm/mdss/Kconfig
@@ -0,0 +1,5 @@
+config FB_MSM_MDSS_WRITEBACK
+	bool "MDSS Writeback Panel"
+	---help---
+	The MDSS Writeback Panel provides support for routing the output of
+	MDSS frame buffer driver and MDP processing to memory.
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
new file mode 100644
index 0000000..2a61f07
--- /dev/null
+++ b/drivers/video/msm/mdss/Makefile
@@ -0,0 +1,6 @@
+mdss-mdp-objs := mdss_mdp.o mdss_mdp_ctl.o mdss_mdp_pipe.o mdss_mdp_util.o
+mdss-mdp-objs += mdss_mdp_intf_writeback.o
+mdss-mdp-objs += mdss_mdp_overlay.o
+obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp.o
+obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
+obj-$(CONFIG_FB_MSM_MDSS_WRITEBACK) += mdss_wb.o
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
new file mode 100644
index 0000000..aaf6690
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss.h
@@ -0,0 +1,63 @@
+/* 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 MDSS_H
+#define MDSS_H
+
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#define MDSS_REG_WRITE(addr, val) writel_relaxed(val, mdss_reg_base + addr)
+#define MDSS_REG_READ(addr) readl_relaxed(mdss_reg_base + addr)
+
+extern unsigned char *mdss_reg_base;
+
+struct mdss_res_type {
+	u32 rev;
+	u32 mdp_rev;
+	struct clk *mdp_clk;
+	struct clk *mdp_pclk;
+	struct clk *mdp_lut_clk;
+	struct clk *vsync_clk;
+	struct regulator *fs;
+
+	struct workqueue_struct *clk_ctrl_wq;
+	struct delayed_work clk_ctrl_worker;
+
+	u32 irq;
+	u32 irq_mask;
+	u32 irq_ena;
+	u32 irq_buzy;
+
+	u32 clk_ena;
+	u32 suspend;
+	u32 timeout;
+
+	u32 fs_ena;
+	u32 vsync_ena;
+
+	u32 intf;
+	u32 eintf_ena;
+	u32 prim_ptype;
+	u32 res_init;
+	u32 pdev_lcnt;
+	u32 bus_hdl;
+
+	u32 smp_mb_cnt;
+	u32 smp_mb_size;
+	u32 *pipe_type_map;
+	u32 *mixer_type_map;
+};
+extern struct mdss_res_type *mdss_res;
+#endif /* MDSS_H */
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
new file mode 100644
index 0000000..0fedb6c
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -0,0 +1,1231 @@
+/*
+ * Core MDSS framebuffer driver.
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * 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.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/android_pmem.h>
+#include <linux/bootmem.h>
+#include <linux/console.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/memory.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/msm_mdp.h>
+#include <linux/proc_fs.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+#include <linux/vmalloc.h>
+
+#include <mach/board.h>
+
+#include "mdss_fb.h"
+#include "mdss_mdp.h"
+
+#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
+#define MDSS_FB_NUM 3
+#else
+#define MDSS_FB_NUM 2
+#endif
+
+#define MAX_FBI_LIST 32
+static struct fb_info *fbi_list[MAX_FBI_LIST];
+static int fbi_list_index;
+
+static u32 mdss_fb_pseudo_palette[16] = {
+	0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+static int mdss_fb_register(struct msm_fb_data_type *mfd);
+static int mdss_fb_open(struct fb_info *info, int user);
+static int mdss_fb_release(struct fb_info *info, int user);
+static int mdss_fb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info);
+static int mdss_fb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static int mdss_fb_set_par(struct fb_info *info);
+static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
+			     int op_enable);
+static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd);
+static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg);
+static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
+
+#define MAX_BACKLIGHT_BRIGHTNESS 255
+static int lcd_backlight_registered;
+
+static void mdss_fb_set_bl_brightness(struct led_classdev *led_cdev,
+				      enum led_brightness value)
+{
+	struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
+	int bl_lvl;
+
+	if (value > MAX_BACKLIGHT_BRIGHTNESS)
+		value = MAX_BACKLIGHT_BRIGHTNESS;
+
+	/* This maps android backlight level 0 to 255 into
+	   driver backlight level 0 to bl_max with rounding */
+	bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)
+		 /(2 * MAX_BACKLIGHT_BRIGHTNESS);
+
+	if (!bl_lvl && value)
+		bl_lvl = 1;
+
+	mdss_fb_set_backlight(mfd, bl_lvl);
+}
+
+static struct led_classdev backlight_led = {
+	.name           = "lcd-backlight",
+	.brightness     = MAX_BACKLIGHT_BRIGHTNESS,
+	.brightness_set = mdss_fb_set_bl_brightness,
+};
+
+static ssize_t mdss_fb_get_type(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+
+	switch (mfd->panel_info.type) {
+	case NO_PANEL:
+		ret = snprintf(buf, PAGE_SIZE, "no panel\n");
+		break;
+	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;
+	case MIPI_VIDEO_PANEL:
+		ret = snprintf(buf, PAGE_SIZE, "mipi dsi video panel\n");
+		break;
+	case MIPI_CMD_PANEL:
+		ret = snprintf(buf, PAGE_SIZE, "mipi dsi cmd panel\n");
+		break;
+	case WRITEBACK_PANEL:
+		ret = snprintf(buf, PAGE_SIZE, "writeback panel\n");
+		break;
+	default:
+		ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
+		break;
+	}
+
+	return ret;
+}
+
+static DEVICE_ATTR(mdss_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
+static struct attribute *mdss_fb_attrs[] = {
+	&dev_attr_mdss_fb_type.attr,
+	NULL,
+};
+
+static struct attribute_group mdss_fb_attr_group = {
+	.attrs = mdss_fb_attrs,
+};
+
+static int mdss_fb_create_sysfs(struct msm_fb_data_type *mfd)
+{
+	int rc;
+
+	rc = sysfs_create_group(&mfd->fbi->dev->kobj, &mdss_fb_attr_group);
+	if (rc)
+		pr_err("sysfs group creation failed, rc=%d\n", rc);
+	return rc;
+}
+
+static void mdss_fb_remove_sysfs(struct msm_fb_data_type *mfd)
+{
+	sysfs_remove_group(&mfd->fbi->dev->kobj, &mdss_fb_attr_group);
+}
+
+static int mdss_fb_probe(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd = NULL;
+	struct mdss_panel_data *pdata;
+	struct fb_info *fbi;
+	int rc;
+
+	if (fbi_list_index >= MAX_FBI_LIST)
+		return -ENOMEM;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (!pdata)
+		return -ENODEV;
+
+	/*
+	 * alloc framebuffer info + par data
+	 */
+	fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), &pdev->dev);
+	if (fbi == NULL) {
+		pr_err("can't allocate framebuffer info data!\n");
+		return -ENOMEM;
+	}
+
+	mfd = (struct msm_fb_data_type *)fbi->par;
+	mfd->key = MFD_KEY;
+	mfd->fbi = fbi;
+	mfd->panel_info = pdata->panel_info;
+	mfd->panel.type = pdata->panel_info.type;
+	mfd->panel.id = mfd->index;
+	mfd->fb_page = MDSS_FB_NUM;
+	mfd->index = fbi_list_index;
+	mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
+	mfd->panel_info.frame_count = 0;
+	mfd->bl_level = 0;
+	mfd->fb_imgType = MDP_RGBA_8888;
+	mfd->iclient = msm_ion_client_create(-1, pdev->name);
+	if (IS_ERR(mfd->iclient))
+		mfd->iclient = NULL;
+
+	mfd->pdev = pdev;
+
+	mutex_init(&mfd->lock);
+
+	fbi_list[fbi_list_index++] = fbi;
+
+	platform_set_drvdata(pdev, mfd);
+
+	rc = mdss_fb_register(mfd);
+	if (rc)
+		return rc;
+
+	rc = pm_runtime_set_active(mfd->fbi->dev);
+	if (rc < 0)
+		pr_err("pm_runtime: fail to set active.\n");
+	pm_runtime_enable(mfd->fbi->dev);
+
+	/* android supports only one lcd-backlight/lcd for now */
+	if (!lcd_backlight_registered) {
+		if (led_classdev_register(&pdev->dev, &backlight_led))
+			pr_err("led_classdev_register failed\n");
+		else
+			lcd_backlight_registered = 1;
+	}
+
+	mdss_fb_create_sysfs(mfd);
+
+	return 0;
+}
+
+static int mdss_fb_remove(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	mdss_fb_remove_sysfs(mfd);
+
+	pm_runtime_disable(mfd->fbi->dev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (mdss_fb_suspend_sub(mfd))
+		pr_err("msm_fb_remove: can't stop the device %d\n",
+			    mfd->index);
+
+	/* remove /dev/fb* */
+	unregister_framebuffer(mfd->fbi);
+
+	if (lcd_backlight_registered) {
+		lcd_backlight_registered = 0;
+		led_classdev_unregister(&backlight_led);
+	}
+
+	return 0;
+}
+
+static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd)
+{
+	int ret = 0;
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	/*
+	 * suspend this channel
+	 */
+	mfd->suspend.op_enable = mfd->op_enable;
+	mfd->suspend.panel_power_on = mfd->panel_power_on;
+
+	if (mfd->op_enable) {
+		ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
+				mfd->suspend.op_enable);
+		if (ret) {
+			pr_warn("can't turn off display!\n");
+			return ret;
+		}
+		mfd->op_enable = false;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_PM)
+static int mdss_fb_resume_sub(struct msm_fb_data_type *mfd)
+{
+	int ret = 0;
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	/* resume state var recover */
+	mfd->op_enable = mfd->suspend.op_enable;
+
+	if (mfd->suspend.panel_power_on) {
+		ret = mdss_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
+					mfd->op_enable);
+		if (ret)
+			pr_warn("can't turn on display!\n");
+	}
+
+	return ret;
+}
+
+static int mdss_fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct msm_fb_data_type *mfd;
+	int ret = 0;
+
+	pr_debug("mdss_fb_suspend\n");
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	console_lock();
+	fb_set_suspend(mfd->fbi, FBINFO_STATE_SUSPENDED);
+
+	ret = mdss_fb_suspend_sub(mfd);
+	if (ret != 0) {
+		pr_err("failed to suspend! %d\n", ret);
+		fb_set_suspend(mfd->fbi, FBINFO_STATE_RUNNING);
+	} else {
+		pdev->dev.power.power_state = state;
+	}
+
+	console_unlock();
+	return ret;
+}
+
+static int mdss_fb_resume(struct platform_device *pdev)
+{
+	/* This resume function is called when interrupt is enabled.
+	 */
+	int ret = 0;
+	struct msm_fb_data_type *mfd;
+
+	pr_debug("mdss_fb_resume\n");
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	console_lock();
+	ret = mdss_fb_resume_sub(mfd);
+	pdev->dev.power.power_state = PMSG_ON;
+	fb_set_suspend(mfd->fbi, FBINFO_STATE_RUNNING);
+	console_unlock();
+
+	return ret;
+}
+#else
+#define mdss_fb_suspend NULL
+#define mdss_fb_resume NULL
+#endif
+
+#if defined(CONFIG_PM) && defined(CONFIG_SUSPEND)
+static int mdss_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 = mdss_fb_suspend_sub(mfd);
+
+	return ret;
+}
+
+static int mdss_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 = mdss_fb_resume_sub(mfd);
+
+	return ret;
+}
+#else
+#define mdss_fb_ext_suspend NULL
+#define mdss_fb_ext_resume NULL
+#endif
+
+static const struct dev_pm_ops mdss_fb_dev_pm_ops = {
+	.suspend = mdss_fb_ext_suspend,
+	.resume = mdss_fb_ext_resume,
+};
+
+static struct platform_driver mdss_fb_driver = {
+	.probe = mdss_fb_probe,
+	.remove = mdss_fb_remove,
+	.suspend = mdss_fb_suspend,
+	.resume = mdss_fb_resume,
+	.shutdown = NULL,
+	.driver = {
+		.name = "mdss_fb",
+		.pm = &mdss_fb_dev_pm_ops,
+	},
+};
+
+static int unset_bl_level, bl_updated;
+static int bl_level_old;
+
+void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
+{
+	struct mdss_panel_data *pdata;
+
+	if (!mfd->panel_power_on || !bl_updated) {
+		unset_bl_level = bkl_lvl;
+		return;
+	} else {
+		unset_bl_level = 0;
+	}
+
+	pdata = dev_get_platdata(&mfd->pdev->dev);
+
+	if ((pdata) && (pdata->set_backlight)) {
+		mutex_lock(&mfd->lock);
+		if (bl_level_old == bkl_lvl) {
+			mutex_unlock(&mfd->lock);
+			return;
+		}
+		mfd->bl_level = bkl_lvl;
+		pdata->set_backlight(mfd->bl_level);
+		bl_level_old = mfd->bl_level;
+		mutex_unlock(&mfd->lock);
+	}
+}
+
+void mdss_fb_update_backlight(struct msm_fb_data_type *mfd)
+{
+	struct mdss_panel_data *pdata;
+
+	if (unset_bl_level && !bl_updated) {
+		pdata = dev_get_platdata(&mfd->pdev->dev);
+		if ((pdata) && (pdata->set_backlight)) {
+			mutex_lock(&mfd->lock);
+			mfd->bl_level = unset_bl_level;
+			pdata->set_backlight(mfd->bl_level);
+			bl_level_old = unset_bl_level;
+			mutex_unlock(&mfd->lock);
+			bl_updated = 1;
+		}
+	}
+}
+
+static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
+			     int op_enable)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	int ret = 0;
+
+	if (!op_enable)
+		return -EPERM;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		if (!mfd->panel_power_on) {
+			msleep(20);
+			ret = mfd->on_fnc(mfd);
+			if (ret == 0)
+				mfd->panel_power_on = true;
+		}
+		break;
+
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_POWERDOWN:
+	default:
+		if (mfd->panel_power_on) {
+			int curr_pwr_state;
+
+			mfd->op_enable = false;
+			curr_pwr_state = mfd->panel_power_on;
+			mfd->panel_power_on = false;
+			bl_updated = 0;
+
+			msleep(20);
+			ret = mfd->off_fnc(mfd);
+			if (ret)
+				mfd->panel_power_on = curr_pwr_state;
+
+			mfd->op_enable = true;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+static int mdss_fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	return mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
+}
+
+/*
+ * Custom Framebuffer mmap() function for MSM driver.
+ * Differs from standard mmap() function by allowing for customized
+ * page-protection.
+ */
+static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	/* Get frame buffer memory range. */
+	unsigned long start = info->fix.smem_start;
+	u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
+	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if (off >= len) {
+		/* memory mapped io */
+		off -= len;
+		if (info->var.accel_flags) {
+			mutex_unlock(&info->lock);
+			return -EINVAL;
+		}
+		start = info->fix.mmio_start;
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+	}
+
+	/* Set VM flags. */
+	start &= PAGE_MASK;
+	if ((vma->vm_end - vma->vm_start + off) > len)
+		return -EINVAL;
+	off += start;
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+	/* This is an IO map - tell maydump to skip this VMA */
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+
+	/* Set VM page protection */
+	if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	else if (mfd->mdp_fb_page_protection ==
+		 MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE)
+		vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot);
+	else if (mfd->mdp_fb_page_protection ==
+		 MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE)
+		vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot);
+	else if (mfd->mdp_fb_page_protection ==
+		 MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE)
+		vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot);
+	else
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	/* Remap the frame buffer I/O range */
+	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
+
+static struct fb_ops mdss_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = mdss_fb_open,
+	.fb_release = mdss_fb_release,
+	.fb_check_var = mdss_fb_check_var,	/* vinfo check */
+	.fb_set_par = mdss_fb_set_par,	/* set the video mode */
+	.fb_blank = mdss_fb_blank,	/* blank display */
+	.fb_pan_display = mdss_fb_pan_display,	/* pan display */
+	.fb_ioctl = mdss_fb_ioctl,	/* perform fb specific ioctl */
+	.fb_mmap = mdss_fb_mmap,
+};
+
+static u32 mdss_fb_line_length(u32 fb_index, u32 xres, int bpp)
+{
+	/* The adreno GPU hardware requires that the pitch be aligned to
+	   32 pixels for color buffers, so for the cases where the GPU
+	   is writing directly to fb0, the framebuffer pitch
+	   also needs to be 32 pixel aligned */
+
+	if (fb_index == 0)
+		return ALIGN(xres, 32) * bpp;
+	else
+		return xres * bpp;
+}
+
+static int mdss_fb_alloc_fbmem(struct msm_fb_data_type *mfd)
+{
+	void *virt = NULL;
+	unsigned long phys = 0;
+	size_t size;
+
+	size = PAGE_ALIGN(mfd->fbi->fix.line_length * mfd->panel_info.yres);
+	size *= mfd->fb_page;
+
+	if (mfd->index == 0) {
+		virt = dma_alloc_coherent(NULL, size, (dma_addr_t *) &phys,
+				GFP_KERNEL);
+		if (!virt) {
+			pr_err("unable to alloc fb memory size=%u\n", size);
+			return -ENOMEM;
+		}
+
+		pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
+			size, virt, phys, mfd->index);
+	} else {
+		pr_debug("no memory allocated for fb%d\n", mfd->index);
+		size = 0;
+	}
+
+	mfd->fbi->screen_base = virt;
+	mfd->fbi->fix.smem_start = phys;
+	mfd->fbi->fix.smem_len = size;
+
+	return 0;
+}
+
+static int mdss_fb_register(struct msm_fb_data_type *mfd)
+{
+	int ret = -ENODEV;
+	int bpp;
+	struct mdss_panel_info *panel_info = &mfd->panel_info;
+	struct fb_info *fbi = mfd->fbi;
+	struct fb_fix_screeninfo *fix;
+	struct fb_var_screeninfo *var;
+	int *id;
+
+	/*
+	 * fb info initialization
+	 */
+	fix = &fbi->fix;
+	var = &fbi->var;
+
+	fix->type_aux = 0;	/* if type == FB_TYPE_INTERLEAVED_PLANES */
+	fix->visual = FB_VISUAL_TRUECOLOR;	/* True Color */
+	fix->ywrapstep = 0;	/* No support */
+	fix->mmio_start = 0;	/* No MMIO Address */
+	fix->mmio_len = 0;	/* No MMIO Address */
+	fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
+
+	var->xoffset = 0,	/* Offset from virtual to visible */
+	var->yoffset = 0,	/* resolution */
+	var->grayscale = 0,	/* No graylevels */
+	var->nonstd = 0,	/* standard pixel format */
+	var->activate = FB_ACTIVATE_VBL,	/* activate it at vsync */
+	var->height = -1,	/* height of picture in mm */
+	var->width = -1,	/* width of picture in mm */
+	var->accel_flags = 0,	/* acceleration flags */
+	var->sync = 0,	/* see FB_SYNC_* */
+	var->rotate = 0,	/* angle we rotate counter clockwise */
+	mfd->op_enable = false;
+
+	switch (mfd->fb_imgType) {
+	case MDP_RGB_565:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 11;
+		var->blue.length = 5;
+		var->green.length = 6;
+		var->red.length = 5;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		bpp = 2;
+		break;
+
+	case MDP_RGB_888:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+		var->blue.offset = 0;
+		var->green.offset = 8;
+		var->red.offset = 16;
+		var->blue.length = 8;
+		var->green.length = 8;
+		var->red.length = 8;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		bpp = 3;
+		break;
+
+	case MDP_ARGB_8888:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+		var->blue.offset = 0;
+		var->green.offset = 8;
+		var->red.offset = 16;
+		var->blue.length = 8;
+		var->green.length = 8;
+		var->red.length = 8;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		bpp = 4;
+		break;
+
+	case MDP_RGBA_8888:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+		var->blue.offset = 8;
+		var->green.offset = 16;
+		var->red.offset = 24;
+		var->blue.length = 8;
+		var->green.length = 8;
+		var->red.length = 8;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 0;
+		var->transp.length = 8;
+		bpp = 4;
+		break;
+
+	case MDP_YCRYCB_H2V1:
+		fix->type = FB_TYPE_INTERLEAVED_PLANES;
+		fix->xpanstep = 2;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		/* how about R/G/B offset? */
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 11;
+		var->blue.length = 5;
+		var->green.length = 6;
+		var->red.length = 5;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		bpp = 2;
+		break;
+
+	default:
+		pr_err("msm_fb_init: fb %d unkown image type!\n",
+			    mfd->index);
+		return ret;
+	}
+
+	fix->type = panel_info->is_3d_panel;
+	fix->line_length = mdss_fb_line_length(mfd->index, panel_info->xres,
+					       bpp);
+	mfd->var_xres = panel_info->xres;
+	mfd->var_yres = panel_info->yres;
+
+	var->pixclock = mfd->panel_info.clk_rate;
+	mfd->var_pixclock = var->pixclock;
+
+	var->xres = panel_info->xres;
+	var->yres = panel_info->yres;
+	var->xres_virtual = panel_info->xres;
+	var->yres_virtual = panel_info->yres * mfd->fb_page;
+	var->bits_per_pixel = bpp * 8;	/* FrameBuffer color depth */
+
+	/* id field for fb app  */
+
+	id = (int *)&mfd->panel;
+
+	snprintf(fix->id, sizeof(fix->id), "mdssfb_%x", (u32) *id);
+
+	fbi->fbops = &mdss_fb_ops;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->pseudo_palette = mdss_fb_pseudo_palette;
+
+	mfd->ref_cnt = 0;
+	mfd->panel_power_on = false;
+
+	if (mdss_fb_alloc_fbmem(mfd)) {
+		pr_err("unable to allocate framebuffer memory\n");
+		return -ENOMEM;
+	}
+
+	mfd->op_enable = true;
+
+	/* cursor memory allocation */
+	if (mfd->cursor_update) {
+		mfd->cursor_buf = dma_alloc_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
+					(dma_addr_t *) &mfd->cursor_buf_phys,
+					GFP_KERNEL);
+		if (!mfd->cursor_buf)
+			mfd->cursor_update = 0;
+	}
+
+	if (mfd->lut_update) {
+		ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+		if (ret)
+			pr_err("fb_alloc_cmap() failed!\n");
+	}
+
+	if (register_framebuffer(fbi) < 0) {
+		if (mfd->lut_update)
+			fb_dealloc_cmap(&fbi->cmap);
+
+		if (mfd->cursor_buf)
+			dma_free_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
+					  mfd->cursor_buf,
+					  (dma_addr_t) mfd->cursor_buf_phys);
+
+		mfd->op_enable = false;
+		return -EPERM;
+	}
+
+	pr_info("FrameBuffer[%d] %dx%d size=%d registered successfully!\n",
+		     mfd->index, fbi->var.xres, fbi->var.yres,
+		     fbi->fix.smem_len);
+
+	ret = 0;
+
+	return ret;
+}
+
+static int mdss_fb_open(struct fb_info *info, int user)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	int result;
+
+	result = pm_runtime_get_sync(info->dev);
+
+	if (result < 0)
+		pr_err("pm_runtime: fail to wake up\n");
+
+
+	if (!mfd->ref_cnt) {
+		result = mdss_fb_blank_sub(FB_BLANK_UNBLANK, info,
+					   mfd->op_enable);
+		if (result) {
+			pr_err("mdss_fb_open: can't turn on display!\n");
+			return result;
+		}
+	}
+
+	mfd->ref_cnt++;
+	return 0;
+}
+
+static int mdss_fb_release(struct fb_info *info, int user)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	int ret = 0;
+
+	if (!mfd->ref_cnt) {
+		pr_info("try to close unopened fb %d!\n", mfd->index);
+		return -EINVAL;
+	}
+
+	mfd->ref_cnt--;
+
+	if (!mfd->ref_cnt) {
+		ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
+				       mfd->op_enable);
+		if (ret) {
+			pr_err("can't turn off display!\n");
+			return ret;
+		}
+	}
+
+	pm_runtime_put(info->dev);
+	return ret;
+}
+
+static int mdss_fb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if ((!mfd->op_enable) || (!mfd->panel_power_on))
+		return -EPERM;
+
+	if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+		return -EINVAL;
+
+	if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+		return -EINVAL;
+
+	if (info->fix.xpanstep)
+		info->var.xoffset =
+		(var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+	if (info->fix.ypanstep)
+		info->var.yoffset =
+		(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+	if (mfd->dma_fnc)
+		mfd->dma_fnc(mfd);
+	else
+		pr_warn("dma function not set for panel type=%d\n",
+				mfd->panel.type);
+
+	mdss_fb_update_backlight(mfd);
+
+	++mfd->panel_info.frame_count;
+	return 0;
+}
+
+static int mdss_fb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	u32 len;
+
+	if (var->rotate != FB_ROTATE_UR)
+		return -EINVAL;
+	if (var->grayscale != info->var.grayscale)
+		return -EINVAL;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		if ((var->green.offset != 5) ||
+		    !((var->blue.offset == 11)
+		      || (var->blue.offset == 0)) ||
+		    !((var->red.offset == 11)
+		      || (var->red.offset == 0)) ||
+		    (var->blue.length != 5) ||
+		    (var->green.length != 6) ||
+		    (var->red.length != 5) ||
+		    (var->blue.msb_right != 0) ||
+		    (var->green.msb_right != 0) ||
+		    (var->red.msb_right != 0) ||
+		    (var->transp.offset != 0) ||
+		    (var->transp.length != 0))
+			return -EINVAL;
+		break;
+
+	case 24:
+		if ((var->blue.offset != 0) ||
+		    (var->green.offset != 8) ||
+		    (var->red.offset != 16) ||
+		    (var->blue.length != 8) ||
+		    (var->green.length != 8) ||
+		    (var->red.length != 8) ||
+		    (var->blue.msb_right != 0) ||
+		    (var->green.msb_right != 0) ||
+		    (var->red.msb_right != 0) ||
+		    !(((var->transp.offset == 0) &&
+		       (var->transp.length == 0)) ||
+		      ((var->transp.offset == 24) &&
+		       (var->transp.length == 8))))
+			return -EINVAL;
+		break;
+
+	case 32:
+		/* Figure out if the user meant RGBA or ARGB
+		   and verify the position of the RGB components */
+
+		if (var->transp.offset == 24) {
+			if ((var->blue.offset != 0) ||
+			    (var->green.offset != 8) ||
+			    (var->red.offset != 16))
+				return -EINVAL;
+		} else if (var->transp.offset == 0) {
+			if ((var->blue.offset != 8) ||
+			    (var->green.offset != 16) ||
+			    (var->red.offset != 24))
+				return -EINVAL;
+		} else
+			return -EINVAL;
+
+		/* Check the common values for both RGBA and ARGB */
+
+		if ((var->blue.length != 8) ||
+		    (var->green.length != 8) ||
+		    (var->red.length != 8) ||
+		    (var->transp.length != 8) ||
+		    (var->blue.msb_right != 0) ||
+		    (var->green.msb_right != 0) ||
+		    (var->red.msb_right != 0))
+			return -EINVAL;
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
+		return -EINVAL;
+
+	len = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
+	if (len > info->fix.smem_len)
+		return -EINVAL;
+
+	if ((var->xres == 0) || (var->yres == 0))
+		return -EINVAL;
+
+	if ((var->xres > mfd->panel_info.xres) ||
+	    (var->yres > mfd->panel_info.yres))
+		return -EINVAL;
+
+	if (var->xoffset > (var->xres_virtual - var->xres))
+		return -EINVAL;
+
+	if (var->yoffset > (var->yres_virtual - var->yres))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mdss_fb_set_par(struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int old_imgType;
+	int blank = 0;
+
+	old_imgType = mfd->fb_imgType;
+	switch (var->bits_per_pixel) {
+	case 16:
+		if (var->red.offset == 0)
+			mfd->fb_imgType = MDP_BGR_565;
+		else
+			mfd->fb_imgType	= MDP_RGB_565;
+		break;
+
+	case 24:
+		if ((var->transp.offset == 0) && (var->transp.length == 0))
+			mfd->fb_imgType = MDP_RGB_888;
+		else if ((var->transp.offset == 24) &&
+			 (var->transp.length == 8)) {
+			mfd->fb_imgType = MDP_ARGB_8888;
+			info->var.bits_per_pixel = 32;
+		}
+		break;
+
+	case 32:
+		if (var->transp.offset == 24)
+			mfd->fb_imgType = MDP_ARGB_8888;
+		else
+			mfd->fb_imgType	= MDP_RGBA_8888;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if ((mfd->var_pixclock != var->pixclock) ||
+	    (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
+				 (mfd->var_pixclock != var->pixclock) ||
+				 (mfd->var_xres != var->xres) ||
+				 (mfd->var_yres != var->yres)))) {
+		mfd->var_xres = var->xres;
+		mfd->var_yres = var->yres;
+		mfd->var_pixclock = var->pixclock;
+		blank = 1;
+	}
+	mfd->fbi->fix.line_length = mdss_fb_line_length(mfd->index, var->xres,
+						var->bits_per_pixel / 8);
+
+	if (blank) {
+		mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
+		mdss_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
+	}
+
+	return 0;
+}
+
+static int mdss_fb_cursor(struct fb_info *info, void __user *p)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct fb_cursor cursor;
+	int ret;
+
+	if (!mfd->cursor_update)
+		return -ENODEV;
+
+	ret = copy_from_user(&cursor, p, sizeof(cursor));
+	if (ret)
+		return ret;
+
+	return mfd->cursor_update(info, &cursor);
+}
+
+static int mdss_fb_set_lut(struct fb_info *info, void __user *p)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct fb_cmap cmap;
+	int ret;
+
+	if (!mfd->lut_update)
+		return -ENODEV;
+
+	ret = copy_from_user(&cmap, p, sizeof(cmap));
+	if (ret)
+		return ret;
+
+	mfd->lut_update(info, &cmap);
+	return 0;
+}
+
+static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	void __user *argp = (void __user *)arg;
+	struct mdp_page_protection fb_page_protection;
+	int ret = -ENOSYS;
+
+	switch (cmd) {
+	case MSMFB_CURSOR:
+		ret = mdss_fb_cursor(info, argp);
+		break;
+
+	case MSMFB_SET_LUT:
+		ret = mdss_fb_set_lut(info, argp);
+		break;
+
+	case MSMFB_GET_PAGE_PROTECTION:
+		fb_page_protection.page_protection =
+			mfd->mdp_fb_page_protection;
+		ret = copy_to_user(argp, &fb_page_protection,
+				   sizeof(fb_page_protection));
+		if (ret)
+			return ret;
+		break;
+
+	default:
+		if (mfd->ioctl_handler)
+			ret = mfd->ioctl_handler(mfd, cmd, argp);
+		break;
+	}
+
+	if (ret == -ENOSYS)
+		pr_err("unsupported ioctl (%x)\n", cmd);
+
+	return ret;
+}
+
+int mdss_register_panel(struct mdss_panel_data *pdata)
+{
+	struct platform_device *mdss_fb_dev = NULL;
+	struct msm_fb_data_type *mfd;
+	int rc;
+
+	if (!mdss_res) {
+		pr_err("mdss mdp resources not initialized yet\n");
+		return -ENODEV;
+	}
+
+	mdss_fb_dev = platform_device_alloc("mdss_fb", pdata->panel_info.pdest);
+	if (!mdss_fb_dev) {
+		pr_err("unable to allocate mdss_fb device\n");
+		return -ENOMEM;
+	}
+
+	mdss_fb_dev->dev.platform_data = pdata;
+
+	rc = platform_device_add(mdss_fb_dev);
+	if (rc) {
+		platform_device_put(mdss_fb_dev);
+		pr_err("unable to probe mdss_fb device (%d)\n", rc);
+		return rc;
+	}
+
+	mfd = platform_get_drvdata(mdss_fb_dev);
+	if (!mfd)
+		return -ENODEV;
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	mfd->on_fnc = mdss_mdp_ctl_on;
+	mfd->off_fnc = mdss_mdp_ctl_off;
+
+	rc = mdss_mdp_overlay_init(mfd);
+	if (rc)
+		pr_err("unable to init overlay\n");
+
+	return rc;
+}
+EXPORT_SYMBOL(mdss_register_panel);
+
+int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num)
+{
+	struct fb_info *info;
+
+	if (fb_num > MAX_FBI_LIST)
+		return -EINVAL;
+
+	info = fbi_list[fb_num];
+	if (!info)
+		return -ENOENT;
+
+	*start = info->fix.smem_start;
+	*len = info->fix.smem_len;
+	return 0;
+}
+EXPORT_SYMBOL(mdss_fb_get_phys_info);
+
+int __init mdss_fb_init(void)
+{
+	int rc = -ENODEV;
+
+	if (platform_driver_register(&mdss_fb_driver))
+		return rc;
+
+	return 0;
+}
+
+module_init(mdss_fb_init);
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
new file mode 100644
index 0000000..a3f0dbe
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -0,0 +1,98 @@
+/* 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
+ * 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 MDSS_FB_H
+#define MDSS_FB_H
+
+#include <linux/ion.h>
+#include <linux/list.h>
+#include <linux/msm_mdp.h>
+#include <linux/types.h>
+
+#include "mdss_mdp.h"
+#include "mdss_panel.h"
+
+#define MSM_FB_DEFAULT_PAGE_SIZE 2
+#define MFD_KEY  0x11161126
+#define MSM_FB_MAX_DEV_LIST 32
+
+#define MSM_FB_ENABLE_DBGFS
+
+#ifndef MAX
+#define  MAX(x, y) (((x) > (y)) ? (x) : (y))
+#endif
+
+#ifndef MIN
+#define  MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
+struct disp_info_type_suspend {
+	int op_enable;
+	int panel_power_on;
+};
+
+struct msm_fb_data_type {
+	u32 key;
+	u32 index;
+	u32 ref_cnt;
+	u32 fb_page;
+
+	struct panel_id panel;
+	struct mdss_panel_info panel_info;
+
+	u32 dest;
+	struct fb_info *fbi;
+
+	int op_enable;
+	u32 fb_imgType;
+
+	int hw_refresh;
+
+	int overlay_play_enable;
+
+	int panel_power_on;
+	struct disp_info_type_suspend suspend;
+
+	int (*on_fnc) (struct msm_fb_data_type *mfd);
+	int (*off_fnc) (struct msm_fb_data_type *mfd);
+	int (*kickoff_fnc) (struct mdss_mdp_ctl *ctl);
+	int (*ioctl_handler) (struct msm_fb_data_type *mfd, u32 cmd, void *arg);
+	void (*dma_fnc) (struct msm_fb_data_type *mfd);
+	int (*cursor_update) (struct fb_info *info,
+			      struct fb_cursor *cursor);
+	int (*lut_update) (struct fb_info *info,
+			   struct fb_cmap *cmap);
+	int (*do_histogram) (struct fb_info *info,
+			     struct mdp_histogram *hist);
+	void *cursor_buf;
+	void *cursor_buf_phys;
+
+	u32 bl_level;
+	struct mutex lock;
+
+	struct platform_device *pdev;
+
+	u32 var_xres;
+	u32 var_yres;
+	u32 var_pixclock;
+
+	u32 mdp_fb_page_protection;
+	struct ion_client *iclient;
+
+	struct mdss_mdp_ctl *ctl;
+};
+
+int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num);
+void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl);
+void mdss_fb_update_backlight(struct msm_fb_data_type *mfd);
+#endif /* MDSS_FB_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
new file mode 100644
index 0000000..d1847c3
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -0,0 +1,494 @@
+/*
+ * MDSS MDP Interface (used by framebuffer core)
+ *
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/hrtimer.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/memory_alloc.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/spinlock.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include <mach/board.h>
+#include <mach/clk.h>
+#include <mach/hardware.h>
+
+#include "mdss.h"
+#include "mdss_fb.h"
+#include "mdss_mdp.h"
+
+/* 1.15 mdp clk factor */
+#define MDP_CLK_FACTOR(rate) (((rate) * 23) / 20)
+
+unsigned char *mdss_reg_base;
+
+struct mdss_res_type *mdss_res;
+static struct msm_panel_common_pdata *mdp_pdata;
+
+static DEFINE_SPINLOCK(mdp_lock);
+static DEFINE_MUTEX(mdp_clk_lock);
+static DEFINE_MUTEX(mdp_suspend_mutex);
+
+u32 mdss_mdp_pipe_type_map[MDSS_MDP_MAX_SSPP] = {
+	MDSS_MDP_PIPE_TYPE_VIG,
+	MDSS_MDP_PIPE_TYPE_VIG,
+	MDSS_MDP_PIPE_TYPE_VIG,
+	MDSS_MDP_PIPE_TYPE_RGB,
+	MDSS_MDP_PIPE_TYPE_RGB,
+	MDSS_MDP_PIPE_TYPE_RGB,
+	MDSS_MDP_PIPE_TYPE_DMA,
+	MDSS_MDP_PIPE_TYPE_DMA,
+};
+
+u32 mdss_mdp_mixer_type_map[MDSS_MDP_MAX_LAYERMIXER] = {
+	MDSS_MDP_MIXER_TYPE_INTF,
+	MDSS_MDP_MIXER_TYPE_INTF,
+	MDSS_MDP_MIXER_TYPE_INTF,
+	MDSS_MDP_MIXER_TYPE_WRITEBACK,
+	MDSS_MDP_MIXER_TYPE_WRITEBACK,
+};
+
+irqreturn_t mdss_irq_handler(int mdss_irq, void *ptr)
+{
+	u32 intr = MDSS_MDP_REG_READ(MDSS_REG_HW_INTR_STATUS);
+
+	mdss_res->irq_buzy = true;
+
+	if (intr & MDSS_INTR_MDP)
+		mdss_mdp_isr(mdss_irq, ptr);
+
+	mdss_res->irq_buzy = false;
+
+	return IRQ_HANDLED;
+}
+
+int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num)
+{
+	u32 irq;
+	unsigned long irq_flags;
+	int ret = 0;
+
+	if (intr_type == MDSS_MDP_IRQ_INTF_UNDER_RUN ||
+	    intr_type == MDSS_MDP_IRQ_INTF_VSYNC)
+		intf_num = intf_num << 1;
+
+	irq =  BIT(intr_type + intf_num);
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	if (mdss_res->irq_mask & irq) {
+		pr_warn("MDSS IRQ-0x%x is already set, mask=%x irq=%d\n",
+			irq, mdss_res->irq_mask, mdss_res->irq_ena);
+		ret = -EBUSY;
+	} else {
+		mdss_res->irq_mask |= irq;
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_CLEAR, irq);
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_EN, mdss_res->irq_mask);
+		if (!mdss_res->irq_ena) {
+			mdss_res->irq_ena = true;
+			enable_irq(mdss_res->irq);
+		}
+	}
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+
+	return ret;
+}
+
+void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num)
+{
+	u32 irq;
+	unsigned long irq_flags;
+
+
+	if (intr_type == MDSS_MDP_IRQ_INTF_UNDER_RUN ||
+	    intr_type == MDSS_MDP_IRQ_INTF_VSYNC)
+		intf_num = intf_num << 1;
+
+	irq = BIT(intr_type + intf_num);
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	if (!(mdss_res->irq_mask & irq)) {
+		pr_warn("MDSS IRQ-%x is NOT set, mask=%x irq=%d\n",
+			irq, mdss_res->irq_mask, mdss_res->irq_ena);
+	} else {
+		mdss_res->irq_mask &= ~irq;
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_EN, mdss_res->irq_mask);
+		if (!mdss_res->irq_mask) {
+			mdss_res->irq_ena = false;
+			disable_irq(mdss_res->irq);
+		}
+	}
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num)
+{
+	u32 irq;
+
+	if (intr_type == MDSS_MDP_IRQ_INTF_UNDER_RUN ||
+	    intr_type == MDSS_MDP_IRQ_INTF_VSYNC)
+		intf_num = intf_num << 1;
+
+	irq = BIT(intr_type + intf_num);
+
+	spin_lock(&mdp_lock);
+	if (!(mdss_res->irq_mask & irq)) {
+		pr_warn("MDSS IRQ-%x is NOT set, mask=%x irq=%d\n",
+			irq, mdss_res->irq_mask, mdss_res->irq_ena);
+	} else {
+		mdss_res->irq_mask &= ~irq;
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_EN, mdss_res->irq_mask);
+		if (!mdss_res->irq_mask) {
+			mdss_res->irq_ena = false;
+			disable_irq_nosync(mdss_res->irq);
+		}
+	}
+	spin_unlock(&mdp_lock);
+}
+
+static void mdss_mdp_clk_ctrl_update(int enable)
+{
+	if (mdss_res->clk_ena == enable)
+		return;
+
+	pr_debug("MDP CLKS %s\n", (enable ? "Enable" : "Disable"));
+	mdss_res->clk_ena = enable;
+}
+
+void mdss_mdp_clk_ctrl(int enable, int isr)
+{
+	static atomic_t clk_ref = ATOMIC_INIT(0);
+	static DEFINE_MUTEX(clk_ctrl_lock);
+	int force_off = 0;
+
+	pr_debug("clk enable=%d isr=%d clk_ref=%d\n", enable, isr,
+			atomic_read(&clk_ref));
+	/*
+	 * It is assumed that if isr = TRUE then start = OFF
+	 * if start = ON when isr = TRUE it could happen that the usercontext
+	 * could turn off the clocks while the interrupt is updating the
+	 * power to ON
+	 */
+	WARN_ON(isr == true && enable);
+
+	if (enable) {
+		atomic_inc(&clk_ref);
+	} else if (!atomic_add_unless(&clk_ref, -1, 0)) {
+		pr_debug("master power-off req\n");
+		force_off = 1;
+	}
+
+	if (isr) {
+		/* if it's power off send workqueue to turn off clocks */
+		if (mdss_res->clk_ena && !atomic_read(&clk_ref))
+			queue_delayed_work(mdss_res->clk_ctrl_wq,
+					   &mdss_res->clk_ctrl_worker,
+					   mdss_res->timeout);
+	} else {
+		mutex_lock(&clk_ctrl_lock);
+		if (delayed_work_pending(&mdss_res->clk_ctrl_worker))
+			cancel_delayed_work(&mdss_res->clk_ctrl_worker);
+
+		if (atomic_read(&clk_ref)) {
+			mdss_mdp_clk_ctrl_update(true);
+		} else if (mdss_res->clk_ena) {
+			mutex_lock(&mdp_suspend_mutex);
+			if (force_off || mdss_res->suspend) {
+				mdss_mdp_clk_ctrl_update(false);
+			} else {
+				/* send workqueue to turn off mdp power */
+				queue_delayed_work(mdss_res->clk_ctrl_wq,
+						   &mdss_res->clk_ctrl_worker,
+						   mdss_res->timeout);
+			}
+			mutex_unlock(&mdp_suspend_mutex);
+		}
+		mutex_unlock(&clk_ctrl_lock);
+	}
+}
+
+static void mdss_mdp_clk_ctrl_workqueue_handler(struct work_struct *work)
+{
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+}
+
+static int mdss_mdp_irq_clk_setup(void)
+{
+	int ret;
+
+	ret = request_irq(mdss_res->irq, mdss_irq_handler, IRQF_DISABLED,
+			  "MDSS", 0);
+	if (ret) {
+		pr_err("mdp request_irq() failed!\n");
+		return ret;
+	}
+	disable_irq(mdss_res->irq);
+
+	mdss_res->fs = regulator_get(NULL, "fs_mdp");
+	if (IS_ERR(mdss_res->fs))
+		mdss_res->fs = NULL;
+	else {
+		regulator_enable(mdss_res->fs);
+		mdss_res->fs_ena = true;
+	}
+
+	return 0;
+}
+
+static struct msm_panel_common_pdata *mdss_mdp_populate_pdata(
+	struct device *dev)
+{
+	struct msm_panel_common_pdata *pdata;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		dev_err(dev, "could not allocate memory for pdata\n");
+	return pdata;
+}
+
+static u32 mdss_mdp_res_init(void)
+{
+	u32 rc;
+
+	rc = mdss_mdp_irq_clk_setup();
+	if (rc)
+		return rc;
+
+	mdss_res->clk_ctrl_wq = create_singlethread_workqueue("mdp_clk_wq");
+	INIT_DELAYED_WORK(&mdss_res->clk_ctrl_worker,
+			  mdss_mdp_clk_ctrl_workqueue_handler);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	mdss_res->rev = MDSS_MDP_REG_READ(MDSS_REG_HW_VERSION);
+	mdss_res->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	mdss_res->smp_mb_cnt = MDSS_MDP_SMP_MMB_BLOCKS;
+	mdss_res->smp_mb_size = MDSS_MDP_SMP_MMB_SIZE;
+	mdss_res->pipe_type_map = mdss_mdp_pipe_type_map;
+	mdss_res->mixer_type_map = mdss_mdp_mixer_type_map;
+
+	pr_info("mdss_revision=%x\n", mdss_res->rev);
+	pr_info("mdp_hw_revision=%x\n", mdss_res->mdp_rev);
+
+	mdss_res->res_init = true;
+	mdss_res->timeout = HZ/20;
+	mdss_res->clk_ena = false;
+	mdss_res->irq_mask = MDSS_MDP_DEFAULT_INTR_MASK;
+	mdss_res->suspend = false;
+	mdss_res->prim_ptype = NO_PANEL;
+	mdss_res->irq_ena = false;
+
+	return 0;
+}
+
+static int mdss_mdp_probe(struct platform_device *pdev)
+{
+	struct resource *mdss_mdp_mres;
+	struct resource *mdss_mdp_ires;
+	resource_size_t size;
+	int rc;
+
+	if (!mdss_res) {
+		mdss_res = devm_kzalloc(&pdev->dev, sizeof(*mdss_res),
+				GFP_KERNEL);
+		if (mdss_res == NULL)
+			return -ENOMEM;
+	}
+
+	if (pdev->dev.of_node) {
+		pdev->id = 0;
+		mdp_pdata = mdss_mdp_populate_pdata(&pdev->dev);
+		mdss_mdp_mres = platform_get_resource(pdev,
+						IORESOURCE_MEM, 0);
+		mdss_mdp_ires = platform_get_resource(pdev,
+						IORESOURCE_IRQ, 0);
+		if (!mdss_mdp_mres || !mdss_mdp_ires) {
+			pr_err("unable to get the MDSS resources");
+			rc = -ENOMEM;
+			goto probe_done;
+		}
+		mdss_reg_base = ioremap(mdss_mdp_mres->start,
+					resource_size(mdss_mdp_mres));
+
+		pr_info("MDP HW Base phy_Address=0x%x virt=0x%x\n",
+			(int) mdss_mdp_mres->start,
+			(int) mdss_reg_base);
+
+		mdss_res->irq = mdss_mdp_ires->start;
+	} else if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+		mdp_pdata = pdev->dev.platform_data;
+
+		size =  resource_size(&pdev->resource[0]);
+		mdss_reg_base = ioremap(pdev->resource[0].start, size);
+
+		pr_info("MDP HW Base phy_Address=0x%x virt=0x%x\n",
+			(int) pdev->resource[0].start,
+			(int) mdss_reg_base);
+
+		mdss_res->irq = platform_get_irq(pdev, 0);
+		if (mdss_res->irq < 0) {
+			pr_err("can not get mdp irq\n");
+			rc = -ENOMEM;
+			goto probe_done;
+		}
+	}
+
+	if (unlikely(!mdss_reg_base)) {
+		rc = -ENOMEM;
+		goto probe_done;
+	}
+
+	rc = mdss_mdp_res_init();
+	if (rc) {
+		pr_err("unable to initialize mdss mdp resources\n");
+		goto probe_done;
+	}
+
+probe_done:
+	if (IS_ERR_VALUE(rc)) {
+		if (mdss_res) {
+			devm_kfree(&pdev->dev, mdss_res);
+			mdss_res = NULL;
+		}
+	}
+
+	return rc;
+}
+
+void mdss_mdp_footswitch_ctrl(int on)
+{
+	mutex_lock(&mdp_suspend_mutex);
+	if (!mdss_res->suspend || mdss_res->eintf_ena || !mdss_res->fs) {
+		mutex_unlock(&mdp_suspend_mutex);
+		return;
+	}
+
+	if (on && !mdss_res->fs_ena) {
+		pr_debug("Enable MDP FS\n");
+		regulator_enable(mdss_res->fs);
+		mdss_res->fs_ena = true;
+	} else if (!on && mdss_res->fs_ena) {
+		pr_debug("Disable MDP FS\n");
+		regulator_disable(mdss_res->fs);
+		mdss_res->fs_ena = false;
+	}
+	mutex_unlock(&mdp_suspend_mutex);
+}
+
+#ifdef CONFIG_PM
+static void mdss_mdp_suspend_sub(void)
+{
+	cancel_delayed_work(&mdss_res->clk_ctrl_worker);
+
+	flush_workqueue(mdss_res->clk_ctrl_wq);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	mutex_lock(&mdp_suspend_mutex);
+	mdss_res->suspend = true;
+	mutex_unlock(&mdp_suspend_mutex);
+}
+
+static int mdss_mdp_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	if (pdev->id == 0) {
+		mdss_mdp_suspend_sub();
+		if (mdss_res->clk_ena) {
+			pr_err("MDP suspend failed\n");
+			return -EBUSY;
+		}
+		mdss_mdp_footswitch_ctrl(false);
+	}
+	return 0;
+}
+
+static int mdss_mdp_resume(struct platform_device *pdev)
+{
+	mdss_mdp_footswitch_ctrl(true);
+	mutex_lock(&mdp_suspend_mutex);
+	mdss_res->suspend = false;
+	mutex_unlock(&mdp_suspend_mutex);
+	return 0;
+}
+#else
+#define mdss_mdp_suspend NULL
+#define mdss_mdp_resume NULL
+#endif
+
+static int mdss_mdp_remove(struct platform_device *pdev)
+{
+	if (mdss_res->fs != NULL)
+		regulator_put(mdss_res->fs);
+	iounmap(mdss_reg_base);
+	pm_runtime_disable(&pdev->dev);
+	return 0;
+}
+
+static const struct of_device_id mdss_mdp_dt_match[] = {
+	{ .compatible = "qcom,mdss_mdp",},
+};
+MODULE_DEVICE_TABLE(of, mdss_mdp_dt_match);
+
+static struct platform_driver mdss_mdp_driver = {
+	.probe = mdss_mdp_probe,
+	.remove = mdss_mdp_remove,
+	.suspend = mdss_mdp_suspend,
+	.resume = mdss_mdp_resume,
+	.shutdown = NULL,
+	.driver = {
+		/*
+		 * Driver name must match the device name added in
+		 * platform.c.
+		 */
+		.name = "mdp",
+		.of_match_table = mdss_mdp_dt_match,
+	},
+};
+
+static int mdss_mdp_register_driver(void)
+{
+	return platform_driver_register(&mdss_mdp_driver);
+}
+
+static int __init mdss_mdp_driver_init(void)
+{
+	int ret;
+
+	ret = mdss_mdp_register_driver();
+	if (ret) {
+		pr_err("mdp_register_driver() failed!\n");
+		return ret;
+	}
+
+	return 0;
+
+}
+
+module_init(mdss_mdp_driver_init);
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
new file mode 100644
index 0000000..c65d5a7
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -0,0 +1,294 @@
+/* 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 MDSS_MDP_H
+#define MDSS_MDP_H
+
+#include <linux/io.h>
+#include <linux/msm_mdp.h>
+#include <linux/platform_device.h>
+
+#include "mdss.h"
+#include "mdss_mdp_hwio.h"
+
+#define MDSS_MDP_DEFAULT_INTR_MASK 0
+#define MDSS_MDP_CURSOR_WIDTH 64
+#define MDSS_MDP_CURSOR_HEIGHT 64
+#define MDSS_MDP_CURSOR_SIZE (MDSS_MDP_CURSOR_WIDTH*MDSS_MDP_CURSOR_WIDTH*4)
+
+#define MDP_CLK_DEFAULT_RATE	37500000
+#define PHASE_STEP_SHIFT	21
+#define MAX_MIXER_WIDTH		2048
+#define MAX_MIXER_HEIGHT	2048
+#define MAX_IMG_WIDTH		0x3FFF
+#define MAX_IMG_HEIGHT		0x3FFF
+#define MIN_DST_W		10
+#define MIN_DST_H		10
+#define MAX_DST_W		MAX_MIXER_WIDTH
+#define MAX_DST_H		MAX_MIXER_HEIGHT
+#define MAX_PLANES		4
+#define MAX_DOWNSCALE_RATIO	4
+#define MAX_UPSCALE_RATIO	20
+
+#ifdef MDSS_MDP_DEBUG_REG
+static inline void mdss_mdp_reg_write(u32 addr, u32 val)
+{
+	pr_debug("0x%05X = 0x%08X\n", addr, val);
+	MDSS_REG_WRITE(addr, val);
+}
+#define MDSS_MDP_REG_WRITE(addr, val) mdss_mdp_reg_write((u32)addr, (u32)(val))
+static inline u32 mdss_mdp_reg_read(u32 addr)
+{
+	u32 val;
+	val = MDSS_REG_READ(addr);
+	pr_debug("0x%05X = 0x%08X\n", addr, val);
+	return val;
+}
+#define MDSS_MDP_REG_READ(addr) mdss_mdp_reg_read((u32)(addr))
+#else
+#define MDSS_MDP_REG_WRITE(addr, val)	MDSS_REG_WRITE((u32)(addr), (u32)(val))
+#define MDSS_MDP_REG_READ(addr)		MDSS_REG_READ((u32)(addr))
+#endif
+
+enum mdss_mdp_block_power_state {
+	MDP_BLOCK_POWER_OFF,
+	MDP_BLOCK_POWER_ON
+};
+
+enum mdss_mdp_mixer_type {
+	MDSS_MDP_MIXER_TYPE_UNUSED,
+	MDSS_MDP_MIXER_TYPE_INTF,
+	MDSS_MDP_MIXER_TYPE_WRITEBACK,
+};
+
+enum mdss_mdp_mixer_mux {
+	MDSS_MDP_MIXER_MUX_DEFAULT,
+	MDSS_MDP_MIXER_MUX_LEFT,
+	MDSS_MDP_MIXER_MUX_RIGHT,
+};
+
+enum mdss_mdp_pipe_type {
+	MDSS_MDP_PIPE_TYPE_UNUSED,
+	MDSS_MDP_PIPE_TYPE_VIG,
+	MDSS_MDP_PIPE_TYPE_RGB,
+	MDSS_MDP_PIPE_TYPE_DMA,
+};
+
+enum mdss_mdp_block_type {
+	MDSS_MDP_BLOCK_UNUSED,
+	MDSS_MDP_BLOCK_SSPP,
+	MDSS_MDP_BLOCK_MIXER,
+	MDSS_MDP_BLOCK_DSPP,
+	MDSS_MDP_BLOCK_WB,
+	MDSS_MDP_BLOCK_MAX
+};
+
+struct mdss_mdp_ctl {
+	u32 num;
+	u32 ref_cnt;
+
+	u32 intf_num;
+	u32 intf_type;
+
+	u32 opmode;
+	u32 flush_bits;
+
+	u32 play_cnt;
+
+	u16 width;
+	u16 height;
+	u32 dst_format;
+
+	struct msm_fb_data_type *mfd;
+	struct mdss_mdp_mixer *mixer_left;
+	struct mdss_mdp_mixer *mixer_right;
+	struct mutex lock;
+
+	int (*start_fnc) (struct mdss_mdp_ctl *ctl);
+	int (*stop_fnc) (struct mdss_mdp_ctl *ctl);
+	int (*prepare_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
+	int (*display_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
+
+	void *priv_data;
+};
+
+struct mdss_mdp_mixer {
+	u32 num;
+	u32 ref_cnt;
+	u8 type;
+	u8 params_changed;
+
+	u16 width;
+	u16 height;
+	u8 cursor_enabled;
+	u8 rotator_mode;
+
+	struct mdss_mdp_ctl *ctl;
+	struct mdss_mdp_pipe *stage_pipe[MDSS_MDP_MAX_STAGE];
+};
+
+struct mdss_mdp_img_rect {
+	u16 x;
+	u16 y;
+	u16 w;
+	u16 h;
+};
+
+struct mdss_mdp_format_params {
+	u32 format;
+	u8 is_yuv;
+
+	u8 frame_format;
+	u8 chroma_sample;
+	u8 solid_fill;
+	u8 fetch_planes;
+	u8 unpack_align_msb;	/* 0 to LSB, 1 to MSB */
+	u8 unpack_tight;	/* 0 for loose, 1 for tight */
+	u8 unpack_count;	/* 0 = 1 component, 1 = 2 component ... */
+	u8 bpp;
+	u8 alpha_enable;	/*  source has alpha */
+
+	/*
+	 * number of bits for source component,
+	 * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
+	 */
+	u8 a_bit;	/* component 3, alpha */
+	u8 r_bit;	/* component 2, R_Cr */
+	u8 b_bit;	/* component 1, B_Cb */
+	u8 g_bit;	/* component 0, G_lumz */
+
+	/*
+	 * unpack pattern
+	 * A = C3, R = C2, B = C1, G = C0
+	 */
+	u8 element3;
+	u8 element2;
+	u8 element1;
+	u8 element0;
+};
+
+struct mdss_mdp_plane_sizes {
+	u32 num_planes;
+	u32 plane_size[MAX_PLANES];
+	u32 total_size;
+	u32 ystride[MAX_PLANES];
+};
+
+struct mdss_mdp_img_data {
+	u32 addr;
+	u32 len;
+	u32 flags;
+	int p_need;
+	struct file *srcp_file;
+	struct ion_handle *srcp_ihdl;
+	struct ion_client *iclient;
+};
+
+struct mdss_mdp_data {
+	u8 num_planes;
+	u8 bwc_enabled;
+	struct mdss_mdp_img_data p[MAX_PLANES];
+};
+
+struct mdss_mdp_pipe {
+	u32 num;
+	u32 type;
+	u32 ndx;
+	atomic_t ref_cnt;
+	u32 play_cnt;
+
+	u32 flags;
+	u32 bwc_mode;
+
+	u16 img_width;
+	u16 img_height;
+	struct mdss_mdp_img_rect src;
+	struct mdss_mdp_img_rect dst;
+
+	struct mdss_mdp_format_params *src_fmt;
+	struct mdss_mdp_plane_sizes src_planes;
+
+	u8 mixer_stage;
+	u8 is_fg;
+	u8 alpha;
+	u32 transp;
+
+	struct msm_fb_data_type *mfd;
+	struct mdss_mdp_mixer *mixer;
+	struct mutex lock;
+
+	struct mdp_overlay req_data;
+	u32 params_changed;
+
+	unsigned long smp[MAX_PLANES];
+};
+
+static inline void mdss_mdp_ctl_write(struct mdss_mdp_ctl *ctl,
+				      u32 reg, u32 val)
+{
+	int offset = MDSS_MDP_REG_CTL_OFFSET(ctl->num);
+	MDSS_MDP_REG_WRITE(offset + reg, val);
+}
+
+static inline u32 mdss_mdp_ctl_read(struct mdss_mdp_ctl *ctl, u32 reg)
+{
+	int offset = MDSS_MDP_REG_CTL_OFFSET(ctl->num);
+	return MDSS_MDP_REG_READ(offset + reg);
+}
+
+irqreturn_t mdss_mdp_isr(int irq, void *ptr);
+int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num);
+void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num);
+void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num);
+int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num,
+			       void (*fnc_ptr)(void *), void *arg);
+
+unsigned long mdss_mdp_get_clk_rate(u32 clk_idx);
+int mdss_mdp_vsync_clk_enable(int enable);
+void mdss_mdp_clk_ctrl(int enable, int isr);
+void mdss_mdp_footswitch_ctrl(int on);
+
+int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
+int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
+
+int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd);
+int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd);
+
+struct mdss_mdp_mixer *mdss_mdp_mixer_get(struct mdss_mdp_ctl *ctl, int mux);
+struct mdss_mdp_pipe *mdss_mdp_mixer_stage_pipe(struct mdss_mdp_ctl *ctl,
+						int mux, int stage);
+int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe, int params_changed);
+int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe);
+int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
+
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum);
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type);
+struct mdss_mdp_pipe *mdss_mdp_pipe_get_locked(u32 ndx);
+int mdss_mdp_pipe_lock(struct mdss_mdp_pipe *pipe);
+void mdss_mdp_pipe_unlock(struct mdss_mdp_pipe *pipe);
+
+int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
+int mdss_mdp_pipe_release_all(struct msm_fb_data_type *mfd);
+int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
+			     struct mdss_mdp_data *src_data);
+
+int mdss_mdp_data_check(struct mdss_mdp_data *data,
+			struct mdss_mdp_plane_sizes *ps);
+int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h,
+			     struct mdss_mdp_plane_sizes *ps);
+struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
+int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
+int mdss_mdp_get_img(struct ion_client *iclient, struct msmfb_data *img,
+		     struct mdss_mdp_img_data *data);
+
+#endif /* MDSS_MDP_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
new file mode 100644
index 0000000..d89347e
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -0,0 +1,600 @@
+/* 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 <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include "mdss_fb.h"
+#include "mdss_mdp.h"
+
+static DEFINE_MUTEX(mdss_mdp_ctl_lock);
+static struct mdss_mdp_ctl mdss_mdp_ctl_list[MDSS_MDP_MAX_CTL];
+static struct mdss_mdp_mixer mdss_mdp_mixer_list[MDSS_MDP_MAX_LAYERMIXER];
+
+static struct mdss_mdp_ctl *mdss_mdp_ctl_alloc(void)
+{
+	struct mdss_mdp_ctl *ctl = NULL;
+	int cnum;
+
+	mutex_lock(&mdss_mdp_ctl_lock);
+	for (cnum = 0; cnum < MDSS_MDP_MAX_CTL; cnum++) {
+		if (mdss_mdp_ctl_list[cnum].ref_cnt == 0) {
+			ctl = &mdss_mdp_ctl_list[cnum];
+			ctl->num = cnum;
+			ctl->ref_cnt++;
+			mutex_init(&ctl->lock);
+
+			pr_debug("alloc ctl_num=%d\n", ctl->num);
+			break;
+		}
+	}
+	mutex_unlock(&mdss_mdp_ctl_lock);
+
+	return ctl;
+}
+
+static int mdss_mdp_ctl_free(struct mdss_mdp_ctl *ctl)
+{
+	if (!ctl)
+		return -ENODEV;
+
+	pr_debug("free ctl_num=%d ref_cnt=%d\n", ctl->num, ctl->ref_cnt);
+
+	if (!ctl->ref_cnt) {
+		pr_err("called with ref_cnt=0\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&mdss_mdp_ctl_lock);
+	if (--ctl->ref_cnt == 0)
+		memset(ctl, 0, sizeof(*ctl));
+	mutex_unlock(&mdss_mdp_ctl_lock);
+
+	return 0;
+}
+
+static struct mdss_mdp_mixer *mdss_mdp_mixer_alloc(u32 type)
+{
+	struct mdss_mdp_mixer *mixer = NULL;
+	int mnum;
+
+	mutex_lock(&mdss_mdp_ctl_lock);
+	for (mnum = 0; mnum < MDSS_MDP_MAX_LAYERMIXER; mnum++) {
+		if (type == mdss_res->mixer_type_map[mnum] &&
+		    mdss_mdp_mixer_list[mnum].ref_cnt == 0) {
+			mixer = &mdss_mdp_mixer_list[mnum];
+			mixer->num = mnum;
+			mixer->ref_cnt++;
+			mixer->params_changed++;
+			mixer->type = type;
+
+			pr_debug("mixer_num=%d\n", mixer->num);
+			break;
+		}
+	}
+	mutex_unlock(&mdss_mdp_ctl_lock);
+
+	return mixer;
+}
+
+static int mdss_mdp_mixer_free(struct mdss_mdp_mixer *mixer)
+{
+	if (!mixer)
+		return -ENODEV;
+
+	pr_debug("free mixer_num=%d ref_cnt=%d\n", mixer->num, mixer->ref_cnt);
+
+	if (!mixer->ref_cnt) {
+		pr_err("called with ref_cnt=0\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&mdss_mdp_ctl_lock);
+	if (--mixer->ref_cnt == 0)
+		memset(mixer, 0, sizeof(*mixer));
+	mutex_unlock(&mdss_mdp_ctl_lock);
+
+	return 0;
+}
+
+static int mdss_mdp_ctl_init(struct msm_fb_data_type *mfd)
+{
+	struct mdss_mdp_ctl *ctl;
+	u32 width, height;
+
+	if (!mfd)
+		return -ENODEV;
+
+	width = mfd->fbi->var.xres;
+	height = mfd->fbi->var.yres;
+
+	if (width > (2 * MAX_MIXER_WIDTH)) {
+		pr_err("unsupported resolution\n");
+		return -EINVAL;
+	}
+
+	ctl = mdss_mdp_ctl_alloc();
+
+	if (!ctl) {
+		pr_err("unable to allocate ctl\n");
+		return -ENOMEM;
+	}
+
+	ctl->mfd = mfd;
+	ctl->width = width;
+	ctl->height = height;
+	ctl->dst_format = mfd->panel_info.out_format;
+
+	ctl->mixer_left = mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+	if (!ctl->mixer_left) {
+		pr_err("unable to allocate layer mixer\n");
+		mdss_mdp_ctl_free(ctl);
+		return -ENOMEM;
+	}
+
+	ctl->mixer_left->width = MIN(width, MAX_MIXER_WIDTH);
+	ctl->mixer_left->height = height;
+	ctl->mixer_left->ctl = ctl;
+
+	width -= ctl->mixer_left->width;
+
+	if (width) {
+		ctl->mixer_right =
+		mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+		if (!ctl->mixer_right) {
+			pr_err("unable to allocate layer mixer\n");
+			mdss_mdp_mixer_free(ctl->mixer_left);
+			mdss_mdp_ctl_free(ctl);
+			return -ENOMEM;
+		}
+		ctl->mixer_right->width = width;
+		ctl->mixer_right->height = height;
+		ctl->mixer_right->ctl = ctl;
+	}
+
+	switch (mfd->panel_info.type) {
+	case WRITEBACK_PANEL:
+		ctl->intf_num = MDSS_MDP_NO_INTF;
+		ctl->opmode = MDSS_MDP_CTL_OP_WFD_MODE;
+		ctl->start_fnc = mdss_mdp_writeback_start;
+		break;
+	default:
+		pr_err("unsupported panel type (%d)\n", mfd->panel_info.type);
+		mdss_mdp_ctl_free(ctl);
+		return -EINVAL;
+
+	}
+
+	ctl->opmode |= (ctl->intf_num << 4);
+
+	if (ctl->mixer_right) {
+		ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+			       MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
+	}
+
+	mfd->ctl = ctl;
+
+	return 0;
+}
+
+static int mdss_mdp_ctl_destroy(struct msm_fb_data_type *mfd)
+{
+	struct mdss_mdp_ctl *ctl;
+	if (!mfd || !mfd->ctl)
+		return -ENODEV;
+
+	ctl = mfd->ctl;
+	mfd->ctl = NULL;
+
+	if (ctl->mixer_left)
+		mdss_mdp_mixer_free(ctl->mixer_left);
+	if (ctl->mixer_right)
+		mdss_mdp_mixer_free(ctl->mixer_right);
+	mdss_mdp_ctl_free(ctl);
+
+	return 0;
+}
+
+int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
+{
+	struct mdss_panel_data *pdata;
+	struct mdss_mdp_ctl *ctl;
+	struct mdss_mdp_mixer *mixer;
+	u32 outsize, temp, off;
+	int ret = 0;
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	pdata = dev_get_platdata(&mfd->pdev->dev);
+	if (!pdata) {
+		pr_err("no panel connected\n");
+		return -ENODEV;
+	}
+
+	if (!mfd->ctl) {
+		if (mdss_mdp_ctl_init(mfd)) {
+			pr_err("unable to initialize ctl\n");
+			return -ENODEV;
+		}
+	}
+	ctl = mfd->ctl;
+
+	mutex_lock(&ctl->lock);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	if (ctl->start_fnc)
+		ret = ctl->start_fnc(ctl);
+	else
+		pr_warn("no start function for ctl=%d type=%d\n", ctl->num,
+				mfd->panel_info.type);
+
+	if (ret) {
+		pr_err("unable to start intf\n");
+		goto start_fail;
+	}
+
+	pr_debug("ctl_num=%d\n", ctl->num);
+
+	mixer = ctl->mixer_left;
+	mixer->params_changed++;
+
+	temp = MDSS_MDP_REG_READ(MDSS_MDP_REG_DISP_INTF_SEL);
+	temp |= (ctl->intf_type << (ctl->intf_num * 8));
+	MDSS_MDP_REG_WRITE(MDSS_MDP_REG_DISP_INTF_SEL, temp);
+
+	outsize = (mixer->height << 16) | mixer->width;
+	off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, outsize);
+
+	if (ctl->mixer_right) {
+		mixer = ctl->mixer_right;
+		mixer->params_changed++;
+		outsize = (mixer->height << 16) | mixer->width;
+		off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, outsize);
+		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
+	}
+
+	ret = pdata->on(pdata);
+
+start_fail:
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	mutex_unlock(&ctl->lock);
+
+	return ret;
+}
+
+int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd)
+{
+	struct mdss_panel_data *pdata;
+	struct mdss_mdp_ctl *ctl;
+	int ret = 0;
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (!mfd->ctl) {
+		pr_err("ctl not initialized\n");
+		return -ENODEV;
+	}
+
+	pdata = dev_get_platdata(&mfd->pdev->dev);
+	if (!pdata) {
+		pr_err("no panel connected\n");
+		return -ENODEV;
+	}
+
+	ctl = mfd->ctl;
+
+	pr_debug("ctl_num=%d\n", mfd->ctl->num);
+
+	mutex_lock(&ctl->lock);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	if (ctl->stop_fnc)
+		ret = ctl->stop_fnc(ctl);
+	else
+		pr_warn("no stop func for ctl=%d\n", ctl->num);
+
+	if (ret)
+		pr_warn("error powering off intf ctl=%d\n", ctl->num);
+
+	ret = pdata->off(pdata);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	ctl->play_cnt = 0;
+	mutex_unlock(&ctl->lock);
+
+	mdss_mdp_pipe_release_all(mfd);
+
+	if (!mfd->ref_cnt)
+		mdss_mdp_ctl_destroy(mfd);
+
+
+	return ret;
+}
+
+static int mdss_mdp_mixer_setup(struct mdss_mdp_ctl *ctl,
+				struct mdss_mdp_mixer *mixer)
+{
+	struct mdss_mdp_pipe *pipe, *bgpipe = NULL;
+	u32 off, blend_op, blend_stage;
+	u32 mixercfg = 0, blend_color_out = 0, bgalpha = 0;
+	int stage;
+
+	if (!mixer)
+		return -ENODEV;
+
+	pr_debug("setup mixer=%d\n", mixer->num);
+
+	for (stage = MDSS_MDP_STAGE_BASE; stage < MDSS_MDP_MAX_STAGE; stage++) {
+		pipe = mixer->stage_pipe[stage];
+		if (pipe == NULL) {
+			if (stage == MDSS_MDP_STAGE_BASE)
+				mixercfg |= MDSS_MDP_LM_BORDER_COLOR;
+			continue;
+		}
+
+		if (stage != pipe->mixer_stage) {
+			mixer->stage_pipe[stage] = NULL;
+			continue;
+		}
+		mixercfg |= stage << (3 * pipe->num);
+
+		if (stage == MDSS_MDP_STAGE_BASE) {
+			bgpipe = pipe;
+			if (pipe->src_fmt->alpha_enable)
+				bgalpha = 1;
+			continue;
+		}
+
+		blend_stage = stage - MDSS_MDP_STAGE_0;
+		off = MDSS_MDP_REG_LM_OFFSET(mixer->num) +
+		      MDSS_MDP_REG_LM_BLEND_OFFSET(blend_stage);
+
+		if (pipe->is_fg) {
+			bgalpha = 0;
+			if (bgpipe) {
+				mixercfg &= ~(0x7 << (3 * bgpipe->num));
+				mixercfg |= MDSS_MDP_LM_BORDER_COLOR;
+			}
+			blend_op = (MDSS_MDP_BLEND_FG_ALPHA_FG_CONST |
+				    MDSS_MDP_BLEND_BG_ALPHA_BG_CONST);
+			/* keep fg alpha */
+			blend_color_out |= 1 << (blend_stage + 1);
+
+			pr_debug("pnum=%d stg=%d alpha=IS_FG\n", pipe->num,
+					stage);
+		} else if (pipe->src_fmt->alpha_enable) {
+			bgalpha = 0;
+			blend_op = (MDSS_MDP_BLEND_BG_ALPHA_FG_PIXEL |
+				    MDSS_MDP_BLEND_BG_INV_ALPHA);
+			/* keep fg alpha */
+			blend_color_out |= 1 << (blend_stage + 1);
+
+			pr_debug("pnum=%d stg=%d alpha=FG PIXEL\n", pipe->num,
+					stage);
+		} else if (bgalpha) {
+			blend_op = (MDSS_MDP_BLEND_BG_ALPHA_BG_PIXEL |
+				    MDSS_MDP_BLEND_FG_ALPHA_BG_PIXEL |
+				    MDSS_MDP_BLEND_FG_INV_ALPHA);
+			/* keep bg alpha */
+			pr_debug("pnum=%d stg=%d alpha=BG_PIXEL\n", pipe->num,
+					stage);
+		} else {
+			blend_op = (MDSS_MDP_BLEND_FG_ALPHA_FG_CONST |
+				    MDSS_MDP_BLEND_BG_ALPHA_BG_CONST);
+			pr_debug("pnum=%d stg=%d alpha=CONST\n", pipe->num,
+					stage);
+		}
+
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OP_MODE, blend_op);
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_BLEND_FG_ALPHA,
+				   pipe->alpha);
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_BLEND_BG_ALPHA,
+				   0xFF - pipe->alpha);
+	}
+
+	if (mixer->cursor_enabled)
+		mixercfg |= MDSS_MDP_LM_CURSOR_OUT;
+
+	pr_debug("mixer=%d mixer_cfg=%x\n", mixer->num, mixercfg);
+
+	ctl->flush_bits |= BIT(6) << mixer->num;	/* LAYER_MIXER */
+
+	off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OP_MODE, blend_color_out);
+	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(mixer->num), mixercfg);
+
+	return 0;
+}
+
+struct mdss_mdp_mixer *mdss_mdp_mixer_get(struct mdss_mdp_ctl *ctl, int mux)
+{
+	struct mdss_mdp_mixer *mixer = NULL;
+	if (!ctl)
+		return NULL;
+
+	switch (mux) {
+	case MDSS_MDP_MIXER_MUX_DEFAULT:
+	case MDSS_MDP_MIXER_MUX_LEFT:
+		mixer = ctl->mixer_left;
+		break;
+	case MDSS_MDP_MIXER_MUX_RIGHT:
+		mixer = ctl->mixer_right;
+		break;
+	}
+
+	return mixer;
+}
+
+struct mdss_mdp_pipe *mdss_mdp_mixer_stage_pipe(struct mdss_mdp_ctl *ctl,
+						int mux, int stage)
+{
+	struct mdss_mdp_pipe *pipe = NULL;
+	struct mdss_mdp_mixer *mixer;
+	if (!ctl)
+		return NULL;
+
+	if (mutex_lock_interruptible(&ctl->lock))
+		return NULL;
+
+	mixer = mdss_mdp_mixer_get(ctl, mux);
+	if (mixer)
+		pipe = mixer->stage_pipe[stage];
+	mutex_unlock(&ctl->lock);
+
+	return pipe;
+}
+
+int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe, int params_changed)
+{
+	struct mdss_mdp_ctl *ctl;
+	struct mdss_mdp_mixer *mixer;
+
+	if (!pipe)
+		return -EINVAL;
+	mixer = pipe->mixer;
+	if (!mixer)
+		return -EINVAL;
+	ctl = mixer->ctl;
+	if (!ctl)
+		return -EINVAL;
+
+	if (pipe->mixer_stage >= MDSS_MDP_MAX_STAGE) {
+		pr_err("invalid mixer stage\n");
+		return -EINVAL;
+	}
+
+	pr_debug("pnum=%x mixer=%d stage=%d\n", pipe->num, mixer->num,
+			pipe->mixer_stage);
+
+	if (mutex_lock_interruptible(&ctl->lock))
+		return -EINTR;
+
+	if (params_changed) {
+		mixer->params_changed++;
+		mixer->stage_pipe[pipe->mixer_stage] = pipe;
+	}
+
+	if (pipe->type == MDSS_MDP_PIPE_TYPE_DMA)
+		ctl->flush_bits |= BIT(pipe->num) << 5;
+	else /* RGB/VIG pipe */
+		ctl->flush_bits |= BIT(pipe->num);
+
+	mutex_unlock(&ctl->lock);
+
+	return 0;
+}
+
+int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe)
+{
+	struct mdss_mdp_ctl *ctl;
+	struct mdss_mdp_mixer *mixer;
+
+	if (!pipe)
+		return -EINVAL;
+	mixer = pipe->mixer;
+	if (!mixer)
+		return -EINVAL;
+	ctl = mixer->ctl;
+	if (!ctl)
+		return -EINVAL;
+
+	pr_debug("unstage pnum=%d stage=%d mixer=%d\n", pipe->num,
+			pipe->mixer_stage, mixer->num);
+
+	if (mutex_lock_interruptible(&ctl->lock))
+		return -EINTR;
+
+	mixer->params_changed++;
+	mixer->stage_pipe[pipe->mixer_stage] = NULL;
+
+	mutex_unlock(&ctl->lock);
+
+	return 0;
+}
+
+static int mdss_mdp_mixer_update(struct mdss_mdp_mixer *mixer)
+{
+	mixer->params_changed = 0;
+
+	/* skip mixer setup for rotator */
+	if (!mixer->rotator_mode)
+		mdss_mdp_mixer_setup(mixer->ctl, mixer);
+
+	return 0;
+}
+
+int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
+{
+	int mixer1_changed, mixer2_changed;
+	int ret = 0;
+
+	if (!ctl) {
+		pr_err("display function not set\n");
+		return -ENODEV;
+	}
+
+	pr_debug("commit ctl=%d\n", ctl->num);
+
+	if (mutex_lock_interruptible(&ctl->lock))
+		return -EINTR;
+
+	mixer1_changed = (ctl->mixer_left && ctl->mixer_left->params_changed);
+	mixer2_changed = (ctl->mixer_right && ctl->mixer_right->params_changed);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	if (mixer1_changed || mixer2_changed) {
+		if (ctl->prepare_fnc)
+			ret = ctl->prepare_fnc(ctl, arg);
+		if (ret) {
+			pr_err("error preparing display\n");
+			goto done;
+		}
+
+		if (mixer1_changed)
+			mdss_mdp_mixer_update(ctl->mixer_left);
+		if (mixer2_changed)
+			mdss_mdp_mixer_update(ctl->mixer_right);
+
+		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, ctl->opmode);
+		ctl->flush_bits |= BIT(17);	/* CTL */
+	}
+
+	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
+	wmb();
+	ctl->flush_bits = 0;
+
+	if (ctl->display_fnc)
+		ret = ctl->display_fnc(ctl, arg); /* kickoff */
+	if (ret)
+		pr_warn("error displaying frame\n");
+
+	ctl->play_cnt++;
+
+done:
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	mutex_unlock(&ctl->lock);
+
+	return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_formats.h b/drivers/video/msm/mdss/mdss_mdp_formats.h
new file mode 100644
index 0000000..07eefc1
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp_formats.h
@@ -0,0 +1,328 @@
+/* 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 MDSS_MDP_FORMATS_H
+#define MDSS_MDP_FORMATS_H
+
+#include <linux/msm_mdp.h>
+
+#include "mdss_mdp.h"
+
+#define C3_ALPHA	3	/* alpha */
+#define C2_R_Cr		2	/* R/Cr */
+#define C1_B_Cb		1	/* B/Cb */
+#define C0_G_Y		0	/* G/luma */
+
+static struct mdss_mdp_format_params mdss_mdp_format_map[MDP_IMGTYPE_LIMIT] = {
+	[MDP_RGB_565] = {
+		.format = MDP_RGB_565,
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.a_bit = 0,
+		.r_bit = 1,	/* R, 5 bits */
+		.b_bit = 1,	/* B, 5 bits */
+		.g_bit = 2,	/* G, 6 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 2,
+		.element2 = C2_R_Cr,
+		.element1 = C0_G_Y,
+		.element0 = C1_B_Cb,
+		.bpp = 1,	/* 2 bpp */
+	},
+	[MDP_BGR_565] = {
+		.format = MDP_BGR_565,
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.a_bit = 0,
+		.r_bit = 1,	/* R, 5 bits */
+		.b_bit = 1,	/* B, 5 bits */
+		.g_bit = 2,	/* G, 6 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 2,
+		.element2 = C1_B_Cb,
+		.element1 = C0_G_Y,
+		.element0 = C2_R_Cr,
+		.bpp = 1,	/* 2 bpp */
+	},
+	[MDP_RGB_888] = {
+		.format = MDP_RGB_888,
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 2,
+		.element2 = C1_B_Cb,
+		.element1 = C0_G_Y,
+		.element0 = C2_R_Cr,
+		.bpp = 2,	/* 3 bpp */
+	},
+	[MDP_XRGB_8888] = {
+		.format = MDP_XRGB_8888,
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.a_bit = 3,	/* alpha, 4 bits */
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 3,
+		.element3 = C1_B_Cb,
+		.element2 = C0_G_Y,
+		.element1 = C2_R_Cr,
+		.element0 = C3_ALPHA,
+		.bpp = 3,	/* 4 bpp */
+	},
+	[MDP_ARGB_8888] = {
+		.format = MDP_ARGB_8888,
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.a_bit = 3,	/* alpha, 4 bits */
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 1,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 3,
+		.element3 = C1_B_Cb,
+		.element2 = C0_G_Y,
+		.element1 = C2_R_Cr,
+		.element0 = C3_ALPHA,
+		.bpp = 3,	/* 4 bpp */
+	},
+	[MDP_RGBA_8888] = {
+		.format = MDP_RGBA_8888,
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.a_bit = 3,	/* alpha, 4 bits */
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 1,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 3,
+		.element3 = C3_ALPHA,
+		.element2 = C1_B_Cb,
+		.element1 = C0_G_Y,
+		.element0 = C2_R_Cr,
+		.bpp = 3,	/* 4 bpp */
+	},
+	[MDP_RGBX_8888] = {
+		.format = MDP_RGBX_8888,
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.a_bit = 3,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 3,
+		.element3 = C3_ALPHA,
+		.element2 = C1_B_Cb,
+		.element1 = C0_G_Y,
+		.element0 = C2_R_Cr,
+		.bpp = 3,	/* 4 bpp */
+	},
+	[MDP_BGRA_8888] = {
+		.format = MDP_BGRA_8888,
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.a_bit = 3,	/* alpha, 4 bits */
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 1,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 3,
+		.element3 = C3_ALPHA,
+		.element2 = C2_R_Cr,
+		.element1 = C0_G_Y,
+		.element0 = C1_B_Cb,
+		.bpp = 3,	/* 4 bpp */
+	},
+	[MDP_YCRYCB_H2V1] = {
+		.format = MDP_YCRYCB_H2V1,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
+		.chroma_sample = MDSS_MDP_CHROMA_H2V1,
+		.unpack_count = 3,
+		.element3 = C0_G_Y,
+		.element2 = C2_R_Cr,
+		.element1 = C0_G_Y,
+		.element0 = C1_B_Cb,
+	},
+	[MDP_Y_CRCB_H2V1] = {
+		.format = MDP_Y_CRCB_H2V1,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_H2V1,
+		.element1 = C1_B_Cb,
+		.element0 = C2_R_Cr,
+	},
+	[MDP_Y_CBCR_H2V1] = {
+		.format = MDP_Y_CBCR_H2V1,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_H2V1,
+		.element1 = C2_R_Cr,
+		.element0 = C1_B_Cb,
+	},
+	[MDP_Y_CRCB_H1V2] = {
+		.format = MDP_Y_CRCB_H1V2,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_H1V2,
+		.element1 = C1_B_Cb,
+		.element0 = C2_R_Cr,
+	},
+	[MDP_Y_CBCR_H1V2] = {
+		.format = MDP_Y_CBCR_H1V2,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_H1V2,
+		.element1 = C2_R_Cr,
+		.element0 = C1_B_Cb,
+	},
+	[MDP_Y_CRCB_H2V2] = {
+		.format = MDP_Y_CRCB_H2V2,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_420,
+		.element1 = C1_B_Cb,
+		.element0 = C2_R_Cr,
+	},
+	[MDP_Y_CBCR_H2V2] = {
+		.format = MDP_Y_CBCR_H2V2,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_420,
+		.element1 = C2_R_Cr,
+		.element0 = C1_B_Cb,
+	},
+	[MDP_Y_CR_CB_H2V2] = {
+		.format = MDP_Y_CR_CB_H2V2,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_420,
+	},
+	[MDP_Y_CB_CR_H2V2] = {
+		.format = MDP_Y_CB_CR_H2V2,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_420,
+	},
+	[MDP_Y_CR_CB_GH2V2] = {
+		.format = MDP_Y_CR_CB_GH2V2,
+		.is_yuv = 1,
+		.a_bit = 0,
+		.r_bit = 3,	/* R, 8 bits */
+		.b_bit = 3,	/* B, 8 bits */
+		.g_bit = 3,	/* G, 8 bits */
+		.alpha_enable = 0,
+		.unpack_tight = 1,
+		.unpack_align_msb = 0,
+		.unpack_count = 1,	/* 2 */
+		.bpp = 1,	/* 2 bpp */
+		.fetch_planes = MDSS_MDP_PLANE_PLANAR,
+		.chroma_sample = MDSS_MDP_CHROMA_420,
+	},
+};
+#endif
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
new file mode 100644
index 0000000..4ca1dce
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -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.
+ *
+ */
+
+#ifndef MDSS_MDP_HWIO_H
+#define MDSS_MDP_HWIO_H
+
+#include <linux/bitops.h>
+
+#define MDSS_REG_HW_VERSION				0x0
+#define MDSS_REG_HW_INTR_STATUS				0x10
+
+#define MDSS_INTR_MDP				BIT(0)
+#define MDSS_INTR_DSI0				BIT(4)
+#define MDSS_INTR_DSI1				BIT(5)
+#define MDSS_INTR_HDMI				BIT(8)
+#define MDSS_INTR_EDP				BIT(12)
+
+#define MDSS_MDP_REG_HW_VERSION				0x00100
+#define MDSS_MDP_REG_DISP_INTF_SEL			0x00104
+#define MDSS_MDP_REG_INTR_EN				0x00110
+#define MDSS_MDP_REG_INTR_STATUS			0x00114
+#define MDSS_MDP_REG_INTR_CLEAR				0x00118
+#define MDSS_MDP_REG_HIST_INTR_EN			0x0011C
+#define MDSS_MDP_REG_HIST_INTR_STATUS			0x00120
+#define MDSS_MDP_REG_HIST_INTR_CLEAR			0x00124
+
+#define MDSS_INTF_DSI	0x1
+#define MDSS_INTF_HDMI	0x3
+#define MDSS_INTF_LCDC	0x5
+#define MDSS_INTF_EDP	0x9
+
+#define MDSS_MDP_INTR_WB_0_DONE				BIT(0)
+#define MDSS_MDP_INTR_WB_1_DONE				BIT(1)
+#define MDSS_MDP_INTR_WB_2_DONE				BIT(4)
+#define MDSS_MDP_INTR_PING_PONG_0_DONE			BIT(8)
+#define MDSS_MDP_INTR_PING_PONG_1_DONE			BIT(9)
+#define MDSS_MDP_INTR_PING_PONG_2_DONE			BIT(10)
+#define MDSS_MDP_INTR_PING_PONG_0_RD_PTR		BIT(12)
+#define MDSS_MDP_INTR_PING_PONG_1_RD_PTR		BIT(13)
+#define MDSS_MDP_INTR_PING_PONG_2_RD_PTR		BIT(14)
+#define MDSS_MDP_INTR_PING_PONG_0_WR_PTR		BIT(16)
+#define MDSS_MDP_INTR_PING_PONG_1_WR_PTR		BIT(17)
+#define MDSS_MDP_INTR_PING_PONG_2_WR_PTR		BIT(18)
+#define MDSS_MDP_INTR_PING_PONG_0_AUTOREFRESH_DONE	BIT(20)
+#define MDSS_MDP_INTR_PING_PONG_1_AUTOREFRESH_DONE	BIT(21)
+#define MDSS_MDP_INTR_PING_PONG_2_AUTOREFRESH_DONE	BIT(22)
+#define MDSS_MDP_INTR_INTF_0_UNDERRUN			BIT(24)
+#define MDSS_MDP_INTR_INTF_0_VSYNC			BIT(25)
+#define MDSS_MDP_INTR_INTF_1_UNDERRUN			BIT(26)
+#define MDSS_MDP_INTR_INTF_1_VSYNC			BIT(27)
+#define MDSS_MDP_INTR_INTF_2_UNDERRUN			BIT(28)
+#define MDSS_MDP_INTR_INTF_2_VSYNC			BIT(29)
+#define MDSS_MDP_INTR_INTF_3_UNDERRUN			BIT(30)
+#define MDSS_MDP_INTR_INTF_3_VSYNC			BIT(31)
+
+enum mdss_mdp_intr_type {
+	MDSS_MDP_IRQ_WB_ROT_COMP = 0,
+	MDSS_MDP_IRQ_WB_WFD = 4,
+	MDSS_MDP_IRQ_PING_PONG_COMP = 8,
+	MDSS_MDP_IRQ_PING_PONG_RD_PTR = 12,
+	MDSS_MDP_IRQ_PING_PONG_WR_PTR = 16,
+	MDSS_MDP_IRQ_PING_PONG_AUTO_REF = 20,
+	MDSS_MDP_IRQ_INTF_UNDER_RUN = 24,
+	MDSS_MDP_IRQ_INTF_VSYNC = 25,
+};
+
+enum mdss_mdp_ctl_index {
+	MDSS_MDP_CTL0,
+	MDSS_MDP_CTL1,
+	MDSS_MDP_CTL2,
+	MDSS_MDP_CTL3,
+	MDSS_MDP_CTL4,
+	MDSS_MDP_MAX_CTL
+};
+
+#define MDSS_MDP_REG_CTL_OFFSET(ctl) (0x00600 + ((ctl) * 0x100))
+
+#define MDSS_MDP_REG_CTL_LAYER(lm)			((lm) * 0x004)
+#define MDSS_MDP_REG_CTL_TOP				0x014
+#define MDSS_MDP_REG_CTL_FLUSH				0x018
+#define MDSS_MDP_REG_CTL_START				0x01C
+#define MDSS_MDP_REG_CTL_PACK_3D			0x020
+
+#define MDSS_MDP_CTL_OP_VIDEO_MODE		(0 << 17)
+#define MDSS_MDP_CTL_OP_CMD_MODE		(1 << 17)
+
+#define MDSS_MDP_CTL_OP_ROT0_MODE		0x1
+#define MDSS_MDP_CTL_OP_ROT1_MODE		0x2
+#define MDSS_MDP_CTL_OP_WB0_MODE		0x3
+#define MDSS_MDP_CTL_OP_WB1_MODE		0x4
+#define MDSS_MDP_CTL_OP_WFD_MODE		0x5
+
+#define MDSS_MDP_CTL_OP_PACK_3D_ENABLE		BIT(19)
+#define MDSS_MDP_CTL_OP_PACK_3D_FRAME_INT	(0 << 20)
+#define MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT	(1 << 20)
+#define MDSS_MDP_CTL_OP_PACK_3D_V_ROW_INT	(2 << 20)
+#define MDSS_MDP_CTL_OP_PACK_3D_COL_INT		(3 << 20)
+
+enum mdss_mdp_sspp_index {
+	MDSS_MDP_SSPP_VIG0,
+	MDSS_MDP_SSPP_VIG1,
+	MDSS_MDP_SSPP_VIG2,
+	MDSS_MDP_SSPP_RGB0,
+	MDSS_MDP_SSPP_RGB1,
+	MDSS_MDP_SSPP_RGB2,
+	MDSS_MDP_SSPP_DMA0,
+	MDSS_MDP_SSPP_DMA1,
+	MDSS_MDP_MAX_SSPP
+};
+
+enum mdss_mdp_sspp_fetch_type {
+	MDSS_MDP_PLANE_INTERLEAVED,
+	MDSS_MDP_PLANE_PLANAR,
+	MDSS_MDP_PLANE_PSEUDO_PLANAR,
+};
+
+enum mdss_mdp_sspp_chroma_samp_type {
+	MDSS_MDP_CHROMA_RGB,
+	MDSS_MDP_CHROMA_H2V1,
+	MDSS_MDP_CHROMA_H1V2,
+	MDSS_MDP_CHROMA_420
+};
+
+#define MDSS_MDP_REG_SSPP_OFFSET(pipe) (0x01200 + ((pipe) * 0x400))
+
+#define MDSS_MDP_REG_SSPP_SRC_SIZE			0x000
+#define MDSS_MDP_REG_SSPP_SRC_IMG_SIZE			0x004
+#define MDSS_MDP_REG_SSPP_SRC_XY			0x008
+#define MDSS_MDP_REG_SSPP_OUT_SIZE			0x00C
+#define MDSS_MDP_REG_SSPP_OUT_XY			0x010
+#define MDSS_MDP_REG_SSPP_SRC0_ADDR			0x014
+#define MDSS_MDP_REG_SSPP_SRC1_ADDR			0x018
+#define MDSS_MDP_REG_SSPP_SRC2_ADDR			0x01C
+#define MDSS_MDP_REG_SSPP_SRC3_ADDR			0x020
+#define MDSS_MDP_REG_SSPP_SRC_YSTRIDE0			0x024
+#define MDSS_MDP_REG_SSPP_SRC_YSTRIDE1			0x028
+#define MDSS_MDP_REG_SSPP_STILE_FRAME_SIZE		0x02C
+#define MDSS_MDP_REG_SSPP_SRC_FORMAT			0x030
+#define MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN		0x034
+
+#define MDSS_MDP_REG_SSPP_SRC_OP_MODE			0x038
+#define MDSS_MDP_OP_DEINTERLACE			BIT(22)
+#define MDSS_MDP_OP_DEINTERLACE_ODD		BIT(23)
+#define MDSS_MDP_OP_FLIP_UD			BIT(14)
+#define MDSS_MDP_OP_FLIP_LR			BIT(13)
+#define MDSS_MDP_OP_BWC_EN			BIT(0)
+#define MDSS_MDP_OP_BWC_LOSSLESS		(0 << 1)
+#define MDSS_MDP_OP_BWC_Q_HIGH			(1 << 1)
+#define MDSS_MDP_OP_BWC_Q_MED			(2 << 1)
+
+#define MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR		0x03C
+#define MDSS_MDP_REG_SSPP_FETCH_CONFIG			0x048
+#define MDSS_MDP_REG_SSPP_VC1_RANGE			0x04C
+
+#define MDSS_MDP_REG_SSPP_CURRENT_SRC0_ADDR		0x0A4
+#define MDSS_MDP_REG_SSPP_CURRENT_SRC1_ADDR		0x0A8
+#define MDSS_MDP_REG_SSPP_CURRENT_SRC2_ADDR		0x0AC
+#define MDSS_MDP_REG_SSPP_CURRENT_SRC3_ADDR		0x0B0
+#define MDSS_MDP_REG_SSPP_LINE_SKIP_STEP_C03		0x0B4
+#define MDSS_MDP_REG_SSPP_LINE_SKIP_STEP_C12		0x0B8
+
+#define MDSS_MDP_REG_VIG_OP_MODE			0x200
+#define MDSS_MDP_REG_VIG_QSEED2_CONFIG			0x204
+#define MDSS_MDP_REG_VIG_QSEED2_C03_PHASESTEPX		0x210
+#define MDSS_MDP_REG_VIG_QSEED2_C03_PHASESTEPY		0x214
+#define MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPX		0x218
+#define MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPY		0x21C
+#define MDSS_MDP_REG_VIG_QSEED2_C03_INIT_PHASEX		0x220
+#define MDSS_MDP_REG_VIG_QSEED2_C03_INIT_PHASEY		0x224
+#define MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEX		0x228
+#define MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEY		0x22C
+
+#define MDSS_MDP_REG_SCALE_CONFIG			0x204
+#define MDSS_MDP_REG_SCALE_PHASE_STEP_X			0x210
+#define MDSS_MDP_REG_SCALE_PHASE_STEP_Y			0x214
+#define MDSS_MDP_REG_SCALE_INIT_PHASE_X			0x220
+#define MDSS_MDP_REG_SCALE_INIT_PHASE_Y			0x224
+
+#define MDSS_MDP_REG_VIG_CSC_0_BASE			0x280
+#define MDSS_MDP_REG_VIG_CSC_1_BASE			0x320
+
+#define MDSS_MDP_SCALE_FILTER_NEAREST		0x0
+#define MDSS_MDP_SCALE_FILTER_BIL		0x1
+#define MDSS_MDP_SCALE_FILTER_PCMN		0x2
+#define MDSS_MDP_SCALE_FILTER_CA		0x3
+#define MDSS_MDP_SCALEY_EN			BIT(1)
+#define MDSS_MDP_SCALEX_EN			BIT(0)
+
+#define MDSS_MDP_NUM_REG_MIXERS 3
+#define MDSS_MDP_NUM_WB_MIXERS 2
+
+enum mdss_mdp_mixer_index {
+	MDSS_MDP_LAYERMIXER0,
+	MDSS_MDP_LAYERMIXER1,
+	MDSS_MDP_LAYERMIXER2,
+	MDSS_MDP_LAYERMIXER3,
+	MDSS_MDP_LAYERMIXER4,
+	MDSS_MDP_MAX_LAYERMIXER
+};
+
+enum mdss_mdp_stage_index {
+	MDSS_MDP_STAGE_UNUSED,
+	MDSS_MDP_STAGE_BASE,
+	MDSS_MDP_STAGE_0,
+	MDSS_MDP_STAGE_1,
+	MDSS_MDP_STAGE_2,
+	MDSS_MDP_STAGE_3,
+	MDSS_MDP_MAX_STAGE
+};
+
+enum mdss_mdp_blend_index {
+	MDSS_MDP_BLEND_STAGE0,
+	MDSS_MDP_BLEND_STAGE1,
+	MDSS_MDP_BLEND_STAGE2,
+	MDSS_MDP_BLEND_STAGE3,
+	MDSS_MDP_MAX_BLEND_STAGE,
+};
+
+#define MDSS_MDP_REG_LM_OFFSET(lm) (0x03200 + ((lm) * 0x400))
+
+#define MDSS_MDP_REG_LM_OP_MODE				0x000
+#define MDSS_MDP_REG_LM_OUT_SIZE			0x004
+#define MDSS_MDP_REG_LM_BORDER_COLOR_0			0x008
+#define MDSS_MDP_REG_LM_BORDER_COLOR_1			0x010
+
+#define MDSS_MDP_REG_LM_BLEND_OFFSET(stage)	(0x20 + ((stage) * 0x30))
+#define MDSS_MDP_REG_LM_BLEND_OP			0x00
+#define MDSS_MDP_REG_LM_BLEND_FG_ALPHA			0x04
+#define MDSS_MDP_REG_LM_BLEND_BG_ALPHA			0x08
+#define MDSS_MDP_REG_LM_BLEND_FG_TRANSP_LOW0		0x0C
+#define MDSS_MDP_REG_LM_BLEND_FG_TRANSP_LOW1		0x10
+#define MDSS_MDP_REG_LM_BLEND_FG_TRANSP_HIGH0		0x14
+#define MDSS_MDP_REG_LM_BLEND_FG_TRANSP_HIGH1		0x18
+#define MDSS_MDP_REG_LM_BLEND_BG_TRANSP_LOW0		0x1C
+#define MDSS_MDP_REG_LM_BLEND_BG_TRANSP_LOW1		0x20
+#define MDSS_MDP_REG_LM_BLEND_BG_TRANSP_HIGH0		0x24
+#define MDSS_MDP_REG_LM_BLEND_BG_TRANSP_HIGH1		0x28
+
+#define MDSS_MDP_REG_LM_CURSOR_IMG_SIZE			0xE0
+#define MDSS_MDP_REG_LM_CURSOR_SIZE			0xE4
+#define MDSS_MDP_REG_LM_CURSOR_XY			0xE8
+#define MDSS_MDP_REG_LM_CURSOR_STRIDE			0xDC
+#define MDSS_MDP_REG_LM_CURSOR_FORMAT			0xEC
+#define MDSS_MDP_REG_LM_CURSOR_BASE_ADDR		0xF0
+#define MDSS_MDP_REG_LM_CURSOR_START_XY			0xF4
+#define MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG		0xF8
+#define MDSS_MDP_REG_LM_CURSOR_BLEND_PARAM		0xFC
+#define MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_LOW0	0x100
+#define MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_LOW1	0x104
+#define MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH0	0x108
+#define MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH1	0x10C
+
+#define MDSS_MDP_LM_BORDER_COLOR		(1 << 24)
+#define MDSS_MDP_LM_CURSOR_OUT			(1 << 25)
+#define MDSS_MDP_BLEND_FG_ALPHA_FG_CONST	(0 << 0)
+#define MDSS_MDP_BLEND_FG_ALPHA_BG_CONST	(1 << 0)
+#define MDSS_MDP_BLEND_FG_ALPHA_FG_PIXEL	(2 << 0)
+#define MDSS_MDP_BLEND_FG_ALPHA_BG_PIXEL	(3 << 0)
+#define MDSS_MDP_BLEND_FG_INV_ALPHA		(1 << 2)
+#define MDSS_MDP_BLEND_FG_MOD_ALPHA		(1 << 3)
+#define MDSS_MDP_BLEND_FG_INV_MOD_ALPHA		(1 << 4)
+#define MDSS_MDP_BLEND_FG_TRANSP_EN		(1 << 5)
+#define MDSS_MDP_BLEND_BG_ALPHA_FG_CONST	(0 << 8)
+#define MDSS_MDP_BLEND_BG_ALPHA_BG_CONST	(1 << 8)
+#define MDSS_MDP_BLEND_BG_ALPHA_FG_PIXEL	(2 << 8)
+#define MDSS_MDP_BLEND_BG_ALPHA_BG_PIXEL	(3 << 8)
+#define MDSS_MDP_BLEND_BG_INV_ALPHA		(1 << 10)
+#define MDSS_MDP_BLEND_BG_MOD_ALPHA		(1 << 11)
+#define MDSS_MDP_BLEND_BG_INV_MOD_ALPHA		(1 << 12)
+#define MDSS_MDP_BLEND_BG_TRANSP_EN		(1 << 13)
+
+enum mdss_mdp_writeback_index {
+	MDSS_MDP_WRITEBACK0,
+	MDSS_MDP_WRITEBACK1,
+	MDSS_MDP_WRITEBACK2,
+	MDSS_MDP_WRITEBACK3,
+	MDSS_MDP_WRITEBACK4,
+	MDSS_MDP_MAX_WRITEBACK
+};
+
+#define MDSS_MDP_REG_WB_OFFSET(wb)	(0x11100 + ((wb) * 0x2000))
+
+#define MDSS_MDP_REG_WB_DST_FORMAT			0x000
+#define MDSS_MDP_REG_WB_DST_OP_MODE			0x004
+#define MDSS_MDP_REG_WB_DST_PACK_PATTERN		0x008
+#define MDSS_MDP_REG_WB_DST0_ADDR			0x00C
+#define MDSS_MDP_REG_WB_DST1_ADDR			0x010
+#define MDSS_MDP_REG_WB_DST2_ADDR			0x014
+#define MDSS_MDP_REG_WB_DST3_ADDR			0x018
+#define MDSS_MDP_REG_WB_DST_YSTRIDE0			0x01C
+#define MDSS_MDP_REG_WB_DST_YSTRIDE1			0x020
+#define MDSS_MDP_REG_WB_DST_YSTRIDE1			0x020
+#define MDSS_MDP_REG_WB_DST_DITHER_BITDEPTH		0x024
+#define MDSS_MDP_REG_WB_DST_MATRIX_ROW0			0x030
+#define MDSS_MDP_REG_WB_DST_MATRIX_ROW1			0x034
+#define MDSS_MDP_REG_WB_DST_MATRIX_ROW2			0x038
+#define MDSS_MDP_REG_WB_DST_MATRIX_ROW3			0x03C
+#define MDSS_MDP_REG_WB_ROTATION_DNSCALER		0x050
+#define MDSS_MDP_REG_WB_N16_INIT_PHASE_X_C03		0x060
+#define MDSS_MDP_REG_WB_N16_INIT_PHASE_X_C12		0x064
+#define MDSS_MDP_REG_WB_N16_INIT_PHASE_Y_C03		0x068
+#define MDSS_MDP_REG_WB_N16_INIT_PHASE_Y_C12		0x06C
+#define MDSS_MDP_REG_WB_OUT_SIZE			0x074
+#define MDSS_MDP_REG_WB_ALPHA_X_VALUE			0x078
+#define MDSS_MDP_REG_WB_CSC_BASE			0x260
+
+enum mdss_mdp_dspp_index {
+	MDSS_MDP_DSPP0,
+	MDSS_MDP_DSPP1,
+	MDSS_MDP_DSPP2,
+	MDSS_MDP_MAX_DSPP
+};
+
+enum mdss_mpd_intf_index {
+	MDSS_MDP_NO_INTF,
+	MDSS_MDP_INTF0,
+	MDSS_MDP_INTF1,
+	MDSS_MDP_INTF2,
+	MDSS_MDP_INTF3,
+	MDSS_MDP_MAX_INTF
+};
+
+#define MDSS_MDP_REG_INTF_OFFSET(intf)		(0x20F00 + ((intf) * 0x200))
+
+#define MDSS_MDP_REG_INTF_TIMING_ENGINE_EN		0x000
+#define MDSS_MDP_REG_INTF_CONFIG			0x004
+#define MDSS_MDP_REG_INTF_HSYNC_CTL			0x008
+#define MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0		0x00C
+#define MDSS_MDP_REG_INTF_VSYNC_PERIOD_F1		0x010
+#define MDSS_MDP_REG_INTF_VSYNC_PULSE_WIDTH_F0		0x014
+#define MDSS_MDP_REG_INTF_VSYNC_PULSE_WIDTH_F1		0x018
+#define MDSS_MDP_REG_INTF_DISPLAY_V_START_F0		0x01C
+#define MDSS_MDP_REG_INTF_DISPLAY_V_START_F1		0x020
+#define MDSS_MDP_REG_INTF_DISPLAY_V_END_F0		0x024
+#define MDSS_MDP_REG_INTF_DISPLAY_V_END_F1		0x028
+#define MDSS_MDP_REG_INTF_ACTIVE_V_START_F0		0x02C
+#define MDSS_MDP_REG_INTF_ACTIVE_V_START_F1		0x030
+#define MDSS_MDP_REG_INTF_ACTIVE_V_END_F0		0x034
+#define MDSS_MDP_REG_INTF_ACTIVE_V_END_F1		0x038
+#define MDSS_MDP_REG_INTF_DISPLAY_HCTL			0x03C
+#define MDSS_MDP_REG_INTF_ACTIVE_HCTL			0x040
+#define MDSS_MDP_REG_INTF_BORDER_COLOR			0x044
+#define MDSS_MDP_REG_INTF_UNDERFLOW_COLOR		0x048
+#define MDSS_MDP_REG_INTF_HSYNC_SKEW			0x04C
+#define MDSS_MDP_REG_INTF_POLARITY_CTL			0x050
+#define MDSS_MDP_REG_INTF_TEST_CTL			0x054
+#define MDSS_MDP_REG_INTF_TP_COLOR0			0x058
+#define MDSS_MDP_REG_INTF_TP_COLOR1			0x05C
+
+#define MDSS_MDP_REG_INTF_DEFLICKER_CONFIG		0x0F0
+#define MDSS_MDP_REG_INTF_DEFLICKER_STRNG_COEFF		0x0F4
+#define MDSS_MDP_REG_INTF_DEFLICKER_WEAK_COEFF		0x0F8
+
+#define MDSS_MDP_REG_INTF_DSI_CMD_MODE_TRIGGER_EN	0x084
+#define MDSS_MDP_REG_INTF_PANEL_FORMAT			0x090
+#define MDSS_MDP_REG_INTF_TPG_ENABLE			0x100
+#define MDSS_MDP_REG_INTF_TPG_MAIN_CONTROL		0x104
+#define MDSS_MDP_REG_INTF_TPG_VIDEO_CONFIG		0x108
+#define MDSS_MDP_REG_INTF_TPG_COMPONENT_LIMITS		0x10C
+#define MDSS_MDP_REG_INTF_TPG_RECTANGLE			0x110
+#define MDSS_MDP_REG_INTF_TPG_INITIAL_VALUE		0x114
+#define MDSS_MDP_REG_INTF_TPG_BLK_WHITE_PATTERN_FRAMES	0x118
+#define MDSS_MDP_REG_INTF_TPG_RGB_MAPPING		0x11C
+
+#define MDSS_MDP_REG_INTF_FRAME_LINE_COUNT_EN		0x0A8
+#define MDSS_MDP_REG_INTF_FRAME_COUNT			0x0AC
+#define MDSS_MDP_REG_INTF_LINE_COUNT			0x0B0
+
+enum mdss_mdp_pingpong_index {
+	MDSS_MDP_PINGPONG0,
+	MDSS_MDP_PINGPONG1,
+	MDSS_MDP_PINGPONG2,
+	MDSS_MDP_MAX_PINGPONG
+};
+
+#define MDSS_MDP_REG_PP_OFFSET(pp)	(0x21B00 + ((pp) * 0x100))
+
+#define MDSS_MDP_REG_PP_TEAR_CHECK_EN			0x000
+#define MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC		0x004
+#define MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT		0x008
+#define MDSS_MDP_REG_PP_SYNC_WRCOUNT			0x00C
+#define MDSS_MDP_REG_PP_VSYNC_INIT_VAL			0x010
+#define MDSS_MDP_REG_PP_INT_COUNT_VAL			0x014
+#define MDSS_MDP_REG_PP_SYNC_THRESH			0x018
+#define MDSS_MDP_REG_PP_START_POS			0x01C
+#define MDSS_MDP_REG_PP_RD_PTR_IRQ			0x020
+#define MDSS_MDP_REG_PP_WR_PTR_IRQ			0x024
+#define MDSS_MDP_REG_PP_OUT_LINE_COUNT			0x028
+#define MDSS_MDP_REG_PP_LINE_COUNT			0x02C
+#define MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG		0x030
+
+#define MDSS_MDP_REG_SMP_ALLOC_W0			0x00180
+#define MDSS_MDP_REG_SMP_ALLOC_R0			0x00230
+
+#define MDSS_MDP_SMP_MMB_SIZE		4096
+#define MDSS_MDP_SMP_MMB_BLOCKS		22
+
+enum mdss_mdp_smp_client_index {
+	MDSS_MDP_SMP_CLIENT_UNUSED,
+	MDSS_MDP_SMP_CLIENT_VIG0_FETCH_Y,
+	MDSS_MDP_SMP_CLIENT_VIG0_FETCH_CR,
+	MDSS_MDP_SMP_CLIENT_VIG0_FETCH_CB,
+	MDSS_MDP_SMP_CLIENT_VIG1_FETCH_Y,
+	MDSS_MDP_SMP_CLIENT_VIG1_FETCH_CR,
+	MDSS_MDP_SMP_CLIENT_VIG1_FETCH_CB,
+	MDSS_MDP_SMP_CLIENT_VIG2_FETCH_Y,
+	MDSS_MDP_SMP_CLIENT_VIG2_FETCH_CR,
+	MDSS_MDP_SMP_CLIENT_VIG2_FETCH_CB,
+	MDSS_MDP_SMP_CLIENT_DMA0_FETCH_Y,
+	MDSS_MDP_SMP_CLIENT_DMA0_FETCH_CR,
+	MDSS_MDP_SMP_CLIENT_DMA0_FETCH_CB,
+	MDSS_MDP_SMP_CLIENT_DMA1_FETCH_Y,
+	MDSS_MDP_SMP_CLIENT_DMA1_FETCH_CR,
+	MDSS_MDP_SMP_CLIENT_DMA1_FETCH_CB,
+	MDSS_MDP_SMP_CLIENT_RGB0_FETCH,
+	MDSS_MDP_SMP_CLIENT_RGB1_FETCH,
+	MDSS_MDP_SMP_CLIENT_RGB2_FETCH,
+};
+
+#endif /* MDSS_MDP_HWIO_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
new file mode 100644
index 0000000..99d4b4c
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -0,0 +1,300 @@
+/* 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 "mdss_fb.h"
+#include "mdss_mdp.h"
+
+#define ROT_BLK_SIZE	128
+
+enum mdss_mdp_writeback_type {
+	MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
+	MDSS_MDP_WRITEBACK_TYPE_LINE,
+	MDSS_MDP_WRITEBACK_TYPE_WFD,
+};
+
+struct mdss_mdp_writeback_ctx {
+	u32 wb_num;
+	u8 ref_cnt;
+	u8 type;
+
+	u32 intr_type;
+	u32 intf_num;
+
+	u32 opmode;
+	u32 format;
+	u16 width;
+	u16 height;
+	u8 rot90;
+
+	struct completion comp;
+	struct mdss_mdp_plane_sizes dst_planes;
+	struct mdss_mdp_data wb_data;
+};
+
+static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = {
+	{
+		.type = MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
+		.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
+		.intf_num = 0,
+	},
+	{
+		.type = MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
+		.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
+		.intf_num = 1,
+	},
+	{
+		.type = MDSS_MDP_WRITEBACK_TYPE_LINE,
+		.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
+		.intf_num = 0,
+	},
+	{
+		.type = MDSS_MDP_WRITEBACK_TYPE_LINE,
+		.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
+		.intf_num = 1,
+	},
+	{
+		.type = MDSS_MDP_WRITEBACK_TYPE_WFD,
+		.intr_type = MDSS_MDP_IRQ_WB_WFD,
+		.intf_num = 0,
+	},
+};
+
+static void *videomemory;
+
+static int mdss_mdp_writeback_addr_setup(struct mdss_mdp_writeback_ctx *ctx,
+					 struct mdss_mdp_data *data)
+{
+	int off, ret;
+
+	if (!data)
+		return -EINVAL;
+
+	pr_debug("wb_num=%d addr=0x%x\n", ctx->wb_num, data->p[0].addr);
+
+	ret = mdss_mdp_data_check(data, &ctx->dst_planes);
+	if (ret)
+		return ret;
+
+	off = MDSS_MDP_REG_WB_OFFSET(ctx->wb_num);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST0_ADDR, data->p[0].addr);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST1_ADDR, data->p[1].addr);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST2_ADDR, data->p[2].addr);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST3_ADDR, data->p[3].addr);
+
+	return 0;
+}
+
+static int mdss_mdp_writeback_format_setup(struct mdss_mdp_writeback_ctx *ctx)
+{
+	struct mdss_mdp_format_params *fmt;
+	u32 dst_format, pattern, ystride0, ystride1, outsize, chroma_samp;
+	int off, ret;
+
+	pr_debug("wb_num=%d format=%d\n", ctx->wb_num, ctx->format);
+
+	mdss_mdp_get_plane_sizes(ctx->format, ctx->width, ctx->height,
+				 &ctx->dst_planes);
+
+	fmt = mdss_mdp_get_format_params(ctx->format);
+	if (!fmt) {
+		pr_err("wb format=%d not supported\n", ctx->format);
+		return ret;
+	}
+
+	chroma_samp = fmt->chroma_sample;
+	if (ctx->rot90) {
+		if (chroma_samp == MDSS_MDP_CHROMA_H2V1)
+			chroma_samp = MDSS_MDP_CHROMA_H1V2;
+		else if (chroma_samp == MDSS_MDP_CHROMA_H1V2)
+			chroma_samp = MDSS_MDP_CHROMA_H2V1;
+	}
+
+	dst_format = (chroma_samp << 23) |
+		     (fmt->fetch_planes << 19) |
+		     (fmt->unpack_align_msb << 18) |
+		     (fmt->unpack_tight << 17) |
+		     (fmt->unpack_count << 12) |
+		     (fmt->bpp << 9) |
+		     (fmt->alpha_enable << 8) |
+		     (fmt->a_bit << 6) |
+		     (fmt->r_bit << 4) |
+		     (fmt->b_bit << 2) |
+		     (fmt->g_bit << 0);
+
+	pattern = (fmt->element3 << 24) |
+		  (fmt->element2 << 15) |
+		  (fmt->element1 << 8) |
+		  (fmt->element0 << 0);
+
+	ystride0 = (ctx->dst_planes.ystride[0]) |
+		   (ctx->dst_planes.ystride[1] << 16);
+	ystride1 = (ctx->dst_planes.ystride[2]) |
+		   (ctx->dst_planes.ystride[3] << 16);
+	outsize = (ctx->height << 16) | ctx->width;
+
+	off = MDSS_MDP_REG_WB_OFFSET(ctx->wb_num);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_FORMAT, dst_format);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_OP_MODE, ctx->opmode);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_PACK_PATTERN, pattern);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_YSTRIDE0, ystride0);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_YSTRIDE1, ystride1);
+	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_OUT_SIZE, outsize);
+
+	return 0;
+}
+
+static int mdss_mdp_writeback_wfd_setup(struct mdss_mdp_ctl *ctl,
+					struct mdss_mdp_writeback_ctx *ctx)
+{
+	struct msm_fb_data_type *mfd;
+	struct fb_info *fbi;
+	int ret;
+	u32 plane_size;
+
+	mfd = ctl->mfd;
+	fbi = mfd->fbi;
+
+	pr_debug("setup ctl=%d\n", ctl->num);
+
+	ctx->opmode = 0;
+	ctx->format = ctl->dst_format;
+	ctx->width = fbi->var.xres;
+	ctx->height = fbi->var.yres;
+
+	plane_size = ctx->width * ctx->height * fbi->var.bits_per_pixel / 8;
+
+	videomemory = (void *) fbi->fix.smem_start + fbi->fix.smem_len -
+		      plane_size;
+
+	ctx->wb_data.num_planes = 1;
+	ctx->wb_data.p[0].addr = (u32) videomemory;
+	ctx->wb_data.p[0].len = plane_size;
+
+	ret = mdss_mdp_writeback_format_setup(ctx);
+	if (ret) {
+		pr_err("format setup failed\n");
+		return ret;
+	}
+
+	ctl->flush_bits |=  BIT(16); /* WB */
+
+	return 0;
+}
+
+static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_mdp_writeback_ctx *ctx;
+
+	pr_debug("stop ctl=%d\n", ctl->num);
+
+	ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
+	if (ctx) {
+		ctl->priv_data = NULL;
+		ctx->ref_cnt--;
+	}
+
+	return 0;
+}
+
+static void mdss_mdp_writeback_intr_done(void *arg)
+{
+	struct mdss_mdp_writeback_ctx *ctx;
+
+	ctx = (struct mdss_mdp_writeback_ctx *) arg;
+	if (!ctx) {
+		pr_err("invalid ctx\n");
+		return;
+	}
+
+	pr_debug("intr wb_num=%d\n", ctx->wb_num);
+
+	mdss_mdp_irq_disable_nosync(ctx->intr_type, ctx->intf_num);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, true);
+
+	complete_all(&ctx->comp);
+}
+
+static int mdss_mdp_writeback_display(struct mdss_mdp_ctl *ctl, void *arg)
+{
+	struct mdss_mdp_writeback_ctx *ctx;
+	struct mdss_mdp_data *wb_data;
+	u32 flush_bits;
+	int ret;
+
+	ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
+	if (!ctx)
+		return -ENODEV;
+
+	wb_data = &ctx->wb_data;
+
+	ret = mdss_mdp_writeback_addr_setup(ctx, wb_data);
+	if (ret) {
+		pr_err("writeback data setup error ctl=%d\n", ctl->num);
+		return ret;
+	}
+
+	flush_bits = BIT(16); /* WB */
+	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, flush_bits);
+
+	INIT_COMPLETION(ctx->comp);
+	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
+				   mdss_mdp_writeback_intr_done, ctx);
+	mdss_mdp_irq_enable(ctx->intr_type, ctx->intf_num);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
+	wmb();
+
+	pr_debug("writeback kickoff wb_num=%d\n", ctx->wb_num);
+	wait_for_completion_interruptible(&ctx->comp);
+
+	return 0;
+}
+
+int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_mdp_writeback_ctx *ctx;
+	u32 mem_sel;
+	int ret = 0;
+
+	pr_debug("start ctl=%d\n", ctl->num);
+
+	mem_sel = (ctl->opmode & 0xF) - 1;
+	if (mem_sel < MDSS_MDP_MAX_WRITEBACK) {
+		ctx = &wb_ctx_list[mem_sel];
+		if (ctx->ref_cnt) {
+			pr_err("writeback in use %d\n", mem_sel);
+			return -EBUSY;
+		}
+		ctx->ref_cnt++;
+	} else {
+		pr_err("invalid writeback mode %d\n", mem_sel);
+		return -EINVAL;
+	}
+	ctl->priv_data = ctx;
+	ctx->wb_num = ctl->num;	/* wb num should match ctl num */
+
+	init_completion(&ctx->comp);
+
+	if (ctx->type == MDSS_MDP_WRITEBACK_TYPE_WFD)
+		ret = mdss_mdp_writeback_wfd_setup(ctl, ctx);
+	else /* line mode not supported */
+		return -ENOSYS;
+
+	ctl->stop_fnc = mdss_mdp_writeback_stop;
+	ctl->display_fnc = mdss_mdp_writeback_display;
+
+	return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
new file mode 100644
index 0000000..bd4a974
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -0,0 +1,701 @@
+/* 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 <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+#include "mdss_fb.h"
+#include "mdss_mdp.h"
+
+#define CHECK_BOUNDS(offset, size, max_size) \
+	(((size) > (max_size)) || ((offset) > ((max_size) - (size))))
+
+static int mdss_mdp_overlay_get(struct msm_fb_data_type *mfd,
+				struct mdp_overlay *req)
+{
+	struct mdss_mdp_pipe *pipe;
+
+	pipe = mdss_mdp_pipe_get_locked(req->id);
+	if (pipe == NULL) {
+		pr_err("invalid pipe ndx=%x\n", req->id);
+		return -ENODEV;
+	}
+
+	*req = pipe->req_data;
+	mdss_mdp_pipe_unlock(pipe);
+
+	return 0;
+}
+
+static int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
+				      struct mdp_overlay *req,
+				      struct mdss_mdp_format_params *fmt)
+{
+	u32 xres, yres;
+	u32 dst_w, dst_h;
+
+	xres = mfd->fbi->var.xres;
+	yres = mfd->fbi->var.yres;
+
+	if (req->z_order >= MDSS_MDP_MAX_STAGE) {
+		pr_err("zorder %d out of range\n", req->z_order);
+		return -ERANGE;
+	}
+
+	if (req->src.width > MAX_IMG_WIDTH ||
+	    req->src.height > MAX_IMG_HEIGHT ||
+	    req->src_rect.w == 0 || req->src_rect.h == 0 ||
+	    req->dst_rect.w < MIN_DST_W || req->dst_rect.h < MIN_DST_H ||
+	    req->dst_rect.w > MAX_DST_W || req->dst_rect.h > MAX_DST_H ||
+	    CHECK_BOUNDS(req->src_rect.x, req->src_rect.w, req->src.width) ||
+	    CHECK_BOUNDS(req->src_rect.y, req->src_rect.h, req->src.height) ||
+	    CHECK_BOUNDS(req->dst_rect.x, req->dst_rect.w, xres) ||
+	    CHECK_BOUNDS(req->dst_rect.y, req->dst_rect.h, yres)) {
+		pr_err("invalid image img_w=%d img_h=%d\n",
+				req->src.width, req->src.height);
+
+		pr_err("\tsrc_rect=%d,%d,%d,%d dst_rect=%d,%d,%d,%d\n",
+		       req->src_rect.x, req->src_rect.y,
+		       req->src_rect.w, req->src_rect.h,
+		       req->dst_rect.x, req->dst_rect.y,
+		       req->dst_rect.w, req->dst_rect.h);
+		return -EINVAL;
+	}
+
+	if (req->flags & MDP_ROT_90) {
+		dst_h = req->dst_rect.w;
+		dst_w = req->dst_rect.h;
+	} else {
+		dst_w = req->dst_rect.w;
+		dst_h = req->dst_rect.h;
+	}
+
+	if ((req->src_rect.w * MAX_UPSCALE_RATIO) < dst_w) {
+		pr_err("too much upscaling Width %d->%d\n",
+		       req->src_rect.w, req->dst_rect.w);
+		return -EINVAL;
+	}
+
+	if ((req->src_rect.h * MAX_UPSCALE_RATIO) < dst_h) {
+		pr_err("too much upscaling. Height %d->%d\n",
+		       req->src_rect.h, req->dst_rect.h);
+		return -EINVAL;
+	}
+
+	if (req->src_rect.w > (dst_w * MAX_DOWNSCALE_RATIO)) {
+		pr_err("too much downscaling. Width %d->%d\n",
+		       req->src_rect.w, req->dst_rect.w);
+		return -EINVAL;
+	}
+
+	if (req->src_rect.h > (dst_h * MAX_DOWNSCALE_RATIO)) {
+		pr_err("too much downscaling. Height %d->%d\n",
+		       req->src_rect.h, req->dst_rect.h);
+		return -EINVAL;
+	}
+
+	if (fmt->is_yuv) {
+		if ((req->src_rect.x & 0x1) || (req->src_rect.y & 0x1) ||
+		    (req->src_rect.w & 0x1) || (req->src_rect.h & 0x1)) {
+			pr_err("invalid odd src resolution\n");
+			return -EINVAL;
+		}
+		if ((req->dst_rect.x & 0x1) || (req->dst_rect.y & 0x1) ||
+		    (req->dst_rect.w & 0x1) || (req->dst_rect.h & 0x1)) {
+			pr_err("invalid odd dst resolution\n");
+			return -EINVAL;
+		}
+
+		if (((req->src_rect.w * (MAX_UPSCALE_RATIO / 2)) < dst_w) &&
+		    (fmt->chroma_sample == MDSS_MDP_CHROMA_420 ||
+		     fmt->chroma_sample == MDSS_MDP_CHROMA_H2V1)) {
+			pr_err("too much YUV upscaling Width %d->%d\n",
+			       req->src_rect.w, req->dst_rect.w);
+			return -EINVAL;
+		}
+
+		if (((req->src_rect.h * (MAX_UPSCALE_RATIO / 2)) < dst_h) &&
+		    (fmt->chroma_sample == MDSS_MDP_CHROMA_420 ||
+		     fmt->chroma_sample == MDSS_MDP_CHROMA_H1V2)) {
+			pr_err("too much YUV upscaling Height %d->%d\n",
+			       req->src_rect.h, req->dst_rect.h);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
+				       struct mdp_overlay *req,
+				       struct mdss_mdp_pipe **ppipe)
+{
+	struct mdss_mdp_format_params *fmt;
+	struct mdss_mdp_pipe *pipe;
+	struct mdss_mdp_mixer *mixer = NULL;
+	u32 pipe_type, mixer_mux;
+	int ret;
+
+	if (mfd == NULL || mfd->ctl == NULL)
+		return -ENODEV;
+
+	if (req->flags & MDSS_MDP_RIGHT_MIXER)
+		mixer_mux = MDSS_MDP_MIXER_MUX_RIGHT;
+	else
+		mixer_mux = MDSS_MDP_MIXER_MUX_LEFT;
+
+	pr_debug("pipe ctl=%u req id=%x mux=%d\n", mfd->ctl->num, req->id,
+			mixer_mux);
+
+	if (req->flags & MDP_ROT_90) {
+		pr_err("unsupported inline rotation\n");
+		return -ENOTSUPP;
+	}
+
+	fmt = mdss_mdp_get_format_params(req->src.format);
+	if (!fmt) {
+		pr_err("invalid pipe format %d\n", req->src.format);
+		return -EINVAL;
+	}
+
+	ret = mdss_mdp_overlay_req_check(mfd, req, fmt);
+	if (ret)
+		return ret;
+
+	pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, mixer_mux, req->z_order);
+	if (pipe && pipe->ndx != req->id) {
+		pr_err("stage %d taken by pnum=%d\n", req->z_order, pipe->num);
+		return -EBUSY;
+	}
+
+
+	if (req->id == MSMFB_NEW_REQUEST) {
+		mixer = mdss_mdp_mixer_get(mfd->ctl, mixer_mux);
+		if (!mixer) {
+			pr_err("unable to get mixer\n");
+			return -ENODEV;
+		}
+
+		if (fmt->is_yuv || (req->flags & MDP_OV_PIPE_SHARE))
+			pipe_type = MDSS_MDP_PIPE_TYPE_VIG;
+		else
+			pipe_type = MDSS_MDP_PIPE_TYPE_RGB;
+
+		pipe = mdss_mdp_pipe_alloc_locked(pipe_type);
+
+		/* VIG pipes can also support RGB format */
+		if (!pipe && pipe_type == MDSS_MDP_PIPE_TYPE_RGB) {
+			pipe_type = MDSS_MDP_PIPE_TYPE_VIG;
+			pipe = mdss_mdp_pipe_alloc_locked(pipe_type);
+		}
+
+		if (pipe == NULL) {
+			pr_err("error allocating pipe\n");
+			return -ENOMEM;
+		}
+
+		pipe->mixer = mixer;
+		pipe->mfd = mfd;
+	} else {
+		pipe = mdss_mdp_pipe_get_locked(req->id);
+		if (pipe == NULL) {
+			pr_err("invalid pipe ndx=%x\n", req->id);
+			return -ENODEV;
+		}
+	}
+
+	pipe->flags = req->flags;
+
+	pipe->img_width = req->src.width & 0x3fff;
+	pipe->img_height = req->src.height & 0x3fff;
+	pipe->src.x = req->src_rect.x;
+	pipe->src.y = req->src_rect.y;
+	pipe->src.w = req->src_rect.w;
+	pipe->src.h = req->src_rect.h;
+	pipe->dst.x = req->dst_rect.x;
+	pipe->dst.y = req->dst_rect.y;
+	pipe->dst.w = req->dst_rect.w;
+	pipe->dst.h = req->dst_rect.h;
+
+	pipe->src_fmt = fmt;
+
+	pipe->mixer_stage = req->z_order;
+	pipe->is_fg = req->is_fg;
+	pipe->alpha = req->alpha;
+	pipe->transp = req->transp_mask;
+
+	pipe->req_data = *req;
+
+	pipe->params_changed++;
+
+	req->id = pipe->ndx;
+
+	*ppipe = pipe;
+
+	mdss_mdp_pipe_unlock(pipe);
+
+	return ret;
+}
+
+static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
+				struct mdp_overlay *req)
+{
+	int ret;
+	struct mdss_mdp_pipe *pipe;
+
+	/* userspace zorder start with stage 0 */
+	req->z_order += MDSS_MDP_STAGE_0;
+
+	ret = mdss_mdp_overlay_pipe_setup(mfd, req, &pipe);
+
+	req->z_order -= MDSS_MDP_STAGE_0;
+
+	return ret;
+}
+
+static int mdss_mdp_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
+{
+	struct mdss_mdp_pipe *pipe;
+	struct mdss_mdp_pipe *cleanup_pipes[MDSS_MDP_MAX_SSPP];
+	int i, ret = 0, clean_cnt = 0;
+	u32 pipe_ndx, unset_ndx = 0;
+
+	if (!mfd || !mfd->ctl)
+		return -ENODEV;
+
+	pr_debug("unset ndx=%x\n", ndx);
+
+	for (i = 0; unset_ndx != ndx && i < MDSS_MDP_MAX_SSPP; i++) {
+		pipe_ndx = BIT(i);
+		if (pipe_ndx & ndx) {
+			unset_ndx |= pipe_ndx;
+			pipe = mdss_mdp_pipe_get_locked(pipe_ndx);
+			if (pipe) {
+				mdss_mdp_mixer_pipe_unstage(pipe);
+				cleanup_pipes[clean_cnt++] = pipe;
+			} else {
+				pr_warn("unknown pipe ndx=%x\n", pipe_ndx);
+			}
+		}
+	}
+
+	if (clean_cnt) {
+		ret = mfd->kickoff_fnc(mfd->ctl);
+
+		for (i = 0; i < clean_cnt; i++)
+			mdss_mdp_pipe_destroy(cleanup_pipes[i]);
+	}
+
+	return ret;
+}
+
+static int mdss_mdp_overlay_play_wait(struct msm_fb_data_type *mfd,
+				      struct msmfb_overlay_data *req)
+{
+	int ret;
+
+	if (!mfd || !mfd->ctl)
+		return -ENODEV;
+
+	ret = mfd->kickoff_fnc(mfd->ctl);
+	if (!ret)
+		pr_err("error displaying\n");
+
+	return ret;
+}
+
+static int mdss_mdp_overlay_queue(struct msmfb_overlay_data *req,
+				  struct mdss_mdp_data *src_data)
+{
+	struct mdss_mdp_pipe *pipe;
+	struct mdss_mdp_ctl *ctl;
+	int ret;
+
+	pipe = mdss_mdp_pipe_get_locked(req->id);
+	if (pipe == NULL) {
+		pr_err("pipe ndx=%x doesn't exist\n", req->id);
+		return -ENODEV;
+	}
+
+	pr_debug("ov queue pnum=%d\n", pipe->num);
+
+	ret = mdss_mdp_pipe_queue_data(pipe, src_data);
+	ctl = pipe->mixer->ctl;
+	mdss_mdp_pipe_unlock(pipe);
+
+	if (ret == 0 && !(pipe->flags & MDP_OV_PLAY_NOWAIT))
+		ret = ctl->mfd->kickoff_fnc(ctl);
+
+
+	return ret;
+}
+
+static int mdss_mdp_overlay_play(struct msm_fb_data_type *mfd,
+				 struct msmfb_overlay_data *req)
+{
+	struct mdss_mdp_data src_data;
+	int ret = 0;
+
+	if (mfd == NULL)
+		return -ENODEV;
+
+	pr_debug("play req id=%x\n", req->id);
+
+	memset(&src_data, 0, sizeof(src_data));
+	mdss_mdp_get_img(mfd->iclient, &req->data, &src_data.p[0]);
+	if (src_data.p[0].len == 0) {
+		pr_err("src data pmem error\n");
+		return -ENOMEM;
+	}
+	src_data.num_planes = 1;
+
+	ret = mdss_mdp_overlay_queue(req, &src_data);
+
+	mdss_mdp_put_img(&src_data.p[0]);
+
+	return ret;
+}
+
+static int mdss_mdp_overlay_get_fb_pipe(struct msm_fb_data_type *mfd,
+					struct mdss_mdp_pipe **ppipe,
+					int mixer_mux)
+{
+	struct mdss_mdp_pipe *pipe;
+
+	pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, mixer_mux,
+					 MDSS_MDP_STAGE_BASE);
+	if (pipe == NULL) {
+		struct mdp_overlay req;
+		int ret;
+
+		memset(&req, 0, sizeof(req));
+
+		req.id = MSMFB_NEW_REQUEST;
+		req.src.format = mfd->fb_imgType;
+		req.src.height = mfd->fbi->var.yres;
+		req.src.width = mfd->fbi->var.xres;
+		if (mixer_mux == MDSS_MDP_MIXER_MUX_RIGHT) {
+			if (req.src.width <= MAX_MIXER_WIDTH)
+				return -ENODEV;
+
+			req.flags |= MDSS_MDP_RIGHT_MIXER;
+			req.src_rect.x = MAX_MIXER_WIDTH;
+			req.src_rect.w = req.src.width - MAX_MIXER_WIDTH;
+		} else {
+			req.src_rect.x = 0;
+			req.src_rect.w = MIN(req.src.width, MAX_MIXER_WIDTH);
+		}
+
+		req.src_rect.y = 0;
+		req.src_rect.h = req.src.height;
+		req.dst_rect.x = req.src_rect.x;
+		req.dst_rect.y = 0;
+		req.dst_rect.w = req.src_rect.w;
+		req.dst_rect.h = req.src_rect.h;
+		req.z_order = MDSS_MDP_STAGE_BASE;
+
+		pr_debug("allocating base pipe mux=%d\n", mixer_mux);
+
+		ret = mdss_mdp_overlay_pipe_setup(mfd, &req, &pipe);
+		if (ret)
+			return ret;
+
+		pr_debug("ctl=%d pnum=%d\n", mfd->ctl->num, pipe->num);
+	}
+
+	*ppipe = pipe;
+	return 0;
+}
+
+static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
+{
+	struct mdss_mdp_data data;
+	struct mdss_mdp_pipe *pipe;
+	struct fb_info *fbi;
+	u32 offset;
+	int bpp, ret;
+
+	if (!mfd)
+		return;
+
+	if (!mfd->ctl || !mfd->panel_power_on)
+		return;
+
+	fbi = mfd->fbi;
+
+	if (fbi->fix.smem_len == 0) {
+		pr_warn("fb memory not allocated\n");
+		return;
+	}
+
+	memset(&data, 0, sizeof(data));
+
+	bpp = fbi->var.bits_per_pixel / 8;
+	offset = fbi->var.xoffset * bpp +
+		 fbi->var.yoffset * fbi->fix.line_length;
+
+	data.p[0].addr = fbi->fix.smem_start + offset;
+	data.p[0].len = fbi->fix.smem_len - offset;
+	data.num_planes = 1;
+
+	ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe, MDSS_MDP_MIXER_MUX_LEFT);
+	if (ret) {
+		pr_err("unable to allocate base pipe\n");
+		return;
+	}
+
+	mdss_mdp_pipe_lock(pipe);
+	ret = mdss_mdp_pipe_queue_data(pipe, &data);
+	mdss_mdp_pipe_unlock(pipe);
+	if (ret) {
+		pr_err("unable to queue data\n");
+		return;
+	}
+
+	if (fbi->var.xres > MAX_MIXER_WIDTH) {
+		ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
+						   MDSS_MDP_MIXER_MUX_RIGHT);
+		if (ret) {
+			pr_err("unable to allocate right base pipe\n");
+			return;
+		}
+		mdss_mdp_pipe_lock(pipe);
+		ret = mdss_mdp_pipe_queue_data(pipe, &data);
+		mdss_mdp_pipe_unlock(pipe);
+		if (ret) {
+			pr_err("unable to queue right data\n");
+			return;
+		}
+	}
+
+	if (fbi->var.activate & FB_ACTIVATE_VBL)
+		mfd->kickoff_fnc(mfd->ctl);
+}
+
+static int mdss_mdp_hw_cursor_update(struct fb_info *info,
+				     struct fb_cursor *cursor)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct mdss_mdp_mixer *mixer;
+	struct fb_image *img = &cursor->image;
+	int calpha_en, transp_en, blendcfg, alpha;
+	int off, ret = 0;
+
+	mixer = mdss_mdp_mixer_get(mfd->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
+	off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
+
+	if ((img->width > MDSS_MDP_CURSOR_WIDTH) ||
+	    (img->height > MDSS_MDP_CURSOR_HEIGHT) ||
+	    (img->depth != 32))
+		return -EINVAL;
+
+	pr_debug("mixer=%d enable=%x set=%x\n", mixer->num, cursor->enable,
+			cursor->set);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	blendcfg = MDSS_MDP_REG_READ(off + MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG);
+
+	if (cursor->set & FB_CUR_SETPOS)
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_START_XY,
+				   (img->dy << 16) | img->dx);
+
+	if (cursor->set & FB_CUR_SETIMAGE) {
+		ret = copy_from_user(mfd->cursor_buf, img->data,
+				     img->width * img->height * 4);
+		if (ret)
+			return ret;
+
+		if (img->bg_color == 0xffffffff)
+			transp_en = 0;
+		else
+			transp_en = 1;
+
+		alpha = (img->fg_color & 0xff000000) >> 24;
+
+		if (alpha)
+			calpha_en = 0x0; /* xrgb */
+		else
+			calpha_en = 0x2; /* argb */
+
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_SIZE,
+				   (img->height << 16) | img->width);
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_STRIDE,
+				   img->width * 4);
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_BASE_ADDR,
+				   mfd->cursor_buf_phys);
+
+		wmb();
+
+		blendcfg &= ~0x1;
+		blendcfg |= (transp_en << 3) | (calpha_en << 1);
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG,
+				   blendcfg);
+		if (calpha_en)
+			MDSS_MDP_REG_WRITE(off +
+					   MDSS_MDP_REG_LM_CURSOR_BLEND_PARAM,
+					   alpha);
+
+		if (transp_en) {
+			MDSS_MDP_REG_WRITE(off +
+				   MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_LOW0,
+				   ((img->bg_color & 0xff00) << 8) |
+				   (img->bg_color & 0xff));
+			MDSS_MDP_REG_WRITE(off +
+				   MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_LOW1,
+				   ((img->bg_color & 0xff0000) >> 16));
+			MDSS_MDP_REG_WRITE(off +
+				   MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH0,
+				   ((img->bg_color & 0xff00) << 8) |
+				   (img->bg_color & 0xff));
+			MDSS_MDP_REG_WRITE(off +
+				   MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH1,
+				   ((img->bg_color & 0xff0000) >> 16));
+		}
+	}
+
+	if (!cursor->enable != !(blendcfg & 0x1)) {
+		if (cursor->enable)
+			blendcfg |= 0x1;
+		else
+			blendcfg &= ~0x1;
+
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG,
+				   blendcfg);
+
+		mixer->cursor_enabled = cursor->enable;
+		mixer->params_changed++;
+	}
+
+	mixer->ctl->flush_bits |= BIT(6) << mixer->num;
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	return 0;
+}
+
+static int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
+{
+	return mdss_mdp_display_commit(ctl, NULL);
+}
+
+static int mdss_mdp_overlay_ioctl_handler(struct msm_fb_data_type *mfd,
+					  u32 cmd, void __user *argp)
+{
+	struct mdp_overlay req;
+	int val, ret = -ENOSYS;
+
+	switch (cmd) {
+	case MSMFB_OVERLAY_GET:
+		ret = copy_from_user(&req, argp, sizeof(req));
+		if (!ret) {
+			ret = mdss_mdp_overlay_get(mfd, &req);
+
+			if (!IS_ERR_VALUE(ret))
+				ret = copy_to_user(argp, &req, sizeof(req));
+		}
+
+		if (ret) {
+			pr_err("OVERLAY_GET failed (%d)\n", ret);
+			ret = -EFAULT;
+		}
+		break;
+
+	case MSMFB_OVERLAY_SET:
+		ret = copy_from_user(&req, argp, sizeof(req));
+		if (!ret) {
+			ret = mdss_mdp_overlay_set(mfd, &req);
+
+			if (!IS_ERR_VALUE(ret))
+				ret = copy_to_user(argp, &req, sizeof(req));
+		}
+		if (ret) {
+			pr_err("OVERLAY_SET failed (%d)\n", ret);
+			ret = -EFAULT;
+		}
+		break;
+
+
+	case MSMFB_OVERLAY_UNSET:
+		if (!IS_ERR_VALUE(copy_from_user(&val, argp, sizeof(val))))
+			ret = mdss_mdp_overlay_unset(mfd, val);
+		break;
+
+	case MSMFB_OVERLAY_PLAY_ENABLE:
+		if (!copy_from_user(&val, argp, sizeof(val))) {
+			mfd->overlay_play_enable = val;
+		} else {
+			pr_err("OVERLAY_PLAY_ENABLE failed (%d)\n", ret);
+			ret = -EFAULT;
+		}
+		break;
+
+	case MSMFB_OVERLAY_PLAY:
+		if (mfd->overlay_play_enable) {
+			struct msmfb_overlay_data data;
+
+			ret = copy_from_user(&data, argp, sizeof(data));
+			if (!ret) {
+				ret = mdss_mdp_overlay_play(mfd, &data);
+				if (!IS_ERR_VALUE(ret))
+					mdss_fb_update_backlight(mfd);
+			}
+
+			if (ret) {
+				pr_err("OVERLAY_PLAY failed (%d)\n", ret);
+				ret = -EFAULT;
+			}
+		} else {
+			ret = 0;
+		}
+		break;
+
+	case MSMFB_OVERLAY_PLAY_WAIT:
+		if (mfd->overlay_play_enable) {
+			struct msmfb_overlay_data data;
+
+			ret = copy_from_user(&data, argp, sizeof(data));
+			if (!ret)
+				ret = mdss_mdp_overlay_play_wait(mfd, &data);
+
+			if (ret) {
+				pr_err("OVERLAY_PLAY_WAIT failed (%d)\n", ret);
+				ret = -EFAULT;
+			}
+		} else {
+			ret = 0;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
+{
+	mfd->on_fnc = mdss_mdp_ctl_on;
+	mfd->off_fnc = mdss_mdp_ctl_off;
+	mfd->hw_refresh = true;
+	mfd->lut_update = NULL;
+	mfd->do_histogram = NULL;
+	mfd->overlay_play_enable = true;
+	mfd->cursor_update = mdss_mdp_hw_cursor_update;
+	mfd->dma_fnc = mdss_mdp_overlay_pan_display;
+	mfd->ioctl_handler = mdss_mdp_overlay_ioctl_handler;
+	mfd->kickoff_fnc = mdss_mdp_overlay_kickoff;
+
+	return 0;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
new file mode 100644
index 0000000..b52cff5
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -0,0 +1,675 @@
+/* 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 <linux/bitmap.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+
+#include "mdss_mdp.h"
+
+#define SMP_MB_CNT (mdss_res->smp_mb_cnt)
+
+static DEFINE_MUTEX(mdss_mdp_sspp_lock);
+static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
+
+static struct mdss_mdp_pipe mdss_mdp_pipe_list[MDSS_MDP_MAX_SSPP];
+
+static u32 mdss_mdp_smp_mmb_reserve(unsigned long *smp, size_t n)
+{
+	u32 i, mmb;
+
+	/* reserve more blocks if needed, but can't free mmb at this point */
+	for (i = bitmap_weight(smp, SMP_MB_CNT); i < n; i++) {
+		if (bitmap_full(mdss_mdp_smp_mmb_pool, SMP_MB_CNT))
+			break;
+
+		mmb = find_first_zero_bit(mdss_mdp_smp_mmb_pool, SMP_MB_CNT);
+		set_bit(mmb, smp);
+		set_bit(mmb, mdss_mdp_smp_mmb_pool);
+	}
+	return i;
+}
+
+static void mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp)
+{
+	u32 mmb, off, data, s;
+
+	for_each_set_bit(mmb, smp, SMP_MB_CNT) {
+		off = (mmb / 3) * 4;
+		s = (mmb % 3) * 8;
+		data = MDSS_MDP_REG_READ(MDSS_MDP_REG_SMP_ALLOC_W0 + off);
+		data &= ~(0xFF << s);
+		data |= client_id << s;
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SMP_ALLOC_W0 + off, data);
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SMP_ALLOC_R0 + off, data);
+	}
+}
+
+static void mdss_mdp_smp_mmb_free(unsigned long *smp)
+{
+	if (!bitmap_empty(smp, SMP_MB_CNT)) {
+		mdss_mdp_smp_mmb_set(MDSS_MDP_SMP_CLIENT_UNUSED, smp);
+		bitmap_andnot(mdss_mdp_smp_mmb_pool, mdss_mdp_smp_mmb_pool,
+			      smp, SMP_MB_CNT);
+		bitmap_zero(smp, SMP_MB_CNT);
+	}
+}
+
+static void mdss_mdp_smp_free(struct mdss_mdp_pipe *pipe)
+{
+	mdss_mdp_smp_mmb_free(&pipe->smp[0]);
+	mdss_mdp_smp_mmb_free(&pipe->smp[1]);
+	mdss_mdp_smp_mmb_free(&pipe->smp[2]);
+}
+
+static int mdss_mdp_smp_reserve(struct mdss_mdp_pipe *pipe)
+{
+	u32 num_blks = 0, reserved = 0;
+	int i;
+
+	if ((pipe->src_planes.num_planes > 1) &&
+	    (pipe->type == MDSS_MDP_PIPE_TYPE_RGB))
+		return -EINVAL;
+
+	mutex_lock(&mdss_mdp_sspp_lock);
+	for (i = 0; i < pipe->src_planes.num_planes; i++) {
+		num_blks = DIV_ROUND_UP(2 * pipe->src_planes.ystride[i],
+					mdss_res->smp_mb_size);
+
+		pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
+				num_blks, pipe->num, i);
+		reserved = mdss_mdp_smp_mmb_reserve(&pipe->smp[i], num_blks);
+
+		if (reserved < num_blks)
+			break;
+	}
+
+	if (reserved < num_blks) {
+		pr_err("insufficient MMB blocks\n");
+		mdss_mdp_smp_free(pipe);
+		return -ENOMEM;
+	}
+	mutex_unlock(&mdss_mdp_sspp_lock);
+
+	return 0;
+}
+
+static int mdss_mdp_smp_alloc(struct mdss_mdp_pipe *pipe)
+{
+	u32 client_id;
+	int i;
+
+	switch (pipe->num) {
+	case MDSS_MDP_SSPP_VIG0:
+		client_id = MDSS_MDP_SMP_CLIENT_VIG0_FETCH_Y;
+		break;
+	case MDSS_MDP_SSPP_VIG1:
+		client_id = MDSS_MDP_SMP_CLIENT_VIG1_FETCH_Y;
+		break;
+	case MDSS_MDP_SSPP_VIG2:
+		client_id = MDSS_MDP_SMP_CLIENT_VIG2_FETCH_Y;
+		break;
+	case MDSS_MDP_SSPP_RGB0:
+		client_id = MDSS_MDP_SMP_CLIENT_RGB0_FETCH;
+		break;
+	case MDSS_MDP_SSPP_RGB1:
+		client_id = MDSS_MDP_SMP_CLIENT_RGB1_FETCH;
+		break;
+	case MDSS_MDP_SSPP_RGB2:
+		client_id = MDSS_MDP_SMP_CLIENT_RGB2_FETCH;
+		break;
+	case MDSS_MDP_SSPP_DMA0:
+		client_id = MDSS_MDP_SMP_CLIENT_DMA0_FETCH_Y;
+		break;
+	case MDSS_MDP_SSPP_DMA1:
+		client_id = MDSS_MDP_SMP_CLIENT_DMA1_FETCH_Y;
+		break;
+	default:
+		pr_err("no valid smp client for pnum=%d\n", pipe->num);
+		return -EINVAL;
+	}
+
+	mutex_lock(&mdss_mdp_sspp_lock);
+	for (i = 0; i < pipe->src_planes.num_planes; i++)
+		mdss_mdp_smp_mmb_set(client_id + i, &pipe->smp[i]);
+	mutex_unlock(&mdss_mdp_sspp_lock);
+	return 0;
+}
+
+void mdss_mdp_pipe_unlock(struct mdss_mdp_pipe *pipe)
+{
+	atomic_dec(&pipe->ref_cnt);
+	mutex_unlock(&pipe->lock);
+}
+
+int mdss_mdp_pipe_lock(struct mdss_mdp_pipe *pipe)
+{
+	if (atomic_inc_not_zero(&pipe->ref_cnt)) {
+		if (mutex_lock_interruptible(&pipe->lock)) {
+			atomic_dec(&pipe->ref_cnt);
+			return -EINTR;
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static struct mdss_mdp_pipe *mdss_mdp_pipe_init(u32 pnum)
+{
+	struct mdss_mdp_pipe *pipe = NULL;
+
+	if (atomic_read(&mdss_mdp_pipe_list[pnum].ref_cnt) == 0) {
+		pipe = &mdss_mdp_pipe_list[pnum];
+		memset(pipe, 0, sizeof(*pipe));
+
+		mutex_init(&pipe->lock);
+		atomic_set(&pipe->ref_cnt, 1);
+
+		if (mdss_mdp_pipe_lock(pipe) == 0) {
+			pipe->num = pnum;
+			pipe->type = mdss_res->pipe_type_map[pnum];
+			pipe->ndx = BIT(pnum);
+
+			pr_debug("ndx=%x pnum=%d\n", pipe->ndx, pipe->num);
+		} else {
+			atomic_set(&pipe->ref_cnt, 0);
+			pipe = NULL;
+		}
+	}
+	return pipe;
+}
+
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum)
+{
+	struct mdss_mdp_pipe *pipe = NULL;
+	mutex_lock(&mdss_mdp_sspp_lock);
+	if (mdss_res->pipe_type_map[pnum] != MDSS_MDP_PIPE_TYPE_UNUSED)
+		pipe = mdss_mdp_pipe_init(pnum);
+	mutex_unlock(&mdss_mdp_sspp_lock);
+	return pipe;
+}
+
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type)
+{
+	struct mdss_mdp_pipe *pipe = NULL;
+	int pnum;
+
+	mutex_lock(&mdss_mdp_sspp_lock);
+	for (pnum = 0; pnum < MDSS_MDP_MAX_SSPP; pnum++) {
+		if (type == mdss_res->pipe_type_map[pnum]) {
+			pipe = mdss_mdp_pipe_init(pnum);
+			if (pipe)
+				break;
+		}
+	}
+	mutex_unlock(&mdss_mdp_sspp_lock);
+
+	return pipe;
+}
+
+struct mdss_mdp_pipe *mdss_mdp_pipe_get_locked(u32 ndx)
+{
+	struct mdss_mdp_pipe *pipe = NULL;
+	int i;
+
+	if (!ndx)
+		return NULL;
+
+	mutex_lock(&mdss_mdp_sspp_lock);
+	for (i = 0; i < MDSS_MDP_MAX_SSPP; i++) {
+		pipe = &mdss_mdp_pipe_list[i];
+		if (ndx == pipe->ndx)
+			break;
+	}
+	mutex_unlock(&mdss_mdp_sspp_lock);
+
+	if (i == MDSS_MDP_MAX_SSPP)
+		return NULL;
+
+	if (mdss_mdp_pipe_lock(pipe))
+		return NULL;
+
+	if (pipe->ndx != ndx) {
+		mdss_mdp_pipe_unlock(pipe);
+		pipe = NULL;
+	}
+
+	return pipe;
+}
+
+
+static void mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe)
+{
+	mdss_mdp_smp_free(pipe);
+	pipe->ndx = 0;
+	atomic_dec(&pipe->ref_cnt);
+	mdss_mdp_pipe_unlock(pipe);
+}
+
+int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe)
+{
+	pr_debug("ndx=%x pnum=%d ref_cnt=%d\n", pipe->ndx, pipe->num,
+			atomic_read(&pipe->ref_cnt));
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	mutex_lock(&mdss_mdp_sspp_lock);
+	mdss_mdp_pipe_free(pipe);
+	mutex_unlock(&mdss_mdp_sspp_lock);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	return 0;
+}
+
+int mdss_mdp_pipe_release_all(struct msm_fb_data_type *mfd)
+{
+	struct mdss_mdp_pipe *pipe;
+	int i;
+
+	if (!mfd)
+		return -ENODEV;
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	mutex_lock(&mdss_mdp_sspp_lock);
+	for (i = 0; i < MDSS_MDP_MAX_SSPP; i++) {
+		pipe = &mdss_mdp_pipe_list[i];
+		if (atomic_read(&pipe->ref_cnt) && pipe->mfd == mfd) {
+			pr_debug("release pnum=%d\n", pipe->num);
+			if (mdss_mdp_pipe_lock(pipe) == 0) {
+				mdss_mdp_mixer_pipe_unstage(pipe);
+				mdss_mdp_pipe_free(pipe);
+			} else {
+				pr_err("unable to lock pipe=%d for release",
+				       pipe->num);
+			}
+		}
+	}
+	mutex_unlock(&mdss_mdp_sspp_lock);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	return 0;
+}
+
+static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
+				       u32 reg, u32 val)
+{
+	int offset = MDSS_MDP_REG_SSPP_OFFSET(pipe->num);
+	MDSS_MDP_REG_WRITE(offset + reg, val);
+}
+
+static inline u32 mdss_mdp_pipe_read(struct mdss_mdp_pipe *pipe, u32 reg)
+{
+	int offset = MDSS_MDP_REG_SSPP_OFFSET(pipe->num);
+	return MDSS_MDP_REG_READ(offset + reg);
+}
+
+static int mdss_mdp_leading_zero(u32 num)
+{
+	u32 bit = 0x80000000;
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		if (bit & num)
+			return i;
+		bit >>= 1;
+	}
+
+	return i;
+}
+
+static u32 mdss_mdp_scale_phase_step(int f_num, u32 src, u32 dst)
+{
+	u32 val, s;
+	int n;
+
+	n = mdss_mdp_leading_zero(src);
+	if (n > f_num)
+		n = f_num;
+	s = src << n;	/* maximum to reduce lose of resolution */
+	val = s / dst;
+	if (n < f_num) {
+		n = f_num - n;
+		val <<= n;
+		val |= ((s % dst) << n) / dst;
+	}
+
+	return val;
+}
+
+static int mdss_mdp_scale_setup(struct mdss_mdp_pipe *pipe)
+{
+	u32 scale_config = 0;
+	u32 phasex_step = 0, phasey_step = 0;
+	u32 chroma_sample;
+
+	if (pipe->type == MDSS_MDP_PIPE_TYPE_DMA) {
+		if (!(pipe->flags & MDP_ROT_90) && (pipe->dst.h != pipe->src.h
+						|| pipe->dst.w != pipe->src.w))
+			return -EINVAL;	/* no scaling supported on dma pipes */
+		else
+			return 0;
+	}
+
+	chroma_sample = pipe->src_fmt->chroma_sample;
+
+	if ((pipe->src.h != pipe->dst.h) ||
+	    (chroma_sample == MDSS_MDP_CHROMA_420) ||
+	    (chroma_sample == MDSS_MDP_CHROMA_H1V2)) {
+		pr_debug("scale y - src_h=%d dst_h=%d\n",
+				pipe->src.h, pipe->dst.h);
+
+		if ((pipe->src.h / MAX_DOWNSCALE_RATIO) > pipe->dst.h) {
+			pr_err("too much downscaling height=%d->%d",
+			       pipe->src.h, pipe->dst.h);
+			return -EINVAL;
+		}
+
+		scale_config |= MDSS_MDP_SCALEY_EN;
+
+		if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
+			u32 chr_dst_h = pipe->dst.h;
+			if ((chroma_sample == MDSS_MDP_CHROMA_420) ||
+			    (chroma_sample == MDSS_MDP_CHROMA_H1V2))
+				chr_dst_h *= 2;	/* 2x upsample chroma */
+
+			if (pipe->src.h <= pipe->dst.h)
+				scale_config |= /* G/Y, A */
+					(MDSS_MDP_SCALE_FILTER_BIL << 10) |
+					(MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+			else
+				scale_config |= /* G/Y, A */
+					(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
+					(MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+
+			if (pipe->src.h <= chr_dst_h)
+				scale_config |= /* CrCb */
+					(MDSS_MDP_SCALE_FILTER_BIL << 14);
+			else
+				scale_config |= /* CrCb */
+					(MDSS_MDP_SCALE_FILTER_PCMN << 14);
+
+			phasey_step = mdss_mdp_scale_phase_step(
+				PHASE_STEP_SHIFT, pipe->src.h, chr_dst_h);
+
+			mdss_mdp_pipe_write(pipe,
+					MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPY,
+					phasey_step);
+		} else {
+			if (pipe->src.h <= pipe->dst.h)
+				scale_config |= /* RGB, A */
+					(MDSS_MDP_SCALE_FILTER_BIL << 10) |
+					(MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+			else
+				scale_config |= /* RGB, A */
+					(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
+					(MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+		}
+
+		phasey_step = mdss_mdp_scale_phase_step(
+			PHASE_STEP_SHIFT, pipe->src.h, pipe->dst.h);
+	}
+
+	if ((pipe->src.w != pipe->dst.w) ||
+	    (chroma_sample == MDSS_MDP_CHROMA_420) ||
+	    (chroma_sample == MDSS_MDP_CHROMA_H2V1)) {
+		pr_debug("scale x - src_w=%d dst_w=%d\n",
+				pipe->src.w, pipe->dst.w);
+
+		if ((pipe->src.w / MAX_DOWNSCALE_RATIO) > pipe->dst.w) {
+			pr_err("too much downscaling width=%d->%d",
+			       pipe->src.w, pipe->dst.w);
+			return -EINVAL;
+		}
+
+		scale_config |= MDSS_MDP_SCALEX_EN;
+
+		if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
+			u32 chr_dst_w = pipe->dst.w;
+
+			if ((chroma_sample == MDSS_MDP_CHROMA_420) ||
+			    (chroma_sample == MDSS_MDP_CHROMA_H2V1))
+				chr_dst_w *= 2;	/* 2x upsample chroma */
+
+			if (pipe->src.w <= pipe->dst.w)
+				scale_config |= /* G/Y, A */
+					(MDSS_MDP_SCALE_FILTER_BIL << 8) |
+					(MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+			else
+				scale_config |= /* G/Y, A */
+					(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
+					(MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+
+			if (pipe->src.w <= chr_dst_w)
+				scale_config |= /* CrCb */
+					(MDSS_MDP_SCALE_FILTER_BIL << 12);
+			else
+				scale_config |= /* CrCb */
+					(MDSS_MDP_SCALE_FILTER_PCMN << 12);
+
+			phasex_step = mdss_mdp_scale_phase_step(
+				PHASE_STEP_SHIFT, pipe->src.w, chr_dst_w);
+			mdss_mdp_pipe_write(pipe,
+					MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPX,
+					phasex_step);
+		} else {
+			if (pipe->src.w <= pipe->dst.w)
+				scale_config |= /* RGB, A */
+					(MDSS_MDP_SCALE_FILTER_BIL << 8) |
+					(MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+			else
+				scale_config |= /* RGB, A */
+					(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
+					(MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+		}
+
+		phasex_step = mdss_mdp_scale_phase_step(
+			PHASE_STEP_SHIFT, pipe->src.w, pipe->dst.w);
+	}
+
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SCALE_CONFIG, scale_config);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SCALE_PHASE_STEP_X, phasex_step);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SCALE_PHASE_STEP_Y, phasey_step);
+	return 0;
+}
+
+static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe)
+{
+	u32 img_size, src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
+
+	pr_debug("pnum=%d wh=%dx%d src={%d,%d,%d,%d} dst={%d,%d,%d,%d}\n",
+		   pipe->num, pipe->img_width, pipe->img_height,
+		   pipe->src.x, pipe->src.y, pipe->src.w, pipe->src.h,
+		   pipe->dst.x, pipe->dst.y, pipe->dst.w, pipe->dst.h);
+
+	if (mdss_mdp_scale_setup(pipe))
+		return -EINVAL;
+
+	mdss_mdp_get_plane_sizes(pipe->src_fmt->format, pipe->img_width,
+				 pipe->img_height, &pipe->src_planes);
+
+	img_size = (pipe->img_height << 16) | pipe->img_width;
+	src_size = (pipe->src.h << 16) | pipe->src.w;
+	src_xy = (pipe->src.y << 16) | pipe->src.x;
+	dst_size = (pipe->dst.h << 16) | pipe->dst.w;
+	dst_xy = (pipe->dst.y << 16) | pipe->dst.x;
+	ystride0 =  (pipe->src_planes.ystride[0]) |
+		    (pipe->src_planes.ystride[1] << 16);
+	ystride1 =  (pipe->src_planes.ystride[2]) |
+		    (pipe->src_planes.ystride[3] << 16);
+
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_IMG_SIZE, img_size);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_SIZE, src_size);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_XY, src_xy);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_OUT_SIZE, dst_size);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_OUT_XY, dst_xy);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_YSTRIDE0, ystride0);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_YSTRIDE1, ystride1);
+
+	return 0;
+}
+
+static int mdss_mdp_format_setup(struct mdss_mdp_pipe *pipe)
+{
+	struct mdss_mdp_format_params *fmt;
+	u32 rot90, opmode, chroma_samp;
+
+	fmt = pipe->src_fmt;
+
+	opmode = pipe->bwc_mode;
+	if (pipe->flags & MDP_FLIP_LR)
+		opmode |= MDSS_MDP_OP_FLIP_LR;
+	if (pipe->flags & MDP_FLIP_UD)
+		opmode |= MDSS_MDP_OP_FLIP_UD;
+
+	pr_debug("pnum=%d format=%d opmode=%x\n", pipe->num, fmt->format,
+			opmode);
+
+	rot90 = !!(pipe->flags & MDP_SOURCE_ROTATED_90);
+
+	chroma_samp = fmt->chroma_sample;
+	if (rot90) {
+		if (chroma_samp == MDSS_MDP_CHROMA_H2V1)
+			chroma_samp = MDSS_MDP_CHROMA_H1V2;
+		else if (chroma_samp == MDSS_MDP_CHROMA_H1V2)
+			chroma_samp = MDSS_MDP_CHROMA_H2V1;
+	}
+
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT,
+			    (chroma_samp << 23) |
+			    (fmt->fetch_planes << 19) |
+			    (fmt->unpack_align_msb << 18) |
+			    (fmt->unpack_tight << 17) |
+			    (fmt->unpack_count << 12) |
+			    (rot90 << 11) |
+			    (fmt->bpp << 9) |
+			    (fmt->alpha_enable << 8) |
+			    (fmt->a_bit << 6) |
+			    (fmt->r_bit << 4) |
+			    (fmt->b_bit << 2) |
+			    (fmt->g_bit << 0));
+
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN,
+			    (fmt->element3 << 24) |
+			    (fmt->element2 << 16) |
+			    (fmt->element1 << 8) |
+			    (fmt->element0 << 0));
+
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_OP_MODE, opmode);
+
+	return 0;
+}
+
+static int mdss_mdp_vig_setup(struct mdss_mdp_pipe *pipe)
+{
+	u32 opmode = 0;
+
+	pr_debug("pnum=%x\n", pipe->num);
+
+	if (pipe->src_fmt->is_yuv)
+		opmode |= (0 << 19) |	/* DST_DATA=RGB */
+			  (1 << 18) |	/* SRC_DATA=YCBCR */
+			  (1 << 17);	/* CSC_1_EN */
+
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE, opmode);
+
+	return 0;
+}
+
+static int mdss_mdp_src_addr_setup(struct mdss_mdp_pipe *pipe,
+				   struct mdss_mdp_data *data)
+{
+	int ret;
+
+	pr_debug("pnum=%d\n", pipe->num);
+
+	if (pipe->type != MDSS_MDP_PIPE_TYPE_DMA)
+		data->bwc_enabled = pipe->bwc_mode;
+
+	ret = mdss_mdp_data_check(data, &pipe->src_planes);
+	if (ret)
+		return ret;
+
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC0_ADDR, data->p[0].addr);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC1_ADDR, data->p[1].addr);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC2_ADDR, data->p[2].addr);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC3_ADDR, data->p[3].addr);
+
+	return 0;
+}
+
+int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
+			     struct mdss_mdp_data *src_data)
+{
+	int ret = 0;
+	u32 params_changed;
+
+	if (!pipe) {
+		pr_err("pipe not setup properly for queue\n");
+		return -ENODEV;
+	}
+
+	if (!pipe->mixer) {
+		pr_err("pipe mixer not setup properly for queue\n");
+		return -ENODEV;
+	}
+
+	pr_debug("pnum=%x mixer=%d\n", pipe->num, pipe->mixer->num);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	params_changed = pipe->params_changed;
+	if (params_changed) {
+		pipe->params_changed = 0;
+
+		ret = mdss_mdp_image_setup(pipe);
+		if (ret) {
+			pr_err("image setup error for pnum=%d\n", pipe->num);
+			goto done;
+		}
+
+		ret = mdss_mdp_format_setup(pipe);
+		if (ret) {
+			pr_err("format %d setup error pnum=%d\n",
+			       pipe->src_fmt->format, pipe->num);
+			goto done;
+		}
+
+		if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
+			mdss_mdp_vig_setup(pipe);
+
+		ret = mdss_mdp_smp_reserve(pipe);
+		if (ret) {
+			pr_err("unable to reserve smp for pnum=%d\n",
+			       pipe->num);
+			goto done;
+		}
+
+		mdss_mdp_smp_alloc(pipe);
+	}
+
+	ret = mdss_mdp_src_addr_setup(pipe, src_data);
+	if (ret) {
+		pr_err("addr setup error for pnum=%d\n", pipe->num);
+		goto done;
+	}
+
+	mdss_mdp_mixer_pipe_update(pipe, params_changed);
+
+	pipe->play_cnt++;
+
+done:
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
new file mode 100644
index 0000000..25c9ac4
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -0,0 +1,349 @@
+/* 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 <linux/android_pmem.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/ion.h>
+#include <linux/msm_kgsl.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include "mdss_fb.h"
+#include "mdss_mdp.h"
+#include "mdss_mdp_formats.h"
+
+enum {
+	MDP_INTR_VSYNC_INTF_0,
+	MDP_INTR_VSYNC_INTF_1,
+	MDP_INTR_VSYNC_INTF_2,
+	MDP_INTR_VSYNC_INTF_3,
+	MDP_INTR_PING_PONG_0,
+	MDP_INTR_PING_PONG_1,
+	MDP_INTR_PING_PONG_2,
+	MDP_INTR_WB_0,
+	MDP_INTR_WB_1,
+	MDP_INTR_WB_2,
+	MDP_INTR_MAX,
+};
+
+struct intr_callback {
+	void (*func)(void *);
+	void *arg;
+};
+
+struct intr_callback mdp_intr_cb[MDP_INTR_MAX];
+static DEFINE_SPINLOCK(mdss_mdp_intr_lock);
+
+static int mdss_mdp_intr2index(u32 intr_type, u32 intf_num)
+{
+	int index = -1;
+	switch (intr_type) {
+	case MDSS_MDP_IRQ_INTF_VSYNC:
+		index = MDP_INTR_VSYNC_INTF_0 + intf_num;
+		break;
+	case MDSS_MDP_IRQ_PING_PONG_COMP:
+		index = MDP_INTR_PING_PONG_0 + intf_num;
+		break;
+	case MDSS_MDP_IRQ_WB_ROT_COMP:
+		index = MDP_INTR_WB_0 + intf_num;
+		break;
+	case MDSS_MDP_IRQ_WB_WFD:
+		index = MDP_INTR_WB_2 + intf_num;
+		break;
+	}
+
+	return index;
+}
+
+int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num,
+			       void (*fnc_ptr)(void *), void *arg)
+{
+	unsigned long flags;
+	int index, ret;
+
+	index = mdss_mdp_intr2index(intr_type, intf_num);
+	if (index < 0) {
+		pr_warn("invalid intr type=%u intf_num=%u\n",
+				intr_type, intf_num);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&mdss_mdp_intr_lock, flags);
+	if (!mdp_intr_cb[index].func) {
+		mdp_intr_cb[index].func = fnc_ptr;
+		mdp_intr_cb[index].arg = arg;
+		ret = 0;
+	} else {
+		ret = -EBUSY;
+	}
+	spin_unlock_irqrestore(&mdss_mdp_intr_lock, flags);
+
+	return ret;
+}
+
+static inline void mdss_mdp_intr_done(int index)
+{
+	void (*fnc)(void *);
+	void *arg;
+
+	spin_lock(&mdss_mdp_intr_lock);
+	fnc = mdp_intr_cb[index].func;
+	arg = mdp_intr_cb[index].arg;
+	if (fnc != NULL)
+		mdp_intr_cb[index].func = NULL;
+	spin_unlock(&mdss_mdp_intr_lock);
+	if (fnc)
+		fnc(arg);
+}
+
+irqreturn_t mdss_mdp_isr(int irq, void *ptr)
+{
+	u32 isr, mask;
+
+
+	isr = MDSS_MDP_REG_READ(MDSS_MDP_REG_INTR_STATUS);
+	if (isr == 0)
+		goto done;
+
+	pr_devel("isr=%x\n", isr);
+
+	mask = MDSS_MDP_REG_READ(MDSS_MDP_REG_INTR_EN);
+	MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_CLEAR, isr);
+
+	isr &= mask;
+	if (isr == 0)
+		goto done;
+
+	if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE)
+		mdss_mdp_intr_done(MDP_INTR_PING_PONG_0);
+
+	if (isr & MDSS_MDP_INTR_PING_PONG_1_DONE)
+		mdss_mdp_intr_done(MDP_INTR_PING_PONG_1);
+
+	if (isr & MDSS_MDP_INTR_PING_PONG_2_DONE)
+		mdss_mdp_intr_done(MDP_INTR_PING_PONG_2);
+
+	if (isr & MDSS_MDP_INTR_INTF_0_VSYNC)
+		mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_0);
+
+	if (isr & MDSS_MDP_INTR_INTF_1_VSYNC)
+		mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_1);
+
+	if (isr & MDSS_MDP_INTR_INTF_2_VSYNC)
+		mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_2);
+
+	if (isr & MDSS_MDP_INTR_INTF_3_VSYNC)
+		mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_3);
+
+	if (isr & MDSS_MDP_INTR_WB_0_DONE)
+		mdss_mdp_intr_done(MDP_INTR_WB_0);
+
+	if (isr & MDSS_MDP_INTR_WB_1_DONE)
+		mdss_mdp_intr_done(MDP_INTR_WB_1);
+
+	if (isr & MDSS_MDP_INTR_WB_2_DONE)
+		mdss_mdp_intr_done(MDP_INTR_WB_2);
+
+done:
+	return IRQ_HANDLED;
+}
+
+struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format)
+{
+	struct mdss_mdp_format_params *fmt = NULL;
+	if (format < MDP_IMGTYPE_LIMIT) {
+		fmt = &mdss_mdp_format_map[format];
+		if (fmt->format != format)
+			fmt = NULL;
+	}
+
+	return fmt;
+}
+
+int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h,
+			     struct mdss_mdp_plane_sizes *ps)
+{
+	struct mdss_mdp_format_params *fmt;
+	int i;
+
+	if (ps == NULL)
+		return -EINVAL;
+
+	if ((w > MAX_IMG_WIDTH) || (h > MAX_IMG_HEIGHT))
+		return -ERANGE;
+
+	fmt = mdss_mdp_get_format_params(format);
+	if (!fmt)
+		return -EINVAL;
+
+	memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes));
+
+	if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
+		u32 bpp = fmt->bpp + 1;
+		ps->num_planes = 1;
+		ps->plane_size[0] = w * h * bpp;
+		ps->ystride[0] = w * bpp;
+	} else {
+		u8 hmap[] = { 1, 2, 1, 2 };
+		u8 vmap[] = { 1, 1, 2, 2 };
+		u8 horiz, vert;
+
+		horiz = hmap[fmt->chroma_sample];
+		vert = vmap[fmt->chroma_sample];
+
+		if (format == MDP_Y_CR_CB_GH2V2) {
+			ps->plane_size[0] = ALIGN(w, 16) * h;
+			ps->plane_size[1] = ALIGN(w / horiz, 16) * (h / vert);
+			ps->ystride[0] = ALIGN(w, 16);
+			ps->ystride[1] = ALIGN(w / horiz, 16);
+		} else {
+			ps->plane_size[0] = w * h;
+			ps->plane_size[1] = (w / horiz) * (h / vert);
+			ps->ystride[0] = w;
+			ps->ystride[1] = (w / horiz);
+		}
+
+		if (fmt->fetch_planes == MDSS_MDP_PLANE_PSEUDO_PLANAR) {
+			ps->num_planes = 2;
+			ps->plane_size[1] *= 2;
+			ps->ystride[1] *= 2;
+		} else { /* planar */
+			ps->num_planes = 3;
+			ps->plane_size[2] = ps->plane_size[1];
+			ps->ystride[2] = ps->ystride[1];
+		}
+	}
+
+	for (i = 0; i < ps->num_planes; i++)
+		ps->total_size += ps->plane_size[i];
+
+	return 0;
+}
+
+int mdss_mdp_data_check(struct mdss_mdp_data *data,
+			struct mdss_mdp_plane_sizes *ps)
+{
+	if (!ps)
+		return 0;
+
+	if (!data || data->num_planes == 0)
+		return -ENOMEM;
+
+	if (data->bwc_enabled) {
+		return -EPERM; /* not supported */
+	} else {
+		struct mdss_mdp_img_data *prev, *curr;
+		int i;
+
+		pr_debug("srcp0=%x len=%u frame_size=%u\n", data->p[0].addr,
+				data->p[0].len, ps->total_size);
+
+		for (i = 0; i < ps->num_planes; i++) {
+			curr = &data->p[i];
+			if (i >= data->num_planes) {
+				u32 psize = ps->plane_size[i-1];
+				prev = &data->p[i-1];
+				if (prev->len > psize) {
+					curr->len = prev->len - psize;
+					prev->len = psize;
+				}
+				curr->addr = prev->addr + psize;
+			}
+			if (curr->len < ps->plane_size[i]) {
+				pr_err("insufficient mem=%u p=%d len=%u\n",
+				       curr->len, i, ps->plane_size[i]);
+				return -ENOMEM;
+			}
+			pr_debug("plane[%d] addr=%x len=%u\n", i,
+					curr->addr, curr->len);
+		}
+		data->num_planes = ps->num_planes;
+	}
+
+	return 0;
+}
+
+int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
+{
+	/* only source may use frame buffer */
+	if (data->flags & MDP_MEMORY_ID_TYPE_FB) {
+		fput_light(data->srcp_file, data->p_need);
+		return 0;
+	}
+	if (data->srcp_file) {
+		put_pmem_file(data->srcp_file);
+		data->srcp_file = NULL;
+		return 0;
+	}
+	if (!IS_ERR_OR_NULL(data->srcp_ihdl)) {
+		ion_free(data->iclient, data->srcp_ihdl);
+		data->iclient = NULL;
+		data->srcp_ihdl = NULL;
+		return 0;
+	}
+
+	return -ENOMEM;
+}
+
+int mdss_mdp_get_img(struct ion_client *iclient, struct msmfb_data *img,
+		     struct mdss_mdp_img_data *data)
+{
+	struct file *file;
+	int ret = -EINVAL;
+	int fb_num;
+	unsigned long *start, *len;
+
+	start = (unsigned long *) &data->addr;
+	len = (unsigned long *) &data->len;
+	data->flags = img->flags;
+	data->p_need = 0;
+
+	if (img->flags & MDP_BLIT_SRC_GEM) {
+		data->srcp_file = NULL;
+		ret = kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
+					start, len);
+	} else if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
+		file = fget_light(img->memory_id, &data->p_need);
+		if (file && FB_MAJOR ==
+				MAJOR(file->f_dentry->d_inode->i_rdev)) {
+			data->srcp_file = file;
+			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+			ret = mdss_fb_get_phys_info(start, len, fb_num);
+		}
+	} else if (iclient) {
+		data->iclient = iclient;
+		data->srcp_ihdl = ion_import_fd(iclient, img->memory_id);
+		if (IS_ERR_OR_NULL(data->srcp_ihdl))
+			return PTR_ERR(data->srcp_ihdl);
+		ret = ion_phys(iclient, data->srcp_ihdl,
+			       start, (size_t *) len);
+	} else {
+		unsigned long vstart;
+		ret = get_pmem_file(img->memory_id, start, &vstart, len,
+				    &data->srcp_file);
+	}
+
+	if (!ret && (img->offset < data->len)) {
+		data->addr += img->offset;
+		data->len -= img->offset;
+	} else {
+		mdss_mdp_put_img(data);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
new file mode 100644
index 0000000..3fd943d
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -0,0 +1,176 @@
+/* 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
+ * 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 MDSS_PANEL_H
+#define MDSS_PANEL_H
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+/* panel id type */
+struct panel_id {
+	u16 id;
+	u16 type;
+};
+
+/* panel type list */
+#define NO_PANEL		0xffff	/* No Panel */
+#define MDDI_PANEL		1	/* MDDI */
+#define EBI2_PANEL		2	/* EBI2 */
+#define LCDC_PANEL		3	/* internal LCDC type */
+#define EXT_MDDI_PANEL		4	/* Ext.MDDI */
+#define TV_PANEL		5	/* TV */
+#define HDMI_PANEL		6	/* HDMI TV */
+#define DTV_PANEL		7	/* DTV */
+#define MIPI_VIDEO_PANEL	8	/* MIPI */
+#define MIPI_CMD_PANEL		9	/* MIPI */
+#define WRITEBACK_PANEL		10	/* Wifi display */
+#define LVDS_PANEL		11	/* LVDS */
+#define EDP_PANEL		12	/* LVDS */
+
+/* panel class */
+enum {
+	DISPLAY_LCD = 0,	/* lcd = ebi2/mddi */
+	DISPLAY_LCDC,		/* lcdc */
+	DISPLAY_TV,		/* TV Out */
+	DISPLAY_EXT_MDDI,	/* External MDDI */
+	DISPLAY_WRITEBACK,
+};
+
+/* panel device locaiton */
+enum {
+	DISPLAY_1 = 0,		/* attached as first device */
+	DISPLAY_2,		/* attached on second device */
+	DISPLAY_3,              /* attached on third writeback device */
+	MAX_PHYS_TARGET_NUM,
+};
+
+/* panel info type */
+struct lcd_panel_info {
+	u32 vsync_enable;
+	u32 refx100;
+	u32 v_back_porch;
+	u32 v_front_porch;
+	u32 v_pulse_width;
+	u32 hw_vsync_mode;
+	u32 vsync_notifier_period;
+	u32 rev;
+};
+
+struct lcdc_panel_info {
+	u32 h_back_porch;
+	u32 h_front_porch;
+	u32 h_pulse_width;
+	u32 v_back_porch;
+	u32 v_front_porch;
+	u32 v_pulse_width;
+	u32 border_clr;
+	u32 underflow_clr;
+	u32 hsync_skew;
+	/* Pad width */
+	u32 xres_pad;
+	/* Pad height */
+	u32 yres_pad;
+};
+
+struct mipi_panel_info {
+	char mode;		/* video/cmd */
+	char interleave_mode;
+	char crc_check;
+	char ecc_check;
+	char dst_format;	/* shared by video and command */
+	char data_lane0;
+	char data_lane1;
+	char data_lane2;
+	char data_lane3;
+	char dlane_swap;	/* data lane swap */
+	char rgb_swap;
+	char b_sel;
+	char g_sel;
+	char r_sel;
+	char rx_eot_ignore;
+	char tx_eot_append;
+	char t_clk_post; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
+	char t_clk_pre;  /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
+	char vc;	/* virtual channel */
+	struct mipi_dsi_phy_ctrl *dsi_phy_db;
+	/* video mode */
+	char pulse_mode_hsa_he;
+	char hfp_power_stop;
+	char hbp_power_stop;
+	char hsa_power_stop;
+	char eof_bllp_power_stop;
+	char bllp_power_stop;
+	char traffic_mode;
+	char frame_rate;
+	/* command mode */
+	char interleave_max;
+	char insert_dcs_cmd;
+	char wr_mem_continue;
+	char wr_mem_start;
+	char te_sel;
+	char stream;	/* 0 or 1 */
+	char mdp_trigger;
+	char dma_trigger;
+	u32 dsi_pclk_rate;
+	/* The packet-size should not bet changed */
+	char no_max_pkt_size;
+	/* Clock required during LP commands */
+	char force_clk_lane_hs;
+};
+
+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 mdss_panel_info {
+	u32 xres;
+	u32 yres;
+	u32 bpp;
+	u32 type;
+	u32 wait_cycle;
+	u32 pdest;
+	u32 bl_max;
+	u32 bl_min;
+	u32 fb_num;
+	u32 clk_rate;
+	u32 clk_min;
+	u32 clk_max;
+	u32 frame_count;
+	u32 is_3d_panel;
+	u32 out_format;
+
+	struct lcd_panel_info lcd;
+	struct lcdc_panel_info lcdc;
+	struct mipi_panel_info mipi;
+	struct lvds_panel_info lvds;
+};
+
+struct mdss_panel_data {
+	struct mdss_panel_info panel_info;
+	void (*set_backlight) (u32 bl_level);
+
+	/* function entry chain */
+	int (*on) (struct mdss_panel_data *pdata);
+	int (*off) (struct mdss_panel_data *pdata);
+};
+
+int mdss_register_panel(struct mdss_panel_data *pdata);
+#endif /* MDSS_PANEL_H */
diff --git a/drivers/video/msm/mdss/mdss_wb.c b/drivers/video/msm/mdss/mdss_wb.c
new file mode 100644
index 0000000..3be4525
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_wb.c
@@ -0,0 +1,111 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/msm_mdp.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+#include "mdss_panel.h"
+
+static int mdss_wb_on(struct mdss_panel_data *pdata)
+{
+	pr_debug("%s\n", __func__);
+	return 0;
+}
+
+static int mdss_wb_off(struct mdss_panel_data *pdata)
+{
+	pr_debug("%s\n", __func__);
+	return 0;
+}
+
+static int mdss_wb_parse_dt(struct platform_device *pdev,
+			    struct mdss_panel_data *pdata)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 res[2], tmp;
+	int rc;
+
+	rc = of_property_read_u32_array(np, "qcom,mdss_pan_res", res, 2);
+	pdata->panel_info.xres = (!rc ? res[0] : 1280);
+	pdata->panel_info.yres = (!rc ? res[1] : 720);
+
+	rc = of_property_read_u32(np, "qcom,mdss_pan_bpp", &tmp);
+	pdata->panel_info.bpp = (!rc ? tmp : 24);
+
+	return 0;
+}
+
+static int mdss_wb_probe(struct platform_device *pdev)
+{
+	struct mdss_panel_data *pdata = NULL;
+	int rc = 0;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	rc = !mdss_wb_parse_dt(pdev, pdata);
+	if (!rc)
+		return rc;
+
+	pdata->panel_info.type = WRITEBACK_PANEL;
+	pdata->panel_info.clk_rate = 74250000;
+	pdata->panel_info.pdest = DISPLAY_3;
+	pdata->panel_info.out_format = MDP_RGB_888;
+
+	pdata->on = mdss_wb_on;
+	pdata->off = mdss_wb_off;
+	pdev->dev.platform_data = pdata;
+
+	rc = mdss_register_panel(pdata);
+	if (rc) {
+		dev_err(&pdev->dev, "unable to register writeback panel\n");
+		return rc;
+	}
+
+	return rc;
+}
+
+static const struct of_device_id mdss_wb_match[] = {
+	{ .compatible = "qcom,mdss_wb", },
+	{ { 0 } }
+};
+
+static struct platform_driver mdss_wb_driver = {
+	.probe = mdss_wb_probe,
+	.driver = {
+		.name = "mdss_wb",
+		.of_match_table = mdss_wb_match,
+	},
+};
+
+static int __init mdss_wb_driver_init(void)
+{
+	int rc = 0;
+	rc = platform_driver_register(&mdss_wb_driver);
+	return rc;
+}
+
+module_init(mdss_wb_driver_init);
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
index 964df4e..e605aed 100644
--- a/drivers/video/msm/mipi_NT35510.c
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -19,6 +19,8 @@
 static struct dsi_buf nt35510_tx_buf;
 static struct dsi_buf nt35510_rx_buf;
 
+static int mipi_nt35510_bl_ctrl;
+
 #define NT35510_SLEEP_OFF_DELAY 150
 #define NT35510_DISPLAY_ON_DELAY 150
 
@@ -174,6 +176,9 @@
 static char cmd19[3] = {
 	0xB1, 0xEC, 0x00,
 };
+static char cmd19_rotate[3] = {
+	0xB1, 0xEC, 0x06,
+};
 static char cmd20[4] = {
 	0xBC, 0x05, 0x05, 0x05,
 };
@@ -246,6 +251,11 @@
 	{DTYPE_DCS_WRITE, 1, 0, 0, 10,	sizeof(write_ram), write_ram},
 };
 
+static struct dsi_cmd_desc nt35510_cmd_display_on_cmds_rotate[] = {
+	{DTYPE_DCS_LWRITE, 1, 0, 0, 50,
+		sizeof(cmd19_rotate), cmd19_rotate},
+};
+
 static char video0[6] = {
 	0xF0, 0x55, 0xAA, 0x52,
 	0x08, 0x01,
@@ -489,6 +499,12 @@
 		mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
 			nt35510_cmd_display_on_cmds,
 			ARRAY_SIZE(nt35510_cmd_display_on_cmds));
+
+		if (rotate) {
+			mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
+				nt35510_cmd_display_on_cmds_rotate,
+			ARRAY_SIZE(nt35510_cmd_display_on_cmds_rotate));
+		}
 	}
 
 	return 0;
@@ -514,8 +530,63 @@
 	return 0;
 }
 
+static ssize_t mipi_nt35510_wta_bl_ctrl(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	ssize_t ret = strnlen(buf, PAGE_SIZE);
+	int err;
+
+	err =  kstrtoint(buf, 0, &mipi_nt35510_bl_ctrl);
+	if (err)
+		return ret;
+
+	pr_info("%s: bl ctrl set to %d\n", __func__, mipi_nt35510_bl_ctrl);
+
+	return ret;
+}
+
+static DEVICE_ATTR(bl_ctrl, S_IWUSR, NULL, mipi_nt35510_wta_bl_ctrl);
+
+static struct attribute *mipi_nt35510_fs_attrs[] = {
+	&dev_attr_bl_ctrl.attr,
+	NULL,
+};
+
+static struct attribute_group mipi_nt35510_fs_attr_group = {
+	.attrs = mipi_nt35510_fs_attrs,
+};
+
+static int mipi_nt35510_create_sysfs(struct platform_device *pdev)
+{
+	int rc;
+	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+	if (!mfd) {
+		pr_err("%s: mfd not found\n", __func__);
+		return -ENODEV;
+	}
+	if (!mfd->fbi) {
+		pr_err("%s: mfd->fbi not found\n", __func__);
+		return -ENODEV;
+	}
+	if (!mfd->fbi->dev) {
+		pr_err("%s: mfd->fbi->dev not found\n", __func__);
+		return -ENODEV;
+	}
+	rc = sysfs_create_group(&mfd->fbi->dev->kobj,
+		&mipi_nt35510_fs_attr_group);
+	if (rc) {
+		pr_err("%s: sysfs group creation failed, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	return 0;
+}
+
 static int __devinit mipi_nt35510_lcd_probe(struct platform_device *pdev)
 {
+	struct platform_device *pthisdev = NULL;
 	pr_debug("%s\n", __func__);
 
 	if (pdev->id == 0) {
@@ -525,7 +596,8 @@
 		return 0;
 	}
 
-	msm_fb_add_device(pdev);
+	pthisdev = msm_fb_add_device(pdev);
+	mipi_nt35510_create_sysfs(pthisdev);
 
 	return 0;
 }
@@ -537,6 +609,8 @@
 	},
 };
 
+static int old_bl_level;
+
 static void mipi_nt35510_set_backlight(struct msm_fb_data_type *mfd)
 {
 	int bl_level;
@@ -544,11 +618,33 @@
 	bl_level = mfd->bl_level;
 
 	if (mipi_nt35510_pdata->bl_lock) {
-		spin_lock_irqsave(&mipi_nt35510_pdata->bl_spinlock, flags);
-		mipi_nt35510_pdata->pmic_backlight(bl_level);
-		spin_unlock_irqrestore(&mipi_nt35510_pdata->bl_spinlock, flags);
-	} else
-		mipi_nt35510_pdata->pmic_backlight(bl_level);
+		if (!mipi_nt35510_bl_ctrl) {
+			/* Level received is of range 1 to bl_max,
+			   We need to convert the levels to 1
+			   to 31 */
+			bl_level = (2 * bl_level * 31 + mfd->panel_info.bl_max)
+					/(2 * mfd->panel_info.bl_max);
+			if (bl_level == old_bl_level)
+				return;
+
+			if (bl_level == 0)
+				mipi_nt35510_pdata->backlight(0, 1);
+
+			if (old_bl_level == 0)
+				mipi_nt35510_pdata->backlight(50, 1);
+
+			spin_lock_irqsave(&mipi_nt35510_pdata->bl_spinlock,
+						flags);
+			mipi_nt35510_pdata->backlight(bl_level, 0);
+			spin_unlock_irqrestore(&mipi_nt35510_pdata->bl_spinlock,
+						flags);
+			old_bl_level = bl_level;
+		} else {
+			mipi_nt35510_pdata->backlight(bl_level, 1);
+		}
+	} else {
+		mipi_nt35510_pdata->backlight(bl_level, mipi_nt35510_bl_ctrl);
+	}
 }
 
 static struct msm_fb_panel_data nt35510_panel_data = {
diff --git a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
index f052e93..1524ce6 100644
--- a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
+++ b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
@@ -56,7 +56,7 @@
 	pinfo.lcdc.border_clr = 0;	/* blk */
 	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
 	pinfo.lcdc.hsync_skew = 0;
-	pinfo.bl_max = 31;
+	pinfo.bl_max = 255;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
index 4e97d99..8a364ba 100644
--- a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
+++ b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
@@ -59,7 +59,7 @@
 	delayed from VSYNC active edge */
 	pinfo.lcdc.hsync_skew = 0;
 	pinfo.clk_rate = 499000000;
-	pinfo.bl_max = 31;
+	pinfo.bl_max = 255;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c b/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c
index 7f5ac70..2ebfad4 100644
--- a/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c
+++ b/drivers/video/msm/mipi_renesas_cmd_fwvga_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
@@ -93,7 +93,7 @@
 	pinfo.lcdc.border_clr = 0;	/* blk */
 	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
 	pinfo.lcdc.hsync_skew = 0;
-	pinfo.bl_max = 100;
+	pinfo.bl_max = 255;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/mipi_renesas_video_fwvga_pt.c b/drivers/video/msm/mipi_renesas_video_fwvga_pt.c
index e826773..144d9ff 100644
--- a/drivers/video/msm/mipi_renesas_video_fwvga_pt.c
+++ b/drivers/video/msm/mipi_renesas_video_fwvga_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
@@ -105,7 +105,7 @@
 	pinfo.lcdc.border_clr = 0;	/* blk */
 	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
 	pinfo.lcdc.hsync_skew = 0;
-	pinfo.bl_max = 100;
+	pinfo.bl_max = 255;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/mipi_tc358764_dsi2lvds.c b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
index f7f353f..2e65c34 100644
--- a/drivers/video/msm/mipi_tc358764_dsi2lvds.c
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
@@ -574,7 +574,8 @@
 	mipi_d2l_enable_3d(mfd, false, false);
 
 	/* Add I2C driver only after DSI-CLK is running */
-	i2c_add_driver(&d2l_i2c_slave_driver);
+	if (d2l_i2c_client == NULL)
+		i2c_add_driver(&d2l_i2c_slave_driver);
 
 	pr_info("%s.ret=%d.\n", __func__, ret);
 
@@ -989,6 +990,8 @@
 {
 	pr_debug("%s.\n", __func__);
 
+	d2l_i2c_client = NULL;
+
 	return platform_driver_register(&d2l_driver);
 }
 
diff --git a/drivers/video/msm/mipi_toshiba.h b/drivers/video/msm/mipi_toshiba.h
index 4107161..dd446b9 100644
--- a/drivers/video/msm/mipi_toshiba.h
+++ b/drivers/video/msm/mipi_toshiba.h
@@ -21,7 +21,7 @@
 int mipi_toshiba_device_register(struct msm_panel_info *pinfo,
 					u32 channel, u32 panel);
 
-#define MIPI_TOSHIBA_PWM_FREQ_HZ 3921
+#define MIPI_TOSHIBA_PWM_FREQ_HZ 300
 #define MIPI_TOSHIBA_PWM_PERIOD_USEC (USEC_PER_SEC / MIPI_TOSHIBA_PWM_FREQ_HZ)
 #define MIPI_TOSHIBA_PWM_LEVEL 255
 #define MIPI_TOSHIBA_PWM_DUTY_LEVEL \
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e.c b/drivers/video/msm/mipi_truly_tft540960_1_e.c
index e465d46..98b24b1 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e.c
@@ -19,6 +19,8 @@
 static struct dsi_buf truly_tx_buf;
 static struct dsi_buf truly_rx_buf;
 
+static int mipi_truly_bl_ctrl;
+
 #define TRULY_CMD_DELAY 0
 #define MIPI_SETTING_DELAY 10
 #define TRULY_SLEEP_OFF_DELAY 150
@@ -720,8 +722,64 @@
 	return 0;
 }
 
+static ssize_t mipi_truly_wta_bl_ctrl(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	ssize_t ret = strnlen(buf, PAGE_SIZE);
+	int err;
+
+	err =  kstrtoint(buf, 0, &mipi_truly_bl_ctrl);
+	if (err)
+		return ret;
+
+	pr_info("%s: bl ctrl set to %d\n", __func__, mipi_truly_bl_ctrl);
+
+	return ret;
+}
+
+static DEVICE_ATTR(bl_ctrl, S_IWUSR, NULL, mipi_truly_wta_bl_ctrl);
+
+static struct attribute *mipi_truly_fs_attrs[] = {
+	&dev_attr_bl_ctrl.attr,
+	NULL,
+};
+
+static struct attribute_group mipi_truly_fs_attr_group = {
+	.attrs = mipi_truly_fs_attrs,
+};
+
+static int mipi_truly_create_sysfs(struct platform_device *pdev)
+{
+	int rc;
+	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+	if (!mfd) {
+		pr_err("%s: mfd not found\n", __func__);
+		return -ENODEV;
+	}
+	if (!mfd->fbi) {
+		pr_err("%s: mfd->fbi not found\n", __func__);
+		return -ENODEV;
+	}
+	if (!mfd->fbi->dev) {
+		pr_err("%s: mfd->fbi->dev not found\n", __func__);
+		return -ENODEV;
+	}
+	rc = sysfs_create_group(&mfd->fbi->dev->kobj,
+		&mipi_truly_fs_attr_group);
+	if (rc) {
+		pr_err("%s: sysfs group creation failed, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+
 static int __devinit mipi_truly_lcd_probe(struct platform_device *pdev)
 {
+	struct platform_device *pthisdev = NULL;
 	int rc = 0;
 
 	if (pdev->id == 0) {
@@ -731,7 +789,8 @@
 		return rc;
 	}
 
-	msm_fb_add_device(pdev);
+	pthisdev = msm_fb_add_device(pdev);
+	mipi_truly_create_sysfs(pthisdev);
 
 	return rc;
 }
@@ -743,6 +802,8 @@
 	},
 };
 
+static int old_bl_level;
+
 static void mipi_truly_set_backlight(struct msm_fb_data_type *mfd)
 {
 	int bl_level;
@@ -750,11 +811,33 @@
 	bl_level = mfd->bl_level;
 
 	if (mipi_truly_pdata->bl_lock) {
-		spin_lock_irqsave(&mipi_truly_pdata->bl_spinlock, flags);
-		mipi_truly_pdata->pmic_backlight(bl_level);
-		spin_unlock_irqrestore(&mipi_truly_pdata->bl_spinlock, flags);
-	} else
-		mipi_truly_pdata->pmic_backlight(bl_level);
+		if (!mipi_truly_bl_ctrl) {
+			/* Level received is of range 1 to bl_max,
+			   We need to convert the levels to 1
+			   to 31 */
+			bl_level = (2 * bl_level * 31 + mfd->panel_info.bl_max)
+					/(2 * mfd->panel_info.bl_max);
+			if (bl_level == old_bl_level)
+				return;
+
+			if (bl_level == 0)
+				mipi_truly_pdata->backlight(0, 1);
+
+			if (old_bl_level == 0)
+				mipi_truly_pdata->backlight(50, 1);
+
+			spin_lock_irqsave(&mipi_truly_pdata->bl_spinlock,
+						flags);
+			mipi_truly_pdata->backlight(bl_level, 0);
+			spin_unlock_irqrestore(&mipi_truly_pdata->bl_spinlock,
+						flags);
+			old_bl_level = bl_level;
+		} else {
+			mipi_truly_pdata->backlight(bl_level, 1);
+		}
+	} else {
+		mipi_truly_pdata->backlight(bl_level, mipi_truly_bl_ctrl);
+	}
 }
 
 static struct msm_fb_panel_data truly_panel_data = {
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
index de98177..3423241 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
@@ -56,7 +56,7 @@
 	pinfo.lcdc.border_clr = 0;	/* blk */
 	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
 	pinfo.lcdc.hsync_skew = 0;
-	pinfo.bl_max = 31;
+	pinfo.bl_max = 255;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c b/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
index ea2ff47..3c0c0b7 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
@@ -59,7 +59,7 @@
 	pinfo.lcdc.hsync_skew = 0;
 	pinfo.clk_rate = 699000000;
 	pinfo.lcd.refx100 = 6000; /* FB driver calc FPS based on this value */
-	pinfo.bl_max = 31;
+	pinfo.bl_max = 255;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
index 70c8afc..682a45a 100644
--- a/drivers/video/msm/msm_dss_io_8960.c
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -747,7 +747,6 @@
 
 void hdmi_msm_reset_core(void)
 {
-	hdmi_msm_set_mode(FALSE);
 	hdmi_msm_clk(0);
 	udelay(5);
 	hdmi_msm_clk(1);
diff --git a/drivers/video/msm/msm_dss_io_8x60.c b/drivers/video/msm/msm_dss_io_8x60.c
index a1897e3..bb6f710 100644
--- a/drivers/video/msm/msm_dss_io_8x60.c
+++ b/drivers/video/msm/msm_dss_io_8x60.c
@@ -548,7 +548,6 @@
 
 void hdmi_msm_reset_core(void)
 {
-	hdmi_msm_set_mode(FALSE);
 	hdmi_msm_clk(0);
 	udelay(5);
 	hdmi_msm_clk(1);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index c9642c3..81a6e50 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -575,9 +575,6 @@
 				      mfd->op_enable);
 		if (ret)
 			MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
-	} else {
-		if (pdata->power_ctrl)
-			pdata->power_ctrl(TRUE);
 	}
 
 	return ret;
@@ -633,29 +630,49 @@
 static int msm_fb_ext_suspend(struct device *dev)
 {
 	struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
+	struct msm_fb_panel_data *pdata = NULL;
 	int ret = 0;
 
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
+	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
 	if (mfd->panel_info.type == HDMI_PANEL ||
-		mfd->panel_info.type == DTV_PANEL)
+		mfd->panel_info.type == DTV_PANEL) {
 		ret = msm_fb_suspend_sub(mfd);
 
+		/* Turn off the HPD circuitry */
+		if (pdata->power_ctrl) {
+			MSM_FB_INFO("%s: Turning off HPD circuitry\n",
+					__func__);
+			pdata->power_ctrl(FALSE);
+		}
+	}
+
 	return ret;
 }
 
 static int msm_fb_ext_resume(struct device *dev)
 {
 	struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
+	struct msm_fb_panel_data *pdata = NULL;
 	int ret = 0;
 
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
+	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
 	if (mfd->panel_info.type == HDMI_PANEL ||
-		mfd->panel_info.type == DTV_PANEL)
+		mfd->panel_info.type == DTV_PANEL) {
+		/* Turn on the HPD circuitry */
+		if (pdata->power_ctrl) {
+			pdata->power_ctrl(TRUE);
+			MSM_FB_INFO("%s: Turning on HPD circuitry\n",
+					__func__);
+		}
+
 		ret = msm_fb_resume_sub(mfd);
+	}
 
 	return ret;
 }
@@ -813,9 +830,6 @@
 				mfd->panel_power_on = curr_pwr_state;
 
 			mfd->op_enable = TRUE;
-		} else {
-			if (pdata->power_ctrl)
-				pdata->power_ctrl(FALSE);
 		}
 		break;
 	}
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 64d2976..6fd5656 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -791,7 +791,7 @@
 		sz_strm = DDL_ALIGN(ddl_get_yuv_buf_size(width, height,
 			DDL_YUV_BUF_TYPE_LINEAR) + ddl_get_yuv_buf_size(width,
 			height/2, DDL_YUV_BUF_TYPE_LINEAR), DDL_KILO_BYTE(4));
-		sz_mv = DDL_ALIGN(2 * mb_x * mb_y * 8, DDL_KILO_BYTE(2));
+		sz_mv = DDL_ALIGN(2 * mb_x * 8, DDL_KILO_BYTE(2));
 		if ((codec == VCD_CODEC_MPEG4) ||
 			(codec == VCD_CODEC_H264)) {
 			sz_col_zero = DDL_ALIGN(((mb_x * mb_y + 7) / 8) *
@@ -900,7 +900,7 @@
 				goto fail_enc_free_exit;
 		}
 		if (buf_size.sz_pred > 0) {
-			enc_bufs->pred.mem_type = DDL_MM_MEM;
+			enc_bufs->pred.mem_type = DDL_FW_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->pred,
 				buf_size.sz_pred, DDL_KILO_BYTE(2));
 			if (!ptr)
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 3827bc1..ab4d51c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -294,6 +294,11 @@
 		}
 	}
 	break;
+	case VCD_I_SET_TURBO_CLK:
+	{
+		vcd_status = VCD_S_SUCCESS;
+	}
+	break;
 	case VCD_I_BUFFER_FORMAT:
 	{
 		struct vcd_property_buffer_format *tile =
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 5b22b21..a5171f0 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
@@ -536,6 +536,9 @@
 	u32 bus_clk_index, client_type = 0;
 	int rc = 0;
 
+	if (dev_ctxt->turbo_mode_set)
+		return rc;
+
 	cctxt_itr = dev_ctxt->cctxt_list_head;
 	while (cctxt_itr) {
 		if (cctxt_itr->decoding)
@@ -565,6 +568,9 @@
 		bus_clk_index = 2;
 	}
 
+	if (bus_clk_index == 3)
+		dev_ctxt->turbo_mode_set = 1;
+
 	bus_clk_index = (bus_clk_index << 1) + (client_type + 1);
 	VCDRES_MSG_LOW("%s(), bus_clk_index = %d", __func__, bus_clk_index);
 	VCDRES_MSG_LOW("%s(),context.pcl = %x", __func__, resource_context.pcl);
@@ -584,6 +590,12 @@
 			__func__, dev_ctxt);
 		return false;
 	}
+	if (dev_ctxt->turbo_mode_set &&
+			(req_perf_lvl < RESTRK_1080P_TURBO_PERF_LEVEL)) {
+		VCDRES_MSG_MED("%s(): TURBO MODE!!\n", __func__);
+		return true;
+	}
+
 	VCDRES_MSG_LOW("%s(), req_perf_lvl = %d", __func__, req_perf_lvl);
 
 	if (resource_context.vidc_platform_data->disable_turbo
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
index d5e656b..01999a4 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
@@ -75,4 +75,8 @@
 #define VCDRES_MSG_ERROR(xx_fmt...)	printk(KERN_ERR "\n err: " xx_fmt)
 #define VCDRES_MSG_FATAL(xx_fmt...)	printk(KERN_ERR "\n<FATAL> " xx_fmt)
 
+#ifdef CONFIG_MSM_BUS_SCALING
+int res_trk_update_bus_perf_level(struct vcd_dev_ctxt *dev_ctxt,
+				u32 perf_level);
+#endif
 #endif
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 11177b8..3076aa1 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -636,6 +636,26 @@
 		return true;
 }
 
+static u32 vid_dec_set_turbo_clk(struct video_client_ctx *client_ctx)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	u32 vcd_status = VCD_ERR_FAIL;
+	u32 dummy = 0;
+
+	if (!client_ctx)
+		return false;
+	vcd_property_hdr.prop_id = VCD_I_SET_TURBO_CLK;
+	vcd_property_hdr.sz = sizeof(struct vcd_property_frame_size);
+
+	vcd_status = vcd_set_property(client_ctx->vcd_handle,
+				      &vcd_property_hdr, &dummy);
+
+	if (vcd_status)
+		return false;
+	else
+		return true;
+}
+
 static u32 vid_dec_get_frame_resolution(struct video_client_ctx *client_ctx,
 					struct vdec_picsize *video_resoultion)
 {
@@ -1682,6 +1702,11 @@
 		}
 		break;
 	}
+	case VDEC_IOCTL_SET_PERF_CLK:
+	{
+		vid_dec_set_turbo_clk(client_ctx);
+		break;
+	}
 	case VDEC_IOCTL_FILL_OUTPUT_BUFFER:
 	{
 		struct vdec_fillbuffer_cmd fill_buffer_cmd;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index 3e02030..8f44a56 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -397,4 +397,5 @@
 
 u32 vcd_update_decoder_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl);
 
+u32 vcd_set_perf_turbo_level(struct vcd_clnt_ctxt *cctxt);
 #endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 5019d31..7c0d9fe 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -541,6 +541,12 @@
 			}
 			break;
 		}
+	case VCD_I_SET_TURBO_CLK:
+	{
+		if (cctxt->sched_clnt_hdl)
+			rc = vcd_set_perf_turbo_level(cctxt);
+		break;
+	}
 	case VCD_I_INTRA_PERIOD:
 		{
 			struct vcd_property_i_period *iperiod =
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index 7ae4f45..5351589 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -146,7 +146,7 @@
 	u32 reqd_perf_lvl;
 	u32 curr_perf_lvl;
 	u32 set_perf_lvl_pending;
-
+	u32 turbo_mode_set;
 };
 
 struct vcd_clnt_status {
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index d517028..96e729d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -219,6 +219,7 @@
 						   VCD_DEVICE_STATE_INITING,
 						   ev_code);
 	}
+	dev_ctxt->turbo_mode_set = 0;
 
 	return rc;
 }
@@ -758,6 +759,7 @@
 	client = dev_ctxt->cctxt_list_head;
 	dev_ctxt->cctxt_list_head = cctxt;
 	cctxt->next = client;
+	dev_ctxt->turbo_mode_set = 0;
 
 	*clnt_cctxt = cctxt;
 
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
index beaa872..33b2300 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
@@ -15,6 +15,7 @@
 #include "vcd_power_sm.h"
 #include "vcd_core.h"
 #include "vcd.h"
+#include "vcd_res_tracker.h"
 
 u32 vcd_power_event(
 	struct vcd_dev_ctxt *dev_ctxt,
@@ -297,6 +298,25 @@
 	return rc;
 }
 
+u32 vcd_set_perf_turbo_level(struct vcd_clnt_ctxt *cctxt)
+{
+	u32 rc = VCD_S_SUCCESS;
+#ifdef CONFIG_MSM_BUS_SCALING
+	struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+	pr_err("\n Setting Turbo mode !!");
+
+	if (res_trk_update_bus_perf_level(dev_ctxt,
+			RESTRK_1080P_TURBO_PERF_LEVEL) < 0) {
+		pr_err("\n %s(): update buf perf level failed\n",
+			__func__);
+		return false;
+	}
+	dev_ctxt->curr_perf_lvl = RESTRK_1080P_TURBO_PERF_LEVEL;
+	vcd_update_decoder_perf_level(dev_ctxt, RESTRK_1080P_TURBO_PERF_LEVEL);
+#endif
+	return rc;
+}
+
 u32 vcd_update_decoder_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl)
 {
 	u32 rc = VCD_S_SUCCESS;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index b71212c..f79a147 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -745,7 +745,8 @@
 		return VCD_ERR_ILLEGAL_PARM;
 	}
 	if (buf_entry->in_use) {
-		VCD_MSG_ERROR("\n Buffer is in use and is not flushed");
+		VCD_MSG_ERROR("Buffer is in use and is not flushed: %p, %d\n",
+			buf_entry, buf_entry->in_use);
 		return VCD_ERR_ILLEGAL_OP;
 	}
 
@@ -1043,6 +1044,7 @@
 {
 	u32 rc = VCD_S_SUCCESS;
 	struct vcd_buffer_entry *buf_entry;
+	struct vcd_buffer_entry *orig_frame = NULL;
 
 	VCD_MSG_LOW("vcd_flush_buffers:");
 
@@ -1066,9 +1068,19 @@
 							 vcd_frame_data),
 						cctxt,
 						cctxt->client_data);
+				orig_frame = vcd_find_buffer_pool_entry(
+						&cctxt->in_buf_pool,
+						buf_entry->virtual);
 				}
 
-			buf_entry->in_use = false;
+			if (orig_frame) {
+				orig_frame->in_use--;
+				if (orig_frame != buf_entry)
+					kfree(buf_entry);
+			} else {
+				buf_entry->in_use = false;
+				VCD_MSG_ERROR("Original frame not found in buffer pool\n");
+			}
 			VCD_BUFFERPOOL_INUSE_DECREMENT(
 				cctxt->in_buf_pool.in_use);
 			buf_entry = NULL;
@@ -3417,7 +3429,7 @@
 	struct vcd_property_slice_delivery_info slice_delivery_info;
 	u32 rc = VCD_S_SUCCESS;
 	prop_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
-	prop_hdr.sz = prop_hdr.sz =
+	prop_hdr.sz =
 		sizeof(struct vcd_property_slice_delivery_info);
 	rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr,
 				&slice_delivery_info);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 1e1e09f..28c0917 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -436,7 +436,6 @@
 header-y += msm_audio_sbc.h
 header-y += msm_ipc.h
 header-y += msm_charm.h
-header-y += tzcom.h
 header-y += qseecom.h
 header-y += qcedev.h
 header-y += idle_stats_device.h
diff --git a/include/linux/input/mpu3050.h b/include/linux/input/mpu3050.h
new file mode 100644
index 0000000..6006abb
--- /dev/null
+++ b/include/linux/input/mpu3050.h
@@ -0,0 +1,31 @@
+/*
+ * 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 __MPU3050_H__
+#define __MPU3050_H__
+
+struct mpu3050_gyro_platform_data {
+	int poll_interval;
+	int min_interval;
+
+	int (*init)(void);
+	void (*exit)(void);
+	int (*power_on)(void);
+	int (*power_off)(void);
+
+	int gpio_int;
+	int gpio_fsync;
+};
+
+#endif /* __MPU3050_H__ */
diff --git a/include/linux/ion.h b/include/linux/ion.h
index d9443ff..fca5517 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -86,6 +86,14 @@
 	FIXED_HIGH,
 };
 
+enum cp_mem_usage {
+	VIDEO_BITSTREAM = 0x1,
+	VIDEO_PIXEL = 0x2,
+	VIDEO_NONPIXEL = 0x3,
+	MAX_USAGE = 0x4,
+	UNKNOWN = 0x7FFFFFFF,
+};
+
 /**
  * Flag to use when allocating to indicate that a heap is secure.
  */
@@ -482,22 +490,28 @@
  *
  * @client - a client that has allocated from the heap heap_id
  * @heap_id - heap id to secure.
+ * @version - version of content protection
+ * @data - extra data needed for protection
  *
  * Secure a heap
  * Returns 0 on success
  */
-int ion_secure_heap(struct ion_device *dev, int heap_id);
+int ion_secure_heap(struct ion_device *dev, int heap_id, int version,
+			void *data);
 
 /**
  * ion_unsecure_heap - un-secure a heap
  *
  * @client - a client that has allocated from the heap heap_id
  * @heap_id - heap id to un-secure.
+ * @version - version of content protection
+ * @data - extra data needed for protection
  *
  * Un-secure a heap
  * Returns 0 on success
  */
-int ion_unsecure_heap(struct ion_device *dev, int heap_id);
+int ion_unsecure_heap(struct ion_device *dev, int heap_id, int version,
+			void *data);
 
 /**
  * msm_ion_secure_heap - secure a heap. Wrapper around ion_secure_heap.
@@ -520,6 +534,30 @@
 int msm_ion_unsecure_heap(int heap_id);
 
 /**
+ * msm_ion_secure_heap_2_0 - secure a heap using 2.0 APIs
+ *  Wrapper around ion_secure_heap.
+ *
+ * @heap_id - heap id to secure.
+ * @usage - usage hint to TZ
+ *
+ * Secure a heap
+ * Returns 0 on success
+ */
+int msm_ion_secure_heap_2_0(int heap_id, enum cp_mem_usage usage);
+
+/**
+ * msm_ion_unsecure_heap - unsecure a heap secured with 3.0 APIs.
+ * Wrapper around ion_unsecure_heap.
+ *
+ * @heap_id - heap id to secure.
+ * @usage - usage hint to TZ
+ *
+ * Un-secure a heap
+ * Returns 0 on success
+ */
+int msm_ion_unsecure_heap_2_0(int heap_id, enum cp_mem_usage usage);
+
+/**
  * msm_ion_do_cache_op - do cache operations.
  *
  * @client - pointer to ION client.
@@ -627,13 +665,15 @@
 	return;
 }
 
-static inline int ion_secure_heap(struct ion_device *dev, int heap_id)
+static inline int ion_secure_heap(struct ion_device *dev, int heap_id,
+					int version, void *data)
 {
 	return -ENODEV;
 
 }
 
-static inline int ion_unsecure_heap(struct ion_device *dev, int heap_id)
+static inline int ion_unsecure_heap(struct ion_device *dev, int heap_id,
+					int version, void *data)
 {
 	return -ENODEV;
 }
@@ -649,6 +689,17 @@
 	return -ENODEV;
 }
 
+static inline int msm_ion_secure_heap_2_0(int heap_id, enum cp_mem_usage usage)
+{
+	return -ENODEV;
+}
+
+static inline int msm_ion_unsecure_heap_2_0(int heap_id,
+					enum cp_mem_usage usage)
+{
+	return -ENODEV;
+}
+
 static inline int msm_ion_do_cache_op(struct ion_client *client,
 			struct ion_handle *handle, void *vaddr,
 			unsigned long len, unsigned int cmd)
diff --git a/include/linux/mfd/pm8xxx/ccadc.h b/include/linux/mfd/pm8xxx/ccadc.h
index 23d0fb0..0bd4cc3 100644
--- a/include/linux/mfd/pm8xxx/ccadc.h
+++ b/include/linux/mfd/pm8xxx/ccadc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,9 +20,11 @@
 /**
  * struct pm8xxx_ccadc_platform_data -
  * @r_sense:		sense resistor value in (mOhms)
+ * @calib_delay_ms:	how often should the adc calculate gain and offset
  */
 struct pm8xxx_ccadc_platform_data {
-	int r_sense;
+	int		r_sense;
+	unsigned int	calib_delay_ms;
 };
 
 #define CCADC_READING_RESOLUTION_N_V1	1085069
diff --git a/include/linux/mfd/pm8xxx/pm8038.h b/include/linux/mfd/pm8xxx/pm8038.h
index 90557b9..682abc8 100644
--- a/include/linux/mfd/pm8xxx/pm8038.h
+++ b/include/linux/mfd/pm8xxx/pm8038.h
@@ -33,6 +33,7 @@
 #include <linux/leds-pm8xxx.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
 #include <linux/mfd/pm8xxx/spk.h>
+#include <linux/mfd/pm8xxx/tm.h>
 
 #define PM8038_CORE_DEV_NAME "pm8038-core"
 
@@ -64,6 +65,9 @@
 
 #define PM8038_RESOUT_IRQ		PM8038_IRQ_BLOCK_BIT(6, 4)
 
+#define PM8038_OVERTEMP_IRQ		PM8038_IRQ_BLOCK_BIT(4, 2)
+#define PM8038_TEMPSTAT_IRQ		PM8038_IRQ_BLOCK_BIT(6, 7)
+
 struct pm8038_platform_data {
 	int					irq_base;
 	struct pm8xxx_gpio_platform_data	*gpio_pdata;
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 537e0b5..90c2d99 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -117,7 +117,6 @@
  * @i_test:		current at which the unusable charger cutoff is to be
  *			calculated or the peak system current (mA)
  * @v_failure:		the voltage at which the battery is considered empty(mV)
- * @calib_delay_ms:	how often should the adc calculate gain and offset
  * @enable_fcc_learning:	if set the driver will learn full charge
  *				capacity of the battery upon end of charge
  */
@@ -127,7 +126,6 @@
 	unsigned int			r_sense;
 	unsigned int			i_test;
 	unsigned int			v_failure;
-	unsigned int			calib_delay_ms;
 	unsigned int			max_voltage_uv;
 	unsigned int			rconn_mohm;
 	int				enable_fcc_learning;
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 612b133..2657ec3 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -90,6 +90,32 @@
 };
 
 
+enum {
+	TAIKO_IRQ_SLIMBUS = 0,
+	TAIKO_IRQ_MBHC_REMOVAL,
+	TAIKO_IRQ_MBHC_SHORT_TERM,
+	TAIKO_IRQ_MBHC_PRESS,
+	TAIKO_IRQ_MBHC_RELEASE,
+	TAIKO_IRQ_MBHC_POTENTIAL,
+	TAIKO_IRQ_MBHC_INSERTION,
+	TAIKO_IRQ_BG_PRECHARGE,
+	TAIKO_IRQ_PA1_STARTUP,
+	TAIKO_IRQ_PA2_STARTUP,
+	TAIKO_IRQ_PA3_STARTUP,
+	TAIKO_IRQ_PA4_STARTUP,
+	TAIKO_IRQ_PA5_STARTUP,
+	TAIKO_IRQ_MICBIAS1_PRECHARGE,
+	TAIKO_IRQ_MICBIAS2_PRECHARGE,
+	TAIKO_IRQ_MICBIAS3_PRECHARGE,
+	TAIKO_IRQ_HPH_PA_OCPL_FAULT,
+	TAIKO_IRQ_HPH_PA_OCPR_FAULT,
+	TAIKO_IRQ_EAR_PA_OCPL_FAULT,
+	TAIKO_IRQ_HPH_L_PA_STARTUP,
+	TAIKO_IRQ_HPH_R_PA_STARTUP,
+	TAIKO_IRQ_EAR_PA_STARTUP,
+	TAIKO_NUM_IRQS,
+};
+
 enum wcd9xxx_pm_state {
 	WCD9XXX_PM_SLEEPABLE,
 	WCD9XXX_PM_AWAKE,
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index db76294..ba71293 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -34,6 +34,16 @@
 #define TABLA_CFILT2_SEL 0x1
 #define TABLA_CFILT3_SEL 0x2
 
+#define TAIKO_CFILT1_SEL 0x0
+#define TAIKO_CFILT2_SEL 0x1
+#define TAIKO_CFILT3_SEL 0x2
+
+#define TAIKO_LDOH_1P95_V 0x0
+#define TAIKO_LDOH_2P35_V 0x1
+#define TAIKO_LDOH_2P75_V 0x2
+#define TAIKO_LDOH_2P85_V 0x3
+
+
 #define MAX_AMIC_CHANNEL 7
 
 #define TABLA_OCP_300_MA 0x0
diff --git a/include/linux/mfd/wcd9xxx/wcd9320_registers.h b/include/linux/mfd/wcd9xxx/wcd9320_registers.h
new file mode 100644
index 0000000..5725e6e
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/wcd9320_registers.h
@@ -0,0 +1,1354 @@
+/* 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 WCD9320_REGISTERS_H
+#define WCD9320_REGISTERS_H
+
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+
+#define TAIKO_A_CHIP_CTL			WCD9XXX_A_CHIP_CTL
+#define TAIKO_A_CHIP_CTL__POR			WCD9XXX_A_CHIP_CTL__POR
+#define TAIKO_A_CHIP_STATUS			WCD9XXX_A_CHIP_STATUS
+#define TAIKO_A_CHIP_STATUS__POR		WCD9XXX_A_CHIP_STATUS__POR
+#define TAIKO_A_CHIP_ID_BYTE_0			WCD9XXX_A_CHIP_ID_BYTE_0
+#define TAIKO_A_CHIP_ID_BYTE_0__POR		WCD9XXX_A_CHIP_ID_BYTE_0__POR
+#define TAIKO_A_CHIP_ID_BYTE_1			WCD9XXX_A_CHIP_ID_BYTE_1
+#define TAIKO_A_CHIP_ID_BYTE_1__POR		WCD9XXX_A_CHIP_ID_BYTE_1__POR
+#define TAIKO_A_CHIP_ID_BYTE_2			WCD9XXX_A_CHIP_ID_BYTE_2
+#define TAIKO_A_CHIP_ID_BYTE_2__POR		WCD9XXX_A_CHIP_ID_BYTE_2__POR
+#define TAIKO_A_CHIP_ID_BYTE_3			WCD9XXX_A_CHIP_ID_BYTE_3
+#define TAIKO_A_CHIP_ID_BYTE_3__POR		WCD9XXX_A_CHIP_ID_BYTE_3__POR
+#define TAIKO_A_CHIP_VERSION			WCD9XXX_A_CHIP_VERSION
+#define TAIKO_A_CHIP_VERSION__POR		WCD9XXX_A_CHIP_VERSION__POR
+#define TAIKO_A_SB_VERSION			WCD9XXX_A_SB_VERSION
+#define TAIKO_A_SB_VERSION__POR			WCD9XXX_A_SB_VERSION__POR
+#define TAIKO_A_SLAVE_ID_1			WCD9XXX_A_SLAVE_ID_1
+#define TAIKO_A_SLAVE_ID_1__POR			WCD9XXX_A_SLAVE_ID_1__POR
+#define TAIKO_A_SLAVE_ID_2			WCD9XXX_A_SLAVE_ID_2
+#define TAIKO_A_SLAVE_ID_2__POR			WCD9XXX_A_SLAVE_ID_2__POR
+#define TAIKO_A_SLAVE_ID_3			WCD9XXX_A_SLAVE_ID_3
+#define TAIKO_A_SLAVE_ID_3__POR			WCD9XXX_A_SLAVE_ID_3__POR
+#define TAIKO_A_PIN_CTL_OE0			(0x010)
+#define TAIKO_A_PIN_CTL_OE0__POR				(0x00)
+#define TAIKO_A_PIN_CTL_OE1			(0x011)
+#define TAIKO_A_PIN_CTL_OE1__POR				(0x00)
+#define TAIKO_A_PIN_CTL_DATA0			(0x012)
+#define TAIKO_A_PIN_CTL_DATA0__POR				(0x00)
+#define TAIKO_A_PIN_CTL_DATA1			(0x013)
+#define TAIKO_A_PIN_CTL_DATA1__POR				(0x00)
+#define TAIKO_A_HDRIVE_GENERIC			(0x018)
+#define TAIKO_A_HDRIVE_GENERIC__POR				(0x00)
+#define TAIKO_A_HDRIVE_OVERRIDE			(0x019)
+#define TAIKO_A_HDRIVE_OVERRIDE__POR				(0x08)
+#define TAIKO_A_ANA_CSR_WAIT_STATE			(0x020)
+#define TAIKO_A_ANA_CSR_WAIT_STATE__POR				(0x44)
+#define TAIKO_A_PROCESS_MONITOR_CTL0			(0x040)
+#define TAIKO_A_PROCESS_MONITOR_CTL0__POR				(0x80)
+#define TAIKO_A_PROCESS_MONITOR_CTL1			(0x041)
+#define TAIKO_A_PROCESS_MONITOR_CTL1__POR				(0x00)
+#define TAIKO_A_PROCESS_MONITOR_CTL2			(0x042)
+#define TAIKO_A_PROCESS_MONITOR_CTL2__POR				(0x00)
+#define TAIKO_A_PROCESS_MONITOR_CTL3			(0x043)
+#define TAIKO_A_PROCESS_MONITOR_CTL3__POR				(0x01)
+#define TAIKO_A_QFUSE_CTL			(0x048)
+#define TAIKO_A_QFUSE_CTL__POR				(0x00)
+#define TAIKO_A_QFUSE_STATUS			(0x049)
+#define TAIKO_A_QFUSE_STATUS__POR				(0x00)
+#define TAIKO_A_QFUSE_DATA_OUT0			(0x04A)
+#define TAIKO_A_QFUSE_DATA_OUT0__POR				(0x00)
+#define TAIKO_A_QFUSE_DATA_OUT1			(0x04B)
+#define TAIKO_A_QFUSE_DATA_OUT1__POR				(0x00)
+#define TAIKO_A_QFUSE_DATA_OUT2			(0x04C)
+#define TAIKO_A_QFUSE_DATA_OUT2__POR				(0x00)
+#define TAIKO_A_QFUSE_DATA_OUT3			(0x04D)
+#define TAIKO_A_QFUSE_DATA_OUT3__POR				(0x00)
+#define TAIKO_A_QFUSE_DATA_OUT4			(0x04E)
+#define TAIKO_A_QFUSE_DATA_OUT4__POR				(0x00)
+#define TAIKO_A_QFUSE_DATA_OUT5			(0x04F)
+#define TAIKO_A_QFUSE_DATA_OUT5__POR				(0x00)
+#define TAIKO_A_QFUSE_DATA_OUT6			(0x050)
+#define TAIKO_A_QFUSE_DATA_OUT6__POR				(0x00)
+#define TAIKO_A_QFUSE_DATA_OUT7			(0x051)
+#define TAIKO_A_QFUSE_DATA_OUT7__POR				(0x00)
+#define TAIKO_A_CDC_CTL				WCD9XXX_A_CDC_CTL
+#define TAIKO_A_CDC_CTL__POR			WCD9XXX_A_CDC_CTL__POR
+#define TAIKO_A_LEAKAGE_CTL			WCD9XXX_A_LEAKAGE_CTL
+#define TAIKO_A_LEAKAGE_CTL__POR		WCD9XXX_A_LEAKAGE_CTL__POR
+#define TAIKO_A_INTR_MODE			(0x090)
+#define TAIKO_A_INTR_MODE__POR				(0x00)
+#define TAIKO_A_INTR_MASK0			(0x094)
+#define TAIKO_A_INTR_MASK0__POR				(0xFF)
+#define TAIKO_A_INTR_MASK1			(0x095)
+#define TAIKO_A_INTR_MASK1__POR				(0xFF)
+#define TAIKO_A_INTR_MASK2			(0x096)
+#define TAIKO_A_INTR_MASK2__POR				(0x3F)
+#define TAIKO_A_INTR_MASK3			(0x097)
+#define TAIKO_A_INTR_MASK3__POR				(0x3F)
+#define TAIKO_A_INTR_STATUS0			(0x098)
+#define TAIKO_A_INTR_STATUS0__POR				(0x00)
+#define TAIKO_A_INTR_STATUS1			(0x099)
+#define TAIKO_A_INTR_STATUS1__POR				(0x00)
+#define TAIKO_A_INTR_STATUS2			(0x09A)
+#define TAIKO_A_INTR_STATUS2__POR				(0x00)
+#define TAIKO_A_INTR_STATUS3			(0x09B)
+#define TAIKO_A_INTR_STATUS3__POR				(0x00)
+#define TAIKO_A_INTR_CLEAR0			(0x09C)
+#define TAIKO_A_INTR_CLEAR0__POR				(0x00)
+#define TAIKO_A_INTR_CLEAR1			(0x09D)
+#define TAIKO_A_INTR_CLEAR1__POR				(0x00)
+#define TAIKO_A_INTR_CLEAR2			(0x09E)
+#define TAIKO_A_INTR_CLEAR2__POR				(0x00)
+#define TAIKO_A_INTR_CLEAR3			(0x09F)
+#define TAIKO_A_INTR_CLEAR3__POR				(0x00)
+#define TAIKO_A_INTR_LEVEL0			(0x0A0)
+#define TAIKO_A_INTR_LEVEL0__POR				(0x01)
+#define TAIKO_A_INTR_LEVEL1			(0x0A1)
+#define TAIKO_A_INTR_LEVEL1__POR				(0x00)
+#define TAIKO_A_INTR_LEVEL2			(0x0A2)
+#define TAIKO_A_INTR_LEVEL2__POR				(0x00)
+#define TAIKO_A_INTR_LEVEL3			(0x0A3)
+#define TAIKO_A_INTR_LEVEL3__POR				(0x00)
+#define TAIKO_A_INTR_TEST0			(0x0A4)
+#define TAIKO_A_INTR_TEST0__POR				(0x00)
+#define TAIKO_A_INTR_TEST1			(0x0A5)
+#define TAIKO_A_INTR_TEST1__POR				(0x00)
+#define TAIKO_A_INTR_TEST2			(0x0A6)
+#define TAIKO_A_INTR_TEST2__POR				(0x00)
+#define TAIKO_A_INTR_TEST3			(0x0A7)
+#define TAIKO_A_INTR_TEST3__POR				(0x00)
+#define TAIKO_A_INTR_SET0			(0x0A8)
+#define TAIKO_A_INTR_SET0__POR				(0x00)
+#define TAIKO_A_INTR_SET1			(0x0A9)
+#define TAIKO_A_INTR_SET1__POR				(0x00)
+#define TAIKO_A_INTR_SET2			(0x0AA)
+#define TAIKO_A_INTR_SET2__POR				(0x00)
+#define TAIKO_A_INTR_SET3			(0x0AB)
+#define TAIKO_A_INTR_SET3__POR				(0x00)
+#define TAIKO_A_INTR_DESTN0			(0x0AC)
+#define TAIKO_A_INTR_DESTN0__POR				(0x00)
+#define TAIKO_A_INTR_DESTN1			(0x0AD)
+#define TAIKO_A_INTR_DESTN1__POR				(0x00)
+#define TAIKO_A_INTR_DESTN2			(0x0AE)
+#define TAIKO_A_INTR_DESTN2__POR				(0x00)
+#define TAIKO_A_INTR_DESTN3			(0x0AF)
+#define TAIKO_A_INTR_DESTN3__POR				(0x00)
+#define TAIKO_A_CDC_TX_I2S_SCK_MODE			(0x0C0)
+#define TAIKO_A_CDC_TX_I2S_SCK_MODE__POR				(0x00)
+#define TAIKO_A_CDC_TX_I2S_WS_MODE			(0x0C1)
+#define TAIKO_A_CDC_TX_I2S_WS_MODE__POR				(0x00)
+#define TAIKO_A_CDC_DMIC_DATA0_MODE			(0x0C4)
+#define TAIKO_A_CDC_DMIC_DATA0_MODE__POR				(0x00)
+#define TAIKO_A_CDC_DMIC_CLK0_MODE			(0x0C5)
+#define TAIKO_A_CDC_DMIC_CLK0_MODE__POR				(0x00)
+#define TAIKO_A_CDC_DMIC_DATA1_MODE			(0x0C6)
+#define TAIKO_A_CDC_DMIC_DATA1_MODE__POR				(0x00)
+#define TAIKO_A_CDC_DMIC_CLK1_MODE			(0x0C7)
+#define TAIKO_A_CDC_DMIC_CLK1_MODE__POR				(0x00)
+#define TAIKO_A_CDC_RX_I2S_SCK_MODE			(0x0C8)
+#define TAIKO_A_CDC_RX_I2S_SCK_MODE__POR				(0x00)
+#define TAIKO_A_CDC_RX_I2S_WS_MODE			(0x0C9)
+#define TAIKO_A_CDC_RX_I2S_WS_MODE__POR				(0x00)
+#define TAIKO_A_CDC_DMIC_DATA2_MODE			(0x0CA)
+#define TAIKO_A_CDC_DMIC_DATA2_MODE__POR				(0x00)
+#define TAIKO_A_CDC_DMIC_CLK2_MODE			(0x0CB)
+#define TAIKO_A_CDC_DMIC_CLK2_MODE__POR				(0x00)
+#define TAIKO_A_CDC_INTR1_MODE			(0x0CC)
+#define TAIKO_A_CDC_INTR1_MODE__POR				(0x00)
+#define TAIKO_A_CDC_SB_NRZ_SEL_MODE			(0x0CD)
+#define TAIKO_A_CDC_SB_NRZ_SEL_MODE__POR				(0x00)
+#define TAIKO_A_CDC_INTR2_MODE			(0x0CE)
+#define TAIKO_A_CDC_INTR2_MODE__POR				(0x00)
+#define TAIKO_A_CDC_RF_PA_ON_MODE			(0x0CF)
+#define TAIKO_A_CDC_RF_PA_ON_MODE__POR				(0x00)
+#define TAIKO_A_BIAS_REF_CTL			(0x100)
+#define TAIKO_A_BIAS_REF_CTL__POR				(0x1C)
+#define TAIKO_A_BIAS_CENTRAL_BG_CTL			(0x101)
+#define TAIKO_A_BIAS_CENTRAL_BG_CTL__POR				(0x50)
+#define TAIKO_A_BIAS_PRECHRG_CTL			(0x102)
+#define TAIKO_A_BIAS_PRECHRG_CTL__POR				(0x07)
+#define TAIKO_A_BIAS_CURR_CTL_1			(0x103)
+#define TAIKO_A_BIAS_CURR_CTL_1__POR				(0x52)
+#define TAIKO_A_BIAS_CURR_CTL_2			(0x104)
+#define TAIKO_A_BIAS_CURR_CTL_2__POR				(0x00)
+#define TAIKO_A_BIAS_OSC_BG_CTL			(0x105)
+#define TAIKO_A_BIAS_OSC_BG_CTL__POR				(0x16)
+#define TAIKO_A_CLK_BUFF_EN1			(0x108)
+#define TAIKO_A_CLK_BUFF_EN1__POR				(0x04)
+#define TAIKO_A_CLK_BUFF_EN2			(0x109)
+#define TAIKO_A_CLK_BUFF_EN2__POR				(0x02)
+#define TAIKO_A_LDO_H_MODE_1			(0x110)
+#define TAIKO_A_LDO_H_MODE_1__POR				(0x65)
+#define TAIKO_A_LDO_H_MODE_2			(0x111)
+#define TAIKO_A_LDO_H_MODE_2__POR				(0xA8)
+#define TAIKO_A_LDO_H_LOOP_CTL			(0x112)
+#define TAIKO_A_LDO_H_LOOP_CTL__POR				(0x6B)
+#define TAIKO_A_LDO_H_COMP_1			(0x113)
+#define TAIKO_A_LDO_H_COMP_1__POR				(0x84)
+#define TAIKO_A_LDO_H_COMP_2			(0x114)
+#define TAIKO_A_LDO_H_COMP_2__POR				(0xE0)
+#define TAIKO_A_LDO_H_BIAS_1			(0x115)
+#define TAIKO_A_LDO_H_BIAS_1__POR				(0x6D)
+#define TAIKO_A_LDO_H_BIAS_2			(0x116)
+#define TAIKO_A_LDO_H_BIAS_2__POR				(0xA5)
+#define TAIKO_A_LDO_H_BIAS_3			(0x117)
+#define TAIKO_A_LDO_H_BIAS_3__POR				(0x60)
+#define TAIKO_A_VBAT_CLK			(0x118)
+#define TAIKO_A_VBAT_CLK__POR				(0x03)
+#define TAIKO_A_VBAT_LOOP			(0x119)
+#define TAIKO_A_VBAT_LOOP__POR				(0x02)
+#define TAIKO_A_VBAT_REF			(0x11A)
+#define TAIKO_A_VBAT_REF__POR				(0x20)
+#define TAIKO_A_VBAT_ADC_TEST			(0x11B)
+#define TAIKO_A_VBAT_ADC_TEST__POR				(0x00)
+#define TAIKO_A_VBAT_FE			(0x11C)
+#define TAIKO_A_VBAT_FE__POR				(0x48)
+#define TAIKO_A_VBAT_BIAS_1			(0x11D)
+#define TAIKO_A_VBAT_BIAS_1__POR				(0x03)
+#define TAIKO_A_VBAT_BIAS_2			(0x11E)
+#define TAIKO_A_VBAT_BIAS_2__POR				(0x00)
+#define TAIKO_A_VBAT_ADC_DATA_MSB			(0x11F)
+#define TAIKO_A_VBAT_ADC_DATA_MSB__POR				(0x00)
+#define TAIKO_A_VBAT_ADC_DATA_LSB			(0x120)
+#define TAIKO_A_VBAT_ADC_DATA_LSB__POR				(0x00)
+#define TAIKO_A_MICB_CFILT_1_CTL			(0x128)
+#define TAIKO_A_MICB_CFILT_1_CTL__POR				(0x40)
+#define TAIKO_A_MICB_CFILT_1_VAL			(0x129)
+#define TAIKO_A_MICB_CFILT_1_VAL__POR				(0x80)
+#define TAIKO_A_MICB_CFILT_1_PRECHRG			(0x12A)
+#define TAIKO_A_MICB_CFILT_1_PRECHRG__POR				(0x38)
+#define TAIKO_A_MICB_1_CTL			(0x12B)
+#define TAIKO_A_MICB_1_CTL__POR				(0x16)
+#define TAIKO_A_MICB_1_INT_RBIAS			(0x12C)
+#define TAIKO_A_MICB_1_INT_RBIAS__POR				(0x24)
+#define TAIKO_A_MICB_1_MBHC			(0x12D)
+#define TAIKO_A_MICB_1_MBHC__POR				(0x01)
+#define TAIKO_A_MICB_CFILT_2_CTL			(0x12E)
+#define TAIKO_A_MICB_CFILT_2_CTL__POR				(0x40)
+#define TAIKO_A_MICB_CFILT_2_VAL			(0x12F)
+#define TAIKO_A_MICB_CFILT_2_VAL__POR				(0x80)
+#define TAIKO_A_MICB_CFILT_2_PRECHRG			(0x130)
+#define TAIKO_A_MICB_CFILT_2_PRECHRG__POR				(0x38)
+#define TAIKO_A_MICB_2_CTL			(0x131)
+#define TAIKO_A_MICB_2_CTL__POR				(0x16)
+#define TAIKO_A_MICB_2_INT_RBIAS			(0x132)
+#define TAIKO_A_MICB_2_INT_RBIAS__POR				(0x24)
+#define TAIKO_A_MICB_2_MBHC			(0x133)
+#define TAIKO_A_MICB_2_MBHC__POR				(0x02)
+#define TAIKO_A_MICB_CFILT_3_CTL			(0x134)
+#define TAIKO_A_MICB_CFILT_3_CTL__POR				(0x40)
+#define TAIKO_A_MICB_CFILT_3_VAL			(0x135)
+#define TAIKO_A_MICB_CFILT_3_VAL__POR				(0x80)
+#define TAIKO_A_MICB_CFILT_3_PRECHRG			(0x136)
+#define TAIKO_A_MICB_CFILT_3_PRECHRG__POR				(0x38)
+#define TAIKO_A_MICB_3_CTL			(0x137)
+#define TAIKO_A_MICB_3_CTL__POR				(0x16)
+#define TAIKO_A_MICB_3_INT_RBIAS			(0x138)
+#define TAIKO_A_MICB_3_INT_RBIAS__POR				(0x24)
+#define TAIKO_A_MICB_3_MBHC			(0x139)
+#define TAIKO_A_MICB_3_MBHC__POR				(0x00)
+#define TAIKO_A_MICB_4_CTL			(0x13D)
+#define TAIKO_A_MICB_4_CTL__POR				(0x16)
+#define TAIKO_A_MICB_4_INT_RBIAS			(0x13E)
+#define TAIKO_A_MICB_4_INT_RBIAS__POR				(0x24)
+#define TAIKO_A_MICB_4_MBHC			(0x13F)
+#define TAIKO_A_MICB_4_MBHC__POR				(0x01)
+#define TAIKO_A_MBHC_INSERT_DETECT			(0x14A)
+#define TAIKO_A_MBHC_INSERT_DETECT__POR				(0x00)
+#define TAIKO_A_MBHC_INSERT_DET_STATUS			(0x14B)
+#define TAIKO_A_MBHC_INSERT_DET_STATUS__POR				(0x00)
+#define TAIKO_A_TX_COM_BIAS			(0x14C)
+#define TAIKO_A_TX_COM_BIAS__POR				(0xF0)
+#define TAIKO_A_MBHC_SCALING_MUX_1			(0x14E)
+#define TAIKO_A_MBHC_SCALING_MUX_1__POR				(0x00)
+#define TAIKO_A_MBHC_SCALING_MUX_2			(0x14F)
+#define TAIKO_A_MBHC_SCALING_MUX_2__POR				(0x80)
+#define TAIKO_A_MAD_ANA_CTRL			(0x150)
+#define TAIKO_A_MAD_ANA_CTRL__POR				(0xF1)
+#define TAIKO_A_TX_SUP_SWITCH_CTRL_1			(0x151)
+#define TAIKO_A_TX_SUP_SWITCH_CTRL_1__POR				(0x00)
+#define TAIKO_A_TX_SUP_SWITCH_CTRL_2			(0x152)
+#define TAIKO_A_TX_SUP_SWITCH_CTRL_2__POR				(0x80)
+#define TAIKO_A_TX_1_2_EN			(0x153)
+#define TAIKO_A_TX_1_2_EN__POR				(0x00)
+#define TAIKO_A_TX_1_2_TEST_EN			(0x154)
+#define TAIKO_A_TX_1_2_TEST_EN__POR				(0xCC)
+#define TAIKO_A_TX_1_2_ADC_CH1			(0x155)
+#define TAIKO_A_TX_1_2_ADC_CH1__POR				(0x44)
+#define TAIKO_A_TX_1_2_ADC_CH2			(0x156)
+#define TAIKO_A_TX_1_2_ADC_CH2__POR				(0x44)
+#define TAIKO_A_TX_1_2_ATEST_REFCTRL			(0x157)
+#define TAIKO_A_TX_1_2_ATEST_REFCTRL__POR				(0x00)
+#define TAIKO_A_TX_1_2_TEST_CTL			(0x158)
+#define TAIKO_A_TX_1_2_TEST_CTL__POR				(0x38)
+#define TAIKO_A_TX_1_2_TEST_BLOCK_EN			(0x159)
+#define TAIKO_A_TX_1_2_TEST_BLOCK_EN__POR				(0xFC)
+#define TAIKO_A_TX_1_2_TXFE_CLKDIV			(0x15A)
+#define TAIKO_A_TX_1_2_TXFE_CLKDIV__POR				(0x55)
+#define TAIKO_A_TX_1_2_SAR_ERR_CH1			(0x15B)
+#define TAIKO_A_TX_1_2_SAR_ERR_CH1__POR				(0x00)
+#define TAIKO_A_TX_1_2_SAR_ERR_CH2			(0x15C)
+#define TAIKO_A_TX_1_2_SAR_ERR_CH2__POR				(0x00)
+#define TAIKO_A_TX_3_4_EN			(0x15D)
+#define TAIKO_A_TX_3_4_EN__POR				(0x00)
+#define TAIKO_A_TX_3_4_TEST_EN			(0x15E)
+#define TAIKO_A_TX_3_4_TEST_EN__POR				(0xCC)
+#define TAIKO_A_TX_3_4_ADC_CH3			(0x15F)
+#define TAIKO_A_TX_3_4_ADC_CH3__POR				(0x44)
+#define TAIKO_A_TX_3_4_ADC_CH4			(0x160)
+#define TAIKO_A_TX_3_4_ADC_CH4__POR				(0x44)
+#define TAIKO_A_TX_3_4_ATEST_REFCTRL			(0x161)
+#define TAIKO_A_TX_3_4_ATEST_REFCTRL__POR				(0x00)
+#define TAIKO_A_TX_3_4_TEST_CTL			(0x162)
+#define TAIKO_A_TX_3_4_TEST_CTL__POR				(0x38)
+#define TAIKO_A_TX_3_4_TEST_BLOCK_EN			(0x163)
+#define TAIKO_A_TX_3_4_TEST_BLOCK_EN__POR				(0xFC)
+#define TAIKO_A_TX_3_4_TXFE_CKDIV			(0x164)
+#define TAIKO_A_TX_3_4_TXFE_CKDIV__POR				(0x55)
+#define TAIKO_A_TX_3_4_SAR_ERR_CH3			(0x165)
+#define TAIKO_A_TX_3_4_SAR_ERR_CH3__POR				(0x00)
+#define TAIKO_A_TX_3_4_SAR_ERR_CH4			(0x166)
+#define TAIKO_A_TX_3_4_SAR_ERR_CH4__POR				(0x00)
+#define TAIKO_A_TX_5_6_EN			(0x167)
+#define TAIKO_A_TX_5_6_EN__POR				(0x11)
+#define TAIKO_A_TX_5_6_TEST_EN			(0x168)
+#define TAIKO_A_TX_5_6_TEST_EN__POR				(0xCC)
+#define TAIKO_A_TX_5_6_ADC_CH5			(0x169)
+#define TAIKO_A_TX_5_6_ADC_CH5__POR				(0x44)
+#define TAIKO_A_TX_5_6_ADC_CH6			(0x16A)
+#define TAIKO_A_TX_5_6_ADC_CH6__POR				(0x44)
+#define TAIKO_A_TX_5_6_ATEST_REFCTRL			(0x16B)
+#define TAIKO_A_TX_5_6_ATEST_REFCTRL__POR				(0x00)
+#define TAIKO_A_TX_5_6_TEST_CTL			(0x16C)
+#define TAIKO_A_TX_5_6_TEST_CTL__POR				(0x38)
+#define TAIKO_A_TX_5_6_TEST_BLOCK_EN			(0x16D)
+#define TAIKO_A_TX_5_6_TEST_BLOCK_EN__POR				(0xFC)
+#define TAIKO_A_TX_5_6_TXFE_CKDIV			(0x16E)
+#define TAIKO_A_TX_5_6_TXFE_CKDIV__POR				(0x55)
+#define TAIKO_A_TX_5_6_SAR_ERR_CH5			(0x16F)
+#define TAIKO_A_TX_5_6_SAR_ERR_CH5__POR				(0x00)
+#define TAIKO_A_TX_5_6_SAR_ERR_CH6			(0x170)
+#define TAIKO_A_TX_5_6_SAR_ERR_CH6__POR				(0x00)
+#define TAIKO_A_TX_7_MBHC_EN			(0x171)
+#define TAIKO_A_TX_7_MBHC_EN__POR				(0x0C)
+#define TAIKO_A_TX_7_MBHC_ATEST_REFCTRL			(0x172)
+#define TAIKO_A_TX_7_MBHC_ATEST_REFCTRL__POR				(0x00)
+#define TAIKO_A_TX_7_MBHC_ADC			(0x173)
+#define TAIKO_A_TX_7_MBHC_ADC__POR				(0x44)
+#define TAIKO_A_TX_7_MBHC_TEST_CTL			(0x174)
+#define TAIKO_A_TX_7_MBHC_TEST_CTL__POR				(0x38)
+#define TAIKO_A_TX_7_MBHC_SAR_ERR			(0x175)
+#define TAIKO_A_TX_7_MBHC_SAR_ERR__POR				(0x00)
+#define TAIKO_A_TX_7_TXFE_CLKDIV			(0x176)
+#define TAIKO_A_TX_7_TXFE_CLKDIV__POR				(0x0B)
+#define TAIKO_A_BUCK_MODE_1			(0x181)
+#define TAIKO_A_BUCK_MODE_1__POR				(0x21)
+#define TAIKO_A_BUCK_MODE_2			(0x182)
+#define TAIKO_A_BUCK_MODE_2__POR				(0xFF)
+#define TAIKO_A_BUCK_MODE_3			(0x183)
+#define TAIKO_A_BUCK_MODE_3__POR				(0xCC)
+#define TAIKO_A_BUCK_MODE_4			(0x184)
+#define TAIKO_A_BUCK_MODE_4__POR				(0x3A)
+#define TAIKO_A_BUCK_MODE_5			(0x185)
+#define TAIKO_A_BUCK_MODE_5__POR				(0x00)
+#define TAIKO_A_BUCK_CTRL_VCL_1			(0x186)
+#define TAIKO_A_BUCK_CTRL_VCL_1__POR				(0x48)
+#define TAIKO_A_BUCK_CTRL_VCL_2			(0x187)
+#define TAIKO_A_BUCK_CTRL_VCL_2__POR				(0xA3)
+#define TAIKO_A_BUCK_CTRL_VCL_3			(0x188)
+#define TAIKO_A_BUCK_CTRL_VCL_3__POR				(0x82)
+#define TAIKO_A_BUCK_CTRL_CCL_1			(0x189)
+#define TAIKO_A_BUCK_CTRL_CCL_1__POR				(0xAB)
+#define TAIKO_A_BUCK_CTRL_CCL_2			(0x18A)
+#define TAIKO_A_BUCK_CTRL_CCL_2__POR				(0xDC)
+#define TAIKO_A_BUCK_CTRL_CCL_3			(0x18B)
+#define TAIKO_A_BUCK_CTRL_CCL_3__POR				(0x6A)
+#define TAIKO_A_BUCK_CTRL_CCL_4			(0x18C)
+#define TAIKO_A_BUCK_CTRL_CCL_4__POR				(0x58)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_1			(0x18D)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_1__POR				(0x50)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_2			(0x18E)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_2__POR				(0x64)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_3			(0x18F)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_3__POR				(0x77)
+#define TAIKO_A_BUCK_TMUX_A_D			(0x190)
+#define TAIKO_A_BUCK_TMUX_A_D__POR				(0x00)
+#define TAIKO_A_NCP_BUCKREF			(0x191)
+#define TAIKO_A_NCP_BUCKREF__POR				(0x00)
+#define TAIKO_A_NCP_EN			(0x192)
+#define TAIKO_A_NCP_EN__POR				(0xFE)
+#define TAIKO_A_NCP_CLK			(0x193)
+#define TAIKO_A_NCP_CLK__POR				(0x94)
+#define TAIKO_A_NCP_STATIC			(0x194)
+#define TAIKO_A_NCP_STATIC__POR				(0x28)
+#define TAIKO_A_NCP_VTH_LOW			(0x195)
+#define TAIKO_A_NCP_VTH_LOW__POR				(0x88)
+#define TAIKO_A_NCP_VTH_HIGH			(0x196)
+#define TAIKO_A_NCP_VTH_HIGH__POR				(0xA0)
+#define TAIKO_A_NCP_ATEST			(0x197)
+#define TAIKO_A_NCP_ATEST__POR				(0x00)
+#define TAIKO_A_NCP_DTEST			(0x198)
+#define TAIKO_A_NCP_DTEST__POR				(0x00)
+#define TAIKO_A_NCP_DLY1			(0x199)
+#define TAIKO_A_NCP_DLY1__POR				(0x06)
+#define TAIKO_A_NCP_DLY2			(0x19A)
+#define TAIKO_A_NCP_DLY2__POR				(0x06)
+#define TAIKO_A_RX_AUX_SW_CTL			(0x19B)
+#define TAIKO_A_RX_AUX_SW_CTL__POR				(0x00)
+#define TAIKO_A_RX_PA_AUX_IN_CONN			(0x19C)
+#define TAIKO_A_RX_PA_AUX_IN_CONN__POR				(0x00)
+#define TAIKO_A_RX_COM_TIMER_DIV			(0x19E)
+#define TAIKO_A_RX_COM_TIMER_DIV__POR				(0xE8)
+#define TAIKO_A_RX_COM_OCP_CTL			(0x19F)
+#define TAIKO_A_RX_COM_OCP_CTL__POR				(0x1F)
+#define TAIKO_A_RX_COM_OCP_COUNT			(0x1A0)
+#define TAIKO_A_RX_COM_OCP_COUNT__POR				(0x77)
+#define TAIKO_A_RX_COM_DAC_CTL			(0x1A1)
+#define TAIKO_A_RX_COM_DAC_CTL__POR				(0x00)
+#define TAIKO_A_RX_COM_BIAS			(0x1A2)
+#define TAIKO_A_RX_COM_BIAS__POR				(0x00)
+#define TAIKO_A_RX_HPH_AUTO_CHOP			(0x1A4)
+#define TAIKO_A_RX_HPH_AUTO_CHOP__POR				(0x38)
+#define TAIKO_A_RX_HPH_CHOP_CTL			(0x1A5)
+#define TAIKO_A_RX_HPH_CHOP_CTL__POR				(0xB4)
+#define TAIKO_A_RX_HPH_BIAS_PA			(0x1A6)
+#define TAIKO_A_RX_HPH_BIAS_PA__POR				(0xAA)
+#define TAIKO_A_RX_HPH_BIAS_LDO			(0x1A7)
+#define TAIKO_A_RX_HPH_BIAS_LDO__POR				(0x87)
+#define TAIKO_A_RX_HPH_BIAS_CNP			(0x1A8)
+#define TAIKO_A_RX_HPH_BIAS_CNP__POR				(0x8A)
+#define TAIKO_A_RX_HPH_BIAS_WG_OCP			(0x1A9)
+#define TAIKO_A_RX_HPH_BIAS_WG_OCP__POR				(0x2A)
+#define TAIKO_A_RX_HPH_OCP_CTL			(0x1AA)
+#define TAIKO_A_RX_HPH_OCP_CTL__POR				(0x68)
+#define TAIKO_A_RX_HPH_CNP_EN			(0x1AB)
+#define TAIKO_A_RX_HPH_CNP_EN__POR				(0x80)
+#define TAIKO_A_RX_HPH_CNP_WG_CTL			(0x1AC)
+#define TAIKO_A_RX_HPH_CNP_WG_CTL__POR				(0xDE)
+#define TAIKO_A_RX_HPH_CNP_WG_TIME			(0x1AD)
+#define TAIKO_A_RX_HPH_CNP_WG_TIME__POR				(0x2A)
+#define TAIKO_A_RX_HPH_L_GAIN			(0x1AE)
+#define TAIKO_A_RX_HPH_L_GAIN__POR				(0x00)
+#define TAIKO_A_RX_HPH_L_TEST			(0x1AF)
+#define TAIKO_A_RX_HPH_L_TEST__POR				(0x00)
+#define TAIKO_A_RX_HPH_L_PA_CTL			(0x1B0)
+#define TAIKO_A_RX_HPH_L_PA_CTL__POR				(0x40)
+#define TAIKO_A_RX_HPH_L_DAC_CTL			(0x1B1)
+#define TAIKO_A_RX_HPH_L_DAC_CTL__POR				(0x00)
+#define TAIKO_A_RX_HPH_L_ATEST			(0x1B2)
+#define TAIKO_A_RX_HPH_L_ATEST__POR				(0x00)
+#define TAIKO_A_RX_HPH_L_STATUS			(0x1B3)
+#define TAIKO_A_RX_HPH_L_STATUS__POR				(0x00)
+#define TAIKO_A_RX_HPH_R_GAIN			(0x1B4)
+#define TAIKO_A_RX_HPH_R_GAIN__POR				(0x00)
+#define TAIKO_A_RX_HPH_R_TEST			(0x1B5)
+#define TAIKO_A_RX_HPH_R_TEST__POR				(0x00)
+#define TAIKO_A_RX_HPH_R_PA_CTL			(0x1B6)
+#define TAIKO_A_RX_HPH_R_PA_CTL__POR				(0x40)
+#define TAIKO_A_RX_HPH_R_DAC_CTL			(0x1B7)
+#define TAIKO_A_RX_HPH_R_DAC_CTL__POR				(0x00)
+#define TAIKO_A_RX_HPH_R_ATEST			(0x1B8)
+#define TAIKO_A_RX_HPH_R_ATEST__POR				(0x00)
+#define TAIKO_A_RX_HPH_R_STATUS			(0x1B9)
+#define TAIKO_A_RX_HPH_R_STATUS__POR				(0x00)
+#define TAIKO_A_RX_EAR_BIAS_PA			(0x1BA)
+#define TAIKO_A_RX_EAR_BIAS_PA__POR				(0xA6)
+#define TAIKO_A_RX_EAR_BIAS_CMBUFF			(0x1BB)
+#define TAIKO_A_RX_EAR_BIAS_CMBUFF__POR				(0xA0)
+#define TAIKO_A_RX_EAR_EN			(0x1BC)
+#define TAIKO_A_RX_EAR_EN__POR				(0x00)
+#define TAIKO_A_RX_EAR_GAIN			(0x1BD)
+#define TAIKO_A_RX_EAR_GAIN__POR				(0x02)
+#define TAIKO_A_RX_EAR_CMBUFF			(0x1BE)
+#define TAIKO_A_RX_EAR_CMBUFF__POR				(0x04)
+#define TAIKO_A_RX_EAR_ICTL			(0x1BF)
+#define TAIKO_A_RX_EAR_ICTL__POR				(0x40)
+#define TAIKO_A_RX_EAR_CCOMP			(0x1C0)
+#define TAIKO_A_RX_EAR_CCOMP__POR				(0x08)
+#define TAIKO_A_RX_EAR_VCM			(0x1C1)
+#define TAIKO_A_RX_EAR_VCM__POR				(0x03)
+#define TAIKO_A_RX_EAR_CNP			(0x1C2)
+#define TAIKO_A_RX_EAR_CNP__POR				(0xF2)
+#define TAIKO_A_RX_EAR_DAC_CTL_ATEST			(0x1C3)
+#define TAIKO_A_RX_EAR_DAC_CTL_ATEST__POR				(0x00)
+#define TAIKO_A_RX_EAR_STATUS			(0x1C5)
+#define TAIKO_A_RX_EAR_STATUS__POR				(0x04)
+#define TAIKO_A_RX_LINE_BIAS_PA			(0x1C6)
+#define TAIKO_A_RX_LINE_BIAS_PA__POR				(0xA8)
+#define TAIKO_A_RX_BUCK_BIAS1			(0x1C7)
+#define TAIKO_A_RX_BUCK_BIAS1__POR				(0x42)
+#define TAIKO_A_RX_BUCK_BIAS2			(0x1C8)
+#define TAIKO_A_RX_BUCK_BIAS2__POR				(0x84)
+#define TAIKO_A_RX_LINE_COM			(0x1C9)
+#define TAIKO_A_RX_LINE_COM__POR				(0x80)
+#define TAIKO_A_RX_LINE_CNP_EN			(0x1CA)
+#define TAIKO_A_RX_LINE_CNP_EN__POR				(0x00)
+#define TAIKO_A_RX_LINE_CNP_WG_CTL			(0x1CB)
+#define TAIKO_A_RX_LINE_CNP_WG_CTL__POR				(0x00)
+#define TAIKO_A_RX_LINE_CNP_WG_TIME			(0x1CC)
+#define TAIKO_A_RX_LINE_CNP_WG_TIME__POR				(0x04)
+#define TAIKO_A_RX_LINE_1_GAIN			(0x1CD)
+#define TAIKO_A_RX_LINE_1_GAIN__POR				(0x00)
+#define TAIKO_A_RX_LINE_1_TEST			(0x1CE)
+#define TAIKO_A_RX_LINE_1_TEST__POR				(0x00)
+#define TAIKO_A_RX_LINE_1_DAC_CTL			(0x1CF)
+#define TAIKO_A_RX_LINE_1_DAC_CTL__POR				(0x00)
+#define TAIKO_A_RX_LINE_1_STATUS			(0x1D0)
+#define TAIKO_A_RX_LINE_1_STATUS__POR				(0x00)
+#define TAIKO_A_RX_LINE_2_GAIN			(0x1D1)
+#define TAIKO_A_RX_LINE_2_GAIN__POR				(0x00)
+#define TAIKO_A_RX_LINE_2_TEST			(0x1D2)
+#define TAIKO_A_RX_LINE_2_TEST__POR				(0x00)
+#define TAIKO_A_RX_LINE_2_DAC_CTL			(0x1D3)
+#define TAIKO_A_RX_LINE_2_DAC_CTL__POR				(0x00)
+#define TAIKO_A_RX_LINE_2_STATUS			(0x1D4)
+#define TAIKO_A_RX_LINE_2_STATUS__POR				(0x00)
+#define TAIKO_A_RX_LINE_3_GAIN			(0x1D5)
+#define TAIKO_A_RX_LINE_3_GAIN__POR				(0x00)
+#define TAIKO_A_RX_LINE_3_TEST			(0x1D6)
+#define TAIKO_A_RX_LINE_3_TEST__POR				(0x00)
+#define TAIKO_A_RX_LINE_3_DAC_CTL			(0x1D7)
+#define TAIKO_A_RX_LINE_3_DAC_CTL__POR				(0x00)
+#define TAIKO_A_RX_LINE_3_STATUS			(0x1D8)
+#define TAIKO_A_RX_LINE_3_STATUS__POR				(0x00)
+#define TAIKO_A_RX_LINE_4_GAIN			(0x1D9)
+#define TAIKO_A_RX_LINE_4_GAIN__POR				(0x00)
+#define TAIKO_A_RX_LINE_4_TEST			(0x1DA)
+#define TAIKO_A_RX_LINE_4_TEST__POR				(0x00)
+#define TAIKO_A_RX_LINE_4_DAC_CTL			(0x1DB)
+#define TAIKO_A_RX_LINE_4_DAC_CTL__POR				(0x00)
+#define TAIKO_A_RX_LINE_4_STATUS			(0x1DC)
+#define TAIKO_A_RX_LINE_4_STATUS__POR				(0x00)
+#define TAIKO_A_RX_LINE_CNP_DBG			(0x1DD)
+#define TAIKO_A_RX_LINE_CNP_DBG__POR				(0x00)
+#define TAIKO_A_SPKR_DRV_EN			(0x1DF)
+#define TAIKO_A_SPKR_DRV_EN__POR				(0x6F)
+#define TAIKO_A_SPKR_DRV_GAIN			(0x1E0)
+#define TAIKO_A_SPKR_DRV_GAIN__POR				(0x00)
+#define TAIKO_A_SPKR_DRV_DAC_CTL			(0x1E1)
+#define TAIKO_A_SPKR_DRV_DAC_CTL__POR				(0x04)
+#define TAIKO_A_SPKR_DRV_OCP_CTL			(0x1E2)
+#define TAIKO_A_SPKR_DRV_OCP_CTL__POR				(0x98)
+#define TAIKO_A_SPKR_DRV_CLIP_DET			(0x1E3)
+#define TAIKO_A_SPKR_DRV_CLIP_DET__POR				(0x48)
+#define TAIKO_A_SPKR_DRV_IEC			(0x1E4)
+#define TAIKO_A_SPKR_DRV_IEC__POR				(0x20)
+#define TAIKO_A_SPKR_DRV_DBG_DAC			(0x1E5)
+#define TAIKO_A_SPKR_DRV_DBG_DAC__POR				(0x05)
+#define TAIKO_A_SPKR_DRV_DBG_PA			(0x1E6)
+#define TAIKO_A_SPKR_DRV_DBG_PA__POR				(0x18)
+#define TAIKO_A_SPKR_DRV_DBG_PWRSTG			(0x1E7)
+#define TAIKO_A_SPKR_DRV_DBG_PWRSTG__POR				(0x00)
+#define TAIKO_A_SPKR_DRV_BIAS_LDO			(0x1E8)
+#define TAIKO_A_SPKR_DRV_BIAS_LDO__POR				(0x45)
+#define TAIKO_A_SPKR_DRV_BIAS_INT			(0x1E9)
+#define TAIKO_A_SPKR_DRV_BIAS_INT__POR				(0xA5)
+#define TAIKO_A_SPKR_DRV_BIAS_PA			(0x1EA)
+#define TAIKO_A_SPKR_DRV_BIAS_PA__POR				(0x55)
+#define TAIKO_A_SPKR_DRV_STATUS_OCP			(0x1EB)
+#define TAIKO_A_SPKR_DRV_STATUS_OCP__POR				(0x00)
+#define TAIKO_A_SPKR_DRV_STATUS_PA			(0x1EC)
+#define TAIKO_A_SPKR_DRV_STATUS_PA__POR				(0x00)
+#define TAIKO_A_SPKR_PROT_EN			(0x1ED)
+#define TAIKO_A_SPKR_PROT_EN__POR				(0x00)
+#define TAIKO_A_SPKR_PROT_ADC_EN			(0x1EE)
+#define TAIKO_A_SPKR_PROT_ADC_EN__POR				(0x44)
+#define TAIKO_A_SPKR_PROT_ISENSE_BIAS			(0x1EF)
+#define TAIKO_A_SPKR_PROT_ISENSE_BIAS__POR				(0x44)
+#define TAIKO_A_SPKR_PROT_VSENSE_BIAS			(0x1F0)
+#define TAIKO_A_SPKR_PROT_VSENSE_BIAS__POR				(0x44)
+#define TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL			(0x1F1)
+#define TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL__POR			(0x00)
+#define TAIKO_A_SPKR_PROT_ADC_TEST_CTL			(0x1F2)
+#define TAIKO_A_SPKR_PROT_ADC_TEST_CTL__POR				(0x38)
+#define TAIKO_A_SPKR_PROT_TEST_BLOCK_EN			(0x1F3)
+#define TAIKO_A_SPKR_PROT_TEST_BLOCK_EN__POR				(0xFC)
+#define TAIKO_A_SPKR_PROT_ATEST			(0x1F4)
+#define TAIKO_A_SPKR_PROT_ATEST__POR				(0x00)
+#define TAIKO_A_SPKR_PROT_V_SAR_ERR			(0x1F5)
+#define TAIKO_A_SPKR_PROT_V_SAR_ERR__POR				(0x00)
+#define TAIKO_A_SPKR_PROT_I_SAR_ERR			(0x1F6)
+#define TAIKO_A_SPKR_PROT_I_SAR_ERR__POR				(0x00)
+#define TAIKO_A_SPKR_PROT_LDO_CTRL			(0x1F7)
+#define TAIKO_A_SPKR_PROT_LDO_CTRL__POR				(0x00)
+#define TAIKO_A_SPKR_PROT_ISENSE_CTRL			(0x1F8)
+#define TAIKO_A_SPKR_PROT_ISENSE_CTRL__POR				(0x00)
+#define TAIKO_A_SPKR_PROT_VSENSE_CTRL			(0x1F9)
+#define TAIKO_A_SPKR_PROT_VSENSE_CTRL__POR				(0x00)
+#define TAIKO_A_RC_OSC_FREQ			(0x1FA)
+#define TAIKO_A_RC_OSC_FREQ__POR				(0x46)
+#define TAIKO_A_RC_OSC_TEST			(0x1FB)
+#define TAIKO_A_RC_OSC_TEST__POR				(0x0A)
+#define TAIKO_A_RC_OSC_STATUS			(0x1FC)
+#define TAIKO_A_RC_OSC_STATUS__POR				(0x18)
+#define TAIKO_A_RC_OSC_TUNER			(0x1FD)
+#define TAIKO_A_RC_OSC_TUNER__POR				(0x00)
+#define TAIKO_A_MBHC_HPH			(0x1FE)
+#define TAIKO_A_MBHC_HPH__POR				(0x44)
+#define TAIKO_A_CDC_ANC1_B1_CTL			(0x200)
+#define TAIKO_A_CDC_ANC1_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_B1_CTL			(0x280)
+#define TAIKO_A_CDC_ANC2_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_SHIFT			(0x201)
+#define TAIKO_A_CDC_ANC1_SHIFT__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_SHIFT			(0x281)
+#define TAIKO_A_CDC_ANC2_SHIFT__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_IIR_B1_CTL			(0x202)
+#define TAIKO_A_CDC_ANC1_IIR_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_IIR_B1_CTL			(0x282)
+#define TAIKO_A_CDC_ANC2_IIR_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_IIR_B2_CTL			(0x203)
+#define TAIKO_A_CDC_ANC1_IIR_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_IIR_B2_CTL			(0x283)
+#define TAIKO_A_CDC_ANC2_IIR_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_IIR_B3_CTL			(0x204)
+#define TAIKO_A_CDC_ANC1_IIR_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_IIR_B3_CTL			(0x284)
+#define TAIKO_A_CDC_ANC2_IIR_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_LPF_B1_CTL			(0x206)
+#define TAIKO_A_CDC_ANC1_LPF_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_LPF_B1_CTL			(0x286)
+#define TAIKO_A_CDC_ANC2_LPF_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_LPF_B2_CTL			(0x207)
+#define TAIKO_A_CDC_ANC1_LPF_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_LPF_B2_CTL			(0x287)
+#define TAIKO_A_CDC_ANC2_LPF_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_SPARE			(0x209)
+#define TAIKO_A_CDC_ANC1_SPARE__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_SPARE			(0x289)
+#define TAIKO_A_CDC_ANC2_SPARE__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_SMLPF_CTL			(0x20A)
+#define TAIKO_A_CDC_ANC1_SMLPF_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_SMLPF_CTL			(0x28A)
+#define TAIKO_A_CDC_ANC2_SMLPF_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_DCFLT_CTL			(0x20B)
+#define TAIKO_A_CDC_ANC1_DCFLT_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_DCFLT_CTL			(0x28B)
+#define TAIKO_A_CDC_ANC2_DCFLT_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_GAIN_CTL			(0x20C)
+#define TAIKO_A_CDC_ANC1_GAIN_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_GAIN_CTL			(0x28C)
+#define TAIKO_A_CDC_ANC2_GAIN_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC1_B2_CTL			(0x20D)
+#define TAIKO_A_CDC_ANC1_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_ANC2_B2_CTL			(0x28D)
+#define TAIKO_A_CDC_ANC2_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX1_VOL_CTL_TIMER			(0x220)
+#define TAIKO_A_CDC_TX1_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX2_VOL_CTL_TIMER			(0x228)
+#define TAIKO_A_CDC_TX2_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX3_VOL_CTL_TIMER			(0x230)
+#define TAIKO_A_CDC_TX3_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX4_VOL_CTL_TIMER			(0x238)
+#define TAIKO_A_CDC_TX4_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX5_VOL_CTL_TIMER			(0x240)
+#define TAIKO_A_CDC_TX5_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX6_VOL_CTL_TIMER			(0x248)
+#define TAIKO_A_CDC_TX6_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX7_VOL_CTL_TIMER			(0x250)
+#define TAIKO_A_CDC_TX7_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX8_VOL_CTL_TIMER			(0x258)
+#define TAIKO_A_CDC_TX8_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX9_VOL_CTL_TIMER			(0x260)
+#define TAIKO_A_CDC_TX9_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX10_VOL_CTL_TIMER			(0x268)
+#define TAIKO_A_CDC_TX10_VOL_CTL_TIMER__POR				(0x00)
+#define TAIKO_A_CDC_TX1_VOL_CTL_GAIN			(0x221)
+#define TAIKO_A_CDC_TX1_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX2_VOL_CTL_GAIN			(0x229)
+#define TAIKO_A_CDC_TX2_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX3_VOL_CTL_GAIN			(0x231)
+#define TAIKO_A_CDC_TX3_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX4_VOL_CTL_GAIN			(0x239)
+#define TAIKO_A_CDC_TX4_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX5_VOL_CTL_GAIN			(0x241)
+#define TAIKO_A_CDC_TX5_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX6_VOL_CTL_GAIN			(0x249)
+#define TAIKO_A_CDC_TX6_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX7_VOL_CTL_GAIN			(0x251)
+#define TAIKO_A_CDC_TX7_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX8_VOL_CTL_GAIN			(0x259)
+#define TAIKO_A_CDC_TX8_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX9_VOL_CTL_GAIN			(0x261)
+#define TAIKO_A_CDC_TX9_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX10_VOL_CTL_GAIN			(0x269)
+#define TAIKO_A_CDC_TX10_VOL_CTL_GAIN__POR				(0x00)
+#define TAIKO_A_CDC_TX1_VOL_CTL_CFG			(0x222)
+#define TAIKO_A_CDC_TX1_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX2_VOL_CTL_CFG			(0x22A)
+#define TAIKO_A_CDC_TX2_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX3_VOL_CTL_CFG			(0x232)
+#define TAIKO_A_CDC_TX3_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX4_VOL_CTL_CFG			(0x23A)
+#define TAIKO_A_CDC_TX4_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX5_VOL_CTL_CFG			(0x242)
+#define TAIKO_A_CDC_TX5_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX6_VOL_CTL_CFG			(0x24A)
+#define TAIKO_A_CDC_TX6_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX7_VOL_CTL_CFG			(0x252)
+#define TAIKO_A_CDC_TX7_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX8_VOL_CTL_CFG			(0x25A)
+#define TAIKO_A_CDC_TX8_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX9_VOL_CTL_CFG			(0x262)
+#define TAIKO_A_CDC_TX9_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX10_VOL_CTL_CFG			(0x26A)
+#define TAIKO_A_CDC_TX10_VOL_CTL_CFG__POR				(0x00)
+#define TAIKO_A_CDC_TX1_MUX_CTL			(0x223)
+#define TAIKO_A_CDC_TX1_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX2_MUX_CTL			(0x22B)
+#define TAIKO_A_CDC_TX2_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX3_MUX_CTL			(0x233)
+#define TAIKO_A_CDC_TX3_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX4_MUX_CTL			(0x23B)
+#define TAIKO_A_CDC_TX4_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX5_MUX_CTL			(0x243)
+#define TAIKO_A_CDC_TX5_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX6_MUX_CTL			(0x24B)
+#define TAIKO_A_CDC_TX6_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX7_MUX_CTL			(0x253)
+#define TAIKO_A_CDC_TX7_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX8_MUX_CTL			(0x25B)
+#define TAIKO_A_CDC_TX8_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX9_MUX_CTL			(0x263)
+#define TAIKO_A_CDC_TX9_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX10_MUX_CTL			(0x26B)
+#define TAIKO_A_CDC_TX10_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX1_CLK_FS_CTL			(0x224)
+#define TAIKO_A_CDC_TX1_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX2_CLK_FS_CTL			(0x22C)
+#define TAIKO_A_CDC_TX2_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX3_CLK_FS_CTL			(0x234)
+#define TAIKO_A_CDC_TX3_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX4_CLK_FS_CTL			(0x23C)
+#define TAIKO_A_CDC_TX4_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX5_CLK_FS_CTL			(0x244)
+#define TAIKO_A_CDC_TX5_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX6_CLK_FS_CTL			(0x24C)
+#define TAIKO_A_CDC_TX6_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX7_CLK_FS_CTL			(0x254)
+#define TAIKO_A_CDC_TX7_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX8_CLK_FS_CTL			(0x25C)
+#define TAIKO_A_CDC_TX8_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX9_CLK_FS_CTL			(0x264)
+#define TAIKO_A_CDC_TX9_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX10_CLK_FS_CTL			(0x26C)
+#define TAIKO_A_CDC_TX10_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX1_DMIC_CTL			(0x225)
+#define TAIKO_A_CDC_TX1_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX2_DMIC_CTL			(0x22D)
+#define TAIKO_A_CDC_TX2_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX3_DMIC_CTL			(0x235)
+#define TAIKO_A_CDC_TX3_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX4_DMIC_CTL			(0x23D)
+#define TAIKO_A_CDC_TX4_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX5_DMIC_CTL			(0x245)
+#define TAIKO_A_CDC_TX5_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX6_DMIC_CTL			(0x24D)
+#define TAIKO_A_CDC_TX6_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX7_DMIC_CTL			(0x255)
+#define TAIKO_A_CDC_TX7_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX8_DMIC_CTL			(0x25D)
+#define TAIKO_A_CDC_TX8_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX9_DMIC_CTL			(0x265)
+#define TAIKO_A_CDC_TX9_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX10_DMIC_CTL			(0x26D)
+#define TAIKO_A_CDC_TX10_DMIC_CTL__POR				(0x00)
+#define TAIKO_A_CDC_DEBUG_B1_CTL			(0x278)
+#define TAIKO_A_CDC_DEBUG_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_DEBUG_B2_CTL			(0x279)
+#define TAIKO_A_CDC_DEBUG_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_DEBUG_B3_CTL			(0x27A)
+#define TAIKO_A_CDC_DEBUG_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_DEBUG_B4_CTL			(0x27B)
+#define TAIKO_A_CDC_DEBUG_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_DEBUG_B5_CTL			(0x27C)
+#define TAIKO_A_CDC_DEBUG_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_DEBUG_B6_CTL			(0x27D)
+#define TAIKO_A_CDC_DEBUG_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_DEBUG_B7_CTL			(0x27E)
+#define TAIKO_A_CDC_DEBUG_B7_CTL__POR				(0x00)
+#define TAIKO_A_CDC_SRC1_PDA_CFG			(0x2A0)
+#define TAIKO_A_CDC_SRC1_PDA_CFG__POR				(0x00)
+#define TAIKO_A_CDC_SRC2_PDA_CFG			(0x2A8)
+#define TAIKO_A_CDC_SRC2_PDA_CFG__POR				(0x00)
+#define TAIKO_A_CDC_SRC1_FS_CTL			(0x2A1)
+#define TAIKO_A_CDC_SRC1_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_SRC2_FS_CTL			(0x2A9)
+#define TAIKO_A_CDC_SRC2_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_B1_CTL			(0x2B0)
+#define TAIKO_A_CDC_RX1_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_B1_CTL			(0x2B8)
+#define TAIKO_A_CDC_RX2_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_B1_CTL			(0x2C0)
+#define TAIKO_A_CDC_RX3_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_B1_CTL			(0x2C8)
+#define TAIKO_A_CDC_RX4_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_B1_CTL			(0x2D0)
+#define TAIKO_A_CDC_RX5_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_B1_CTL			(0x2D8)
+#define TAIKO_A_CDC_RX6_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_B1_CTL			(0x2E0)
+#define TAIKO_A_CDC_RX7_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_B2_CTL			(0x2B1)
+#define TAIKO_A_CDC_RX1_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_B2_CTL			(0x2B9)
+#define TAIKO_A_CDC_RX2_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_B2_CTL			(0x2C1)
+#define TAIKO_A_CDC_RX3_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_B2_CTL			(0x2C9)
+#define TAIKO_A_CDC_RX4_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_B2_CTL			(0x2D1)
+#define TAIKO_A_CDC_RX5_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_B2_CTL			(0x2D9)
+#define TAIKO_A_CDC_RX6_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_B2_CTL			(0x2E1)
+#define TAIKO_A_CDC_RX7_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_B3_CTL			(0x2B2)
+#define TAIKO_A_CDC_RX1_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_B3_CTL			(0x2BA)
+#define TAIKO_A_CDC_RX2_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_B3_CTL			(0x2C2)
+#define TAIKO_A_CDC_RX3_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_B3_CTL			(0x2CA)
+#define TAIKO_A_CDC_RX4_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_B3_CTL			(0x2D2)
+#define TAIKO_A_CDC_RX5_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_B3_CTL			(0x2DA)
+#define TAIKO_A_CDC_RX6_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_B3_CTL			(0x2E2)
+#define TAIKO_A_CDC_RX7_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_B4_CTL			(0x2B3)
+#define TAIKO_A_CDC_RX1_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_B4_CTL			(0x2BB)
+#define TAIKO_A_CDC_RX2_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_B4_CTL			(0x2C3)
+#define TAIKO_A_CDC_RX3_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_B4_CTL			(0x2CB)
+#define TAIKO_A_CDC_RX4_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_B4_CTL			(0x2D3)
+#define TAIKO_A_CDC_RX5_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_B4_CTL			(0x2DB)
+#define TAIKO_A_CDC_RX6_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_B4_CTL			(0x2E3)
+#define TAIKO_A_CDC_RX7_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_B5_CTL			(0x2B4)
+#define TAIKO_A_CDC_RX1_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_B5_CTL			(0x2BC)
+#define TAIKO_A_CDC_RX2_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_B5_CTL			(0x2C4)
+#define TAIKO_A_CDC_RX3_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_B5_CTL			(0x2CC)
+#define TAIKO_A_CDC_RX4_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_B5_CTL			(0x2D4)
+#define TAIKO_A_CDC_RX5_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_B5_CTL			(0x2DC)
+#define TAIKO_A_CDC_RX6_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_B5_CTL			(0x2E4)
+#define TAIKO_A_CDC_RX7_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_B6_CTL			(0x2B5)
+#define TAIKO_A_CDC_RX1_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_B6_CTL			(0x2BD)
+#define TAIKO_A_CDC_RX2_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_B6_CTL			(0x2C5)
+#define TAIKO_A_CDC_RX3_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_B6_CTL			(0x2CD)
+#define TAIKO_A_CDC_RX4_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_B6_CTL			(0x2D5)
+#define TAIKO_A_CDC_RX5_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_B6_CTL			(0x2DD)
+#define TAIKO_A_CDC_RX6_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_B6_CTL			(0x2E5)
+#define TAIKO_A_CDC_RX7_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL			(0x2B6)
+#define TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL			(0x2BE)
+#define TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL			(0x2C6)
+#define TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL			(0x2CE)
+#define TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL			(0x2D6)
+#define TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL			(0x2DE)
+#define TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL			(0x2E6)
+#define TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL			(0x2B7)
+#define TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL			(0x2BF)
+#define TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL			(0x2C7)
+#define TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL			(0x2CF)
+#define TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL			(0x2D7)
+#define TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL			(0x2DF)
+#define TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL			(0x2E7)
+#define TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_VBAT_CFG			(0x2E8)
+#define TAIKO_A_CDC_VBAT_CFG__POR				(0x1A)
+#define TAIKO_A_CDC_VBAT_ADC_CAL1			(0x2E9)
+#define TAIKO_A_CDC_VBAT_ADC_CAL1__POR				(0x00)
+#define TAIKO_A_CDC_VBAT_ADC_CAL2			(0x2EA)
+#define TAIKO_A_CDC_VBAT_ADC_CAL2__POR				(0x00)
+#define TAIKO_A_CDC_VBAT_ADC_CAL3			(0x2EB)
+#define TAIKO_A_CDC_VBAT_ADC_CAL3__POR				(0x04)
+#define TAIKO_A_CDC_VBAT_PK_EST1			(0x2EC)
+#define TAIKO_A_CDC_VBAT_PK_EST1__POR				(0xE0)
+#define TAIKO_A_CDC_VBAT_PK_EST2			(0x2ED)
+#define TAIKO_A_CDC_VBAT_PK_EST2__POR				(0x01)
+#define TAIKO_A_CDC_VBAT_PK_EST3			(0x2EE)
+#define TAIKO_A_CDC_VBAT_PK_EST3__POR				(0x40)
+#define TAIKO_A_CDC_VBAT_RF_PROC1			(0x2EF)
+#define TAIKO_A_CDC_VBAT_RF_PROC1__POR				(0x2A)
+#define TAIKO_A_CDC_VBAT_RF_PROC2			(0x2F0)
+#define TAIKO_A_CDC_VBAT_RF_PROC2__POR				(0x86)
+#define TAIKO_A_CDC_VBAT_TAC1			(0x2F1)
+#define TAIKO_A_CDC_VBAT_TAC1__POR				(0x70)
+#define TAIKO_A_CDC_VBAT_TAC2			(0x2F2)
+#define TAIKO_A_CDC_VBAT_TAC2__POR				(0x18)
+#define TAIKO_A_CDC_VBAT_TAC3			(0x2F3)
+#define TAIKO_A_CDC_VBAT_TAC3__POR				(0x18)
+#define TAIKO_A_CDC_VBAT_TAC4			(0x2F4)
+#define TAIKO_A_CDC_VBAT_TAC4__POR				(0x03)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD1			(0x2F5)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD1__POR				(0x01)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD2			(0x2F6)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD2__POR				(0x00)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD3			(0x2F7)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD3__POR				(0x64)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD4			(0x2F8)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD4__POR				(0x01)
+#define TAIKO_A_CDC_VBAT_DEBUG1			(0x2F9)
+#define TAIKO_A_CDC_VBAT_DEBUG1__POR				(0x00)
+#define TAIKO_A_CDC_CLK_ANC_RESET_CTL			(0x300)
+#define TAIKO_A_CDC_CLK_ANC_RESET_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_RX_RESET_CTL			(0x301)
+#define TAIKO_A_CDC_CLK_RX_RESET_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_TX_RESET_B1_CTL			(0x302)
+#define TAIKO_A_CDC_CLK_TX_RESET_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_TX_RESET_B2_CTL			(0x303)
+#define TAIKO_A_CDC_CLK_TX_RESET_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_DMIC_B1_CTL			(0x304)
+#define TAIKO_A_CDC_CLK_DMIC_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_DMIC_B2_CTL			(0x305)
+#define TAIKO_A_CDC_CLK_DMIC_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_RX_I2S_CTL			(0x306)
+#define TAIKO_A_CDC_CLK_RX_I2S_CTL__POR				(0x03)
+#define TAIKO_A_CDC_CLK_TX_I2S_CTL			(0x307)
+#define TAIKO_A_CDC_CLK_TX_I2S_CTL__POR				(0x03)
+#define TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL			(0x308)
+#define TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL			(0x309)
+#define TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL			(0x30A)
+#define TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL			(0x30B)
+#define TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_OTHR_CTL			(0x30C)
+#define TAIKO_A_CDC_CLK_OTHR_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL			(0x30D)
+#define TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL			(0x30E)
+#define TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_RX_B1_CTL			(0x30F)
+#define TAIKO_A_CDC_CLK_RX_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_RX_B2_CTL			(0x310)
+#define TAIKO_A_CDC_CLK_RX_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_MCLK_CTL			(0x311)
+#define TAIKO_A_CDC_CLK_MCLK_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_PDM_CTL			(0x312)
+#define TAIKO_A_CDC_CLK_PDM_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_SD_CTL			(0x313)
+#define TAIKO_A_CDC_CLK_SD_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLK_POWER_CTL			(0x314)
+#define TAIKO_A_CDC_CLK_POWER_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLSH_B1_CTL			(0x320)
+#define TAIKO_A_CDC_CLSH_B1_CTL__POR				(0xE4)
+#define TAIKO_A_CDC_CLSH_B2_CTL			(0x321)
+#define TAIKO_A_CDC_CLSH_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLSH_B3_CTL			(0x322)
+#define TAIKO_A_CDC_CLSH_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CLSH_BUCK_NCP_VARS			(0x323)
+#define TAIKO_A_CDC_CLSH_BUCK_NCP_VARS__POR				(0x00)
+#define TAIKO_A_CDC_CLSH_IDLE_HPH_THSD			(0x324)
+#define TAIKO_A_CDC_CLSH_IDLE_HPH_THSD__POR				(0x12)
+#define TAIKO_A_CDC_CLSH_IDLE_EAR_THSD			(0x325)
+#define TAIKO_A_CDC_CLSH_IDLE_EAR_THSD__POR				(0x0C)
+#define TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD			(0x326)
+#define TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD__POR				(0x18)
+#define TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD			(0x327)
+#define TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD__POR				(0x23)
+#define TAIKO_A_CDC_CLSH_K_ADDR			(0x328)
+#define TAIKO_A_CDC_CLSH_K_ADDR__POR				(0x00)
+#define TAIKO_A_CDC_CLSH_K_DATA			(0x329)
+#define TAIKO_A_CDC_CLSH_K_DATA__POR				(0xA4)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L			(0x32A)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L__POR				(0xD7)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U			(0x32B)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U__POR				(0x05)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L			(0x32C)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L__POR				(0x60)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U			(0x32D)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U__POR				(0x09)
+#define TAIKO_A_CDC_CLSH_V_PA_HD_EAR			(0x32E)
+#define TAIKO_A_CDC_CLSH_V_PA_HD_EAR__POR				(0x00)
+#define TAIKO_A_CDC_CLSH_V_PA_HD_HPH			(0x32F)
+#define TAIKO_A_CDC_CLSH_V_PA_HD_HPH__POR				(0x00)
+#define TAIKO_A_CDC_CLSH_V_PA_MIN_EAR			(0x330)
+#define TAIKO_A_CDC_CLSH_V_PA_MIN_EAR__POR				(0x00)
+#define TAIKO_A_CDC_CLSH_V_PA_MIN_HPH			(0x331)
+#define TAIKO_A_CDC_CLSH_V_PA_MIN_HPH__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B1_CTL			(0x340)
+#define TAIKO_A_CDC_IIR1_GAIN_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B1_CTL			(0x350)
+#define TAIKO_A_CDC_IIR2_GAIN_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B2_CTL			(0x341)
+#define TAIKO_A_CDC_IIR1_GAIN_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B2_CTL			(0x351)
+#define TAIKO_A_CDC_IIR2_GAIN_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B3_CTL			(0x342)
+#define TAIKO_A_CDC_IIR1_GAIN_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B3_CTL			(0x352)
+#define TAIKO_A_CDC_IIR2_GAIN_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B4_CTL			(0x343)
+#define TAIKO_A_CDC_IIR1_GAIN_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B4_CTL			(0x353)
+#define TAIKO_A_CDC_IIR2_GAIN_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B5_CTL			(0x344)
+#define TAIKO_A_CDC_IIR1_GAIN_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B5_CTL			(0x354)
+#define TAIKO_A_CDC_IIR2_GAIN_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B6_CTL			(0x345)
+#define TAIKO_A_CDC_IIR1_GAIN_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B6_CTL			(0x355)
+#define TAIKO_A_CDC_IIR2_GAIN_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B7_CTL			(0x346)
+#define TAIKO_A_CDC_IIR1_GAIN_B7_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B7_CTL			(0x356)
+#define TAIKO_A_CDC_IIR2_GAIN_B7_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B8_CTL			(0x347)
+#define TAIKO_A_CDC_IIR1_GAIN_B8_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B8_CTL			(0x357)
+#define TAIKO_A_CDC_IIR2_GAIN_B8_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_CTL			(0x348)
+#define TAIKO_A_CDC_IIR1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_CTL			(0x358)
+#define TAIKO_A_CDC_IIR2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL			(0x349)
+#define TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL			(0x359)
+#define TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_COEF_B1_CTL			(0x34A)
+#define TAIKO_A_CDC_IIR1_COEF_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_COEF_B1_CTL			(0x35A)
+#define TAIKO_A_CDC_IIR2_COEF_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_COEF_B2_CTL			(0x34B)
+#define TAIKO_A_CDC_IIR1_COEF_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_COEF_B2_CTL			(0x35B)
+#define TAIKO_A_CDC_IIR2_COEF_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TOP_GAIN_UPDATE			(0x360)
+#define TAIKO_A_CDC_TOP_GAIN_UPDATE__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B1_CTL			(0x368)
+#define TAIKO_A_CDC_COMP0_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B1_CTL			(0x370)
+#define TAIKO_A_CDC_COMP1_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B1_CTL			(0x378)
+#define TAIKO_A_CDC_COMP2_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B2_CTL			(0x369)
+#define TAIKO_A_CDC_COMP0_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B2_CTL			(0x371)
+#define TAIKO_A_CDC_COMP1_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B2_CTL			(0x379)
+#define TAIKO_A_CDC_COMP2_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B3_CTL			(0x36A)
+#define TAIKO_A_CDC_COMP0_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B3_CTL			(0x372)
+#define TAIKO_A_CDC_COMP1_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B3_CTL			(0x37A)
+#define TAIKO_A_CDC_COMP2_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B4_CTL			(0x36B)
+#define TAIKO_A_CDC_COMP0_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B4_CTL			(0x373)
+#define TAIKO_A_CDC_COMP1_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B4_CTL			(0x37B)
+#define TAIKO_A_CDC_COMP2_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B5_CTL			(0x36C)
+#define TAIKO_A_CDC_COMP0_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B5_CTL			(0x374)
+#define TAIKO_A_CDC_COMP1_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B5_CTL			(0x37C)
+#define TAIKO_A_CDC_COMP2_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B6_CTL			(0x36D)
+#define TAIKO_A_CDC_COMP0_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B6_CTL			(0x375)
+#define TAIKO_A_CDC_COMP1_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B6_CTL			(0x37D)
+#define TAIKO_A_CDC_COMP2_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS			(0x36E)
+#define TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS			(0x376)
+#define TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS			(0x37E)
+#define TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_FS_CFG			(0x36F)
+#define TAIKO_A_CDC_COMP0_FS_CFG__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_FS_CFG			(0x377)
+#define TAIKO_A_CDC_COMP1_FS_CFG__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_FS_CFG			(0x37F)
+#define TAIKO_A_CDC_COMP2_FS_CFG__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX1_B1_CTL			(0x380)
+#define TAIKO_A_CDC_CONN_RX1_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX1_B2_CTL			(0x381)
+#define TAIKO_A_CDC_CONN_RX1_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX1_B3_CTL			(0x382)
+#define TAIKO_A_CDC_CONN_RX1_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX2_B1_CTL			(0x383)
+#define TAIKO_A_CDC_CONN_RX2_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX2_B2_CTL			(0x384)
+#define TAIKO_A_CDC_CONN_RX2_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX2_B3_CTL			(0x385)
+#define TAIKO_A_CDC_CONN_RX2_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX3_B1_CTL			(0x386)
+#define TAIKO_A_CDC_CONN_RX3_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX3_B2_CTL			(0x387)
+#define TAIKO_A_CDC_CONN_RX3_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX4_B1_CTL			(0x388)
+#define TAIKO_A_CDC_CONN_RX4_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX4_B2_CTL			(0x389)
+#define TAIKO_A_CDC_CONN_RX4_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX5_B1_CTL			(0x38A)
+#define TAIKO_A_CDC_CONN_RX5_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX5_B2_CTL			(0x38B)
+#define TAIKO_A_CDC_CONN_RX5_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX6_B1_CTL			(0x38C)
+#define TAIKO_A_CDC_CONN_RX6_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX6_B2_CTL			(0x38D)
+#define TAIKO_A_CDC_CONN_RX6_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX7_B1_CTL			(0x38E)
+#define TAIKO_A_CDC_CONN_RX7_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX7_B2_CTL			(0x38F)
+#define TAIKO_A_CDC_CONN_RX7_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX7_B3_CTL			(0x390)
+#define TAIKO_A_CDC_CONN_RX7_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_ANC_B1_CTL			(0x391)
+#define TAIKO_A_CDC_CONN_ANC_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_ANC_B2_CTL			(0x392)
+#define TAIKO_A_CDC_CONN_ANC_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_B1_CTL			(0x393)
+#define TAIKO_A_CDC_CONN_TX_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_B2_CTL			(0x394)
+#define TAIKO_A_CDC_CONN_TX_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_B3_CTL			(0x395)
+#define TAIKO_A_CDC_CONN_TX_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_B4_CTL			(0x396)
+#define TAIKO_A_CDC_CONN_TX_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_EQ1_B1_CTL			(0x397)
+#define TAIKO_A_CDC_CONN_EQ1_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_EQ1_B2_CTL			(0x398)
+#define TAIKO_A_CDC_CONN_EQ1_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_EQ1_B3_CTL			(0x399)
+#define TAIKO_A_CDC_CONN_EQ1_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_EQ1_B4_CTL			(0x39A)
+#define TAIKO_A_CDC_CONN_EQ1_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_EQ2_B1_CTL			(0x39B)
+#define TAIKO_A_CDC_CONN_EQ2_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_EQ2_B2_CTL			(0x39C)
+#define TAIKO_A_CDC_CONN_EQ2_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_EQ2_B3_CTL			(0x39D)
+#define TAIKO_A_CDC_CONN_EQ2_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_EQ2_B4_CTL			(0x39E)
+#define TAIKO_A_CDC_CONN_EQ2_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_SRC1_B1_CTL			(0x39F)
+#define TAIKO_A_CDC_CONN_SRC1_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_SRC1_B2_CTL			(0x3A0)
+#define TAIKO_A_CDC_CONN_SRC1_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_SRC2_B1_CTL			(0x3A1)
+#define TAIKO_A_CDC_CONN_SRC2_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_SRC2_B2_CTL			(0x3A2)
+#define TAIKO_A_CDC_CONN_SRC2_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B1_CTL			(0x3A3)
+#define TAIKO_A_CDC_CONN_TX_SB_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B2_CTL			(0x3A4)
+#define TAIKO_A_CDC_CONN_TX_SB_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B3_CTL			(0x3A5)
+#define TAIKO_A_CDC_CONN_TX_SB_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B4_CTL			(0x3A6)
+#define TAIKO_A_CDC_CONN_TX_SB_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B5_CTL			(0x3A7)
+#define TAIKO_A_CDC_CONN_TX_SB_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B6_CTL			(0x3A8)
+#define TAIKO_A_CDC_CONN_TX_SB_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B7_CTL			(0x3A9)
+#define TAIKO_A_CDC_CONN_TX_SB_B7_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B8_CTL			(0x3AA)
+#define TAIKO_A_CDC_CONN_TX_SB_B8_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B9_CTL			(0x3AB)
+#define TAIKO_A_CDC_CONN_TX_SB_B9_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B10_CTL			(0x3AC)
+#define TAIKO_A_CDC_CONN_TX_SB_B10_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B11_CTL			(0x3AD)
+#define TAIKO_A_CDC_CONN_TX_SB_B11_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX_SB_B1_CTL			(0x3AE)
+#define TAIKO_A_CDC_CONN_RX_SB_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_RX_SB_B2_CTL			(0x3AF)
+#define TAIKO_A_CDC_CONN_RX_SB_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_CLSH_CTL			(0x3B0)
+#define TAIKO_A_CDC_CONN_CLSH_CTL__POR				(0x00)
+#define TAIKO_A_CDC_CONN_MISC			(0x3B1)
+#define TAIKO_A_CDC_CONN_MISC__POR				(0x01)
+#define TAIKO_A_CDC_CONN_MAD			(0x3B2)
+#define TAIKO_A_CDC_CONN_MAD__POR				(0x01)
+#define TAIKO_A_CDC_MBHC_EN_CTL			(0x3C0)
+#define TAIKO_A_CDC_MBHC_EN_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_FIR_B1_CFG			(0x3C1)
+#define TAIKO_A_CDC_MBHC_FIR_B1_CFG__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_FIR_B2_CFG			(0x3C2)
+#define TAIKO_A_CDC_MBHC_FIR_B2_CFG__POR				(0x06)
+#define TAIKO_A_CDC_MBHC_TIMER_B1_CTL			(0x3C3)
+#define TAIKO_A_CDC_MBHC_TIMER_B1_CTL__POR				(0x03)
+#define TAIKO_A_CDC_MBHC_TIMER_B2_CTL			(0x3C4)
+#define TAIKO_A_CDC_MBHC_TIMER_B2_CTL__POR				(0x09)
+#define TAIKO_A_CDC_MBHC_TIMER_B3_CTL			(0x3C5)
+#define TAIKO_A_CDC_MBHC_TIMER_B3_CTL__POR				(0x1E)
+#define TAIKO_A_CDC_MBHC_TIMER_B4_CTL			(0x3C6)
+#define TAIKO_A_CDC_MBHC_TIMER_B4_CTL__POR				(0x45)
+#define TAIKO_A_CDC_MBHC_TIMER_B5_CTL			(0x3C7)
+#define TAIKO_A_CDC_MBHC_TIMER_B5_CTL__POR				(0x04)
+#define TAIKO_A_CDC_MBHC_TIMER_B6_CTL			(0x3C8)
+#define TAIKO_A_CDC_MBHC_TIMER_B6_CTL__POR				(0x78)
+#define TAIKO_A_CDC_MBHC_B1_STATUS			(0x3C9)
+#define TAIKO_A_CDC_MBHC_B1_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_B2_STATUS			(0x3CA)
+#define TAIKO_A_CDC_MBHC_B2_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_B3_STATUS			(0x3CB)
+#define TAIKO_A_CDC_MBHC_B3_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_B4_STATUS			(0x3CC)
+#define TAIKO_A_CDC_MBHC_B4_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_B5_STATUS			(0x3CD)
+#define TAIKO_A_CDC_MBHC_B5_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_B1_CTL			(0x3CE)
+#define TAIKO_A_CDC_MBHC_B1_CTL__POR				(0xC0)
+#define TAIKO_A_CDC_MBHC_B2_CTL			(0x3CF)
+#define TAIKO_A_CDC_MBHC_B2_CTL__POR				(0x5D)
+#define TAIKO_A_CDC_MBHC_VOLT_B1_CTL			(0x3D0)
+#define TAIKO_A_CDC_MBHC_VOLT_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B2_CTL			(0x3D1)
+#define TAIKO_A_CDC_MBHC_VOLT_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B3_CTL			(0x3D2)
+#define TAIKO_A_CDC_MBHC_VOLT_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B4_CTL			(0x3D3)
+#define TAIKO_A_CDC_MBHC_VOLT_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B5_CTL			(0x3D4)
+#define TAIKO_A_CDC_MBHC_VOLT_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B6_CTL			(0x3D5)
+#define TAIKO_A_CDC_MBHC_VOLT_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B7_CTL			(0x3D6)
+#define TAIKO_A_CDC_MBHC_VOLT_B7_CTL__POR				(0xFF)
+#define TAIKO_A_CDC_MBHC_VOLT_B8_CTL			(0x3D7)
+#define TAIKO_A_CDC_MBHC_VOLT_B8_CTL__POR				(0x07)
+#define TAIKO_A_CDC_MBHC_VOLT_B9_CTL			(0x3D8)
+#define TAIKO_A_CDC_MBHC_VOLT_B9_CTL__POR				(0xFF)
+#define TAIKO_A_CDC_MBHC_VOLT_B10_CTL			(0x3D9)
+#define TAIKO_A_CDC_MBHC_VOLT_B10_CTL__POR				(0x7F)
+#define TAIKO_A_CDC_MBHC_VOLT_B11_CTL			(0x3DA)
+#define TAIKO_A_CDC_MBHC_VOLT_B11_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B12_CTL			(0x3DB)
+#define TAIKO_A_CDC_MBHC_VOLT_B12_CTL__POR				(0x80)
+#define TAIKO_A_CDC_MBHC_CLK_CTL			(0x3DC)
+#define TAIKO_A_CDC_MBHC_CLK_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_INT_CTL			(0x3DD)
+#define TAIKO_A_CDC_MBHC_INT_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_DEBUG_CTL			(0x3DE)
+#define TAIKO_A_CDC_MBHC_DEBUG_CTL__POR				(0x00)
+#define TAIKO_A_CDC_MBHC_SPARE			(0x3DF)
+#define TAIKO_A_CDC_MBHC_SPARE__POR				(0x00)
+#define TAIKO_A_CDC_MAD_MAIN_CTL_1			(0x3E0)
+#define TAIKO_A_CDC_MAD_MAIN_CTL_1__POR				(0x00)
+#define TAIKO_A_CDC_MAD_MAIN_CTL_2			(0x3E1)
+#define TAIKO_A_CDC_MAD_MAIN_CTL_2__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_1			(0x3E2)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_1__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_2			(0x3E3)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_2__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_3			(0x3E4)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_3__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_4			(0x3E5)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_4__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_5			(0x3E6)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_5__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_6			(0x3E7)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_6__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_7			(0x3E8)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_7__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_8			(0x3E9)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_8__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR			(0x3EA)
+#define TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR__POR				(0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL			(0x3EB)
+#define TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL__POR				(0x40)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_1			(0x3EC)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_1__POR				(0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_2			(0x3ED)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_2__POR				(0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_3			(0x3EE)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_3__POR				(0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_4			(0x3EF)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_4__POR				(0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_5			(0x3F0)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_5__POR				(0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_6			(0x3F1)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_6__POR				(0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_7			(0x3F2)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_7__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_1			(0x3F3)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_1__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_2			(0x3F4)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_2__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_3			(0x3F5)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_3__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_4			(0x3F6)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_4__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_5			(0x3F7)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_5__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_6			(0x3F8)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_6__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_7			(0x3F9)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_7__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_8			(0x3FA)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_8__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR			(0x3FB)
+#define TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR__POR				(0x00)
+#define TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL			(0x3FC)
+#define TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL__POR				(0x00)
+
+
+/* SLIMBUS Slave Registers */
+#define TAIKO_SLIM_PGD_PORT_INT_EN0                     (0x30)
+#define TAIKO_SLIM_PGD_PORT_INT_STATUS0                 (0x34)
+#define TAIKO_SLIM_PGD_PORT_INT_CLR0                    (0x38)
+#define TAIKO_SLIM_PGD_PORT_INT_SOURCE0			(0x60)
+
+/* Macros for Packing Register Writes into a U32 */
+#define TAIKO_PACKED_REG_SIZE sizeof(u32)
+
+#define TAIKO_CODEC_PACK_ENTRY(reg, mask, val) ((val & 0xff)|\
+	((mask & 0xff) << 8)|((reg & 0xffff) << 16))
+
+#define TAIKO_CODEC_UNPACK_ENTRY(packed, reg, mask, val) \
+	do { \
+		((reg) = ((packed >> 16) & (0xffff))); \
+		((mask) = ((packed >> 8) & (0xff))); \
+		((val) = ((packed) & (0xff))); \
+	} while (0);
+
+#endif
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 71484da..447fbbb 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -253,7 +253,6 @@
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
-#ifdef CONFIG_MMC_CLKGATE
 	int			clk_requests;	/* internal reference counter */
 	unsigned int		clk_delay;	/* number of MCI clk hold cycles */
 	bool			clk_gated;	/* clock gated */
@@ -263,7 +262,6 @@
 	struct mutex		clk_gate_mutex;	/* mutex for clock gating */
 	struct device_attribute clkgate_delay_attr;
 	unsigned long           clkgate_delay;
-#endif
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index f757fae..8b6351f 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -86,6 +86,8 @@
 	MDP_YCRYCB_H2V1,  /* YCrYCb interleave */
 	MDP_Y_CRCB_H2V1,  /* Y and CrCb, pseduo planer w/ Cr is in MSB */
 	MDP_Y_CBCR_H2V1,   /* Y and CrCb, pseduo planer w/ Cr is in MSB */
+	MDP_Y_CRCB_H1V2,
+	MDP_Y_CBCR_H1V2,
 	MDP_RGBA_8888,    /* ARGB 888 */
 	MDP_BGRA_8888,	  /* ABGR 888 */
 	MDP_RGBX_8888,	  /* RGBX 888 */
@@ -98,10 +100,10 @@
 	MDP_Y_CBCR_H1V1,  /* Y and CbCr, pseduo planer w/ Cb is in MSB */
 	MDP_YCRCB_H1V1,   /* YCrCb interleave */
 	MDP_YCBCR_H1V1,   /* YCbCr interleave */
+	MDP_BGR_565,      /* BGR 565 planer */
 	MDP_IMGTYPE_LIMIT,
 	MDP_RGB_BORDERFILL,	/* border fill pipe */
-	MDP_BGR_565 = MDP_IMGTYPE2_START,      /* BGR 565 planer */
-	MDP_FB_FORMAT,    /* framebuffer format */
+	MDP_FB_FORMAT = MDP_IMGTYPE2_START,    /* framebuffer format */
 	MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
 };
 
@@ -118,6 +120,8 @@
 	NUM_HSIC_PARAM,
 };
 
+#define MDSS_MDP_RIGHT_MIXER		0x100
+
 /* mdp_blit_req flag values */
 #define MDP_ROT_NOP 0
 #define MDP_FLIP_LR 0x1
diff --git a/include/linux/msm_vidc_dec.h b/include/linux/msm_vidc_dec.h
index 0c03e13..3d8907a 100644
--- a/include/linux/msm_vidc_dec.h
+++ b/include/linux/msm_vidc_dec.h
@@ -207,6 +207,9 @@
 #define VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT \
 	_IOR(VDEC_IOCTL_MAGIC, 37, struct vdec_ioctl_msg)
 
+#define VDEC_IOCTL_SET_PERF_CLK \
+	_IOR(VDEC_IOCTL_MAGIC, 38, struct vdec_ioctl_msg)
+
 enum vdec_picture {
 	PICTURE_TYPE_I,
 	PICTURE_TYPE_P,
diff --git a/include/linux/tzcom.h b/include/linux/tzcom.h
deleted file mode 100644
index 448ab2a..0000000
--- a/include/linux/tzcom.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Qualcomm TrustZone communicator API */
-
-#ifndef __TZCOM_H_
-#define __TZCOM_H_
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#define MAX_ION_FD  4
-/**
- * struct tzcom_register_svc_op_req - for register service ioctl request
- * @svc_id - service id (shared between userspace and TZ)
- * @cmd_id_low - low number in cmd_id range (shared between userspace and TZ)
- * @cmd_id_high - high number in cmd_id range (shared between userspace and TZ)
- * @instance_id - unique id for the given service generated by tzcom driver
- */
-struct tzcom_register_svc_op_req {
-	uint32_t svc_id; /* in */
-	uint32_t cmd_id_low; /* in */
-	uint32_t cmd_id_high; /* in */
-	uint32_t instance_id; /* out */
-};
-
-/**
- * struct tzcom_unregister_svc_op_req - for unregister service ioctl request
- * @svc_id - service id to unregister (provided in register_service request)
- * @instance_id - instance id generated in register service request
- */
-struct tzcom_unregister_svc_op_req {
-	uint32_t svc_id; /* in */
-	uint32_t instance_id; /* in */
-};
-
-/**
- * struct tzcom_next_cmd_op_req - for read next command ioctl request
- * @svc_id - has to be a registered svc_id (see @tzcom_register_svc_op_req)
- * @instance_id - unique id for the given service (see @tzcom_register_svc_op_req)
- * @cmd_id - command to execute on the given service, received from TZ
- * @req_len - request buffer length, received from TZ
- * @req - request buffer, received from TZ
- */
-struct tzcom_next_cmd_op_req {
-	uint32_t svc_id; /* in */
-	uint32_t instance_id; /* in */
-	uint32_t cmd_id; /* out */
-	unsigned int req_len; /* in/out */
-	void *req_buf; /* in/out */
-};
-
-/**
- * struct tzcom_send_cmd_op_req - for send command ioctl request
- * @cmd_id - command to execute on TZBSP side
- * @ifd_data_fd - ion handle to some memory allocated in user space
- * @cmd_buf_offset - command buffer offset
- * @cmd_len - command buffer length
- * @cmd_buf - command buffer
- * @resp_len - response buffer length
- * @resp_buf - response buffer
- */
-struct tzcom_send_cmd_op_req {
-	uint32_t cmd_id; /* in */
-	unsigned int cmd_len; /* in */
-	void *cmd_buf; /* in */
-	unsigned int resp_len; /* in/out */
-	void *resp_buf; /* in/out */
-};
-
-/**
- * struct tzcom_ion_fd_info - ion fd handle data information
- * @fd - ion handle to some memory allocated in user space
- * @cmd_buf_offset - command buffer offset
- */
-struct tzcom_ion_fd_info {
-	int32_t fd;
-	uint32_t cmd_buf_offset;
-};
-
-/**
- * struct tzcom_send_cmd_op_req - for send command ioctl request
- * @cmd_id - command to execute on TZBSP side
- * @ifd_data_fd - ion handle to some memory allocated in user space
- * @cmd_buf_offset - command buffer offset
- * @cmd_len - command buffer length
- * @cmd_buf - command buffer
- * @resp_len - response buffer length
- * @resp_buf - response buffer
- */
-struct tzcom_send_cmd_fd_op_req {
-	uint32_t cmd_id; /* in */
-	struct tzcom_ion_fd_info ifd_data[MAX_ION_FD];
-	unsigned int cmd_len; /* in */
-	void *cmd_buf; /* in */
-	unsigned int resp_len; /* in/out */
-	void *resp_buf; /* in/out */
-};
-/**
- * struct tzcom_cont_cmd_op_req - for continue command ioctl request. used
- * as a trigger from HLOS service to notify TZCOM that it's done with its
- * operation and provide the response for TZCOM can continue the incomplete
- * command execution
- * @cmd_id - Command to continue filled in by tzcom as tzcom knows about the
- *           last incomplete command.
- * @instance_id - Instance id of the svc
- * @resp_len - Length of the response
- * @resp_buf - Response buffer where the response of the cmd should go.
- */
-struct tzcom_cont_cmd_op_req {
-	uint32_t cmd_id; /* out */
-	uint32_t instance_id; /* in */
-	unsigned int resp_len; /* in */
-	void *resp_buf; /* in */
-};
-
-#define TZCOM_IOC_MAGIC    0x97
-
-/* For HLOS service */
-#define TZCOM_IOCTL_REGISTER_SERVICE_REQ \
-	_IOWR(TZCOM_IOC_MAGIC, 1, struct tzcom_register_svc_op_req)
-/* For HLOS service */
-#define TZCOM_IOCTL_UNREGISTER_SERVICE_REQ \
-	_IOWR(TZCOM_IOC_MAGIC, 2, struct tzcom_unregister_svc_op_req)
-/* For TZ service */
-#define TZCOM_IOCTL_SEND_CMD_REQ \
-	_IOWR(TZCOM_IOC_MAGIC, 3, struct tzcom_send_cmd_op_req)
-/* For HLOS service */
-#define TZCOM_IOCTL_READ_NEXT_CMD_REQ \
-	_IOWR(TZCOM_IOC_MAGIC, 4, struct tzcom_next_cmd_op_req)
-/* For TZ service */
-#define TZCOM_IOCTL_CONTINUE_CMD_REQ \
-	_IOWR(TZCOM_IOC_MAGIC, 5, struct tzcom_cont_cmd_op_req)
-
-#define TZCOM_IOCTL_ABORT_REQ _IO(TZCOM_IOC_MAGIC, 6)
-/* For TZ service */
-#define TZCOM_IOCTL_SEND_CMD_FD_REQ \
-	_IOWR(TZCOM_IOC_MAGIC, 7, struct tzcom_send_cmd_fd_op_req)
-#endif /* __TZCOM_H_ */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index f8329dd..22d4997 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -160,6 +160,16 @@
 };
 
 /**
+ * Used different VDDCX voltage values
+ */
+enum usb_vdd_value {
+	VDD_NONE = 0,
+	VDD_MIN,
+	VDD_MAX,
+	VDD_VAL_MAX,
+};
+
+/**
  * struct msm_otg_platform_data - platform device data
  *              for msm_otg driver.
  * @phy_init_seq: PHY configuration sequence. val, reg pairs
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index f6f3c1e..63ebdea 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -2295,6 +2295,12 @@
 #define V4L2_EVENT_FRAME_SYNC			4
 #define V4L2_EVENT_PRIVATE_START		0x08000000
 
+#define V4L2_EVENT_MSM_VIDC_START	(V4L2_EVENT_PRIVATE_START + 0x00001000)
+#define V4L2_EVENT_MSM_VIDC_FLUSH_DONE	(V4L2_EVENT_PRIVATE_START + 1)
+#define V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED	\
+		(V4L2_EVENT_PRIVATE_START + 2)
+#define V4L2_EVENT_MSM_VIDC_CLOSE_DONE	(V4L2_EVENT_PRIVATE_START + 3)
+
 /* Payload for V4L2_EVENT_VSYNC */
 struct v4l2_event_vsync {
 	/* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 37d2343..acd0fa3 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -54,6 +54,7 @@
 #define VCD_REQ_PERF_LEVEL (VCD_START_BASE + 0x26)
 #define VCD_I_SLICE_DELIVERY_MODE (VCD_START_BASE + 0x27)
 #define VCD_I_VOP_TIMING_CONSTANT_DELTA (VCD_START_BASE + 0x28)
+#define VCD_I_SET_TURBO_CLK (VCD_START_BASE + 0x29)
 
 #define VCD_START_REQ      (VCD_START_BASE + 0x1000)
 #define VCD_I_REQ_IFRAME   (VCD_START_REQ + 0x1)
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 271079e..320ac8b 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -190,6 +190,9 @@
 #define MSM_CAM_IOCTL_EEPROM_IO_CFG \
 	_IOW(MSM_CAM_IOCTL_MAGIC, 53, struct msm_eeprom_cfg_data *)
 
+#define MSM_CAM_IOCTL_ISPIF_IO_CFG \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 54, struct ispif_cfg_data *)
+
 struct msm_mctl_pp_cmd {
 	int32_t  id;
 	uint16_t length;
@@ -605,6 +608,7 @@
 
 	struct ion_allocation_data ion_alloc;
 	struct ion_fd_data fd_data;
+	int ion_dev_fd;
 };
 
 enum msm_st_frame_packing {
@@ -796,7 +800,10 @@
 #define CFG_SET_AUTOFLASH             41
 #define CFG_SET_EXPOSURE_COMPENSATION 42
 #define CFG_SET_ISO                   43
-#define CFG_MAX			44
+#define CFG_START_STREAM              44
+#define CFG_STOP_STREAM               45
+#define CFG_GET_CSI_PARAMS            46
+#define CFG_MAX			47
 
 
 #define MOVE_NEAR	0
@@ -1126,6 +1133,112 @@
 	uint16_t index;
 };
 
+struct msm_camera_csid_vc_cfg {
+	uint8_t cid;
+	uint8_t dt;
+	uint8_t decode_format;
+};
+
+struct csi_lane_params_t {
+	uint8_t csi_lane_assign;
+	uint8_t csi_lane_mask;
+	uint8_t csi_if;
+	uint8_t csid_core;
+	uint32_t csid_version;
+};
+
+#define CSI_EMBED_DATA 0x12
+#define CSI_RESERVED_DATA_0 0x13
+#define CSI_YUV422_8  0x1E
+#define CSI_RAW8    0x2A
+#define CSI_RAW10   0x2B
+#define CSI_RAW12   0x2C
+
+#define CSI_DECODE_6BIT 0
+#define CSI_DECODE_8BIT 1
+#define CSI_DECODE_10BIT 2
+#define CSI_DECODE_DPCM_10_8_10 5
+
+#define ISPIF_STREAM(intf, action) (((intf)<<ISPIF_S_STREAM_SHIFT)+(action))
+#define ISPIF_ON_FRAME_BOUNDARY	(0x01 << 0)
+#define ISPIF_OFF_FRAME_BOUNDARY    (0x01 << 1)
+#define ISPIF_OFF_IMMEDIATELY       (0x01 << 2)
+#define ISPIF_S_STREAM_SHIFT	4
+
+
+#define PIX_0 (0x01 << 0)
+#define RDI_0 (0x01 << 1)
+#define PIX_1 (0x01 << 2)
+#define RDI_1 (0x01 << 3)
+#define PIX_2 (0x01 << 4)
+#define RDI_2 (0x01 << 5)
+
+
+enum msm_ispif_intftype {
+	PIX0,
+	RDI0,
+	PIX1,
+	RDI1,
+	PIX2,
+	RDI2,
+	INTF_MAX,
+};
+
+enum msm_ispif_vc {
+	VC0,
+	VC1,
+	VC2,
+	VC3,
+};
+
+enum msm_ispif_cid {
+	CID0,
+	CID1,
+	CID2,
+	CID3,
+	CID4,
+	CID5,
+	CID6,
+	CID7,
+	CID8,
+	CID9,
+	CID10,
+	CID11,
+	CID12,
+	CID13,
+	CID14,
+	CID15,
+};
+
+struct msm_ispif_params {
+	uint8_t intftype;
+	uint16_t cid_mask;
+	uint8_t csid;
+};
+
+struct msm_ispif_params_list {
+	uint32_t len;
+	struct msm_ispif_params params[4];
+};
+
+enum ispif_cfg_type_t {
+	ISPIF_INIT,
+	ISPIF_SET_CFG,
+	ISPIF_SET_ON_FRAME_BOUNDARY,
+	ISPIF_SET_OFF_FRAME_BOUNDARY,
+	ISPIF_SET_OFF_IMMEDIATELY,
+	ISPIF_RELEASE,
+};
+
+struct ispif_cfg_data {
+	enum ispif_cfg_type_t cfgtype;
+	union {
+		uint32_t csid_version;
+		int cmd;
+		struct msm_ispif_params_list ispif_params;
+	} cfg;
+};
+
 struct sensor_cfg_data {
 	int cfgtype;
 	int mode;
@@ -1152,6 +1265,7 @@
 		struct sensor_calib_data calib_info;
 		struct sensor_output_info_t output_info;
 		struct msm_eeprom_data_t eeprom_data;
+		struct csi_lane_params_t csi_lane_params;
 		/* QRD */
 		uint16_t antibanding;
 		uint8_t contrast;
@@ -1409,6 +1523,7 @@
 	uint8_t flash_enabled;
 	uint8_t strobe_flash_enabled;
 	uint8_t actuator_enabled;
+	uint8_t ispif_supported;
 	int8_t total_steps;
 	uint8_t support_3d;
 	enum flash_type flashtype;
@@ -1479,4 +1594,66 @@
 	uint32_t len;
 };
 
+enum msm_camss_irq_idx {
+	CAMERA_SS_IRQ_0,
+	CAMERA_SS_IRQ_1,
+	CAMERA_SS_IRQ_2,
+	CAMERA_SS_IRQ_3,
+	CAMERA_SS_IRQ_4,
+	CAMERA_SS_IRQ_5,
+	CAMERA_SS_IRQ_6,
+	CAMERA_SS_IRQ_7,
+	CAMERA_SS_IRQ_8,
+	CAMERA_SS_IRQ_9,
+	CAMERA_SS_IRQ_10,
+	CAMERA_SS_IRQ_11,
+	CAMERA_SS_IRQ_12,
+	CAMERA_SS_IRQ_MAX
+};
+
+enum msm_cam_hw_idx {
+	MSM_CAM_HW_MICRO,
+	MSM_CAM_HW_CCI,
+	MSM_CAM_HW_CSI0,
+	MSM_CAM_HW_CSI1,
+	MSM_CAM_HW_CSI2,
+	MSM_CAM_HW_CSI3,
+	MSM_CAM_HW_ISPIF,
+	MSM_CAM_HW_CPP,
+	MSM_CAM_HW_VFE0,
+	MSM_CAM_HW_VFE1,
+	MSM_CAM_HW_JPEG0,
+	MSM_CAM_HW_JPEG1,
+	MSM_CAM_HW_JPEG2,
+	MSM_CAM_HW_MAX
+};
+
+struct msm_camera_irq_cfg {
+	/* Bit mask of all the camera hardwares that needs to
+	 * be composited into a single IRQ to the MSM.
+	 * Current usage: (may be updated based on hw changes)
+	 * Bits 31:13 - Reserved.
+	 * Bits 12:0
+	 * 12 - MSM_CAM_HW_JPEG2
+	 * 11 - MSM_CAM_HW_JPEG1
+	 * 10 - MSM_CAM_HW_JPEG0
+	 *  9 - MSM_CAM_HW_VFE1
+	 *  8 - MSM_CAM_HW_VFE0
+	 *  7 - MSM_CAM_HW_CPP
+	 *  6 - MSM_CAM_HW_ISPIF
+	 *  5 - MSM_CAM_HW_CSI3
+	 *  4 - MSM_CAM_HW_CSI2
+	 *  3 - MSM_CAM_HW_CSI1
+	 *  2 - MSM_CAM_HW_CSI0
+	 *  1 - MSM_CAM_HW_CCI
+	 *  0 - MSM_CAM_HW_MICRO
+	 */
+	uint32_t cam_hw_mask;
+	uint8_t  irq_idx;
+	uint8_t  num_hwcore;
+};
+
+#define MSM_IRQROUTER_CFG_COMPIRQ \
+	_IOWR('V', BASE_VIDIOC_PRIVATE, void __user *)
+
 #endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index cb728a0..333d0df 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -327,5 +327,10 @@
 #define VFE_OUTPUTS_JPEG_AND_THUMB	BIT(9)
 #define VFE_OUTPUTS_THUMB_AND_JPEG	BIT(10)
 
+struct msm_frame_info {
+	uint32_t image_mode;
+	uint32_t path;
+};
+
 #endif /*__MSM_ISP_H__*/
 
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index 52194f9..9943287 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -172,6 +172,10 @@
 	V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD, /* 0x800002E */
 	V4L2_CID_PRIVATE_SINR_THRESHOLD,  /* 0x800002F : IRIS */
 	V4L2_CID_PRIVATE_SINR_SAMPLES,  /* 0x8000030 : IRIS */
+	V4L2_CID_PRIVATE_SPUR_FREQ,
+	V4L2_CID_PRIVATE_SPUR_FREQ_RMSSI,
+	V4L2_CID_PRIVATE_SPUR_SELECTION,
+	V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE,
 
 };
 
@@ -484,4 +488,47 @@
 	TAVARUA_REGION_OTHER
 };
 
+enum {
+	ONE_BYTE = 1,
+	TWO_BYTE,
+	THREE_BYTE,
+	FOUR_BYTE,
+	FIVE_BYTE,
+	SIX_BYTE,
+	SEVEN_BYTE,
+	EIGHT_BYTE,
+	NINE_BYTE,
+	TEN_BYTE,
+	ELEVEN_BYTE,
+	TWELVE_BYTE,
+	THIRTEEN_BYTE
+};
+#define XFR_READ		(0)
+#define XFR_WRITE		(1)
+#define XFR_MODE_OFFSET		(0)
+#define XFR_ADDR_MSB_OFFSET	(1)
+#define XFR_ADDR_LSB_OFFSET	(2)
+#define XFR_DATA_OFFSET		(3)
+#define SPUR_DATA_SIZE		(3)
+#define MAX_SPUR_FREQ_LIMIT	(30)
+#define READ_COMPLETE		(0x20)
+#define SPUR_TABLE_ADDR		(0x0BB7)
+#define SPUR_TABLE_START_ADDR	(SPUR_TABLE_ADDR + 1)
+#define XFR_PEEK_COMPLETE	(XFR_PEEK_MODE | READ_COMPLETE)
+#define XFR_POKE_COMPLETE	(XFR_POKE_MODE)
+
+#define COMPUTE_SPUR(val)	((((val) - (76000)) / (50)))
+#define GET_FREQ(val, bit)	((bit == 1) ? ((val) >> 8) : ((val) & 0xFF))
+
+struct fm_spur_data {
+	int freq[MAX_SPUR_FREQ_LIMIT];
+	__s8 rmssi[MAX_SPUR_FREQ_LIMIT];
+} __packed;
+
+struct fm_def_data_wr_req {
+	__u8    mode;
+	__u8    length;
+	__u8   data[XFR_REG_NUM];
+} __packed;
+
 #endif /* __LINUX_TAVARUA_H */
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 51b45ac..92240bf1 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -15,7 +15,19 @@
 #define VCAP_FMT_H
 
 #define V4L2_BUF_TYPE_INTERLACED_IN_DECODER (V4L2_BUF_TYPE_PRIVATE)
-#define V4L2_BUF_TYPE_VP_OUT (V4L2_BUF_TYPE_PRIVATE + 1)
+
+#define VCAP_GENERIC_NOTIFY_EVENT 0
+#define VCAP_VC_PIX_ERR_EVENT 1
+#define VCAP_VC_LINE_ERR_EVENT 2
+#define VCAP_VC_VSYNC_ERR_EVENT 3
+#define VCAP_VC_NPL_OFLOW_ERR_EVENT 4
+#define VCAP_VC_LBUF_OFLOW_ERR_EVENT 5
+#define VCAP_VC_BUF_OVERWRITE_EVENT 6
+#define VCAP_VP_REG_R_ERR_EVENT 7
+#define VCAP_VP_REG_W_ERR_EVENT 8
+#define VCAP_VP_IN_HEIGHT_ERR_EVENT 9
+#define VCAP_VP_IN_WIDTH_ERR_EVENT 10
+#define VCAP_MAX_NOTIFY_EVENT 11
 
 enum hal_vcap_mode {
 	HAL_VCAP_MODE_PRO = 0,
@@ -39,7 +51,8 @@
 	enum hal_vcap_polar    d_polar;
 	enum hal_vcap_color    color_space;
 
-	float  clk_freq;
+	uint32_t clk_freq;
+	uint32_t frame_rate;
 	uint32_t vtotal;
 	uint32_t htotal;
 	uint32_t hactive_start;
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 374e681..045c107 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -29,6 +29,8 @@
 #include <media/vcap_fmt.h>
 #include <mach/board.h>
 
+#define to_client_data(val)     container_of(val, struct vcap_client_data, vfh)
+
 #define writel_iowmb(val, addr)		\
 	do {							\
 		__iowmb();					\
@@ -146,6 +148,7 @@
 	struct clk				*vcap_clk;
 	struct clk				*vcap_p_clk;
 	struct clk				*vcap_npl_clk;
+	struct device			*ddev;
 	/*struct platform_device	*pdev;*/
 
 	uint32_t				bus_client_handle;
@@ -156,8 +159,10 @@
 	atomic_t			    vc_enabled;
 	atomic_t			    vp_enabled;
 
-	atomic_t				vc_resource;
-	atomic_t				vp_resource;
+	spinlock_t				dev_slock;
+	atomic_t			    open_clients;
+	bool					vc_resource;
+	bool					vp_resource;
 
 	struct workqueue_struct	*vcap_wq;
 	struct vp_work_t		vp_work;
@@ -204,6 +209,8 @@
 
 	spinlock_t				cap_slock;
 	bool					streaming;
+
+	struct v4l2_fh			vfh;
 };
 
 struct vcap_hacked_vals {
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 4676a02..17fef15 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -241,7 +241,7 @@
 	struct snd_soc_dai_driver *driver;
 
 	/* DAI runtime info */
-	unsigned int capture_active:1;		/* stream is in use */
+	unsigned int capture_active;		/* stream is in use */
 	unsigned int playback_active:1;		/* stream is in use */
 	unsigned int symmetric_rates:1;
 	struct snd_pcm_runtime *runtime;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 05e8b06..d5d8541 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -535,7 +535,7 @@
 	unsigned long page_idx;
 	unsigned long combined_idx;
 	unsigned long uninitialized_var(buddy_idx);
-	struct page *buddy;
+	struct page *buddy = NULL;
 
 	if (unlikely(PageCompound(page)))
 		if (unlikely(destroy_compound_page(page, order)))
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7719b82..980b846 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -59,10 +59,11 @@
 #include <net/bluetooth/amp.h>
 
 bool disable_ertm;
+bool enable_hs;
 bool enable_reconfig;
 
 static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
-static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_A2MP, };
+static u8 l2cap_fc_mask = L2CAP_FC_L2CAP;
 
 struct workqueue_struct *_l2cap_wq;
 
@@ -754,6 +755,7 @@
 
 			if (l2cap_pi(sk)->amp_pref ==
 					BT_AMP_POLICY_PREFER_AMP &&
+					enable_hs &&
 					conn->fc_mask & L2CAP_FC_A2MP)
 				amp_create_physical(conn, sk);
 			else
@@ -862,6 +864,7 @@
 
 			if (l2cap_pi(sk)->amp_pref ==
 					BT_AMP_POLICY_PREFER_AMP &&
+					enable_hs &&
 					conn->fc_mask & L2CAP_FC_A2MP)
 				amp_create_physical(conn, sk);
 			else
@@ -2723,7 +2726,7 @@
 	if (!l2cap_pi(sk)->conn)
 		return;
 
-	if (!(l2cap_pi(sk)->conn->fc_mask & L2CAP_FC_A2MP))
+	if (!(l2cap_pi(sk)->conn->fc_mask & L2CAP_FC_A2MP) || !enable_hs)
 		return;
 
 	if (l2cap_pi(sk)->amp_id == 0) {
@@ -4654,10 +4657,14 @@
 					L2CAP_INFO_RSP, sizeof(buf), buf);
 	} else if (type == L2CAP_IT_FIXED_CHAN) {
 		u8 buf[12];
+		u8 fc_mask = l2cap_fc_mask;
 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
-		memcpy(buf + 4, l2cap_fixed_chan, 8);
+		if (enable_hs)
+			fc_mask |= L2CAP_FC_A2MP;
+		memset(rsp->data, 0, 8);
+		rsp->data[0] = fc_mask;
 		l2cap_send_cmd(conn, cmd->ident,
 					L2CAP_INFO_RSP, sizeof(buf), buf);
 	} else {
@@ -7367,7 +7374,7 @@
 				l2cap_data_channel(sk, skb);
 
 			bh_unlock_sock(sk);
-		} else if (cid == L2CAP_CID_A2MP) {
+		} else if ((cid == L2CAP_CID_A2MP) && enable_hs) {
 			BT_DBG("A2MP");
 			amp_conn_ind(conn->hcon, skb);
 		} else {
@@ -7522,8 +7529,9 @@
 			if (!status) {
 				l2cap_pi(sk)->conf_state |=
 						L2CAP_CONF_CONNECT_PEND;
-				if (l2cap_pi(sk)->amp_pref ==
-						BT_AMP_POLICY_PREFER_AMP) {
+				if ((l2cap_pi(sk)->amp_pref ==
+						BT_AMP_POLICY_PREFER_AMP) &&
+						enable_hs) {
 					amp_create_physical(l2cap_pi(sk)->conn,
 								sk);
 				} else
@@ -7825,5 +7833,8 @@
 module_param(disable_ertm, bool, 0644);
 MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
 
+module_param(enable_hs, bool, 0644);
+MODULE_PARM_DESC(enable_hs, "Enable A2MP protocol");
+
 module_param(enable_reconfig, bool, 0644);
 MODULE_PARM_DESC(enable_reconfig, "Enable reconfig after initiating AMP move");
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 80204f5..b211ac4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -292,6 +292,9 @@
 config SND_SOC_CS8427
 	tristate
 
+config SND_SOC_WCD9320
+        tristate
+
 config SND_SOC_WL1273
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 965d6a1..5aabfee 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -51,6 +51,7 @@
 snd-soc-wcd9304-objs := wcd9304.o wcd9304-tables.o
 snd-soc-wcd9310-objs := wcd9310.o wcd9310-tables.o
 snd-soc-cs8427-objs := cs8427.o
+snd-soc-wcd9320-objs := wcd9320.o wcd9320-tables.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm2000-objs := wm2000.o
@@ -158,6 +159,7 @@
 obj-$(CONFIG_SND_SOC_WCD9304)	+= snd-soc-wcd9304.o
 obj-$(CONFIG_SND_SOC_WCD9310)	+= snd-soc-wcd9310.o
 obj-$(CONFIG_SND_SOC_CS8427)	+= snd-soc-cs8427.o
+obj-$(CONFIG_SND_SOC_WCD9320)	+= snd-soc-wcd9320.o
 obj-$(CONFIG_SND_SOC_WL1273)	+= snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
 obj-$(CONFIG_SND_SOC_WM2000)	+= snd-soc-wm2000.o
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 94bdd27..9ade172 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1944,10 +1944,12 @@
 	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
 
 	{"LINEOUT2", NULL, "LINEOUT2 PA"},
+	{"LINEOUT2 PA", NULL, "CP"},
 	{"LINEOUT2 PA", NULL, "LINEOUT2 DAC"},
 	{"LINEOUT2 DAC", NULL, "DAC3 MUX"},
 
 	{"LINEOUT1", NULL, "LINEOUT1 PA"},
+	{"LINEOUT2 PA", NULL, "CP"},
 	{"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
 	{"LINEOUT1 DAC", NULL, "DAC2 MUX"},
 
@@ -4640,7 +4642,7 @@
 	/* Initialize current threshold to 350MA
 	* number of wait and run cycles to 4096
 	*/
-	{SITAR_A_RX_HPH_OCP_CTL, 0xF8, 0x60},
+	{SITAR_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
 	{SITAR_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
 
 	{SITAR_A_QFUSE_CTL, 0xFF, 0x03},
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 9dcfc1c..e85e9f5 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -4256,7 +4256,8 @@
 				continue;
 			if (!strncmp(w->sname,
 				tabla_dai[j].playback.stream_name, 13)) {
-				--tabla_p->dai[j].ch_act;
+				if (tabla_p->dai[j].ch_act)
+					--tabla_p->dai[j].ch_act;
 				break;
 			}
 		}
@@ -6129,14 +6130,14 @@
 	int scaled;
 	struct tabla_mbhc_plug_type_cfg *plug_type_ptr;
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-	const bool vddio = (tabla->mbhc_data.micb_mv != VDDIO_MICBIAS_MV);
-	int num_det = (MBHC_NUM_DCE_PLUG_DETECT + vddio);
+	int num_det = MBHC_NUM_DCE_PLUG_DETECT + 1;
 	enum tabla_mbhc_plug_type plug_type[num_det];
 	s16 mb_v[num_det];
 	s32 mic_mv[num_det];
 	bool inval;
 	bool highdelta;
 	bool ahighv = false, highv;
+	bool gndmicswapped = false;
 
 	/* make sure override is on */
 	WARN_ON(!(snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x04));
@@ -6153,11 +6154,10 @@
 	 * 1st: check if voltage is in invalid range
 	 * 2nd - N-2nd: check voltage range and delta
 	 * N-1st: check voltage range, delta with HPHR GND switch
-	 * Nth: check voltage range with VDDIO switch if micbias V != vddio V*/
+	 * Nth: check voltage range with VDDIO switch */
 	for (i = 0; i < num_det; i++) {
-		gndswitch = (i == (num_det - 1 - vddio));
-		vddioswitch = (vddio && ((i == num_det - 1) ||
-					 (i == num_det - 2)));
+		gndswitch = (i == (num_det - 2));
+		vddioswitch = (i == (num_det - 1)) || (i == (num_det - 2));
 		if (i == 0) {
 			mb_v[i] = tabla_codec_setup_hs_polling(codec);
 			mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
@@ -6183,7 +6183,7 @@
 			 * was done with gndswitch, don't compare with DCE
 			 * with gndswitch */
 			highdelta = tabla_is_inval_ins_delta(codec, scaled,
-					mic_mv[i - !gndswitch - vddioswitch],
+					mic_mv[i - 1],
 					TABLA_MBHC_FAKE_INS_DELTA_SCALED_MV);
 			inval = (tabla_is_inval_ins_range(codec, mic_mv[i],
 							  highhph, &highv) ||
@@ -6198,9 +6198,13 @@
 			 * good headset is detected but HPHR GND switch makes
 			 * delta difference */
 			if (i == (num_det - 2) && highdelta && !ahighv)
-				plug_type[0] = PLUG_TYPE_GND_MIC_SWAP;
-			else if (i == (num_det - 1) && inval)
-				plug_type[0] = PLUG_TYPE_INVALID;
+				gndmicswapped = true;
+			else if (i == (num_det - 1) && inval) {
+				if (gndmicswapped)
+					plug_type[0] = PLUG_TYPE_GND_MIC_SWAP;
+				else
+					plug_type[0] = PLUG_TYPE_INVALID;
+			}
 		}
 		pr_debug("%s: DCE #%d, %04x, V %d, scaled V %d, GND %d, "
 			 "VDDIO %d, inval %d\n", __func__,
diff --git a/sound/soc/codecs/wcd9320-tables.c b/sound/soc/codecs/wcd9320-tables.c
new file mode 100644
index 0000000..68a4670
--- /dev/null
+++ b/sound/soc/codecs/wcd9320-tables.c
@@ -0,0 +1,1359 @@
+/* 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/mfd/wcd9xxx/wcd9320_registers.h>
+#include "wcd9320.h"
+
+const u8 taiko_reg_readable[TAIKO_CACHE_SIZE] = {
+	[TAIKO_A_CHIP_CTL] = 1,
+	[TAIKO_A_CHIP_STATUS] = 1,
+	[TAIKO_A_CHIP_ID_BYTE_0] = 1,
+	[TAIKO_A_CHIP_ID_BYTE_1] = 1,
+	[TAIKO_A_CHIP_ID_BYTE_2] = 1,
+	[TAIKO_A_CHIP_ID_BYTE_3] = 1,
+	[TAIKO_A_CHIP_VERSION] = 1,
+	[TAIKO_A_SLAVE_ID_1] = 1,
+	[TAIKO_A_SLAVE_ID_2] = 1,
+	[TAIKO_A_SLAVE_ID_3] = 1,
+	[TAIKO_A_PIN_CTL_OE0] = 1,
+	[TAIKO_A_PIN_CTL_OE1] = 1,
+	[TAIKO_A_PIN_CTL_DATA0] = 1,
+	[TAIKO_A_PIN_CTL_DATA1] = 1,
+	[TAIKO_A_HDRIVE_GENERIC] = 1,
+	[TAIKO_A_HDRIVE_OVERRIDE] = 1,
+	[TAIKO_A_ANA_CSR_WAIT_STATE] = 1,
+	[TAIKO_A_PROCESS_MONITOR_CTL0] = 1,
+	[TAIKO_A_PROCESS_MONITOR_CTL1] = 1,
+	[TAIKO_A_PROCESS_MONITOR_CTL2] = 1,
+	[TAIKO_A_PROCESS_MONITOR_CTL3] = 1,
+	[TAIKO_A_QFUSE_CTL] = 1,
+	[TAIKO_A_QFUSE_STATUS] = 1,
+	[TAIKO_A_QFUSE_DATA_OUT0] = 1,
+	[TAIKO_A_QFUSE_DATA_OUT1] = 1,
+	[TAIKO_A_QFUSE_DATA_OUT2] = 1,
+	[TAIKO_A_QFUSE_DATA_OUT3] = 1,
+	[TAIKO_A_QFUSE_DATA_OUT4] = 1,
+	[TAIKO_A_QFUSE_DATA_OUT5] = 1,
+	[TAIKO_A_QFUSE_DATA_OUT6] = 1,
+	[TAIKO_A_QFUSE_DATA_OUT7] = 1,
+	[TAIKO_A_CDC_CTL] = 1,
+	[TAIKO_A_LEAKAGE_CTL] = 1,
+	[TAIKO_A_INTR_MODE] = 1,
+	[TAIKO_A_INTR_MASK0] = 1,
+	[TAIKO_A_INTR_MASK1] = 1,
+	[TAIKO_A_INTR_MASK2] = 1,
+	[TAIKO_A_INTR_MASK3] = 1,
+	[TAIKO_A_INTR_STATUS0] = 1,
+	[TAIKO_A_INTR_STATUS1] = 1,
+	[TAIKO_A_INTR_STATUS2] = 1,
+	[TAIKO_A_INTR_STATUS3] = 1,
+	[TAIKO_A_INTR_CLEAR0] = 0,
+	[TAIKO_A_INTR_CLEAR1] = 0,
+	[TAIKO_A_INTR_CLEAR2] = 0,
+	[TAIKO_A_INTR_CLEAR3] = 0,
+	[TAIKO_A_INTR_LEVEL0] = 1,
+	[TAIKO_A_INTR_LEVEL1] = 1,
+	[TAIKO_A_INTR_LEVEL2] = 1,
+	[TAIKO_A_INTR_LEVEL3] = 1,
+	[TAIKO_A_INTR_TEST0] = 1,
+	[TAIKO_A_INTR_TEST1] = 1,
+	[TAIKO_A_INTR_TEST2] = 1,
+	[TAIKO_A_INTR_TEST3] = 1,
+	[TAIKO_A_INTR_SET0] = 1,
+	[TAIKO_A_INTR_SET1] = 1,
+	[TAIKO_A_INTR_SET2] = 1,
+	[TAIKO_A_INTR_SET3] = 1,
+	[TAIKO_A_INTR_DESTN0] = 1,
+	[TAIKO_A_INTR_DESTN1] = 1,
+	[TAIKO_A_INTR_DESTN2] = 1,
+	[TAIKO_A_INTR_DESTN3] = 1,
+	[TAIKO_A_CDC_TX_I2S_SCK_MODE] = 1,
+	[TAIKO_A_CDC_TX_I2S_WS_MODE] = 1,
+	[TAIKO_A_CDC_DMIC_DATA0_MODE] = 1,
+	[TAIKO_A_CDC_DMIC_CLK0_MODE] = 1,
+	[TAIKO_A_CDC_DMIC_DATA1_MODE] = 1,
+	[TAIKO_A_CDC_DMIC_CLK1_MODE] = 1,
+	[TAIKO_A_CDC_RX_I2S_SCK_MODE] = 1,
+	[TAIKO_A_CDC_RX_I2S_WS_MODE] = 1,
+	[TAIKO_A_CDC_DMIC_DATA2_MODE] = 1,
+	[TAIKO_A_CDC_DMIC_CLK2_MODE] = 1,
+	[TAIKO_A_CDC_INTR1_MODE] = 1,
+	[TAIKO_A_CDC_SB_NRZ_SEL_MODE] = 1,
+	[TAIKO_A_CDC_INTR2_MODE] = 1,
+	[TAIKO_A_CDC_RF_PA_ON_MODE] = 1,
+	[TAIKO_A_BIAS_REF_CTL] = 1,
+	[TAIKO_A_BIAS_CENTRAL_BG_CTL] = 1,
+	[TAIKO_A_BIAS_PRECHRG_CTL] = 1,
+	[TAIKO_A_BIAS_CURR_CTL_1] = 1,
+	[TAIKO_A_BIAS_CURR_CTL_2] = 1,
+	[TAIKO_A_BIAS_OSC_BG_CTL] = 1,
+	[TAIKO_A_CLK_BUFF_EN1] = 1,
+	[TAIKO_A_CLK_BUFF_EN2] = 1,
+	[TAIKO_A_LDO_H_MODE_1] = 1,
+	[TAIKO_A_LDO_H_MODE_2] = 1,
+	[TAIKO_A_LDO_H_LOOP_CTL] = 1,
+	[TAIKO_A_LDO_H_COMP_1] = 1,
+	[TAIKO_A_LDO_H_COMP_2] = 1,
+	[TAIKO_A_LDO_H_BIAS_1] = 1,
+	[TAIKO_A_LDO_H_BIAS_2] = 1,
+	[TAIKO_A_LDO_H_BIAS_3] = 1,
+	[TAIKO_A_VBAT_CLK] = 1,
+	[TAIKO_A_VBAT_LOOP] = 1,
+	[TAIKO_A_VBAT_REF] = 1,
+	[TAIKO_A_VBAT_ADC_TEST] = 1,
+	[TAIKO_A_VBAT_FE] = 1,
+	[TAIKO_A_VBAT_BIAS_1] = 1,
+	[TAIKO_A_VBAT_BIAS_2] = 1,
+	[TAIKO_A_VBAT_ADC_DATA_MSB] = 1,
+	[TAIKO_A_VBAT_ADC_DATA_LSB] = 1,
+	[TAIKO_A_MICB_CFILT_1_CTL] = 1,
+	[TAIKO_A_MICB_CFILT_1_VAL] = 1,
+	[TAIKO_A_MICB_CFILT_1_PRECHRG] = 1,
+	[TAIKO_A_MICB_1_CTL] = 1,
+	[TAIKO_A_MICB_1_INT_RBIAS] = 1,
+	[TAIKO_A_MICB_1_MBHC] = 1,
+	[TAIKO_A_MICB_CFILT_2_CTL] = 1,
+	[TAIKO_A_MICB_CFILT_2_VAL] = 1,
+	[TAIKO_A_MICB_CFILT_2_PRECHRG] = 1,
+	[TAIKO_A_MICB_2_CTL] = 1,
+	[TAIKO_A_MICB_2_INT_RBIAS] = 1,
+	[TAIKO_A_MICB_2_MBHC] = 1,
+	[TAIKO_A_MICB_CFILT_3_CTL] = 1,
+	[TAIKO_A_MICB_CFILT_3_VAL] = 1,
+	[TAIKO_A_MICB_CFILT_3_PRECHRG] = 1,
+	[TAIKO_A_MICB_3_CTL] = 1,
+	[TAIKO_A_MICB_3_INT_RBIAS] = 1,
+	[TAIKO_A_MICB_3_MBHC] = 1,
+	[TAIKO_A_MICB_4_CTL] = 1,
+	[TAIKO_A_MICB_4_INT_RBIAS] = 1,
+	[TAIKO_A_MICB_4_MBHC] = 1,
+	[TAIKO_A_MBHC_INSERT_DETECT] = 1,
+	[TAIKO_A_MBHC_INSERT_DET_STATUS] = 1,
+	[TAIKO_A_TX_COM_BIAS] = 1,
+	[TAIKO_A_MBHC_SCALING_MUX_1] = 1,
+	[TAIKO_A_MBHC_SCALING_MUX_2] = 1,
+	[TAIKO_A_MAD_ANA_CTRL] = 1,
+	[TAIKO_A_TX_SUP_SWITCH_CTRL_1] = 1,
+	[TAIKO_A_TX_SUP_SWITCH_CTRL_2] = 1,
+	[TAIKO_A_TX_1_2_EN] = 1,
+	[TAIKO_A_TX_1_2_TEST_EN] = 1,
+	[TAIKO_A_TX_1_2_ADC_CH1] = 1,
+	[TAIKO_A_TX_1_2_ADC_CH2] = 1,
+	[TAIKO_A_TX_1_2_ATEST_REFCTRL] = 1,
+	[TAIKO_A_TX_1_2_TEST_CTL] = 1,
+	[TAIKO_A_TX_1_2_TEST_BLOCK_EN] = 1,
+	[TAIKO_A_TX_1_2_TXFE_CLKDIV] = 1,
+	[TAIKO_A_TX_1_2_SAR_ERR_CH1] = 1,
+	[TAIKO_A_TX_1_2_SAR_ERR_CH2] = 1,
+	[TAIKO_A_TX_3_4_EN] = 1,
+	[TAIKO_A_TX_3_4_TEST_EN] = 1,
+	[TAIKO_A_TX_3_4_ADC_CH3] = 1,
+	[TAIKO_A_TX_3_4_ADC_CH4] = 1,
+	[TAIKO_A_TX_3_4_ATEST_REFCTRL] = 1,
+	[TAIKO_A_TX_3_4_TEST_CTL] = 1,
+	[TAIKO_A_TX_3_4_TEST_BLOCK_EN] = 1,
+	[TAIKO_A_TX_3_4_TXFE_CKDIV] = 1,
+	[TAIKO_A_TX_3_4_SAR_ERR_CH3] = 1,
+	[TAIKO_A_TX_3_4_SAR_ERR_CH4] = 1,
+	[TAIKO_A_TX_5_6_EN] = 1,
+	[TAIKO_A_TX_5_6_TEST_EN] = 1,
+	[TAIKO_A_TX_5_6_ADC_CH5] = 1,
+	[TAIKO_A_TX_5_6_ADC_CH6] = 1,
+	[TAIKO_A_TX_5_6_ATEST_REFCTRL] = 1,
+	[TAIKO_A_TX_5_6_TEST_CTL] = 1,
+	[TAIKO_A_TX_5_6_TEST_BLOCK_EN] = 1,
+	[TAIKO_A_TX_5_6_TXFE_CKDIV] = 1,
+	[TAIKO_A_TX_5_6_SAR_ERR_CH5] = 1,
+	[TAIKO_A_TX_5_6_SAR_ERR_CH6] = 1,
+	[TAIKO_A_TX_7_MBHC_EN] = 1,
+	[TAIKO_A_TX_7_MBHC_ATEST_REFCTRL] = 1,
+	[TAIKO_A_TX_7_MBHC_ADC] = 1,
+	[TAIKO_A_TX_7_MBHC_TEST_CTL] = 1,
+	[TAIKO_A_TX_7_MBHC_SAR_ERR] = 1,
+	[TAIKO_A_TX_7_TXFE_CLKDIV] = 1,
+	[TAIKO_A_BUCK_MODE_1] = 1,
+	[TAIKO_A_BUCK_MODE_2] = 1,
+	[TAIKO_A_BUCK_MODE_3] = 1,
+	[TAIKO_A_BUCK_MODE_4] = 1,
+	[TAIKO_A_BUCK_MODE_5] = 1,
+	[TAIKO_A_BUCK_CTRL_VCL_1] = 1,
+	[TAIKO_A_BUCK_CTRL_VCL_2] = 1,
+	[TAIKO_A_BUCK_CTRL_VCL_3] = 1,
+	[TAIKO_A_BUCK_CTRL_CCL_1] = 1,
+	[TAIKO_A_BUCK_CTRL_CCL_2] = 1,
+	[TAIKO_A_BUCK_CTRL_CCL_3] = 1,
+	[TAIKO_A_BUCK_CTRL_CCL_4] = 1,
+	[TAIKO_A_BUCK_CTRL_PWM_DRVR_1] = 1,
+	[TAIKO_A_BUCK_CTRL_PWM_DRVR_2] = 1,
+	[TAIKO_A_BUCK_CTRL_PWM_DRVR_3] = 1,
+	[TAIKO_A_BUCK_TMUX_A_D] = 1,
+	[TAIKO_A_NCP_BUCKREF] = 1,
+	[TAIKO_A_NCP_EN] = 1,
+	[TAIKO_A_NCP_CLK] = 1,
+	[TAIKO_A_NCP_STATIC] = 1,
+	[TAIKO_A_NCP_VTH_LOW] = 1,
+	[TAIKO_A_NCP_VTH_HIGH] = 1,
+	[TAIKO_A_NCP_ATEST] = 1,
+	[TAIKO_A_NCP_DTEST] = 1,
+	[TAIKO_A_NCP_DLY1] = 1,
+	[TAIKO_A_NCP_DLY2] = 1,
+	[TAIKO_A_RX_AUX_SW_CTL] = 1,
+	[TAIKO_A_RX_PA_AUX_IN_CONN] = 1,
+	[TAIKO_A_RX_COM_TIMER_DIV] = 1,
+	[TAIKO_A_RX_COM_OCP_CTL] = 1,
+	[TAIKO_A_RX_COM_OCP_COUNT] = 1,
+	[TAIKO_A_RX_COM_DAC_CTL] = 1,
+	[TAIKO_A_RX_COM_BIAS] = 1,
+	[TAIKO_A_RX_HPH_AUTO_CHOP] = 1,
+	[TAIKO_A_RX_HPH_CHOP_CTL] = 1,
+	[TAIKO_A_RX_HPH_BIAS_PA] = 1,
+	[TAIKO_A_RX_HPH_BIAS_LDO] = 1,
+	[TAIKO_A_RX_HPH_BIAS_CNP] = 1,
+	[TAIKO_A_RX_HPH_BIAS_WG_OCP] = 1,
+	[TAIKO_A_RX_HPH_OCP_CTL] = 1,
+	[TAIKO_A_RX_HPH_CNP_EN] = 1,
+	[TAIKO_A_RX_HPH_CNP_WG_CTL] = 1,
+	[TAIKO_A_RX_HPH_CNP_WG_TIME] = 1,
+	[TAIKO_A_RX_HPH_L_GAIN] = 1,
+	[TAIKO_A_RX_HPH_L_TEST] = 1,
+	[TAIKO_A_RX_HPH_L_PA_CTL] = 1,
+	[TAIKO_A_RX_HPH_L_DAC_CTL] = 1,
+	[TAIKO_A_RX_HPH_L_ATEST] = 1,
+	[TAIKO_A_RX_HPH_L_STATUS] = 1,
+	[TAIKO_A_RX_HPH_R_GAIN] = 1,
+	[TAIKO_A_RX_HPH_R_TEST] = 1,
+	[TAIKO_A_RX_HPH_R_PA_CTL] = 1,
+	[TAIKO_A_RX_HPH_R_DAC_CTL] = 1,
+	[TAIKO_A_RX_HPH_R_ATEST] = 1,
+	[TAIKO_A_RX_HPH_R_STATUS] = 1,
+	[TAIKO_A_RX_EAR_BIAS_PA] = 1,
+	[TAIKO_A_RX_EAR_BIAS_CMBUFF] = 1,
+	[TAIKO_A_RX_EAR_EN] = 1,
+	[TAIKO_A_RX_EAR_GAIN] = 1,
+	[TAIKO_A_RX_EAR_CMBUFF] = 1,
+	[TAIKO_A_RX_EAR_ICTL] = 1,
+	[TAIKO_A_RX_EAR_CCOMP] = 1,
+	[TAIKO_A_RX_EAR_VCM] = 1,
+	[TAIKO_A_RX_EAR_CNP] = 1,
+	[TAIKO_A_RX_EAR_DAC_CTL_ATEST] = 1,
+	[TAIKO_A_RX_EAR_STATUS] = 1,
+	[TAIKO_A_RX_LINE_BIAS_PA] = 1,
+	[TAIKO_A_RX_BUCK_BIAS1] = 1,
+	[TAIKO_A_RX_BUCK_BIAS2] = 1,
+	[TAIKO_A_RX_LINE_COM] = 1,
+	[TAIKO_A_RX_LINE_CNP_EN] = 1,
+	[TAIKO_A_RX_LINE_CNP_WG_CTL] = 1,
+	[TAIKO_A_RX_LINE_CNP_WG_TIME] = 1,
+	[TAIKO_A_RX_LINE_1_GAIN] = 1,
+	[TAIKO_A_RX_LINE_1_TEST] = 1,
+	[TAIKO_A_RX_LINE_1_DAC_CTL] = 1,
+	[TAIKO_A_RX_LINE_1_STATUS] = 1,
+	[TAIKO_A_RX_LINE_2_GAIN] = 1,
+	[TAIKO_A_RX_LINE_2_TEST] = 1,
+	[TAIKO_A_RX_LINE_2_DAC_CTL] = 1,
+	[TAIKO_A_RX_LINE_2_STATUS] = 1,
+	[TAIKO_A_RX_LINE_3_GAIN] = 1,
+	[TAIKO_A_RX_LINE_3_TEST] = 1,
+	[TAIKO_A_RX_LINE_3_DAC_CTL] = 1,
+	[TAIKO_A_RX_LINE_3_STATUS] = 1,
+	[TAIKO_A_RX_LINE_4_GAIN] = 1,
+	[TAIKO_A_RX_LINE_4_TEST] = 1,
+	[TAIKO_A_RX_LINE_4_DAC_CTL] = 1,
+	[TAIKO_A_RX_LINE_4_STATUS] = 1,
+	[TAIKO_A_RX_LINE_CNP_DBG] = 1,
+	[TAIKO_A_SPKR_DRV_EN] = 1,
+	[TAIKO_A_SPKR_DRV_GAIN] = 1,
+	[TAIKO_A_SPKR_DRV_DAC_CTL] = 1,
+	[TAIKO_A_SPKR_DRV_OCP_CTL] = 1,
+	[TAIKO_A_SPKR_DRV_CLIP_DET] = 1,
+	[TAIKO_A_SPKR_DRV_IEC] = 1,
+	[TAIKO_A_SPKR_DRV_DBG_DAC] = 1,
+	[TAIKO_A_SPKR_DRV_DBG_PA] = 1,
+	[TAIKO_A_SPKR_DRV_DBG_PWRSTG] = 1,
+	[TAIKO_A_SPKR_DRV_BIAS_LDO] = 1,
+	[TAIKO_A_SPKR_DRV_BIAS_INT] = 1,
+	[TAIKO_A_SPKR_DRV_BIAS_PA] = 1,
+	[TAIKO_A_SPKR_DRV_STATUS_OCP] = 1,
+	[TAIKO_A_SPKR_DRV_STATUS_PA] = 1,
+	[TAIKO_A_SPKR_PROT_EN] = 1,
+	[TAIKO_A_SPKR_PROT_ADC_EN] = 1,
+	[TAIKO_A_SPKR_PROT_ISENSE_BIAS] = 1,
+	[TAIKO_A_SPKR_PROT_VSENSE_BIAS] = 1,
+	[TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL] = 1,
+	[TAIKO_A_SPKR_PROT_ADC_TEST_CTL] = 1,
+	[TAIKO_A_SPKR_PROT_TEST_BLOCK_EN] = 1,
+	[TAIKO_A_SPKR_PROT_ATEST] = 1,
+	[TAIKO_A_SPKR_PROT_V_SAR_ERR] = 1,
+	[TAIKO_A_SPKR_PROT_I_SAR_ERR] = 1,
+	[TAIKO_A_SPKR_PROT_LDO_CTRL] = 1,
+	[TAIKO_A_SPKR_PROT_ISENSE_CTRL] = 1,
+	[TAIKO_A_SPKR_PROT_VSENSE_CTRL] = 1,
+	[TAIKO_A_RC_OSC_FREQ] = 1,
+	[TAIKO_A_RC_OSC_TEST] = 1,
+	[TAIKO_A_RC_OSC_STATUS] = 1,
+	[TAIKO_A_RC_OSC_TUNER] = 1,
+	[TAIKO_A_MBHC_HPH] = 1,
+	[TAIKO_A_CDC_ANC1_B1_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_B1_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_SHIFT] = 1,
+	[TAIKO_A_CDC_ANC2_SHIFT] = 1,
+	[TAIKO_A_CDC_ANC1_IIR_B1_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_IIR_B1_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_IIR_B2_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_IIR_B2_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_IIR_B3_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_IIR_B3_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_LPF_B1_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_LPF_B1_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_LPF_B2_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_LPF_B2_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_SPARE] = 1,
+	[TAIKO_A_CDC_ANC2_SPARE] = 1,
+	[TAIKO_A_CDC_ANC1_SMLPF_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_SMLPF_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_DCFLT_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_DCFLT_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_GAIN_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_GAIN_CTL] = 1,
+	[TAIKO_A_CDC_ANC1_B2_CTL] = 1,
+	[TAIKO_A_CDC_ANC2_B2_CTL] = 1,
+	[TAIKO_A_CDC_TX1_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX2_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX3_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX4_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX5_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX6_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX7_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX8_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX9_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX10_VOL_CTL_TIMER] = 1,
+	[TAIKO_A_CDC_TX1_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX2_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX3_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX4_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX5_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX6_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX7_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX8_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX9_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX10_VOL_CTL_GAIN] = 1,
+	[TAIKO_A_CDC_TX1_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX2_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX3_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX4_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX5_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX6_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX7_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX8_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX9_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX10_VOL_CTL_CFG] = 1,
+	[TAIKO_A_CDC_TX1_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX2_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX3_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX4_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX5_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX6_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX7_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX8_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX9_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX10_MUX_CTL] = 1,
+	[TAIKO_A_CDC_TX1_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX2_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX3_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX4_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX5_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX6_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX7_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX8_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX9_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX10_CLK_FS_CTL] = 1,
+	[TAIKO_A_CDC_TX1_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX2_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX3_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX4_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX5_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX6_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX7_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX8_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX9_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_TX10_DMIC_CTL] = 1,
+	[TAIKO_A_CDC_DEBUG_B1_CTL] = 1,
+	[TAIKO_A_CDC_DEBUG_B2_CTL] = 1,
+	[TAIKO_A_CDC_DEBUG_B3_CTL] = 1,
+	[TAIKO_A_CDC_DEBUG_B4_CTL] = 1,
+	[TAIKO_A_CDC_DEBUG_B5_CTL] = 1,
+	[TAIKO_A_CDC_DEBUG_B6_CTL] = 1,
+	[TAIKO_A_CDC_DEBUG_B7_CTL] = 1,
+	[TAIKO_A_CDC_SRC1_PDA_CFG] = 1,
+	[TAIKO_A_CDC_SRC2_PDA_CFG] = 1,
+	[TAIKO_A_CDC_SRC1_FS_CTL] = 1,
+	[TAIKO_A_CDC_SRC2_FS_CTL] = 1,
+	[TAIKO_A_CDC_RX1_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX2_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX3_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX4_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX5_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX6_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX7_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX1_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX2_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX3_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX4_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX5_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX6_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX7_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX1_B3_CTL] = 1,
+	[TAIKO_A_CDC_RX2_B3_CTL] = 1,
+	[TAIKO_A_CDC_RX3_B3_CTL] = 1,
+	[TAIKO_A_CDC_RX4_B3_CTL] = 1,
+	[TAIKO_A_CDC_RX5_B3_CTL] = 1,
+	[TAIKO_A_CDC_RX6_B3_CTL] = 1,
+	[TAIKO_A_CDC_RX7_B3_CTL] = 1,
+	[TAIKO_A_CDC_RX1_B4_CTL] = 1,
+	[TAIKO_A_CDC_RX2_B4_CTL] = 1,
+	[TAIKO_A_CDC_RX3_B4_CTL] = 1,
+	[TAIKO_A_CDC_RX4_B4_CTL] = 1,
+	[TAIKO_A_CDC_RX5_B4_CTL] = 1,
+	[TAIKO_A_CDC_RX6_B4_CTL] = 1,
+	[TAIKO_A_CDC_RX7_B4_CTL] = 1,
+	[TAIKO_A_CDC_RX1_B5_CTL] = 1,
+	[TAIKO_A_CDC_RX2_B5_CTL] = 1,
+	[TAIKO_A_CDC_RX3_B5_CTL] = 1,
+	[TAIKO_A_CDC_RX4_B5_CTL] = 1,
+	[TAIKO_A_CDC_RX5_B5_CTL] = 1,
+	[TAIKO_A_CDC_RX6_B5_CTL] = 1,
+	[TAIKO_A_CDC_RX7_B5_CTL] = 1,
+	[TAIKO_A_CDC_RX1_B6_CTL] = 1,
+	[TAIKO_A_CDC_RX2_B6_CTL] = 1,
+	[TAIKO_A_CDC_RX3_B6_CTL] = 1,
+	[TAIKO_A_CDC_RX4_B6_CTL] = 1,
+	[TAIKO_A_CDC_RX5_B6_CTL] = 1,
+	[TAIKO_A_CDC_RX6_B6_CTL] = 1,
+	[TAIKO_A_CDC_RX7_B6_CTL] = 1,
+	[TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL] = 1,
+	[TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL] = 1,
+	[TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL] = 1,
+	[TAIKO_A_CDC_VBAT_CFG] = 1,
+	[TAIKO_A_CDC_VBAT_ADC_CAL1] = 1,
+	[TAIKO_A_CDC_VBAT_ADC_CAL2] = 1,
+	[TAIKO_A_CDC_VBAT_ADC_CAL3] = 1,
+	[TAIKO_A_CDC_VBAT_PK_EST1] = 1,
+	[TAIKO_A_CDC_VBAT_PK_EST2] = 1,
+	[TAIKO_A_CDC_VBAT_PK_EST3] = 1,
+	[TAIKO_A_CDC_VBAT_RF_PROC1] = 1,
+	[TAIKO_A_CDC_VBAT_RF_PROC2] = 1,
+	[TAIKO_A_CDC_VBAT_TAC1] = 1,
+	[TAIKO_A_CDC_VBAT_TAC2] = 1,
+	[TAIKO_A_CDC_VBAT_TAC3] = 1,
+	[TAIKO_A_CDC_VBAT_TAC4] = 1,
+	[TAIKO_A_CDC_VBAT_GAIN_UPD1] = 1,
+	[TAIKO_A_CDC_VBAT_GAIN_UPD2] = 1,
+	[TAIKO_A_CDC_VBAT_GAIN_UPD3] = 1,
+	[TAIKO_A_CDC_VBAT_GAIN_UPD4] = 1,
+	[TAIKO_A_CDC_VBAT_DEBUG1] = 1,
+	[TAIKO_A_CDC_CLK_ANC_RESET_CTL] = 1,
+	[TAIKO_A_CDC_CLK_RX_RESET_CTL] = 1,
+	[TAIKO_A_CDC_CLK_TX_RESET_B1_CTL] = 1,
+	[TAIKO_A_CDC_CLK_TX_RESET_B2_CTL] = 1,
+	[TAIKO_A_CDC_CLK_DMIC_B1_CTL] = 1,
+	[TAIKO_A_CDC_CLK_DMIC_B2_CTL] = 1,
+	[TAIKO_A_CDC_CLK_RX_I2S_CTL] = 1,
+	[TAIKO_A_CDC_CLK_TX_I2S_CTL] = 1,
+	[TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL] = 1,
+	[TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL] = 1,
+	[TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL] = 1,
+	[TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL] = 1,
+	[TAIKO_A_CDC_CLK_OTHR_CTL] = 1,
+	[TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL] = 1,
+	[TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL] = 1,
+	[TAIKO_A_CDC_CLK_RX_B1_CTL] = 1,
+	[TAIKO_A_CDC_CLK_RX_B2_CTL] = 1,
+	[TAIKO_A_CDC_CLK_MCLK_CTL] = 1,
+	[TAIKO_A_CDC_CLK_PDM_CTL] = 1,
+	[TAIKO_A_CDC_CLK_SD_CTL] = 1,
+	[TAIKO_A_CDC_CLK_POWER_CTL] = 1,
+	[TAIKO_A_CDC_CLSH_B1_CTL] = 1,
+	[TAIKO_A_CDC_CLSH_B2_CTL] = 1,
+	[TAIKO_A_CDC_CLSH_B3_CTL] = 1,
+	[TAIKO_A_CDC_CLSH_BUCK_NCP_VARS] = 1,
+	[TAIKO_A_CDC_CLSH_IDLE_HPH_THSD] = 1,
+	[TAIKO_A_CDC_CLSH_IDLE_EAR_THSD] = 1,
+	[TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD] = 1,
+	[TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD] = 1,
+	[TAIKO_A_CDC_CLSH_K_ADDR] = 1,
+	[TAIKO_A_CDC_CLSH_K_DATA] = 1,
+	[TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L] = 1,
+	[TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U] = 1,
+	[TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L] = 1,
+	[TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U] = 1,
+	[TAIKO_A_CDC_CLSH_V_PA_HD_EAR] = 1,
+	[TAIKO_A_CDC_CLSH_V_PA_HD_HPH] = 1,
+	[TAIKO_A_CDC_CLSH_V_PA_MIN_EAR] = 1,
+	[TAIKO_A_CDC_CLSH_V_PA_MIN_HPH] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_B1_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_B1_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_B2_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_B2_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_B3_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_B3_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_B4_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_B4_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_B5_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_B5_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_B6_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_B6_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_B7_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_B7_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_B8_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_B8_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_COEF_B1_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_COEF_B1_CTL] = 1,
+	[TAIKO_A_CDC_IIR1_COEF_B2_CTL] = 1,
+	[TAIKO_A_CDC_IIR2_COEF_B2_CTL] = 1,
+	[TAIKO_A_CDC_TOP_GAIN_UPDATE] = 1,
+	[TAIKO_A_CDC_COMP0_B1_CTL] = 1,
+	[TAIKO_A_CDC_COMP1_B1_CTL] = 1,
+	[TAIKO_A_CDC_COMP2_B1_CTL] = 1,
+	[TAIKO_A_CDC_COMP0_B2_CTL] = 1,
+	[TAIKO_A_CDC_COMP1_B2_CTL] = 1,
+	[TAIKO_A_CDC_COMP2_B2_CTL] = 1,
+	[TAIKO_A_CDC_COMP0_B3_CTL] = 1,
+	[TAIKO_A_CDC_COMP1_B3_CTL] = 1,
+	[TAIKO_A_CDC_COMP2_B3_CTL] = 1,
+	[TAIKO_A_CDC_COMP0_B4_CTL] = 1,
+	[TAIKO_A_CDC_COMP1_B4_CTL] = 1,
+	[TAIKO_A_CDC_COMP2_B4_CTL] = 1,
+	[TAIKO_A_CDC_COMP0_B5_CTL] = 1,
+	[TAIKO_A_CDC_COMP1_B5_CTL] = 1,
+	[TAIKO_A_CDC_COMP2_B5_CTL] = 1,
+	[TAIKO_A_CDC_COMP0_B6_CTL] = 1,
+	[TAIKO_A_CDC_COMP1_B6_CTL] = 1,
+	[TAIKO_A_CDC_COMP2_B6_CTL] = 1,
+	[TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS] = 1,
+	[TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS] = 1,
+	[TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS] = 1,
+	[TAIKO_A_CDC_COMP0_FS_CFG] = 1,
+	[TAIKO_A_CDC_COMP1_FS_CFG] = 1,
+	[TAIKO_A_CDC_COMP2_FS_CFG] = 1,
+	[TAIKO_A_CDC_CONN_RX1_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX1_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX1_B3_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX2_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX2_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX2_B3_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX3_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX3_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX4_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX4_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX5_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX5_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX6_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX6_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX7_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX7_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX7_B3_CTL] = 1,
+	[TAIKO_A_CDC_CONN_ANC_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_ANC_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_B3_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_B4_CTL] = 1,
+	[TAIKO_A_CDC_CONN_EQ1_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_EQ1_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_EQ1_B3_CTL] = 1,
+	[TAIKO_A_CDC_CONN_EQ1_B4_CTL] = 1,
+	[TAIKO_A_CDC_CONN_EQ2_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_EQ2_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_EQ2_B3_CTL] = 1,
+	[TAIKO_A_CDC_CONN_EQ2_B4_CTL] = 1,
+	[TAIKO_A_CDC_CONN_SRC1_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_SRC1_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_SRC2_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_SRC2_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B3_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B4_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B5_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B6_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B7_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B8_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B9_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B10_CTL] = 1,
+	[TAIKO_A_CDC_CONN_TX_SB_B11_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX_SB_B1_CTL] = 1,
+	[TAIKO_A_CDC_CONN_RX_SB_B2_CTL] = 1,
+	[TAIKO_A_CDC_CONN_CLSH_CTL] = 1,
+	[TAIKO_A_CDC_CONN_MISC] = 1,
+	[TAIKO_A_CDC_CONN_MAD] = 1,
+	[TAIKO_A_CDC_MBHC_EN_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_FIR_B1_CFG] = 1,
+	[TAIKO_A_CDC_MBHC_FIR_B2_CFG] = 1,
+	[TAIKO_A_CDC_MBHC_TIMER_B1_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_TIMER_B2_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_TIMER_B3_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_TIMER_B4_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_TIMER_B5_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_TIMER_B6_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_B1_STATUS] = 1,
+	[TAIKO_A_CDC_MBHC_B2_STATUS] = 1,
+	[TAIKO_A_CDC_MBHC_B3_STATUS] = 1,
+	[TAIKO_A_CDC_MBHC_B4_STATUS] = 1,
+	[TAIKO_A_CDC_MBHC_B5_STATUS] = 1,
+	[TAIKO_A_CDC_MBHC_B1_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_B2_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B1_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B2_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B3_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B4_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B5_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B6_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B7_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B8_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B9_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B10_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B11_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_VOLT_B12_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_CLK_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_INT_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_DEBUG_CTL] = 1,
+	[TAIKO_A_CDC_MBHC_SPARE] = 1,
+	[TAIKO_A_CDC_MAD_MAIN_CTL_1] = 1,
+	[TAIKO_A_CDC_MAD_MAIN_CTL_2] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_1] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_2] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_3] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_4] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_5] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_6] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_7] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_8] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR] = 1,
+	[TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL] = 1,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_1] = 1,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_2] = 1,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_3] = 1,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_4] = 1,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_5] = 1,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_6] = 1,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_7] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_1] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_2] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_3] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_4] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_5] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_6] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_7] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_8] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR] = 1,
+	[TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL] = 1,
+};
+
+const u8 taiko_reg_defaults[TAIKO_CACHE_SIZE] = {
+	[TAIKO_A_CHIP_CTL] = TAIKO_A_CHIP_CTL__POR,
+	[TAIKO_A_CHIP_STATUS] = TAIKO_A_CHIP_STATUS__POR,
+	[TAIKO_A_CHIP_ID_BYTE_0] = TAIKO_A_CHIP_ID_BYTE_0__POR,
+	[TAIKO_A_CHIP_ID_BYTE_1] = TAIKO_A_CHIP_ID_BYTE_1__POR,
+	[TAIKO_A_CHIP_ID_BYTE_2] = TAIKO_A_CHIP_ID_BYTE_2__POR,
+	[TAIKO_A_CHIP_ID_BYTE_3] = TAIKO_A_CHIP_ID_BYTE_3__POR,
+	[TAIKO_A_CHIP_VERSION] = TAIKO_A_CHIP_VERSION__POR,
+	[TAIKO_A_SLAVE_ID_1] = TAIKO_A_SLAVE_ID_1__POR,
+	[TAIKO_A_SLAVE_ID_2] = TAIKO_A_SLAVE_ID_2__POR,
+	[TAIKO_A_SLAVE_ID_3] = TAIKO_A_SLAVE_ID_3__POR,
+	[TAIKO_A_PIN_CTL_OE0] = TAIKO_A_PIN_CTL_OE0__POR,
+	[TAIKO_A_PIN_CTL_OE1] = TAIKO_A_PIN_CTL_OE1__POR,
+	[TAIKO_A_PIN_CTL_DATA0] = TAIKO_A_PIN_CTL_DATA0__POR,
+	[TAIKO_A_PIN_CTL_DATA1] = TAIKO_A_PIN_CTL_DATA1__POR,
+	[TAIKO_A_HDRIVE_GENERIC] = TAIKO_A_HDRIVE_GENERIC__POR,
+	[TAIKO_A_HDRIVE_OVERRIDE] = TAIKO_A_HDRIVE_OVERRIDE__POR,
+	[TAIKO_A_ANA_CSR_WAIT_STATE] = TAIKO_A_ANA_CSR_WAIT_STATE__POR,
+	[TAIKO_A_PROCESS_MONITOR_CTL0] = TAIKO_A_PROCESS_MONITOR_CTL0__POR,
+	[TAIKO_A_PROCESS_MONITOR_CTL1] = TAIKO_A_PROCESS_MONITOR_CTL1__POR,
+	[TAIKO_A_PROCESS_MONITOR_CTL2] = TAIKO_A_PROCESS_MONITOR_CTL2__POR,
+	[TAIKO_A_PROCESS_MONITOR_CTL3] = TAIKO_A_PROCESS_MONITOR_CTL3__POR,
+	[TAIKO_A_QFUSE_CTL] = TAIKO_A_QFUSE_CTL__POR,
+	[TAIKO_A_QFUSE_STATUS] = TAIKO_A_QFUSE_STATUS__POR,
+	[TAIKO_A_QFUSE_DATA_OUT0] = TAIKO_A_QFUSE_DATA_OUT0__POR,
+	[TAIKO_A_QFUSE_DATA_OUT1] = TAIKO_A_QFUSE_DATA_OUT1__POR,
+	[TAIKO_A_QFUSE_DATA_OUT2] = TAIKO_A_QFUSE_DATA_OUT2__POR,
+	[TAIKO_A_QFUSE_DATA_OUT3] = TAIKO_A_QFUSE_DATA_OUT3__POR,
+	[TAIKO_A_QFUSE_DATA_OUT4] = TAIKO_A_QFUSE_DATA_OUT4__POR,
+	[TAIKO_A_QFUSE_DATA_OUT5] = TAIKO_A_QFUSE_DATA_OUT5__POR,
+	[TAIKO_A_QFUSE_DATA_OUT6] = TAIKO_A_QFUSE_DATA_OUT6__POR,
+	[TAIKO_A_QFUSE_DATA_OUT7] = TAIKO_A_QFUSE_DATA_OUT7__POR,
+	[TAIKO_A_CDC_CTL] = TAIKO_A_CDC_CTL__POR,
+	[TAIKO_A_LEAKAGE_CTL] = TAIKO_A_LEAKAGE_CTL__POR,
+	[TAIKO_A_INTR_MODE] = TAIKO_A_INTR_MODE__POR,
+	[TAIKO_A_INTR_MASK0] = TAIKO_A_INTR_MASK0__POR,
+	[TAIKO_A_INTR_MASK1] = TAIKO_A_INTR_MASK1__POR,
+	[TAIKO_A_INTR_MASK2] = TAIKO_A_INTR_MASK2__POR,
+	[TAIKO_A_INTR_MASK3] = TAIKO_A_INTR_MASK3__POR,
+	[TAIKO_A_INTR_STATUS0] = TAIKO_A_INTR_STATUS0__POR,
+	[TAIKO_A_INTR_STATUS1] = TAIKO_A_INTR_STATUS1__POR,
+	[TAIKO_A_INTR_STATUS2] = TAIKO_A_INTR_STATUS2__POR,
+	[TAIKO_A_INTR_STATUS3] = TAIKO_A_INTR_STATUS3__POR,
+	[TAIKO_A_INTR_CLEAR0] = TAIKO_A_INTR_CLEAR0__POR,
+	[TAIKO_A_INTR_CLEAR1] = TAIKO_A_INTR_CLEAR1__POR,
+	[TAIKO_A_INTR_CLEAR2] = TAIKO_A_INTR_CLEAR2__POR,
+	[TAIKO_A_INTR_CLEAR3] = TAIKO_A_INTR_CLEAR3__POR,
+	[TAIKO_A_INTR_LEVEL0] = TAIKO_A_INTR_LEVEL0__POR,
+	[TAIKO_A_INTR_LEVEL1] = TAIKO_A_INTR_LEVEL1__POR,
+	[TAIKO_A_INTR_LEVEL2] = TAIKO_A_INTR_LEVEL2__POR,
+	[TAIKO_A_INTR_LEVEL3] = TAIKO_A_INTR_LEVEL3__POR,
+	[TAIKO_A_INTR_TEST0] = TAIKO_A_INTR_TEST0__POR,
+	[TAIKO_A_INTR_TEST1] = TAIKO_A_INTR_TEST1__POR,
+	[TAIKO_A_INTR_TEST2] = TAIKO_A_INTR_TEST2__POR,
+	[TAIKO_A_INTR_TEST3] = TAIKO_A_INTR_TEST3__POR,
+	[TAIKO_A_INTR_SET0] = TAIKO_A_INTR_SET0__POR,
+	[TAIKO_A_INTR_SET1] = TAIKO_A_INTR_SET1__POR,
+	[TAIKO_A_INTR_SET2] = TAIKO_A_INTR_SET2__POR,
+	[TAIKO_A_INTR_SET3] = TAIKO_A_INTR_SET3__POR,
+	[TAIKO_A_INTR_DESTN0] = TAIKO_A_INTR_DESTN0__POR,
+	[TAIKO_A_INTR_DESTN1] = TAIKO_A_INTR_DESTN1__POR,
+	[TAIKO_A_INTR_DESTN2] = TAIKO_A_INTR_DESTN2__POR,
+	[TAIKO_A_INTR_DESTN3] = TAIKO_A_INTR_DESTN3__POR,
+	[TAIKO_A_CDC_TX_I2S_SCK_MODE] = TAIKO_A_CDC_TX_I2S_SCK_MODE__POR,
+	[TAIKO_A_CDC_TX_I2S_WS_MODE] = TAIKO_A_CDC_TX_I2S_WS_MODE__POR,
+	[TAIKO_A_CDC_DMIC_DATA0_MODE] = TAIKO_A_CDC_DMIC_DATA0_MODE__POR,
+	[TAIKO_A_CDC_DMIC_CLK0_MODE] = TAIKO_A_CDC_DMIC_CLK0_MODE__POR,
+	[TAIKO_A_CDC_DMIC_DATA1_MODE] = TAIKO_A_CDC_DMIC_DATA1_MODE__POR,
+	[TAIKO_A_CDC_DMIC_CLK1_MODE] = TAIKO_A_CDC_DMIC_CLK1_MODE__POR,
+	[TAIKO_A_CDC_RX_I2S_SCK_MODE] = TAIKO_A_CDC_RX_I2S_SCK_MODE__POR,
+	[TAIKO_A_CDC_RX_I2S_WS_MODE] = TAIKO_A_CDC_RX_I2S_WS_MODE__POR,
+	[TAIKO_A_CDC_DMIC_DATA2_MODE] = TAIKO_A_CDC_DMIC_DATA2_MODE__POR,
+	[TAIKO_A_CDC_DMIC_CLK2_MODE] = TAIKO_A_CDC_DMIC_CLK2_MODE__POR,
+	[TAIKO_A_CDC_INTR1_MODE] = TAIKO_A_CDC_INTR1_MODE__POR,
+	[TAIKO_A_CDC_SB_NRZ_SEL_MODE] = TAIKO_A_CDC_SB_NRZ_SEL_MODE__POR,
+	[TAIKO_A_CDC_INTR2_MODE] = TAIKO_A_CDC_INTR2_MODE__POR,
+	[TAIKO_A_CDC_RF_PA_ON_MODE] = TAIKO_A_CDC_RF_PA_ON_MODE__POR,
+	[TAIKO_A_BIAS_REF_CTL] = TAIKO_A_BIAS_REF_CTL__POR,
+	[TAIKO_A_BIAS_CENTRAL_BG_CTL] = TAIKO_A_BIAS_CENTRAL_BG_CTL__POR,
+	[TAIKO_A_BIAS_PRECHRG_CTL] = TAIKO_A_BIAS_PRECHRG_CTL__POR,
+	[TAIKO_A_BIAS_CURR_CTL_1] = TAIKO_A_BIAS_CURR_CTL_1__POR,
+	[TAIKO_A_BIAS_CURR_CTL_2] = TAIKO_A_BIAS_CURR_CTL_2__POR,
+	[TAIKO_A_BIAS_OSC_BG_CTL] = TAIKO_A_BIAS_OSC_BG_CTL__POR,
+	[TAIKO_A_CLK_BUFF_EN1] = TAIKO_A_CLK_BUFF_EN1__POR,
+	[TAIKO_A_CLK_BUFF_EN2] = TAIKO_A_CLK_BUFF_EN2__POR,
+	[TAIKO_A_LDO_H_MODE_1] = TAIKO_A_LDO_H_MODE_1__POR,
+	[TAIKO_A_LDO_H_MODE_2] = TAIKO_A_LDO_H_MODE_2__POR,
+	[TAIKO_A_LDO_H_LOOP_CTL] = TAIKO_A_LDO_H_LOOP_CTL__POR,
+	[TAIKO_A_LDO_H_COMP_1] = TAIKO_A_LDO_H_COMP_1__POR,
+	[TAIKO_A_LDO_H_COMP_2] = TAIKO_A_LDO_H_COMP_2__POR,
+	[TAIKO_A_LDO_H_BIAS_1] = TAIKO_A_LDO_H_BIAS_1__POR,
+	[TAIKO_A_LDO_H_BIAS_2] = TAIKO_A_LDO_H_BIAS_2__POR,
+	[TAIKO_A_LDO_H_BIAS_3] = TAIKO_A_LDO_H_BIAS_3__POR,
+	[TAIKO_A_VBAT_CLK] = TAIKO_A_VBAT_CLK__POR,
+	[TAIKO_A_VBAT_LOOP] = TAIKO_A_VBAT_LOOP__POR,
+	[TAIKO_A_VBAT_REF] = TAIKO_A_VBAT_REF__POR,
+	[TAIKO_A_VBAT_ADC_TEST] = TAIKO_A_VBAT_ADC_TEST__POR,
+	[TAIKO_A_VBAT_FE] = TAIKO_A_VBAT_FE__POR,
+	[TAIKO_A_VBAT_BIAS_1] = TAIKO_A_VBAT_BIAS_1__POR,
+	[TAIKO_A_VBAT_BIAS_2] = TAIKO_A_VBAT_BIAS_2__POR,
+	[TAIKO_A_VBAT_ADC_DATA_MSB] = TAIKO_A_VBAT_ADC_DATA_MSB__POR,
+	[TAIKO_A_VBAT_ADC_DATA_LSB] = TAIKO_A_VBAT_ADC_DATA_LSB__POR,
+	[TAIKO_A_MICB_CFILT_1_CTL] = TAIKO_A_MICB_CFILT_1_CTL__POR,
+	[TAIKO_A_MICB_CFILT_1_VAL] = TAIKO_A_MICB_CFILT_1_VAL__POR,
+	[TAIKO_A_MICB_CFILT_1_PRECHRG] = TAIKO_A_MICB_CFILT_1_PRECHRG__POR,
+	[TAIKO_A_MICB_1_CTL] = TAIKO_A_MICB_1_CTL__POR,
+	[TAIKO_A_MICB_1_INT_RBIAS] = TAIKO_A_MICB_1_INT_RBIAS__POR,
+	[TAIKO_A_MICB_1_MBHC] = TAIKO_A_MICB_1_MBHC__POR,
+	[TAIKO_A_MICB_CFILT_2_CTL] = TAIKO_A_MICB_CFILT_2_CTL__POR,
+	[TAIKO_A_MICB_CFILT_2_VAL] = TAIKO_A_MICB_CFILT_2_VAL__POR,
+	[TAIKO_A_MICB_CFILT_2_PRECHRG] = TAIKO_A_MICB_CFILT_2_PRECHRG__POR,
+	[TAIKO_A_MICB_2_CTL] = TAIKO_A_MICB_2_CTL__POR,
+	[TAIKO_A_MICB_2_INT_RBIAS] = TAIKO_A_MICB_2_INT_RBIAS__POR,
+	[TAIKO_A_MICB_2_MBHC] = TAIKO_A_MICB_2_MBHC__POR,
+	[TAIKO_A_MICB_CFILT_3_CTL] = TAIKO_A_MICB_CFILT_3_CTL__POR,
+	[TAIKO_A_MICB_CFILT_3_VAL] = TAIKO_A_MICB_CFILT_3_VAL__POR,
+	[TAIKO_A_MICB_CFILT_3_PRECHRG] = TAIKO_A_MICB_CFILT_3_PRECHRG__POR,
+	[TAIKO_A_MICB_3_CTL] = TAIKO_A_MICB_3_CTL__POR,
+	[TAIKO_A_MICB_3_INT_RBIAS] = TAIKO_A_MICB_3_INT_RBIAS__POR,
+	[TAIKO_A_MICB_3_MBHC] = TAIKO_A_MICB_3_MBHC__POR,
+	[TAIKO_A_MICB_4_CTL] = TAIKO_A_MICB_4_CTL__POR,
+	[TAIKO_A_MICB_4_INT_RBIAS] = TAIKO_A_MICB_4_INT_RBIAS__POR,
+	[TAIKO_A_MICB_4_MBHC] = TAIKO_A_MICB_4_MBHC__POR,
+	[TAIKO_A_MBHC_INSERT_DETECT] = TAIKO_A_MBHC_INSERT_DETECT__POR,
+	[TAIKO_A_MBHC_INSERT_DET_STATUS] = TAIKO_A_MBHC_INSERT_DET_STATUS__POR,
+	[TAIKO_A_TX_COM_BIAS] = TAIKO_A_TX_COM_BIAS__POR,
+	[TAIKO_A_MBHC_SCALING_MUX_1] = TAIKO_A_MBHC_SCALING_MUX_1__POR,
+	[TAIKO_A_MBHC_SCALING_MUX_2] = TAIKO_A_MBHC_SCALING_MUX_2__POR,
+	[TAIKO_A_MAD_ANA_CTRL] = TAIKO_A_MAD_ANA_CTRL__POR,
+	[TAIKO_A_TX_SUP_SWITCH_CTRL_1] = TAIKO_A_TX_SUP_SWITCH_CTRL_1__POR,
+	[TAIKO_A_TX_SUP_SWITCH_CTRL_2] = TAIKO_A_TX_SUP_SWITCH_CTRL_2__POR,
+	[TAIKO_A_TX_1_2_EN] = TAIKO_A_TX_1_2_EN__POR,
+	[TAIKO_A_TX_1_2_TEST_EN] = TAIKO_A_TX_1_2_TEST_EN__POR,
+	[TAIKO_A_TX_1_2_ADC_CH1] = TAIKO_A_TX_1_2_ADC_CH1__POR,
+	[TAIKO_A_TX_1_2_ADC_CH2] = TAIKO_A_TX_1_2_ADC_CH2__POR,
+	[TAIKO_A_TX_1_2_ATEST_REFCTRL] = TAIKO_A_TX_1_2_ATEST_REFCTRL__POR,
+	[TAIKO_A_TX_1_2_TEST_CTL] = TAIKO_A_TX_1_2_TEST_CTL__POR,
+	[TAIKO_A_TX_1_2_TEST_BLOCK_EN] = TAIKO_A_TX_1_2_TEST_BLOCK_EN__POR,
+	[TAIKO_A_TX_1_2_TXFE_CLKDIV] = TAIKO_A_TX_1_2_TXFE_CLKDIV__POR,
+	[TAIKO_A_TX_1_2_SAR_ERR_CH1] = TAIKO_A_TX_1_2_SAR_ERR_CH1__POR,
+	[TAIKO_A_TX_1_2_SAR_ERR_CH2] = TAIKO_A_TX_1_2_SAR_ERR_CH2__POR,
+	[TAIKO_A_TX_3_4_EN] = TAIKO_A_TX_3_4_EN__POR,
+	[TAIKO_A_TX_3_4_TEST_EN] = TAIKO_A_TX_3_4_TEST_EN__POR,
+	[TAIKO_A_TX_3_4_ADC_CH3] = TAIKO_A_TX_3_4_ADC_CH3__POR,
+	[TAIKO_A_TX_3_4_ADC_CH4] = TAIKO_A_TX_3_4_ADC_CH4__POR,
+	[TAIKO_A_TX_3_4_ATEST_REFCTRL] = TAIKO_A_TX_3_4_ATEST_REFCTRL__POR,
+	[TAIKO_A_TX_3_4_TEST_CTL] = TAIKO_A_TX_3_4_TEST_CTL__POR,
+	[TAIKO_A_TX_3_4_TEST_BLOCK_EN] = TAIKO_A_TX_3_4_TEST_BLOCK_EN__POR,
+	[TAIKO_A_TX_3_4_TXFE_CKDIV] = TAIKO_A_TX_3_4_TXFE_CKDIV__POR,
+	[TAIKO_A_TX_3_4_SAR_ERR_CH3] = TAIKO_A_TX_3_4_SAR_ERR_CH3__POR,
+	[TAIKO_A_TX_3_4_SAR_ERR_CH4] = TAIKO_A_TX_3_4_SAR_ERR_CH4__POR,
+	[TAIKO_A_TX_5_6_EN] = TAIKO_A_TX_5_6_EN__POR,
+	[TAIKO_A_TX_5_6_TEST_EN] = TAIKO_A_TX_5_6_TEST_EN__POR,
+	[TAIKO_A_TX_5_6_ADC_CH5] = TAIKO_A_TX_5_6_ADC_CH5__POR,
+	[TAIKO_A_TX_5_6_ADC_CH6] = TAIKO_A_TX_5_6_ADC_CH6__POR,
+	[TAIKO_A_TX_5_6_ATEST_REFCTRL] = TAIKO_A_TX_5_6_ATEST_REFCTRL__POR,
+	[TAIKO_A_TX_5_6_TEST_CTL] = TAIKO_A_TX_5_6_TEST_CTL__POR,
+	[TAIKO_A_TX_5_6_TEST_BLOCK_EN] = TAIKO_A_TX_5_6_TEST_BLOCK_EN__POR,
+	[TAIKO_A_TX_5_6_TXFE_CKDIV] = TAIKO_A_TX_5_6_TXFE_CKDIV__POR,
+	[TAIKO_A_TX_5_6_SAR_ERR_CH5] = TAIKO_A_TX_5_6_SAR_ERR_CH5__POR,
+	[TAIKO_A_TX_5_6_SAR_ERR_CH6] = TAIKO_A_TX_5_6_SAR_ERR_CH6__POR,
+	[TAIKO_A_TX_7_MBHC_EN] = TAIKO_A_TX_7_MBHC_EN__POR,
+	[TAIKO_A_TX_7_MBHC_ATEST_REFCTRL] =
+	    TAIKO_A_TX_7_MBHC_ATEST_REFCTRL__POR,
+	[TAIKO_A_TX_7_MBHC_ADC] = TAIKO_A_TX_7_MBHC_ADC__POR,
+	[TAIKO_A_TX_7_MBHC_TEST_CTL] = TAIKO_A_TX_7_MBHC_TEST_CTL__POR,
+	[TAIKO_A_TX_7_MBHC_SAR_ERR] = TAIKO_A_TX_7_MBHC_SAR_ERR__POR,
+	[TAIKO_A_TX_7_TXFE_CLKDIV] = TAIKO_A_TX_7_TXFE_CLKDIV__POR,
+	[TAIKO_A_BUCK_MODE_1] = TAIKO_A_BUCK_MODE_1__POR,
+	[TAIKO_A_BUCK_MODE_2] = TAIKO_A_BUCK_MODE_2__POR,
+	[TAIKO_A_BUCK_MODE_3] = TAIKO_A_BUCK_MODE_3__POR,
+	[TAIKO_A_BUCK_MODE_4] = TAIKO_A_BUCK_MODE_4__POR,
+	[TAIKO_A_BUCK_MODE_5] = TAIKO_A_BUCK_MODE_5__POR,
+	[TAIKO_A_BUCK_CTRL_VCL_1] = TAIKO_A_BUCK_CTRL_VCL_1__POR,
+	[TAIKO_A_BUCK_CTRL_VCL_2] = TAIKO_A_BUCK_CTRL_VCL_2__POR,
+	[TAIKO_A_BUCK_CTRL_VCL_3] = TAIKO_A_BUCK_CTRL_VCL_3__POR,
+	[TAIKO_A_BUCK_CTRL_CCL_1] = TAIKO_A_BUCK_CTRL_CCL_1__POR,
+	[TAIKO_A_BUCK_CTRL_CCL_2] = TAIKO_A_BUCK_CTRL_CCL_2__POR,
+	[TAIKO_A_BUCK_CTRL_CCL_3] = TAIKO_A_BUCK_CTRL_CCL_3__POR,
+	[TAIKO_A_BUCK_CTRL_CCL_4] = TAIKO_A_BUCK_CTRL_CCL_4__POR,
+	[TAIKO_A_BUCK_CTRL_PWM_DRVR_1] = TAIKO_A_BUCK_CTRL_PWM_DRVR_1__POR,
+	[TAIKO_A_BUCK_CTRL_PWM_DRVR_2] = TAIKO_A_BUCK_CTRL_PWM_DRVR_2__POR,
+	[TAIKO_A_BUCK_CTRL_PWM_DRVR_3] = TAIKO_A_BUCK_CTRL_PWM_DRVR_3__POR,
+	[TAIKO_A_BUCK_TMUX_A_D] = TAIKO_A_BUCK_TMUX_A_D__POR,
+	[TAIKO_A_NCP_BUCKREF] = TAIKO_A_NCP_BUCKREF__POR,
+	[TAIKO_A_NCP_EN] = TAIKO_A_NCP_EN__POR,
+	[TAIKO_A_NCP_CLK] = TAIKO_A_NCP_CLK__POR,
+	[TAIKO_A_NCP_STATIC] = TAIKO_A_NCP_STATIC__POR,
+	[TAIKO_A_NCP_VTH_LOW] = TAIKO_A_NCP_VTH_LOW__POR,
+	[TAIKO_A_NCP_VTH_HIGH] = TAIKO_A_NCP_VTH_HIGH__POR,
+	[TAIKO_A_NCP_ATEST] = TAIKO_A_NCP_ATEST__POR,
+	[TAIKO_A_NCP_DTEST] = TAIKO_A_NCP_DTEST__POR,
+	[TAIKO_A_NCP_DLY1] = TAIKO_A_NCP_DLY1__POR,
+	[TAIKO_A_NCP_DLY2] = TAIKO_A_NCP_DLY2__POR,
+	[TAIKO_A_RX_AUX_SW_CTL] = TAIKO_A_RX_AUX_SW_CTL__POR,
+	[TAIKO_A_RX_PA_AUX_IN_CONN] = TAIKO_A_RX_PA_AUX_IN_CONN__POR,
+	[TAIKO_A_RX_COM_TIMER_DIV] = TAIKO_A_RX_COM_TIMER_DIV__POR,
+	[TAIKO_A_RX_COM_OCP_CTL] = TAIKO_A_RX_COM_OCP_CTL__POR,
+	[TAIKO_A_RX_COM_OCP_COUNT] = TAIKO_A_RX_COM_OCP_COUNT__POR,
+	[TAIKO_A_RX_COM_DAC_CTL] = TAIKO_A_RX_COM_DAC_CTL__POR,
+	[TAIKO_A_RX_COM_BIAS] = TAIKO_A_RX_COM_BIAS__POR,
+	[TAIKO_A_RX_HPH_AUTO_CHOP] = TAIKO_A_RX_HPH_AUTO_CHOP__POR,
+	[TAIKO_A_RX_HPH_CHOP_CTL] = TAIKO_A_RX_HPH_CHOP_CTL__POR,
+	[TAIKO_A_RX_HPH_BIAS_PA] = TAIKO_A_RX_HPH_BIAS_PA__POR,
+	[TAIKO_A_RX_HPH_BIAS_LDO] = TAIKO_A_RX_HPH_BIAS_LDO__POR,
+	[TAIKO_A_RX_HPH_BIAS_CNP] = TAIKO_A_RX_HPH_BIAS_CNP__POR,
+	[TAIKO_A_RX_HPH_BIAS_WG_OCP] = TAIKO_A_RX_HPH_BIAS_WG_OCP__POR,
+	[TAIKO_A_RX_HPH_OCP_CTL] = TAIKO_A_RX_HPH_OCP_CTL__POR,
+	[TAIKO_A_RX_HPH_CNP_EN] = TAIKO_A_RX_HPH_CNP_EN__POR,
+	[TAIKO_A_RX_HPH_CNP_WG_CTL] = TAIKO_A_RX_HPH_CNP_WG_CTL__POR,
+	[TAIKO_A_RX_HPH_CNP_WG_TIME] = TAIKO_A_RX_HPH_CNP_WG_TIME__POR,
+	[TAIKO_A_RX_HPH_L_GAIN] = TAIKO_A_RX_HPH_L_GAIN__POR,
+	[TAIKO_A_RX_HPH_L_TEST] = TAIKO_A_RX_HPH_L_TEST__POR,
+	[TAIKO_A_RX_HPH_L_PA_CTL] = TAIKO_A_RX_HPH_L_PA_CTL__POR,
+	[TAIKO_A_RX_HPH_L_DAC_CTL] = TAIKO_A_RX_HPH_L_DAC_CTL__POR,
+	[TAIKO_A_RX_HPH_L_ATEST] = TAIKO_A_RX_HPH_L_ATEST__POR,
+	[TAIKO_A_RX_HPH_L_STATUS] = TAIKO_A_RX_HPH_L_STATUS__POR,
+	[TAIKO_A_RX_HPH_R_GAIN] = TAIKO_A_RX_HPH_R_GAIN__POR,
+	[TAIKO_A_RX_HPH_R_TEST] = TAIKO_A_RX_HPH_R_TEST__POR,
+	[TAIKO_A_RX_HPH_R_PA_CTL] = TAIKO_A_RX_HPH_R_PA_CTL__POR,
+	[TAIKO_A_RX_HPH_R_DAC_CTL] = TAIKO_A_RX_HPH_R_DAC_CTL__POR,
+	[TAIKO_A_RX_HPH_R_ATEST] = TAIKO_A_RX_HPH_R_ATEST__POR,
+	[TAIKO_A_RX_HPH_R_STATUS] = TAIKO_A_RX_HPH_R_STATUS__POR,
+	[TAIKO_A_RX_EAR_BIAS_PA] = TAIKO_A_RX_EAR_BIAS_PA__POR,
+	[TAIKO_A_RX_EAR_BIAS_CMBUFF] = TAIKO_A_RX_EAR_BIAS_CMBUFF__POR,
+	[TAIKO_A_RX_EAR_EN] = TAIKO_A_RX_EAR_EN__POR,
+	[TAIKO_A_RX_EAR_GAIN] = TAIKO_A_RX_EAR_GAIN__POR,
+	[TAIKO_A_RX_EAR_CMBUFF] = TAIKO_A_RX_EAR_CMBUFF__POR,
+	[TAIKO_A_RX_EAR_ICTL] = TAIKO_A_RX_EAR_ICTL__POR,
+	[TAIKO_A_RX_EAR_CCOMP] = TAIKO_A_RX_EAR_CCOMP__POR,
+	[TAIKO_A_RX_EAR_VCM] = TAIKO_A_RX_EAR_VCM__POR,
+	[TAIKO_A_RX_EAR_CNP] = TAIKO_A_RX_EAR_CNP__POR,
+	[TAIKO_A_RX_EAR_DAC_CTL_ATEST] = TAIKO_A_RX_EAR_DAC_CTL_ATEST__POR,
+	[TAIKO_A_RX_EAR_STATUS] = TAIKO_A_RX_EAR_STATUS__POR,
+	[TAIKO_A_RX_LINE_BIAS_PA] = TAIKO_A_RX_LINE_BIAS_PA__POR,
+	[TAIKO_A_RX_BUCK_BIAS1] = TAIKO_A_RX_BUCK_BIAS1__POR,
+	[TAIKO_A_RX_BUCK_BIAS2] = TAIKO_A_RX_BUCK_BIAS2__POR,
+	[TAIKO_A_RX_LINE_COM] = TAIKO_A_RX_LINE_COM__POR,
+	[TAIKO_A_RX_LINE_CNP_EN] = TAIKO_A_RX_LINE_CNP_EN__POR,
+	[TAIKO_A_RX_LINE_CNP_WG_CTL] = TAIKO_A_RX_LINE_CNP_WG_CTL__POR,
+	[TAIKO_A_RX_LINE_CNP_WG_TIME] = TAIKO_A_RX_LINE_CNP_WG_TIME__POR,
+	[TAIKO_A_RX_LINE_1_GAIN] = TAIKO_A_RX_LINE_1_GAIN__POR,
+	[TAIKO_A_RX_LINE_1_TEST] = TAIKO_A_RX_LINE_1_TEST__POR,
+	[TAIKO_A_RX_LINE_1_DAC_CTL] = TAIKO_A_RX_LINE_1_DAC_CTL__POR,
+	[TAIKO_A_RX_LINE_1_STATUS] = TAIKO_A_RX_LINE_1_STATUS__POR,
+	[TAIKO_A_RX_LINE_2_GAIN] = TAIKO_A_RX_LINE_2_GAIN__POR,
+	[TAIKO_A_RX_LINE_2_TEST] = TAIKO_A_RX_LINE_2_TEST__POR,
+	[TAIKO_A_RX_LINE_2_DAC_CTL] = TAIKO_A_RX_LINE_2_DAC_CTL__POR,
+	[TAIKO_A_RX_LINE_2_STATUS] = TAIKO_A_RX_LINE_2_STATUS__POR,
+	[TAIKO_A_RX_LINE_3_GAIN] = TAIKO_A_RX_LINE_3_GAIN__POR,
+	[TAIKO_A_RX_LINE_3_TEST] = TAIKO_A_RX_LINE_3_TEST__POR,
+	[TAIKO_A_RX_LINE_3_DAC_CTL] = TAIKO_A_RX_LINE_3_DAC_CTL__POR,
+	[TAIKO_A_RX_LINE_3_STATUS] = TAIKO_A_RX_LINE_3_STATUS__POR,
+	[TAIKO_A_RX_LINE_4_GAIN] = TAIKO_A_RX_LINE_4_GAIN__POR,
+	[TAIKO_A_RX_LINE_4_TEST] = TAIKO_A_RX_LINE_4_TEST__POR,
+	[TAIKO_A_RX_LINE_4_DAC_CTL] = TAIKO_A_RX_LINE_4_DAC_CTL__POR,
+	[TAIKO_A_RX_LINE_4_STATUS] = TAIKO_A_RX_LINE_4_STATUS__POR,
+	[TAIKO_A_RX_LINE_CNP_DBG] = TAIKO_A_RX_LINE_CNP_DBG__POR,
+	[TAIKO_A_SPKR_DRV_EN] = TAIKO_A_SPKR_DRV_EN__POR,
+	[TAIKO_A_SPKR_DRV_GAIN] = TAIKO_A_SPKR_DRV_GAIN__POR,
+	[TAIKO_A_SPKR_DRV_DAC_CTL] = TAIKO_A_SPKR_DRV_DAC_CTL__POR,
+	[TAIKO_A_SPKR_DRV_OCP_CTL] = TAIKO_A_SPKR_DRV_OCP_CTL__POR,
+	[TAIKO_A_SPKR_DRV_CLIP_DET] = TAIKO_A_SPKR_DRV_CLIP_DET__POR,
+	[TAIKO_A_SPKR_DRV_IEC] = TAIKO_A_SPKR_DRV_IEC__POR,
+	[TAIKO_A_SPKR_DRV_DBG_DAC] = TAIKO_A_SPKR_DRV_DBG_DAC__POR,
+	[TAIKO_A_SPKR_DRV_DBG_PA] = TAIKO_A_SPKR_DRV_DBG_PA__POR,
+	[TAIKO_A_SPKR_DRV_DBG_PWRSTG] = TAIKO_A_SPKR_DRV_DBG_PWRSTG__POR,
+	[TAIKO_A_SPKR_DRV_BIAS_LDO] = TAIKO_A_SPKR_DRV_BIAS_LDO__POR,
+	[TAIKO_A_SPKR_DRV_BIAS_INT] = TAIKO_A_SPKR_DRV_BIAS_INT__POR,
+	[TAIKO_A_SPKR_DRV_BIAS_PA] = TAIKO_A_SPKR_DRV_BIAS_PA__POR,
+	[TAIKO_A_SPKR_DRV_STATUS_OCP] = TAIKO_A_SPKR_DRV_STATUS_OCP__POR,
+	[TAIKO_A_SPKR_DRV_STATUS_PA] = TAIKO_A_SPKR_DRV_STATUS_PA__POR,
+	[TAIKO_A_SPKR_PROT_EN] = TAIKO_A_SPKR_PROT_EN__POR,
+	[TAIKO_A_SPKR_PROT_ADC_EN] = TAIKO_A_SPKR_PROT_ADC_EN__POR,
+	[TAIKO_A_SPKR_PROT_ISENSE_BIAS] = TAIKO_A_SPKR_PROT_ISENSE_BIAS__POR,
+	[TAIKO_A_SPKR_PROT_VSENSE_BIAS] = TAIKO_A_SPKR_PROT_VSENSE_BIAS__POR,
+	[TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL] =
+	    TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL__POR,
+	[TAIKO_A_SPKR_PROT_ADC_TEST_CTL] = TAIKO_A_SPKR_PROT_ADC_TEST_CTL__POR,
+	[TAIKO_A_SPKR_PROT_TEST_BLOCK_EN] =
+	    TAIKO_A_SPKR_PROT_TEST_BLOCK_EN__POR,
+	[TAIKO_A_SPKR_PROT_ATEST] = TAIKO_A_SPKR_PROT_ATEST__POR,
+	[TAIKO_A_SPKR_PROT_V_SAR_ERR] = TAIKO_A_SPKR_PROT_V_SAR_ERR__POR,
+	[TAIKO_A_SPKR_PROT_I_SAR_ERR] = TAIKO_A_SPKR_PROT_I_SAR_ERR__POR,
+	[TAIKO_A_SPKR_PROT_LDO_CTRL] = TAIKO_A_SPKR_PROT_LDO_CTRL__POR,
+	[TAIKO_A_SPKR_PROT_ISENSE_CTRL] = TAIKO_A_SPKR_PROT_ISENSE_CTRL__POR,
+	[TAIKO_A_SPKR_PROT_VSENSE_CTRL] = TAIKO_A_SPKR_PROT_VSENSE_CTRL__POR,
+	[TAIKO_A_RC_OSC_FREQ] = TAIKO_A_RC_OSC_FREQ__POR,
+	[TAIKO_A_RC_OSC_TEST] = TAIKO_A_RC_OSC_TEST__POR,
+	[TAIKO_A_RC_OSC_STATUS] = TAIKO_A_RC_OSC_STATUS__POR,
+	[TAIKO_A_RC_OSC_TUNER] = TAIKO_A_RC_OSC_TUNER__POR,
+	[TAIKO_A_MBHC_HPH] = TAIKO_A_MBHC_HPH__POR,
+	[TAIKO_A_CDC_ANC1_B1_CTL] = TAIKO_A_CDC_ANC1_B1_CTL__POR,
+	[TAIKO_A_CDC_ANC2_B1_CTL] = TAIKO_A_CDC_ANC2_B1_CTL__POR,
+	[TAIKO_A_CDC_ANC1_SHIFT] = TAIKO_A_CDC_ANC1_SHIFT__POR,
+	[TAIKO_A_CDC_ANC2_SHIFT] = TAIKO_A_CDC_ANC2_SHIFT__POR,
+	[TAIKO_A_CDC_ANC1_IIR_B1_CTL] = TAIKO_A_CDC_ANC1_IIR_B1_CTL__POR,
+	[TAIKO_A_CDC_ANC2_IIR_B1_CTL] = TAIKO_A_CDC_ANC2_IIR_B1_CTL__POR,
+	[TAIKO_A_CDC_ANC1_IIR_B2_CTL] = TAIKO_A_CDC_ANC1_IIR_B2_CTL__POR,
+	[TAIKO_A_CDC_ANC2_IIR_B2_CTL] = TAIKO_A_CDC_ANC2_IIR_B2_CTL__POR,
+	[TAIKO_A_CDC_ANC1_IIR_B3_CTL] = TAIKO_A_CDC_ANC1_IIR_B3_CTL__POR,
+	[TAIKO_A_CDC_ANC2_IIR_B3_CTL] = TAIKO_A_CDC_ANC2_IIR_B3_CTL__POR,
+	[TAIKO_A_CDC_ANC1_LPF_B1_CTL] = TAIKO_A_CDC_ANC1_LPF_B1_CTL__POR,
+	[TAIKO_A_CDC_ANC2_LPF_B1_CTL] = TAIKO_A_CDC_ANC2_LPF_B1_CTL__POR,
+	[TAIKO_A_CDC_ANC1_LPF_B2_CTL] = TAIKO_A_CDC_ANC1_LPF_B2_CTL__POR,
+	[TAIKO_A_CDC_ANC2_LPF_B2_CTL] = TAIKO_A_CDC_ANC2_LPF_B2_CTL__POR,
+	[TAIKO_A_CDC_ANC1_SPARE] = TAIKO_A_CDC_ANC1_SPARE__POR,
+	[TAIKO_A_CDC_ANC2_SPARE] = TAIKO_A_CDC_ANC2_SPARE__POR,
+	[TAIKO_A_CDC_ANC1_SMLPF_CTL] = TAIKO_A_CDC_ANC1_SMLPF_CTL__POR,
+	[TAIKO_A_CDC_ANC2_SMLPF_CTL] = TAIKO_A_CDC_ANC2_SMLPF_CTL__POR,
+	[TAIKO_A_CDC_ANC1_DCFLT_CTL] = TAIKO_A_CDC_ANC1_DCFLT_CTL__POR,
+	[TAIKO_A_CDC_ANC2_DCFLT_CTL] = TAIKO_A_CDC_ANC2_DCFLT_CTL__POR,
+	[TAIKO_A_CDC_ANC1_GAIN_CTL] = TAIKO_A_CDC_ANC1_GAIN_CTL__POR,
+	[TAIKO_A_CDC_ANC2_GAIN_CTL] = TAIKO_A_CDC_ANC2_GAIN_CTL__POR,
+	[TAIKO_A_CDC_ANC1_B2_CTL] = TAIKO_A_CDC_ANC1_B2_CTL__POR,
+	[TAIKO_A_CDC_ANC2_B2_CTL] = TAIKO_A_CDC_ANC2_B2_CTL__POR,
+	[TAIKO_A_CDC_TX1_VOL_CTL_TIMER] = TAIKO_A_CDC_TX1_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX2_VOL_CTL_TIMER] = TAIKO_A_CDC_TX2_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX3_VOL_CTL_TIMER] = TAIKO_A_CDC_TX3_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX4_VOL_CTL_TIMER] = TAIKO_A_CDC_TX4_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX5_VOL_CTL_TIMER] = TAIKO_A_CDC_TX5_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX6_VOL_CTL_TIMER] = TAIKO_A_CDC_TX6_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX7_VOL_CTL_TIMER] = TAIKO_A_CDC_TX7_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX8_VOL_CTL_TIMER] = TAIKO_A_CDC_TX8_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX9_VOL_CTL_TIMER] = TAIKO_A_CDC_TX9_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX10_VOL_CTL_TIMER] = TAIKO_A_CDC_TX10_VOL_CTL_TIMER__POR,
+	[TAIKO_A_CDC_TX1_VOL_CTL_GAIN] = TAIKO_A_CDC_TX1_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX2_VOL_CTL_GAIN] = TAIKO_A_CDC_TX2_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX3_VOL_CTL_GAIN] = TAIKO_A_CDC_TX3_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX4_VOL_CTL_GAIN] = TAIKO_A_CDC_TX4_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX5_VOL_CTL_GAIN] = TAIKO_A_CDC_TX5_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX6_VOL_CTL_GAIN] = TAIKO_A_CDC_TX6_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX7_VOL_CTL_GAIN] = TAIKO_A_CDC_TX7_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX8_VOL_CTL_GAIN] = TAIKO_A_CDC_TX8_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX9_VOL_CTL_GAIN] = TAIKO_A_CDC_TX9_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX10_VOL_CTL_GAIN] = TAIKO_A_CDC_TX10_VOL_CTL_GAIN__POR,
+	[TAIKO_A_CDC_TX1_VOL_CTL_CFG] = TAIKO_A_CDC_TX1_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX2_VOL_CTL_CFG] = TAIKO_A_CDC_TX2_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX3_VOL_CTL_CFG] = TAIKO_A_CDC_TX3_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX4_VOL_CTL_CFG] = TAIKO_A_CDC_TX4_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX5_VOL_CTL_CFG] = TAIKO_A_CDC_TX5_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX6_VOL_CTL_CFG] = TAIKO_A_CDC_TX6_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX7_VOL_CTL_CFG] = TAIKO_A_CDC_TX7_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX8_VOL_CTL_CFG] = TAIKO_A_CDC_TX8_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX9_VOL_CTL_CFG] = TAIKO_A_CDC_TX9_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX10_VOL_CTL_CFG] = TAIKO_A_CDC_TX10_VOL_CTL_CFG__POR,
+	[TAIKO_A_CDC_TX1_MUX_CTL] = TAIKO_A_CDC_TX1_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX2_MUX_CTL] = TAIKO_A_CDC_TX2_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX3_MUX_CTL] = TAIKO_A_CDC_TX3_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX4_MUX_CTL] = TAIKO_A_CDC_TX4_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX5_MUX_CTL] = TAIKO_A_CDC_TX5_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX6_MUX_CTL] = TAIKO_A_CDC_TX6_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX7_MUX_CTL] = TAIKO_A_CDC_TX7_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX8_MUX_CTL] = TAIKO_A_CDC_TX8_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX9_MUX_CTL] = TAIKO_A_CDC_TX9_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX10_MUX_CTL] = TAIKO_A_CDC_TX10_MUX_CTL__POR,
+	[TAIKO_A_CDC_TX1_CLK_FS_CTL] = TAIKO_A_CDC_TX1_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX2_CLK_FS_CTL] = TAIKO_A_CDC_TX2_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX3_CLK_FS_CTL] = TAIKO_A_CDC_TX3_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX4_CLK_FS_CTL] = TAIKO_A_CDC_TX4_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX5_CLK_FS_CTL] = TAIKO_A_CDC_TX5_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX6_CLK_FS_CTL] = TAIKO_A_CDC_TX6_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX7_CLK_FS_CTL] = TAIKO_A_CDC_TX7_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX8_CLK_FS_CTL] = TAIKO_A_CDC_TX8_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX9_CLK_FS_CTL] = TAIKO_A_CDC_TX9_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX10_CLK_FS_CTL] = TAIKO_A_CDC_TX10_CLK_FS_CTL__POR,
+	[TAIKO_A_CDC_TX1_DMIC_CTL] = TAIKO_A_CDC_TX1_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX2_DMIC_CTL] = TAIKO_A_CDC_TX2_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX3_DMIC_CTL] = TAIKO_A_CDC_TX3_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX4_DMIC_CTL] = TAIKO_A_CDC_TX4_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX5_DMIC_CTL] = TAIKO_A_CDC_TX5_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX6_DMIC_CTL] = TAIKO_A_CDC_TX6_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX7_DMIC_CTL] = TAIKO_A_CDC_TX7_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX8_DMIC_CTL] = TAIKO_A_CDC_TX8_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX9_DMIC_CTL] = TAIKO_A_CDC_TX9_DMIC_CTL__POR,
+	[TAIKO_A_CDC_TX10_DMIC_CTL] = TAIKO_A_CDC_TX10_DMIC_CTL__POR,
+	[TAIKO_A_CDC_DEBUG_B1_CTL] = TAIKO_A_CDC_DEBUG_B1_CTL__POR,
+	[TAIKO_A_CDC_DEBUG_B2_CTL] = TAIKO_A_CDC_DEBUG_B2_CTL__POR,
+	[TAIKO_A_CDC_DEBUG_B3_CTL] = TAIKO_A_CDC_DEBUG_B3_CTL__POR,
+	[TAIKO_A_CDC_DEBUG_B4_CTL] = TAIKO_A_CDC_DEBUG_B4_CTL__POR,
+	[TAIKO_A_CDC_DEBUG_B5_CTL] = TAIKO_A_CDC_DEBUG_B5_CTL__POR,
+	[TAIKO_A_CDC_DEBUG_B6_CTL] = TAIKO_A_CDC_DEBUG_B6_CTL__POR,
+	[TAIKO_A_CDC_DEBUG_B7_CTL] = TAIKO_A_CDC_DEBUG_B7_CTL__POR,
+	[TAIKO_A_CDC_SRC1_PDA_CFG] = TAIKO_A_CDC_SRC1_PDA_CFG__POR,
+	[TAIKO_A_CDC_SRC2_PDA_CFG] = TAIKO_A_CDC_SRC2_PDA_CFG__POR,
+	[TAIKO_A_CDC_SRC1_FS_CTL] = TAIKO_A_CDC_SRC1_FS_CTL__POR,
+	[TAIKO_A_CDC_SRC2_FS_CTL] = TAIKO_A_CDC_SRC2_FS_CTL__POR,
+	[TAIKO_A_CDC_RX1_B1_CTL] = TAIKO_A_CDC_RX1_B1_CTL__POR,
+	[TAIKO_A_CDC_RX2_B1_CTL] = TAIKO_A_CDC_RX2_B1_CTL__POR,
+	[TAIKO_A_CDC_RX3_B1_CTL] = TAIKO_A_CDC_RX3_B1_CTL__POR,
+	[TAIKO_A_CDC_RX4_B1_CTL] = TAIKO_A_CDC_RX4_B1_CTL__POR,
+	[TAIKO_A_CDC_RX5_B1_CTL] = TAIKO_A_CDC_RX5_B1_CTL__POR,
+	[TAIKO_A_CDC_RX6_B1_CTL] = TAIKO_A_CDC_RX6_B1_CTL__POR,
+	[TAIKO_A_CDC_RX7_B1_CTL] = TAIKO_A_CDC_RX7_B1_CTL__POR,
+	[TAIKO_A_CDC_RX1_B2_CTL] = TAIKO_A_CDC_RX1_B2_CTL__POR,
+	[TAIKO_A_CDC_RX2_B2_CTL] = TAIKO_A_CDC_RX2_B2_CTL__POR,
+	[TAIKO_A_CDC_RX3_B2_CTL] = TAIKO_A_CDC_RX3_B2_CTL__POR,
+	[TAIKO_A_CDC_RX4_B2_CTL] = TAIKO_A_CDC_RX4_B2_CTL__POR,
+	[TAIKO_A_CDC_RX5_B2_CTL] = TAIKO_A_CDC_RX5_B2_CTL__POR,
+	[TAIKO_A_CDC_RX6_B2_CTL] = TAIKO_A_CDC_RX6_B2_CTL__POR,
+	[TAIKO_A_CDC_RX7_B2_CTL] = TAIKO_A_CDC_RX7_B2_CTL__POR,
+	[TAIKO_A_CDC_RX1_B3_CTL] = TAIKO_A_CDC_RX1_B3_CTL__POR,
+	[TAIKO_A_CDC_RX2_B3_CTL] = TAIKO_A_CDC_RX2_B3_CTL__POR,
+	[TAIKO_A_CDC_RX3_B3_CTL] = TAIKO_A_CDC_RX3_B3_CTL__POR,
+	[TAIKO_A_CDC_RX4_B3_CTL] = TAIKO_A_CDC_RX4_B3_CTL__POR,
+	[TAIKO_A_CDC_RX5_B3_CTL] = TAIKO_A_CDC_RX5_B3_CTL__POR,
+	[TAIKO_A_CDC_RX6_B3_CTL] = TAIKO_A_CDC_RX6_B3_CTL__POR,
+	[TAIKO_A_CDC_RX7_B3_CTL] = TAIKO_A_CDC_RX7_B3_CTL__POR,
+	[TAIKO_A_CDC_RX1_B4_CTL] = TAIKO_A_CDC_RX1_B4_CTL__POR,
+	[TAIKO_A_CDC_RX2_B4_CTL] = TAIKO_A_CDC_RX2_B4_CTL__POR,
+	[TAIKO_A_CDC_RX3_B4_CTL] = TAIKO_A_CDC_RX3_B4_CTL__POR,
+	[TAIKO_A_CDC_RX4_B4_CTL] = TAIKO_A_CDC_RX4_B4_CTL__POR,
+	[TAIKO_A_CDC_RX5_B4_CTL] = TAIKO_A_CDC_RX5_B4_CTL__POR,
+	[TAIKO_A_CDC_RX6_B4_CTL] = TAIKO_A_CDC_RX6_B4_CTL__POR,
+	[TAIKO_A_CDC_RX7_B4_CTL] = TAIKO_A_CDC_RX7_B4_CTL__POR,
+	[TAIKO_A_CDC_RX1_B5_CTL] = TAIKO_A_CDC_RX1_B5_CTL__POR,
+	[TAIKO_A_CDC_RX2_B5_CTL] = TAIKO_A_CDC_RX2_B5_CTL__POR,
+	[TAIKO_A_CDC_RX3_B5_CTL] = TAIKO_A_CDC_RX3_B5_CTL__POR,
+	[TAIKO_A_CDC_RX4_B5_CTL] = TAIKO_A_CDC_RX4_B5_CTL__POR,
+	[TAIKO_A_CDC_RX5_B5_CTL] = TAIKO_A_CDC_RX5_B5_CTL__POR,
+	[TAIKO_A_CDC_RX6_B5_CTL] = TAIKO_A_CDC_RX6_B5_CTL__POR,
+	[TAIKO_A_CDC_RX7_B5_CTL] = TAIKO_A_CDC_RX7_B5_CTL__POR,
+	[TAIKO_A_CDC_RX1_B6_CTL] = TAIKO_A_CDC_RX1_B6_CTL__POR,
+	[TAIKO_A_CDC_RX2_B6_CTL] = TAIKO_A_CDC_RX2_B6_CTL__POR,
+	[TAIKO_A_CDC_RX3_B6_CTL] = TAIKO_A_CDC_RX3_B6_CTL__POR,
+	[TAIKO_A_CDC_RX4_B6_CTL] = TAIKO_A_CDC_RX4_B6_CTL__POR,
+	[TAIKO_A_CDC_RX5_B6_CTL] = TAIKO_A_CDC_RX5_B6_CTL__POR,
+	[TAIKO_A_CDC_RX6_B6_CTL] = TAIKO_A_CDC_RX6_B6_CTL__POR,
+	[TAIKO_A_CDC_RX7_B6_CTL] = TAIKO_A_CDC_RX7_B6_CTL__POR,
+	[TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL__POR,
+	[TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL__POR,
+	[TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL__POR,
+	[TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL__POR,
+	[TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL__POR,
+	[TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL__POR,
+	[TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL__POR,
+	[TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL__POR,
+	[TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL__POR,
+	[TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL__POR,
+	[TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL__POR,
+	[TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL__POR,
+	[TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL__POR,
+	[TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL__POR,
+	[TAIKO_A_CDC_VBAT_CFG] = TAIKO_A_CDC_VBAT_CFG__POR,
+	[TAIKO_A_CDC_VBAT_ADC_CAL1] = TAIKO_A_CDC_VBAT_ADC_CAL1__POR,
+	[TAIKO_A_CDC_VBAT_ADC_CAL2] = TAIKO_A_CDC_VBAT_ADC_CAL2__POR,
+	[TAIKO_A_CDC_VBAT_ADC_CAL3] = TAIKO_A_CDC_VBAT_ADC_CAL3__POR,
+	[TAIKO_A_CDC_VBAT_PK_EST1] = TAIKO_A_CDC_VBAT_PK_EST1__POR,
+	[TAIKO_A_CDC_VBAT_PK_EST2] = TAIKO_A_CDC_VBAT_PK_EST2__POR,
+	[TAIKO_A_CDC_VBAT_PK_EST3] = TAIKO_A_CDC_VBAT_PK_EST3__POR,
+	[TAIKO_A_CDC_VBAT_RF_PROC1] = TAIKO_A_CDC_VBAT_RF_PROC1__POR,
+	[TAIKO_A_CDC_VBAT_RF_PROC2] = TAIKO_A_CDC_VBAT_RF_PROC2__POR,
+	[TAIKO_A_CDC_VBAT_TAC1] = TAIKO_A_CDC_VBAT_TAC1__POR,
+	[TAIKO_A_CDC_VBAT_TAC2] = TAIKO_A_CDC_VBAT_TAC2__POR,
+	[TAIKO_A_CDC_VBAT_TAC3] = TAIKO_A_CDC_VBAT_TAC3__POR,
+	[TAIKO_A_CDC_VBAT_TAC4] = TAIKO_A_CDC_VBAT_TAC4__POR,
+	[TAIKO_A_CDC_VBAT_GAIN_UPD1] = TAIKO_A_CDC_VBAT_GAIN_UPD1__POR,
+	[TAIKO_A_CDC_VBAT_GAIN_UPD2] = TAIKO_A_CDC_VBAT_GAIN_UPD2__POR,
+	[TAIKO_A_CDC_VBAT_GAIN_UPD3] = TAIKO_A_CDC_VBAT_GAIN_UPD3__POR,
+	[TAIKO_A_CDC_VBAT_GAIN_UPD4] = TAIKO_A_CDC_VBAT_GAIN_UPD4__POR,
+	[TAIKO_A_CDC_VBAT_DEBUG1] = TAIKO_A_CDC_VBAT_DEBUG1__POR,
+	[TAIKO_A_CDC_CLK_ANC_RESET_CTL] = TAIKO_A_CDC_CLK_ANC_RESET_CTL__POR,
+	[TAIKO_A_CDC_CLK_RX_RESET_CTL] = TAIKO_A_CDC_CLK_RX_RESET_CTL__POR,
+	[TAIKO_A_CDC_CLK_TX_RESET_B1_CTL] =
+	    TAIKO_A_CDC_CLK_TX_RESET_B1_CTL__POR,
+	[TAIKO_A_CDC_CLK_TX_RESET_B2_CTL] =
+	    TAIKO_A_CDC_CLK_TX_RESET_B2_CTL__POR,
+	[TAIKO_A_CDC_CLK_DMIC_B1_CTL] = TAIKO_A_CDC_CLK_DMIC_B1_CTL__POR,
+	[TAIKO_A_CDC_CLK_DMIC_B2_CTL] = TAIKO_A_CDC_CLK_DMIC_B2_CTL__POR,
+	[TAIKO_A_CDC_CLK_RX_I2S_CTL] = TAIKO_A_CDC_CLK_RX_I2S_CTL__POR,
+	[TAIKO_A_CDC_CLK_TX_I2S_CTL] = TAIKO_A_CDC_CLK_TX_I2S_CTL__POR,
+	[TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL] =
+	    TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL__POR,
+	[TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL] =
+	    TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL__POR,
+	[TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL] =
+	    TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR,
+	[TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL] =
+	    TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL__POR,
+	[TAIKO_A_CDC_CLK_OTHR_CTL] = TAIKO_A_CDC_CLK_OTHR_CTL__POR,
+	[TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL] =
+	    TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL__POR,
+	[TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL] = TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL__POR,
+	[TAIKO_A_CDC_CLK_RX_B1_CTL] = TAIKO_A_CDC_CLK_RX_B1_CTL__POR,
+	[TAIKO_A_CDC_CLK_RX_B2_CTL] = TAIKO_A_CDC_CLK_RX_B2_CTL__POR,
+	[TAIKO_A_CDC_CLK_MCLK_CTL] = TAIKO_A_CDC_CLK_MCLK_CTL__POR,
+	[TAIKO_A_CDC_CLK_PDM_CTL] = TAIKO_A_CDC_CLK_PDM_CTL__POR,
+	[TAIKO_A_CDC_CLK_SD_CTL] = TAIKO_A_CDC_CLK_SD_CTL__POR,
+	[TAIKO_A_CDC_CLK_POWER_CTL] = TAIKO_A_CDC_CLK_POWER_CTL__POR,
+	[TAIKO_A_CDC_CLSH_B1_CTL] = TAIKO_A_CDC_CLSH_B1_CTL__POR,
+	[TAIKO_A_CDC_CLSH_B2_CTL] = TAIKO_A_CDC_CLSH_B2_CTL__POR,
+	[TAIKO_A_CDC_CLSH_B3_CTL] = TAIKO_A_CDC_CLSH_B3_CTL__POR,
+	[TAIKO_A_CDC_CLSH_BUCK_NCP_VARS] = TAIKO_A_CDC_CLSH_BUCK_NCP_VARS__POR,
+	[TAIKO_A_CDC_CLSH_IDLE_HPH_THSD] = TAIKO_A_CDC_CLSH_IDLE_HPH_THSD__POR,
+	[TAIKO_A_CDC_CLSH_IDLE_EAR_THSD] = TAIKO_A_CDC_CLSH_IDLE_EAR_THSD__POR,
+	[TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD] =
+	    TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD__POR,
+	[TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD] =
+	    TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD__POR,
+	[TAIKO_A_CDC_CLSH_K_ADDR] = TAIKO_A_CDC_CLSH_K_ADDR__POR,
+	[TAIKO_A_CDC_CLSH_K_DATA] = TAIKO_A_CDC_CLSH_K_DATA__POR,
+	[TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L] =
+	    TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L__POR,
+	[TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U] =
+	    TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U__POR,
+	[TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L] =
+	    TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L__POR,
+	[TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U] =
+	    TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U__POR,
+	[TAIKO_A_CDC_CLSH_V_PA_HD_EAR] = TAIKO_A_CDC_CLSH_V_PA_HD_EAR__POR,
+	[TAIKO_A_CDC_CLSH_V_PA_HD_HPH] = TAIKO_A_CDC_CLSH_V_PA_HD_HPH__POR,
+	[TAIKO_A_CDC_CLSH_V_PA_MIN_EAR] = TAIKO_A_CDC_CLSH_V_PA_MIN_EAR__POR,
+	[TAIKO_A_CDC_CLSH_V_PA_MIN_HPH] = TAIKO_A_CDC_CLSH_V_PA_MIN_HPH__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_B1_CTL] = TAIKO_A_CDC_IIR1_GAIN_B1_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_B1_CTL] = TAIKO_A_CDC_IIR2_GAIN_B1_CTL__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_B2_CTL] = TAIKO_A_CDC_IIR1_GAIN_B2_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_B2_CTL] = TAIKO_A_CDC_IIR2_GAIN_B2_CTL__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_B3_CTL] = TAIKO_A_CDC_IIR1_GAIN_B3_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_B3_CTL] = TAIKO_A_CDC_IIR2_GAIN_B3_CTL__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_B4_CTL] = TAIKO_A_CDC_IIR1_GAIN_B4_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_B4_CTL] = TAIKO_A_CDC_IIR2_GAIN_B4_CTL__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_B5_CTL] = TAIKO_A_CDC_IIR1_GAIN_B5_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_B5_CTL] = TAIKO_A_CDC_IIR2_GAIN_B5_CTL__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_B6_CTL] = TAIKO_A_CDC_IIR1_GAIN_B6_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_B6_CTL] = TAIKO_A_CDC_IIR2_GAIN_B6_CTL__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_B7_CTL] = TAIKO_A_CDC_IIR1_GAIN_B7_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_B7_CTL] = TAIKO_A_CDC_IIR2_GAIN_B7_CTL__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_B8_CTL] = TAIKO_A_CDC_IIR1_GAIN_B8_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_B8_CTL] = TAIKO_A_CDC_IIR2_GAIN_B8_CTL__POR,
+	[TAIKO_A_CDC_IIR1_CTL] = TAIKO_A_CDC_IIR1_CTL__POR,
+	[TAIKO_A_CDC_IIR2_CTL] = TAIKO_A_CDC_IIR2_CTL__POR,
+	[TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL] =
+	    TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL__POR,
+	[TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL] =
+	    TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL__POR,
+	[TAIKO_A_CDC_IIR1_COEF_B1_CTL] = TAIKO_A_CDC_IIR1_COEF_B1_CTL__POR,
+	[TAIKO_A_CDC_IIR2_COEF_B1_CTL] = TAIKO_A_CDC_IIR2_COEF_B1_CTL__POR,
+	[TAIKO_A_CDC_IIR1_COEF_B2_CTL] = TAIKO_A_CDC_IIR1_COEF_B2_CTL__POR,
+	[TAIKO_A_CDC_IIR2_COEF_B2_CTL] = TAIKO_A_CDC_IIR2_COEF_B2_CTL__POR,
+	[TAIKO_A_CDC_TOP_GAIN_UPDATE] = TAIKO_A_CDC_TOP_GAIN_UPDATE__POR,
+	[TAIKO_A_CDC_COMP0_B1_CTL] = TAIKO_A_CDC_COMP0_B1_CTL__POR,
+	[TAIKO_A_CDC_COMP1_B1_CTL] = TAIKO_A_CDC_COMP1_B1_CTL__POR,
+	[TAIKO_A_CDC_COMP2_B1_CTL] = TAIKO_A_CDC_COMP2_B1_CTL__POR,
+	[TAIKO_A_CDC_COMP0_B2_CTL] = TAIKO_A_CDC_COMP0_B2_CTL__POR,
+	[TAIKO_A_CDC_COMP1_B2_CTL] = TAIKO_A_CDC_COMP1_B2_CTL__POR,
+	[TAIKO_A_CDC_COMP2_B2_CTL] = TAIKO_A_CDC_COMP2_B2_CTL__POR,
+	[TAIKO_A_CDC_COMP0_B3_CTL] = TAIKO_A_CDC_COMP0_B3_CTL__POR,
+	[TAIKO_A_CDC_COMP1_B3_CTL] = TAIKO_A_CDC_COMP1_B3_CTL__POR,
+	[TAIKO_A_CDC_COMP2_B3_CTL] = TAIKO_A_CDC_COMP2_B3_CTL__POR,
+	[TAIKO_A_CDC_COMP0_B4_CTL] = TAIKO_A_CDC_COMP0_B4_CTL__POR,
+	[TAIKO_A_CDC_COMP1_B4_CTL] = TAIKO_A_CDC_COMP1_B4_CTL__POR,
+	[TAIKO_A_CDC_COMP2_B4_CTL] = TAIKO_A_CDC_COMP2_B4_CTL__POR,
+	[TAIKO_A_CDC_COMP0_B5_CTL] = TAIKO_A_CDC_COMP0_B5_CTL__POR,
+	[TAIKO_A_CDC_COMP1_B5_CTL] = TAIKO_A_CDC_COMP1_B5_CTL__POR,
+	[TAIKO_A_CDC_COMP2_B5_CTL] = TAIKO_A_CDC_COMP2_B5_CTL__POR,
+	[TAIKO_A_CDC_COMP0_B6_CTL] = TAIKO_A_CDC_COMP0_B6_CTL__POR,
+	[TAIKO_A_CDC_COMP1_B6_CTL] = TAIKO_A_CDC_COMP1_B6_CTL__POR,
+	[TAIKO_A_CDC_COMP2_B6_CTL] = TAIKO_A_CDC_COMP2_B6_CTL__POR,
+	[TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS] =
+	    TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS__POR,
+	[TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS] =
+	    TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS__POR,
+	[TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS] =
+	    TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS__POR,
+	[TAIKO_A_CDC_COMP0_FS_CFG] = TAIKO_A_CDC_COMP0_FS_CFG__POR,
+	[TAIKO_A_CDC_COMP1_FS_CFG] = TAIKO_A_CDC_COMP1_FS_CFG__POR,
+	[TAIKO_A_CDC_COMP2_FS_CFG] = TAIKO_A_CDC_COMP2_FS_CFG__POR,
+	[TAIKO_A_CDC_CONN_RX1_B1_CTL] = TAIKO_A_CDC_CONN_RX1_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX1_B2_CTL] = TAIKO_A_CDC_CONN_RX1_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX1_B3_CTL] = TAIKO_A_CDC_CONN_RX1_B3_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX2_B1_CTL] = TAIKO_A_CDC_CONN_RX2_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX2_B2_CTL] = TAIKO_A_CDC_CONN_RX2_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX2_B3_CTL] = TAIKO_A_CDC_CONN_RX2_B3_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX3_B1_CTL] = TAIKO_A_CDC_CONN_RX3_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX3_B2_CTL] = TAIKO_A_CDC_CONN_RX3_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX4_B1_CTL] = TAIKO_A_CDC_CONN_RX4_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX4_B2_CTL] = TAIKO_A_CDC_CONN_RX4_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX5_B1_CTL] = TAIKO_A_CDC_CONN_RX5_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX5_B2_CTL] = TAIKO_A_CDC_CONN_RX5_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX6_B1_CTL] = TAIKO_A_CDC_CONN_RX6_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX6_B2_CTL] = TAIKO_A_CDC_CONN_RX6_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX7_B1_CTL] = TAIKO_A_CDC_CONN_RX7_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX7_B2_CTL] = TAIKO_A_CDC_CONN_RX7_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX7_B3_CTL] = TAIKO_A_CDC_CONN_RX7_B3_CTL__POR,
+	[TAIKO_A_CDC_CONN_ANC_B1_CTL] = TAIKO_A_CDC_CONN_ANC_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_ANC_B2_CTL] = TAIKO_A_CDC_CONN_ANC_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_B1_CTL] = TAIKO_A_CDC_CONN_TX_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_B2_CTL] = TAIKO_A_CDC_CONN_TX_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_B3_CTL] = TAIKO_A_CDC_CONN_TX_B3_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_B4_CTL] = TAIKO_A_CDC_CONN_TX_B4_CTL__POR,
+	[TAIKO_A_CDC_CONN_EQ1_B1_CTL] = TAIKO_A_CDC_CONN_EQ1_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_EQ1_B2_CTL] = TAIKO_A_CDC_CONN_EQ1_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_EQ1_B3_CTL] = TAIKO_A_CDC_CONN_EQ1_B3_CTL__POR,
+	[TAIKO_A_CDC_CONN_EQ1_B4_CTL] = TAIKO_A_CDC_CONN_EQ1_B4_CTL__POR,
+	[TAIKO_A_CDC_CONN_EQ2_B1_CTL] = TAIKO_A_CDC_CONN_EQ2_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_EQ2_B2_CTL] = TAIKO_A_CDC_CONN_EQ2_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_EQ2_B3_CTL] = TAIKO_A_CDC_CONN_EQ2_B3_CTL__POR,
+	[TAIKO_A_CDC_CONN_EQ2_B4_CTL] = TAIKO_A_CDC_CONN_EQ2_B4_CTL__POR,
+	[TAIKO_A_CDC_CONN_SRC1_B1_CTL] = TAIKO_A_CDC_CONN_SRC1_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_SRC1_B2_CTL] = TAIKO_A_CDC_CONN_SRC1_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_SRC2_B1_CTL] = TAIKO_A_CDC_CONN_SRC2_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_SRC2_B2_CTL] = TAIKO_A_CDC_CONN_SRC2_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B1_CTL] = TAIKO_A_CDC_CONN_TX_SB_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B2_CTL] = TAIKO_A_CDC_CONN_TX_SB_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B3_CTL] = TAIKO_A_CDC_CONN_TX_SB_B3_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B4_CTL] = TAIKO_A_CDC_CONN_TX_SB_B4_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B5_CTL] = TAIKO_A_CDC_CONN_TX_SB_B5_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B6_CTL] = TAIKO_A_CDC_CONN_TX_SB_B6_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B7_CTL] = TAIKO_A_CDC_CONN_TX_SB_B7_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B8_CTL] = TAIKO_A_CDC_CONN_TX_SB_B8_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B9_CTL] = TAIKO_A_CDC_CONN_TX_SB_B9_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B10_CTL] = TAIKO_A_CDC_CONN_TX_SB_B10_CTL__POR,
+	[TAIKO_A_CDC_CONN_TX_SB_B11_CTL] = TAIKO_A_CDC_CONN_TX_SB_B11_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX_SB_B1_CTL] = TAIKO_A_CDC_CONN_RX_SB_B1_CTL__POR,
+	[TAIKO_A_CDC_CONN_RX_SB_B2_CTL] = TAIKO_A_CDC_CONN_RX_SB_B2_CTL__POR,
+	[TAIKO_A_CDC_CONN_CLSH_CTL] = TAIKO_A_CDC_CONN_CLSH_CTL__POR,
+	[TAIKO_A_CDC_CONN_MISC] = TAIKO_A_CDC_CONN_MISC__POR,
+	[TAIKO_A_CDC_CONN_MAD] = TAIKO_A_CDC_CONN_MAD__POR,
+	[TAIKO_A_CDC_MBHC_EN_CTL] = TAIKO_A_CDC_MBHC_EN_CTL__POR,
+	[TAIKO_A_CDC_MBHC_FIR_B1_CFG] = TAIKO_A_CDC_MBHC_FIR_B1_CFG__POR,
+	[TAIKO_A_CDC_MBHC_FIR_B2_CFG] = TAIKO_A_CDC_MBHC_FIR_B2_CFG__POR,
+	[TAIKO_A_CDC_MBHC_TIMER_B1_CTL] = TAIKO_A_CDC_MBHC_TIMER_B1_CTL__POR,
+	[TAIKO_A_CDC_MBHC_TIMER_B2_CTL] = TAIKO_A_CDC_MBHC_TIMER_B2_CTL__POR,
+	[TAIKO_A_CDC_MBHC_TIMER_B3_CTL] = TAIKO_A_CDC_MBHC_TIMER_B3_CTL__POR,
+	[TAIKO_A_CDC_MBHC_TIMER_B4_CTL] = TAIKO_A_CDC_MBHC_TIMER_B4_CTL__POR,
+	[TAIKO_A_CDC_MBHC_TIMER_B5_CTL] = TAIKO_A_CDC_MBHC_TIMER_B5_CTL__POR,
+	[TAIKO_A_CDC_MBHC_TIMER_B6_CTL] = TAIKO_A_CDC_MBHC_TIMER_B6_CTL__POR,
+	[TAIKO_A_CDC_MBHC_B1_STATUS] = TAIKO_A_CDC_MBHC_B1_STATUS__POR,
+	[TAIKO_A_CDC_MBHC_B2_STATUS] = TAIKO_A_CDC_MBHC_B2_STATUS__POR,
+	[TAIKO_A_CDC_MBHC_B3_STATUS] = TAIKO_A_CDC_MBHC_B3_STATUS__POR,
+	[TAIKO_A_CDC_MBHC_B4_STATUS] = TAIKO_A_CDC_MBHC_B4_STATUS__POR,
+	[TAIKO_A_CDC_MBHC_B5_STATUS] = TAIKO_A_CDC_MBHC_B5_STATUS__POR,
+	[TAIKO_A_CDC_MBHC_B1_CTL] = TAIKO_A_CDC_MBHC_B1_CTL__POR,
+	[TAIKO_A_CDC_MBHC_B2_CTL] = TAIKO_A_CDC_MBHC_B2_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B1_CTL] = TAIKO_A_CDC_MBHC_VOLT_B1_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B2_CTL] = TAIKO_A_CDC_MBHC_VOLT_B2_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B3_CTL] = TAIKO_A_CDC_MBHC_VOLT_B3_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B4_CTL] = TAIKO_A_CDC_MBHC_VOLT_B4_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B5_CTL] = TAIKO_A_CDC_MBHC_VOLT_B5_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B6_CTL] = TAIKO_A_CDC_MBHC_VOLT_B6_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B7_CTL] = TAIKO_A_CDC_MBHC_VOLT_B7_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B8_CTL] = TAIKO_A_CDC_MBHC_VOLT_B8_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B9_CTL] = TAIKO_A_CDC_MBHC_VOLT_B9_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B10_CTL] = TAIKO_A_CDC_MBHC_VOLT_B10_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B11_CTL] = TAIKO_A_CDC_MBHC_VOLT_B11_CTL__POR,
+	[TAIKO_A_CDC_MBHC_VOLT_B12_CTL] = TAIKO_A_CDC_MBHC_VOLT_B12_CTL__POR,
+	[TAIKO_A_CDC_MBHC_CLK_CTL] = TAIKO_A_CDC_MBHC_CLK_CTL__POR,
+	[TAIKO_A_CDC_MBHC_INT_CTL] = TAIKO_A_CDC_MBHC_INT_CTL__POR,
+	[TAIKO_A_CDC_MBHC_DEBUG_CTL] = TAIKO_A_CDC_MBHC_DEBUG_CTL__POR,
+	[TAIKO_A_CDC_MBHC_SPARE] = TAIKO_A_CDC_MBHC_SPARE__POR,
+	[TAIKO_A_CDC_MAD_MAIN_CTL_1] = TAIKO_A_CDC_MAD_MAIN_CTL_1__POR,
+	[TAIKO_A_CDC_MAD_MAIN_CTL_2] = TAIKO_A_CDC_MAD_MAIN_CTL_2__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_1] = TAIKO_A_CDC_MAD_AUDIO_CTL_1__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_2] = TAIKO_A_CDC_MAD_AUDIO_CTL_2__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_3] = TAIKO_A_CDC_MAD_AUDIO_CTL_3__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_4] = TAIKO_A_CDC_MAD_AUDIO_CTL_4__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_5] = TAIKO_A_CDC_MAD_AUDIO_CTL_5__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_6] = TAIKO_A_CDC_MAD_AUDIO_CTL_6__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_7] = TAIKO_A_CDC_MAD_AUDIO_CTL_7__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_CTL_8] = TAIKO_A_CDC_MAD_AUDIO_CTL_8__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR] =
+	    TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR__POR,
+	[TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL] =
+	    TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL__POR,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_1] = TAIKO_A_CDC_MAD_ULTR_CTL_1__POR,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_2] = TAIKO_A_CDC_MAD_ULTR_CTL_2__POR,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_3] = TAIKO_A_CDC_MAD_ULTR_CTL_3__POR,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_4] = TAIKO_A_CDC_MAD_ULTR_CTL_4__POR,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_5] = TAIKO_A_CDC_MAD_ULTR_CTL_5__POR,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_6] = TAIKO_A_CDC_MAD_ULTR_CTL_6__POR,
+	[TAIKO_A_CDC_MAD_ULTR_CTL_7] = TAIKO_A_CDC_MAD_ULTR_CTL_7__POR,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_1] = TAIKO_A_CDC_MAD_BEACON_CTL_1__POR,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_2] = TAIKO_A_CDC_MAD_BEACON_CTL_2__POR,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_3] = TAIKO_A_CDC_MAD_BEACON_CTL_3__POR,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_4] = TAIKO_A_CDC_MAD_BEACON_CTL_4__POR,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_5] = TAIKO_A_CDC_MAD_BEACON_CTL_5__POR,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_6] = TAIKO_A_CDC_MAD_BEACON_CTL_6__POR,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_7] = TAIKO_A_CDC_MAD_BEACON_CTL_7__POR,
+	[TAIKO_A_CDC_MAD_BEACON_CTL_8] = TAIKO_A_CDC_MAD_BEACON_CTL_8__POR,
+	[TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR] =
+	    TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR__POR,
+	[TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL] =
+	    TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL__POR,
+};
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
new file mode 100644
index 0000000..67a5d8a
--- /dev/null
+++ b/sound/soc/codecs/wcd9320.c
@@ -0,0 +1,7471 @@
+/* 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/init.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/debugfs.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9320_registers.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include "wcd9320.h"
+
+#define WCD9320_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+
+
+#define NUM_DECIMATORS 10
+#define NUM_INTERPOLATORS 7
+#define BITS_PER_REG 8
+#define TAIKO_CFILT_FAST_MODE 0x00
+#define TAIKO_CFILT_SLOW_MODE 0x40
+#define MBHC_FW_READ_ATTEMPTS 15
+#define MBHC_FW_READ_TIMEOUT 2000000
+
+enum {
+	MBHC_USE_HPHL_TRIGGER = 1,
+	MBHC_USE_MB_TRIGGER = 2
+};
+
+#define MBHC_NUM_DCE_PLUG_DETECT 3
+#define NUM_ATTEMPTS_INSERT_DETECT 25
+#define NUM_ATTEMPTS_TO_REPORT 5
+
+#define TAIKO_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | \
+			 SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED)
+
+#define TAIKO_I2S_MASTER_MODE_MASK 0x08
+
+#define TAIKO_OCP_ATTEMPT 1
+
+#define AIF1_PB 1
+#define AIF1_CAP 2
+#define AIF2_PB 3
+#define AIF2_CAP 4
+#define AIF3_CAP 5
+#define AIF3_PB  6
+
+#define NUM_CODEC_DAIS 6
+#define TAIKO_COMP_DIGITAL_GAIN_OFFSET 3
+
+struct taiko_codec_dai_data {
+	u32 rate;
+	u32 *ch_num;
+	u32 ch_act;
+	u32 ch_tot;
+};
+
+#define TAIKO_MCLK_RATE_12288KHZ 12288000
+#define TAIKO_MCLK_RATE_9600KHZ 9600000
+
+#define TAIKO_FAKE_INS_THRESHOLD_MS 2500
+#define TAIKO_FAKE_REMOVAL_MIN_PERIOD_MS 50
+
+#define TAIKO_MBHC_BUTTON_MIN 0x8000
+
+#define TAIKO_MBHC_FAKE_INSERT_LOW 10
+#define TAIKO_MBHC_FAKE_INSERT_HIGH 80
+#define TAIKO_MBHC_FAKE_INS_HIGH_NO_GPIO 150
+
+#define TAIKO_MBHC_STATUS_REL_DETECTION 0x0C
+
+#define TAIKO_MBHC_GPIO_REL_DEBOUNCE_TIME_MS 200
+
+#define TAIKO_MBHC_FAKE_INS_DELTA_MV 200
+#define TAIKO_MBHC_FAKE_INS_DELTA_SCALED_MV 300
+
+#define TAIKO_HS_DETECT_PLUG_TIME_MS (5 * 1000)
+#define TAIKO_HS_DETECT_PLUG_INERVAL_MS 100
+
+#define TAIKO_GPIO_IRQ_DEBOUNCE_TIME_US 5000
+
+#define TAIKO_MBHC_GND_MIC_SWAP_THRESHOLD 2
+
+#define TAIKO_ACQUIRE_LOCK(x) do { mutex_lock(&x); } while (0)
+#define TAIKO_RELEASE_LOCK(x) do { mutex_unlock(&x); } while (0)
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver taiko_dai[];
+static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
+
+enum taiko_bandgap_type {
+	TAIKO_BANDGAP_OFF = 0,
+	TAIKO_BANDGAP_AUDIO_MODE,
+	TAIKO_BANDGAP_MBHC_MODE,
+};
+
+struct mbhc_micbias_regs {
+	u16 cfilt_val;
+	u16 cfilt_ctl;
+	u16 mbhc_reg;
+	u16 int_rbias;
+	u16 ctl_reg;
+	u8 cfilt_sel;
+};
+
+/* Codec supports 2 IIR filters */
+enum {
+	IIR1 = 0,
+	IIR2,
+	IIR_MAX,
+};
+/* Codec supports 5 bands */
+enum {
+	BAND1 = 0,
+	BAND2,
+	BAND3,
+	BAND4,
+	BAND5,
+	BAND_MAX,
+};
+
+enum {
+	COMPANDER_1 = 0,
+	COMPANDER_2,
+	COMPANDER_MAX,
+};
+
+enum {
+	COMPANDER_FS_8KHZ = 0,
+	COMPANDER_FS_16KHZ,
+	COMPANDER_FS_32KHZ,
+	COMPANDER_FS_48KHZ,
+	COMPANDER_FS_96KHZ,
+	COMPANDER_FS_192KHZ,
+	COMPANDER_FS_MAX,
+};
+
+/* Flags to track of PA and DAC state.
+ * PA and DAC should be tracked separately as AUXPGA loopback requires
+ * only PA to be turned on without DAC being on. */
+enum taiko_priv_ack_flags {
+	TAIKO_HPHL_PA_OFF_ACK = 0,
+	TAIKO_HPHR_PA_OFF_ACK,
+	TAIKO_HPHL_DAC_OFF_ACK,
+	TAIKO_HPHR_DAC_OFF_ACK
+};
+
+
+struct comp_sample_dependent_params {
+	u32 peak_det_timeout;
+	u32 rms_meter_div_fact;
+	u32 rms_meter_resamp_fact;
+};
+
+/* Data used by MBHC */
+struct mbhc_internal_cal_data {
+	u16 dce_z;
+	u16 dce_mb;
+	u16 sta_z;
+	u16 sta_mb;
+	u32 t_sta_dce;
+	u32 t_dce;
+	u32 t_sta;
+	u32 micb_mv;
+	u16 v_ins_hu;
+	u16 v_ins_h;
+	u16 v_b1_hu;
+	u16 v_b1_h;
+	u16 v_b1_huc;
+	u16 v_brh;
+	u16 v_brl;
+	u16 v_no_mic;
+	u8 npoll;
+	u8 nbounce_wait;
+	s16 adj_v_hs_max;
+	u16 adj_v_ins_hu;
+	u16 adj_v_ins_h;
+	s16 v_inval_ins_low;
+	s16 v_inval_ins_high;
+};
+
+struct taiko_reg_address {
+	u16 micb_4_ctl;
+	u16 micb_4_int_rbias;
+	u16 micb_4_mbhc;
+};
+
+enum taiko_mbhc_plug_type {
+	PLUG_TYPE_INVALID = -1,
+	PLUG_TYPE_NONE,
+	PLUG_TYPE_HEADSET,
+	PLUG_TYPE_HEADPHONE,
+	PLUG_TYPE_HIGH_HPH,
+	PLUG_TYPE_GND_MIC_SWAP,
+};
+
+enum taiko_mbhc_state {
+	MBHC_STATE_NONE = -1,
+	MBHC_STATE_POTENTIAL,
+	MBHC_STATE_POTENTIAL_RECOVERY,
+	MBHC_STATE_RELEASE,
+};
+
+struct hpf_work {
+	struct taiko_priv *taiko;
+	u32 decimator;
+	u8 tx_hpf_cut_of_freq;
+	struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
+struct taiko_priv {
+	struct snd_soc_codec *codec;
+	struct taiko_reg_address reg_addr;
+	u32 adc_count;
+	u32 cfilt1_cnt;
+	u32 cfilt2_cnt;
+	u32 cfilt3_cnt;
+	u32 rx_bias_count;
+	s32 dmic_1_2_clk_cnt;
+	s32 dmic_3_4_clk_cnt;
+	s32 dmic_5_6_clk_cnt;
+
+	enum taiko_bandgap_type bandgap_type;
+	bool mclk_enabled;
+	bool clock_active;
+	bool config_mode_active;
+	bool mbhc_polling_active;
+	unsigned long mbhc_fake_ins_start;
+	int buttons_pressed;
+	enum taiko_mbhc_state mbhc_state;
+	struct taiko_mbhc_config mbhc_cfg;
+	struct mbhc_internal_cal_data mbhc_data;
+
+	struct wcd9xxx_pdata *pdata;
+	u32 anc_slot;
+
+	bool no_mic_headset_override;
+	/* Delayed work to report long button press */
+	struct delayed_work mbhc_btn_dwork;
+
+	struct mbhc_micbias_regs mbhc_bias_regs;
+	bool mbhc_micbias_switched;
+
+	/* track PA/DAC state */
+	unsigned long hph_pa_dac_state;
+
+	/*track taiko interface type*/
+	u8 intf_type;
+
+	u32 hph_status; /* track headhpone status */
+	/* define separate work for left and right headphone OCP to avoid
+	 * additional checking on which OCP event to report so no locking
+	 * to ensure synchronization is required
+	 */
+	struct work_struct hphlocp_work; /* reporting left hph ocp off */
+	struct work_struct hphrocp_work; /* reporting right hph ocp off */
+
+	u8 hphlocp_cnt; /* headphone left ocp retry */
+	u8 hphrocp_cnt; /* headphone right ocp retry */
+
+	/* Work to perform MBHC Firmware Read */
+	struct delayed_work mbhc_firmware_dwork;
+	const struct firmware *mbhc_fw;
+
+	/* num of slim ports required */
+	struct taiko_codec_dai_data dai[NUM_CODEC_DAIS];
+
+	/*compander*/
+	int comp_enabled[COMPANDER_MAX];
+	u32 comp_fs[COMPANDER_MAX];
+
+	/* Maintain the status of AUX PGA */
+	int aux_pga_cnt;
+	u8 aux_l_gain;
+	u8 aux_r_gain;
+
+	struct delayed_work mbhc_insert_dwork;
+	unsigned long mbhc_last_resume; /* in jiffies */
+
+	u8 current_plug;
+	struct work_struct hs_correct_plug_work;
+	bool hs_detect_work_stop;
+	bool hs_polling_irq_prepared;
+	bool lpi_enabled; /* low power insertion detection */
+	bool in_gpio_handler;
+	/* Currently, only used for mbhc purpose, to protect
+	 * concurrent execution of mbhc threaded irq handlers and
+	 * kill race between DAPM and MBHC.But can serve as a
+	 * general lock to protect codec resource
+	 */
+	struct mutex codec_resource_lock;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_poke;
+	struct dentry *debugfs_mbhc;
+#endif
+};
+
+
+static const u32 comp_shift[] = {
+	0,
+	2,
+};
+
+static const int comp_rx_path[] = {
+	COMPANDER_1,
+	COMPANDER_1,
+	COMPANDER_2,
+	COMPANDER_2,
+	COMPANDER_2,
+	COMPANDER_2,
+	COMPANDER_MAX,
+};
+
+static const struct comp_sample_dependent_params comp_samp_params[] = {
+	{
+		.peak_det_timeout = 0x2,
+		.rms_meter_div_fact = 0x8 << 4,
+		.rms_meter_resamp_fact = 0x21,
+	},
+	{
+		.peak_det_timeout = 0x3,
+		.rms_meter_div_fact = 0x9 << 4,
+		.rms_meter_resamp_fact = 0x28,
+	},
+
+	{
+		.peak_det_timeout = 0x5,
+		.rms_meter_div_fact = 0xB << 4,
+		.rms_meter_resamp_fact = 0x28,
+	},
+
+	{
+		.peak_det_timeout = 0x5,
+		.rms_meter_div_fact = 0xB << 4,
+		.rms_meter_resamp_fact = 0x28,
+	},
+};
+
+static unsigned short rx_digital_gain_reg[] = {
+	TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
+	TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
+	TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
+	TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
+	TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
+	TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
+	TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
+};
+
+
+static unsigned short tx_digital_gain_reg[] = {
+	TAIKO_A_CDC_TX1_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX2_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX3_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX4_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX5_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX6_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX7_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX8_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX9_VOL_CTL_GAIN,
+	TAIKO_A_CDC_TX10_VOL_CTL_GAIN,
+};
+
+static int taiko_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_debug("%s %d\n", __func__, event);
+
+	 /* FIX . need to use CLASS-H controller */
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x01,
+			0x01);
+		usleep_range(200, 200);
+		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x10, 0x00);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL,
+				0x01, 0x01);
+		usleep_range(20, 20);
+		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x08, 0x08);
+		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x10, 0x10);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x01,
+			0x00);
+		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x08, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static int taiko_get_anc_slot(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	ucontrol->value.integer.value[0] = taiko->anc_slot;
+	return 0;
+}
+
+static int taiko_put_anc_slot(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	taiko->anc_slot = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 ear_pa_gain;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	ear_pa_gain = snd_soc_read(codec, TAIKO_A_RX_EAR_GAIN);
+
+	ear_pa_gain = ear_pa_gain >> 5;
+
+	if (ear_pa_gain == 0x00) {
+		ucontrol->value.integer.value[0] = 0;
+	} else if (ear_pa_gain == 0x04) {
+		ucontrol->value.integer.value[0] = 1;
+	} else  {
+		pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
+				__func__, ear_pa_gain);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+
+	return 0;
+}
+
+static int taiko_pa_gain_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 ear_pa_gain;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	pr_debug("%s: ucontrol->value.integer.value[0]  = %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		ear_pa_gain = 0x00;
+		break;
+	case 1:
+		ear_pa_gain = 0x80;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, TAIKO_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
+	return 0;
+}
+
+static int taiko_get_iir_enable_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] =
+		snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
+		(1 << band_idx);
+
+	pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int taiko_put_iir_enable_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+
+	/* Mask first 5 bits, 6-8 are reserved */
+	snd_soc_update_bits(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx),
+		(1 << band_idx), (value << band_idx));
+
+	pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx, value);
+	return 0;
+}
+static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
+				int iir_idx, int band_idx,
+				int coeff_idx)
+{
+	/* Address does not automatically update if reading */
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		(band_idx * BAND_MAX + coeff_idx) & 0x1F);
+
+	/* Mask bits top 2 bits since they are reserved */
+	return ((snd_soc_read(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24)) &
+		0x3FFFFFFF;
+}
+
+static int taiko_get_iir_band_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 0);
+	ucontrol->value.integer.value[1] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 1);
+	ucontrol->value.integer.value[2] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 2);
+	ucontrol->value.integer.value[3] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 3);
+	ucontrol->value.integer.value[4] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 4);
+
+	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[1],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[2],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[3],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[4]);
+	return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_codec *codec,
+				int iir_idx, int band_idx,
+				int coeff_idx, uint32_t value)
+{
+	/* Mask top 3 bits, 6-8 are reserved */
+	/* Update address manually each time */
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		(band_idx * BAND_MAX + coeff_idx) & 0x1F);
+
+	/* Mask top 2 bits, 7-8 are reserved */
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+		(value >> 24) & 0x3F);
+
+}
+
+static int taiko_put_iir_band_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+				ucontrol->value.integer.value[0]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+				ucontrol->value.integer.value[1]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+				ucontrol->value.integer.value[2]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+				ucontrol->value.integer.value[3]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+				ucontrol->value.integer.value[4]);
+
+	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 0),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 1),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 2),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 3),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 4));
+	return 0;
+}
+
+static int taiko_compander_gain_offset(
+	struct snd_soc_codec *codec, u32 enable,
+	unsigned int reg, int mask,	int event)
+{
+	int pa_mode = snd_soc_read(codec, reg) & mask;
+	int gain_offset = 0;
+	/*  if PMU && enable is 1-> offset is 3
+	 *  if PMU && enable is 0-> offset is 0
+	 *  if PMD && pa_mode is PA -> offset is 0: PMU compander is off
+	 *  if PMD && pa_mode is comp -> offset is -3: PMU compander is on.
+	 */
+
+	if (SND_SOC_DAPM_EVENT_ON(event) && (enable != 0))
+		gain_offset = TAIKO_COMP_DIGITAL_GAIN_OFFSET;
+	if (SND_SOC_DAPM_EVENT_OFF(event) && (pa_mode == 0))
+		gain_offset = -TAIKO_COMP_DIGITAL_GAIN_OFFSET;
+	return gain_offset;
+}
+
+
+static int taiko_config_gain_compander(
+				struct snd_soc_codec *codec,
+				u32 compander, u32 enable, int event)
+{
+	int value = 0;
+	int mask = 1 << 4;
+	int gain = 0;
+	int gain_offset;
+	if (compander >= COMPANDER_MAX) {
+		pr_err("%s: Error, invalid compander channel\n", __func__);
+		return -EINVAL;
+	}
+
+	if ((enable == 0) || SND_SOC_DAPM_EVENT_OFF(event))
+		value = 1 << 4;
+
+	if (compander == COMPANDER_1) {
+		gain_offset = taiko_compander_gain_offset(codec, enable,
+				TAIKO_A_RX_HPH_L_GAIN, mask, event);
+		snd_soc_update_bits(codec, TAIKO_A_RX_HPH_L_GAIN, mask, value);
+		gain = snd_soc_read(codec, TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
+				0xFF, gain - gain_offset);
+		gain_offset = taiko_compander_gain_offset(codec, enable,
+				TAIKO_A_RX_HPH_R_GAIN, mask, event);
+		snd_soc_update_bits(codec, TAIKO_A_RX_HPH_R_GAIN, mask, value);
+		gain = snd_soc_read(codec, TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
+				0xFF, gain - gain_offset);
+	} else if (compander == COMPANDER_2) {
+		gain_offset = taiko_compander_gain_offset(codec, enable,
+				TAIKO_A_RX_LINE_1_GAIN, mask, event);
+		snd_soc_update_bits(codec, TAIKO_A_RX_LINE_1_GAIN, mask, value);
+		gain = snd_soc_read(codec, TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
+				0xFF, gain - gain_offset);
+		gain_offset = taiko_compander_gain_offset(codec, enable,
+				TAIKO_A_RX_LINE_3_GAIN, mask, event);
+		snd_soc_update_bits(codec, TAIKO_A_RX_LINE_3_GAIN, mask, value);
+		gain = snd_soc_read(codec, TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
+				0xFF, gain - gain_offset);
+		gain_offset = taiko_compander_gain_offset(codec, enable,
+				TAIKO_A_RX_LINE_2_GAIN, mask, event);
+		snd_soc_update_bits(codec, TAIKO_A_RX_LINE_2_GAIN, mask, value);
+		gain = snd_soc_read(codec, TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
+				0xFF, gain - gain_offset);
+		gain_offset = taiko_compander_gain_offset(codec, enable,
+				TAIKO_A_RX_LINE_4_GAIN, mask, event);
+		snd_soc_update_bits(codec, TAIKO_A_RX_LINE_4_GAIN, mask, value);
+		gain = snd_soc_read(codec, TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
+				0xFF, gain - gain_offset);
+	}
+	return 0;
+}
+static int taiko_get_compander(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int comp = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->max;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = taiko->comp_enabled[comp];
+
+	return 0;
+}
+
+static int taiko_set_compander(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	int comp = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->max;
+	int value = ucontrol->value.integer.value[0];
+
+	if (value == taiko->comp_enabled[comp]) {
+		pr_debug("%s: compander #%d enable %d no change\n",
+			    __func__, comp, value);
+		return 0;
+	}
+	taiko->comp_enabled[comp] = value;
+	return 0;
+}
+
+
+static int taiko_config_compander(struct snd_soc_dapm_widget *w,
+						  struct snd_kcontrol *kcontrol,
+						  int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u32 rate = taiko->comp_fs[w->shift];
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (taiko->comp_enabled[w->shift] != 0) {
+			/* Enable both L/R compander clocks */
+			snd_soc_update_bits(codec,
+					TAIKO_A_CDC_CLK_RX_B2_CTL,
+					0x03 << comp_shift[w->shift],
+					0x03 << comp_shift[w->shift]);
+			/* Clar the HALT for the compander*/
+			snd_soc_update_bits(codec,
+					TAIKO_A_CDC_COMP1_B1_CTL +
+					w->shift * 8, 1 << 2, 0);
+			/* Toggle compander reset bits*/
+			snd_soc_update_bits(codec,
+					TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
+					0x03 << comp_shift[w->shift],
+					0x03 << comp_shift[w->shift]);
+			snd_soc_update_bits(codec,
+					TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
+					0x03 << comp_shift[w->shift], 0);
+			taiko_config_gain_compander(codec, w->shift, 1, event);
+			/* Update the RMS meter resampling*/
+			snd_soc_update_bits(codec,
+					TAIKO_A_CDC_COMP1_B3_CTL +
+					w->shift * 8, 0xFF, 0x01);
+			/* Wait for 1ms*/
+			usleep_range(1000, 1000);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* Set sample rate dependent paramater*/
+		if (taiko->comp_enabled[w->shift] != 0) {
+			snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_FS_CFG +
+			w->shift * 8, 0x03,	rate);
+			snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B2_CTL +
+			w->shift * 8, 0x0F,
+			comp_samp_params[rate].peak_det_timeout);
+			snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B2_CTL +
+			w->shift * 8, 0xF0,
+			comp_samp_params[rate].rms_meter_div_fact);
+			snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B3_CTL +
+			w->shift * 8, 0xFF,
+			comp_samp_params[rate].rms_meter_resamp_fact);
+			/* Compander enable -> 0x370/0x378*/
+			snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
+			w->shift * 8, 0x03, 0x03);
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		/* Halt the compander*/
+		snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
+			w->shift * 8, 1 << 2, 1 << 2);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Restore the gain */
+		taiko_config_gain_compander(codec, w->shift,
+				taiko->comp_enabled[w->shift], event);
+		/* Disable the compander*/
+		snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
+			w->shift * 8, 0x03, 0x00);
+		/* Turn off the clock for compander in pair*/
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
+			0x03 << comp_shift[w->shift], 0);
+		break;
+	}
+	return 0;
+}
+
+static const char * const taiko_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum taiko_ear_pa_gain_enum[] = {
+		SOC_ENUM_SINGLE_EXT(2, taiko_ear_pa_gain_text),
+};
+
+/*cut of frequency for high pass filter*/
+static const char * const cf_text[] = {
+	"MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
+};
+
+static const struct soc_enum cf_dec1_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec2_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec3_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec4_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec5_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX5_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec6_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX6_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec7_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX7_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec8_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX8_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec9_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX9_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec10_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_TX10_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_rxmix1_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX1_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix2_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX2_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix3_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX3_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix4_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX4_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix5_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX5_B4_CTL, 1, 3, cf_text)
+;
+static const struct soc_enum cf_rxmix6_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX6_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix7_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX7_B4_CTL, 1, 3, cf_text);
+
+static const struct snd_kcontrol_new taiko_snd_controls[] = {
+
+	SOC_ENUM_EXT("EAR PA Gain", taiko_ear_pa_gain_enum[0],
+		taiko_pa_gain_get, taiko_pa_gain_put),
+
+	SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 12, 1,
+		line_gain),
+	SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 12, 1,
+		line_gain),
+	SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 12, 1,
+		line_gain),
+	SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 12, 1,
+		line_gain),
+
+	SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 12, 1,
+		line_gain),
+	SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 12, 1,
+		line_gain),
+
+	SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX3 Digital Volume", TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX4 Digital Volume", TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX5 Digital Volume", TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX6 Digital Volume", TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX7 Digital Volume", TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+
+	SOC_SINGLE_S8_TLV("DEC1 Volume", TAIKO_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC2 Volume", TAIKO_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC3 Volume", TAIKO_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC4 Volume", TAIKO_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC5 Volume", TAIKO_A_CDC_TX5_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC6 Volume", TAIKO_A_CDC_TX6_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC7 Volume", TAIKO_A_CDC_TX7_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC8 Volume", TAIKO_A_CDC_TX8_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC9 Volume", TAIKO_A_CDC_TX9_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC10 Volume", TAIKO_A_CDC_TX10_VOL_CTL_GAIN, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TAIKO_A_CDC_IIR1_GAIN_B1_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TAIKO_A_CDC_IIR1_GAIN_B2_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TAIKO_A_CDC_IIR1_GAIN_B3_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
+
+
+	SOC_SINGLE("MICBIAS1 CAPLESS Switch", TAIKO_A_MICB_1_CTL, 4, 1, 1),
+	SOC_SINGLE("MICBIAS2 CAPLESS Switch", TAIKO_A_MICB_2_CTL, 4, 1, 1),
+	SOC_SINGLE("MICBIAS3 CAPLESS Switch", TAIKO_A_MICB_3_CTL, 4, 1, 1),
+	SOC_SINGLE("MICBIAS4 CAPLESS Switch", TAIKO_A_MICB_4_CTL, 4, 1, 1),
+
+	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, taiko_get_anc_slot,
+		taiko_put_anc_slot),
+	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+	SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
+	SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
+	SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
+	SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
+	SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
+	SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
+	SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
+	SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),
+
+	SOC_SINGLE("TX1 HPF Switch", TAIKO_A_CDC_TX1_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX2 HPF Switch", TAIKO_A_CDC_TX2_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX3 HPF Switch", TAIKO_A_CDC_TX3_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX4 HPF Switch", TAIKO_A_CDC_TX4_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX5 HPF Switch", TAIKO_A_CDC_TX5_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX6 HPF Switch", TAIKO_A_CDC_TX6_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX7 HPF Switch", TAIKO_A_CDC_TX7_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX8 HPF Switch", TAIKO_A_CDC_TX8_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX9 HPF Switch", TAIKO_A_CDC_TX9_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX10 HPF Switch", TAIKO_A_CDC_TX10_MUX_CTL, 3, 1, 0),
+
+	SOC_SINGLE("RX1 HPF Switch", TAIKO_A_CDC_RX1_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX2 HPF Switch", TAIKO_A_CDC_RX2_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX3 HPF Switch", TAIKO_A_CDC_RX3_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX4 HPF Switch", TAIKO_A_CDC_RX4_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX5 HPF Switch", TAIKO_A_CDC_RX5_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX6 HPF Switch", TAIKO_A_CDC_RX6_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX7 HPF Switch", TAIKO_A_CDC_RX7_B5_CTL, 2, 1, 0),
+
+	SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
+	SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
+	SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
+	SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
+	SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
+	SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
+	SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
+
+	SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+	taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+
+	SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+	taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+
+	SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, 1, COMPANDER_1, 0,
+				   taiko_get_compander, taiko_set_compander),
+	SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, 0, COMPANDER_2, 0,
+				   taiko_get_compander, taiko_set_compander),
+
+};
+
+static const char * const rx_mix1_text[] = {
+	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
+		"RX5", "RX6", "RX7"
+};
+
+static const char * const rx_mix2_text[] = {
+	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
+};
+
+static const char * const rx_dsm_text[] = {
+	"CIC_OUT", "DSM_INV"
+};
+
+static const char * const sb_tx1_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC1"
+};
+
+static const char * const sb_tx2_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC2"
+};
+
+static const char * const sb_tx3_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC3"
+};
+
+static const char * const sb_tx4_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC4"
+};
+
+static const char * const sb_tx5_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC5"
+};
+
+static const char * const sb_tx6_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC6"
+};
+
+static const char * const sb_tx7_to_tx10_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
+		"DEC9", "DEC10"
+};
+
+static const char * const dec1_mux_text[] = {
+	"ZERO", "DMIC1", "ADC6",
+};
+
+static const char * const dec2_mux_text[] = {
+	"ZERO", "DMIC2", "ADC5",
+};
+
+static const char * const dec3_mux_text[] = {
+	"ZERO", "DMIC3", "ADC4",
+};
+
+static const char * const dec4_mux_text[] = {
+	"ZERO", "DMIC4", "ADC3",
+};
+
+static const char * const dec5_mux_text[] = {
+	"ZERO", "DMIC5", "ADC2",
+};
+
+static const char * const dec6_mux_text[] = {
+	"ZERO", "DMIC6", "ADC1",
+};
+
+static const char * const dec7_mux_text[] = {
+	"ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
+};
+
+static const char * const dec8_mux_text[] = {
+	"ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5",
+};
+
+static const char * const dec9_mux_text[] = {
+	"ZERO", "DMIC4", "DMIC5", "ADC2", "ADC3", "ADCMB", "ANC1_FB", "ANC2_FB",
+};
+
+static const char * const dec10_mux_text[] = {
+	"ZERO", "DMIC3", "DMIC6", "ADC1", "ADC4", "ADCMB", "ANC1_FB", "ANC2_FB",
+};
+
+static const char * const anc_mux_text[] = {
+	"ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
+		"RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
+};
+
+static const char * const anc1_fb_mux_text[] = {
+	"ZERO", "EAR_HPH_L", "EAR_LINE_1",
+};
+
+static const char * const iir1_inp1_text[] = {
+	"ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
+	"DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
+};
+
+static const struct soc_enum rx_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp3_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx4_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx4_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx5_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx5_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx6_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx6_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx7_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx7_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx1_mix2_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx1_mix2_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 3, 5, rx_mix2_text);
+
+static const struct soc_enum rx2_mix2_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx2_mix2_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
+
+static const struct soc_enum rx7_mix2_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx7_mix2_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 3, 5, rx_mix2_text);
+
+static const struct soc_enum rx4_dsm_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX4_B6_CTL, 4, 2, rx_dsm_text);
+
+static const struct soc_enum rx6_dsm_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX6_B6_CTL, 4, 2, rx_dsm_text);
+
+static const struct soc_enum sb_tx1_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
+
+static const struct soc_enum sb_tx2_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
+
+static const struct soc_enum sb_tx3_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
+
+static const struct soc_enum sb_tx4_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
+
+static const struct soc_enum sb_tx5_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
+
+static const struct soc_enum sb_tx6_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0, 9, sb_tx6_mux_text);
+
+static const struct soc_enum sb_tx7_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
+			sb_tx7_to_tx10_mux_text);
+
+static const struct soc_enum sb_tx8_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
+			sb_tx7_to_tx10_mux_text);
+
+static const struct soc_enum sb_tx9_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0, 18,
+			sb_tx7_to_tx10_mux_text);
+
+static const struct soc_enum sb_tx10_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0, 18,
+			sb_tx7_to_tx10_mux_text);
+
+static const struct soc_enum dec1_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
+
+static const struct soc_enum dec2_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
+
+static const struct soc_enum dec3_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
+
+static const struct soc_enum dec4_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
+
+static const struct soc_enum dec5_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
+
+static const struct soc_enum dec6_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
+
+static const struct soc_enum dec7_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
+
+static const struct soc_enum dec8_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
+
+static const struct soc_enum dec9_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
+
+static const struct soc_enum dec10_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
+
+static const struct soc_enum anc1_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 0, 16, anc_mux_text);
+
+static const struct soc_enum anc2_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 4, 16, anc_mux_text);
+
+static const struct soc_enum anc1_fb_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
+
+static const struct snd_kcontrol_new rx_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp3_mux =
+	SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
+	SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp2_mux =
+	SOC_DAPM_ENUM("RX1 MIX2 INP2 Mux", rx1_mix2_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
+	SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
+	SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx7_mix2_inp1_mux =
+	SOC_DAPM_ENUM("RX7 MIX2 INP1 Mux", rx7_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx7_mix2_inp2_mux =
+	SOC_DAPM_ENUM("RX7 MIX2 INP2 Mux", rx7_mix2_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx4_dsm_mux =
+	SOC_DAPM_ENUM("RX4 DSM MUX Mux", rx4_dsm_enum);
+
+static const struct snd_kcontrol_new rx6_dsm_mux =
+	SOC_DAPM_ENUM("RX6 DSM MUX Mux", rx6_dsm_enum);
+
+static const struct snd_kcontrol_new sb_tx1_mux =
+	SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx2_mux =
+	SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx3_mux =
+	SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx4_mux =
+	SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx5_mux =
+	SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx6_mux =
+	SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx7_mux =
+	SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx8_mux =
+	SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx9_mux =
+	SOC_DAPM_ENUM("SLIM TX9 MUX Mux", sb_tx9_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx10_mux =
+	SOC_DAPM_ENUM("SLIM TX10 MUX Mux", sb_tx10_mux_enum);
+
+
+static int wcd9320_put_dec_enum(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *w = wlist->widgets[0];
+	struct snd_soc_codec *codec = w->codec;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int dec_mux, decimator;
+	char *dec_name = NULL;
+	char *widget_name = NULL;
+	char *temp;
+	u16 tx_mux_ctl_reg;
+	u8 adc_dmic_sel = 0x0;
+	int ret = 0;
+
+	if (ucontrol->value.enumerated.item[0] > e->max - 1)
+		return -EINVAL;
+
+	dec_mux = ucontrol->value.enumerated.item[0];
+
+	widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+	if (!widget_name)
+		return -ENOMEM;
+	temp = widget_name;
+
+	dec_name = strsep(&widget_name, " ");
+	widget_name = temp;
+	if (!dec_name) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
+	if (ret < 0) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
+		, __func__, w->name, decimator, dec_mux);
+
+
+	switch (decimator) {
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		if (dec_mux == 1)
+			adc_dmic_sel = 0x1;
+		else
+			adc_dmic_sel = 0x0;
+		break;
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+		if ((dec_mux == 1) || (dec_mux == 2))
+			adc_dmic_sel = 0x1;
+		else
+			adc_dmic_sel = 0x0;
+		break;
+	default:
+		pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
+	snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
+
+	ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+out:
+	kfree(widget_name);
+	return ret;
+}
+
+#define WCD9320_DEC_ENUM(xname, xenum) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_enum_double, \
+	.get = snd_soc_dapm_get_enum_double, \
+	.put = wcd9320_put_dec_enum, \
+	.private_value = (unsigned long)&xenum }
+
+static const struct snd_kcontrol_new dec1_mux =
+	WCD9320_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+
+static const struct snd_kcontrol_new dec2_mux =
+	WCD9320_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+
+static const struct snd_kcontrol_new dec3_mux =
+	WCD9320_DEC_ENUM("DEC3 MUX Mux", dec3_mux_enum);
+
+static const struct snd_kcontrol_new dec4_mux =
+	WCD9320_DEC_ENUM("DEC4 MUX Mux", dec4_mux_enum);
+
+static const struct snd_kcontrol_new dec5_mux =
+	WCD9320_DEC_ENUM("DEC5 MUX Mux", dec5_mux_enum);
+
+static const struct snd_kcontrol_new dec6_mux =
+	WCD9320_DEC_ENUM("DEC6 MUX Mux", dec6_mux_enum);
+
+static const struct snd_kcontrol_new dec7_mux =
+	WCD9320_DEC_ENUM("DEC7 MUX Mux", dec7_mux_enum);
+
+static const struct snd_kcontrol_new dec8_mux =
+	WCD9320_DEC_ENUM("DEC8 MUX Mux", dec8_mux_enum);
+
+static const struct snd_kcontrol_new dec9_mux =
+	WCD9320_DEC_ENUM("DEC9 MUX Mux", dec9_mux_enum);
+
+static const struct snd_kcontrol_new dec10_mux =
+	WCD9320_DEC_ENUM("DEC10 MUX Mux", dec10_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp1_mux =
+	SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+
+static const struct snd_kcontrol_new anc1_mux =
+	SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
+
+static const struct snd_kcontrol_new anc2_mux =
+	SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
+
+static const struct snd_kcontrol_new anc1_fb_mux =
+	SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
+
+static const struct snd_kcontrol_new dac1_switch[] = {
+	SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_EAR_EN, 5, 1, 0)
+};
+static const struct snd_kcontrol_new hphl_switch[] = {
+	SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
+};
+
+static const struct snd_kcontrol_new hphl_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+					7, 1, 0),
+};
+
+static const struct snd_kcontrol_new hphr_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+					6, 1, 0),
+};
+
+static const struct snd_kcontrol_new ear_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+					5, 1, 0),
+};
+static const struct snd_kcontrol_new lineout1_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+					4, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout2_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+					3, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout3_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+					2, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout4_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+					1, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout3_ground_switch =
+	SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
+
+static const struct snd_kcontrol_new lineout4_ground_switch =
+	SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
+
+static void taiko_codec_enable_adc_block(struct snd_soc_codec *codec,
+					 int enable)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s %d\n", __func__, enable);
+
+	if (enable) {
+		taiko->adc_count++;
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x2, 0x2);
+	} else {
+		taiko->adc_count--;
+		if (!taiko->adc_count)
+			snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL,
+					    0x2, 0x0);
+	}
+}
+
+static int taiko_codec_enable_adc(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	u16 adc_reg;
+	u8 init_bit_shift;
+
+	pr_debug("%s %d\n", __func__, event);
+
+	if (w->reg == TAIKO_A_TX_1_2_EN)
+		adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
+	else if (w->reg == TAIKO_A_TX_3_4_EN)
+		adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
+	else if (w->reg == TAIKO_A_TX_5_6_EN)
+		adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
+	else {
+		pr_err("%s: Error, invalid adc register\n", __func__);
+		return -EINVAL;
+	}
+
+	if (w->shift == 3)
+		init_bit_shift = 6;
+	else if  (w->shift == 7)
+		init_bit_shift = 7;
+	else {
+		pr_err("%s: Error, invalid init bit postion adc register\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		taiko_codec_enable_adc_block(codec, 1);
+		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
+				1 << init_bit_shift);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+
+		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		taiko_codec_enable_adc_block(codec, 0);
+		break;
+	}
+	return 0;
+}
+
+static void taiko_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
+{
+	snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x80,
+		0x80);
+	snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x04,
+		0x04);
+	snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x01,
+		0x01);
+	usleep_range(1000, 1000);
+	snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x80,
+		0x00);
+}
+
+static void taiko_codec_enable_bandgap(struct snd_soc_codec *codec,
+	enum taiko_bandgap_type choice)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	/* TODO lock resources accessed by audio streams and threaded
+	 * interrupt handlers
+	 */
+
+	pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
+		taiko->bandgap_type);
+
+	if (taiko->bandgap_type == choice)
+		return;
+
+	if ((taiko->bandgap_type == TAIKO_BANDGAP_OFF) &&
+		(choice == TAIKO_BANDGAP_AUDIO_MODE)) {
+		taiko_codec_enable_audio_mode_bandgap(codec);
+	} else if (choice == TAIKO_BANDGAP_MBHC_MODE) {
+		/* bandgap mode becomes fast,
+		 * mclk should be off or clk buff source souldn't be VBG
+		 * Let's turn off mclk always */
+		WARN_ON(snd_soc_read(codec, TAIKO_A_CLK_BUFF_EN2) & (1 << 2));
+		snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x2,
+			0x2);
+		snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x80,
+			0x80);
+		snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x4,
+			0x4);
+		snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x01,
+			0x01);
+		usleep_range(1000, 1000);
+		snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x80,
+			0x00);
+	} else if ((taiko->bandgap_type == TAIKO_BANDGAP_MBHC_MODE) &&
+		(choice == TAIKO_BANDGAP_AUDIO_MODE)) {
+		snd_soc_write(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x00);
+		usleep_range(100, 100);
+		taiko_codec_enable_audio_mode_bandgap(codec);
+	} else if (choice == TAIKO_BANDGAP_OFF) {
+		snd_soc_write(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x00);
+	} else {
+		pr_err("%s: Error, Invalid bandgap settings\n", __func__);
+	}
+	taiko->bandgap_type = choice;
+}
+
+static void taiko_codec_disable_clock_block(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	pr_debug("%s\n", __func__);
+	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x04, 0x00);
+	usleep_range(50, 50);
+	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x02, 0x02);
+	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x05, 0x00);
+	usleep_range(50, 50);
+	taiko->clock_active = false;
+}
+
+static int taiko_codec_mclk_index(const struct taiko_priv *taiko)
+{
+	if (taiko->mbhc_cfg.mclk_rate == TAIKO_MCLK_RATE_12288KHZ)
+		return 0;
+	else if (taiko->mbhc_cfg.mclk_rate == TAIKO_MCLK_RATE_9600KHZ)
+		return 1;
+	else {
+		BUG_ON(1);
+		return -EINVAL;
+	}
+}
+
+static void taiko_enable_rx_bias(struct snd_soc_codec *codec, u32  enable)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	if (enable) {
+		taiko->rx_bias_count++;
+		if (taiko->rx_bias_count == 1)
+			snd_soc_update_bits(codec, TAIKO_A_RX_COM_BIAS,
+				0x80, 0x80);
+	} else {
+		taiko->rx_bias_count--;
+		if (!taiko->rx_bias_count)
+			snd_soc_update_bits(codec, TAIKO_A_RX_COM_BIAS,
+				0x80, 0x00);
+	}
+}
+
+static int taiko_codec_enable_config_mode(struct snd_soc_codec *codec,
+	int enable)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: enable = %d\n", __func__, enable);
+	if (enable) {
+
+		snd_soc_update_bits(codec, TAIKO_A_RC_OSC_FREQ, 0x10, 0);
+		/* bandgap mode to fast */
+		snd_soc_write(codec, TAIKO_A_BIAS_OSC_BG_CTL, 0x17);
+		usleep_range(5, 5);
+		snd_soc_update_bits(codec, TAIKO_A_RC_OSC_FREQ, 0x80,
+				    0x80);
+		snd_soc_update_bits(codec, TAIKO_A_RC_OSC_TEST, 0x80,
+				    0x80);
+		usleep_range(10, 10);
+		snd_soc_update_bits(codec, TAIKO_A_RC_OSC_TEST, 0x80, 0);
+		usleep_range(10000, 10000);
+		snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x08, 0x08);
+
+	} else {
+		snd_soc_update_bits(codec, TAIKO_A_BIAS_OSC_BG_CTL, 0x1,
+				    0);
+		snd_soc_update_bits(codec, TAIKO_A_RC_OSC_FREQ, 0x80, 0);
+		/* clk source to ext clk and clk buff ref to VBG */
+		snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x0C, 0x04);
+	}
+	taiko->config_mode_active = enable ? true : false;
+
+	return 0;
+}
+
+static int taiko_codec_enable_clock_block(struct snd_soc_codec *codec,
+					  int config_mode)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: config_mode = %d\n", __func__, config_mode);
+
+	/* transit to RCO requires mclk off */
+	WARN_ON(snd_soc_read(codec, TAIKO_A_CLK_BUFF_EN2) & (1 << 2));
+	if (config_mode) {
+		/* enable RCO and switch to it */
+		taiko_codec_enable_config_mode(codec, 1);
+		snd_soc_write(codec, TAIKO_A_CLK_BUFF_EN2, 0x02);
+		usleep_range(1000, 1000);
+	} else {
+		/* switch to MCLK */
+		snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x08, 0x00);
+
+		if (taiko->mbhc_polling_active) {
+			snd_soc_write(codec, TAIKO_A_CLK_BUFF_EN2, 0x02);
+			taiko_codec_enable_config_mode(codec, 0);
+		}
+	}
+
+	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x01, 0x01);
+	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x02, 0x00);
+	/* on MCLK */
+	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x04, 0x04);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
+	usleep_range(50, 50);
+	taiko->clock_active = true;
+	return 0;
+}
+
+static int taiko_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		taiko_codec_enable_bandgap(codec, TAIKO_BANDGAP_AUDIO_MODE);
+		taiko_enable_rx_bias(codec, 1);
+
+		if (taiko->aux_pga_cnt++ == 1
+			&& !taiko->mclk_enabled) {
+			taiko_codec_enable_clock_block(codec, 1);
+			pr_debug("AUX PGA enabled RC osc\n");
+		}
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		taiko_enable_rx_bias(codec, 0);
+
+		if (taiko->aux_pga_cnt-- == 0) {
+			if (taiko->mbhc_polling_active)
+				taiko_codec_enable_bandgap(codec,
+					TAIKO_BANDGAP_MBHC_MODE);
+			else
+				taiko_codec_enable_bandgap(codec,
+					TAIKO_BANDGAP_OFF);
+
+			if (!taiko->mclk_enabled &&
+				!taiko->mbhc_polling_active) {
+				taiko_codec_enable_clock_block(codec, 0);
+			}
+		}
+		break;
+	}
+	return 0;
+}
+
+static int taiko_codec_enable_lineout(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	u16 lineout_gain_reg;
+
+	pr_debug("%s %d %s\n", __func__, event, w->name);
+
+	switch (w->shift) {
+	case 0:
+		lineout_gain_reg = TAIKO_A_RX_LINE_1_GAIN;
+		break;
+	case 1:
+		lineout_gain_reg = TAIKO_A_RX_LINE_2_GAIN;
+		break;
+	case 2:
+		lineout_gain_reg = TAIKO_A_RX_LINE_3_GAIN;
+		break;
+	case 3:
+		lineout_gain_reg = TAIKO_A_RX_LINE_4_GAIN;
+		break;
+	default:
+		pr_err("%s: Error, incorrect lineout register value\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
+				__func__, w->name);
+		usleep_range(16000, 16000);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
+		break;
+	}
+	return 0;
+}
+
+
+static int taiko_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u8  dmic_clk_en;
+	u16 dmic_clk_reg;
+	s32 *dmic_clk_cnt;
+	unsigned int dmic;
+	int ret;
+
+	ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
+	if (ret < 0) {
+		pr_err("%s: Invalid DMIC line on the codec\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (dmic) {
+	case 1:
+	case 2:
+		dmic_clk_en = 0x01;
+		dmic_clk_cnt = &(taiko->dmic_1_2_clk_cnt);
+		dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
+		pr_debug("%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
+			__func__, event,  dmic, *dmic_clk_cnt);
+
+		break;
+
+	case 3:
+	case 4:
+		dmic_clk_en = 0x10;
+		dmic_clk_cnt = &(taiko->dmic_3_4_clk_cnt);
+		dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
+
+		pr_debug("%s() event %d DMIC%d dmic_3_4_clk_cnt %d\n",
+			__func__, event,  dmic, *dmic_clk_cnt);
+		break;
+
+	case 5:
+	case 6:
+		dmic_clk_en = 0x01;
+		dmic_clk_cnt = &(taiko->dmic_5_6_clk_cnt);
+		dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B2_CTL;
+
+		pr_debug("%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
+			__func__, event,  dmic, *dmic_clk_cnt);
+
+		break;
+
+	default:
+		pr_err("%s: Invalid DMIC Selection\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+
+		(*dmic_clk_cnt)++;
+		if (*dmic_clk_cnt == 1)
+			snd_soc_update_bits(codec, dmic_clk_reg,
+					dmic_clk_en, dmic_clk_en);
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+
+		(*dmic_clk_cnt)--;
+		if (*dmic_clk_cnt  == 0)
+			snd_soc_update_bits(codec, dmic_clk_reg,
+					dmic_clk_en, 0);
+		break;
+	}
+	return 0;
+}
+
+static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	const char *filename;
+	const struct firmware *fw;
+	int i;
+	int ret;
+	int num_anc_slots;
+	struct anc_header *anc_head;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u32 anc_writes_size = 0;
+	int anc_size_remaining;
+	u32 *anc_ptr;
+	u16 reg;
+	u8 mask, val, old_val;
+
+	pr_debug("%s %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+
+		filename = "wcd9320/wcd9320_anc.bin";
+
+		ret = request_firmware(&fw, filename, codec->dev);
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
+				ret);
+			return -ENODEV;
+		}
+
+		if (fw->size < sizeof(struct anc_header)) {
+			dev_err(codec->dev, "Not enough data\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+
+		/* First number is the number of register writes */
+		anc_head = (struct anc_header *)(fw->data);
+		anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
+		anc_size_remaining = fw->size - sizeof(struct anc_header);
+		num_anc_slots = anc_head->num_anc_slots;
+
+		if (taiko->anc_slot >= num_anc_slots) {
+			dev_err(codec->dev, "Invalid ANC slot selected\n");
+			release_firmware(fw);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < num_anc_slots; i++) {
+
+			if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -EINVAL;
+			}
+			anc_writes_size = (u32)(*anc_ptr);
+			anc_size_remaining -= sizeof(u32);
+			anc_ptr += 1;
+
+			if (anc_writes_size * TAIKO_PACKED_REG_SIZE
+				> anc_size_remaining) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -ENOMEM;
+			}
+
+			if (taiko->anc_slot == i)
+				break;
+
+			anc_size_remaining -= (anc_writes_size *
+				TAIKO_PACKED_REG_SIZE);
+			anc_ptr += anc_writes_size;
+		}
+		if (i == num_anc_slots) {
+			dev_err(codec->dev, "Selected ANC slot not present\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < anc_writes_size; i++) {
+			TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
+				mask, val);
+			old_val = snd_soc_read(codec, reg);
+			snd_soc_write(codec, reg, (old_val & ~mask) |
+				(val & mask));
+		}
+		release_firmware(fw);
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+		break;
+	}
+	return 0;
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_start_hs_polling(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	int mbhc_state = taiko->mbhc_state;
+
+	pr_debug("%s: enter\n", __func__);
+	if (!taiko->mbhc_polling_active) {
+		pr_debug("Polling is not active, do not start polling\n");
+		return;
+	}
+	snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x84);
+
+	if (!taiko->no_mic_headset_override) {
+		if (mbhc_state == MBHC_STATE_POTENTIAL) {
+			pr_debug("%s recovering MBHC state macine\n", __func__);
+			taiko->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
+			/* set to max button press threshold */
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B2_CTL,
+				      0x7F);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B1_CTL,
+				      0xFF);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B4_CTL,
+				       0x7F);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B3_CTL,
+				      0xFF);
+			/* set to max */
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B6_CTL,
+				      0x7F);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B5_CTL,
+				      0xFF);
+		}
+	}
+
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x1);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x1);
+	pr_debug("%s: leave\n", __func__);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_pause_hs_polling(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: enter\n", __func__);
+	if (!taiko->mbhc_polling_active) {
+		pr_debug("polling not active, nothing to pause\n");
+		return;
+	}
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+	pr_debug("%s: leave\n", __func__);
+}
+
+static void taiko_codec_switch_cfilt_mode(struct snd_soc_codec *codec, int mode)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u8 reg_mode_val, cur_mode_val;
+	bool mbhc_was_polling = false;
+
+	if (mode)
+		reg_mode_val = TAIKO_CFILT_FAST_MODE;
+	else
+		reg_mode_val = TAIKO_CFILT_SLOW_MODE;
+
+	cur_mode_val = snd_soc_read(codec,
+					taiko->mbhc_bias_regs.cfilt_ctl) & 0x40;
+
+	if (cur_mode_val != reg_mode_val) {
+		TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+		if (taiko->mbhc_polling_active) {
+			taiko_codec_pause_hs_polling(codec);
+			mbhc_was_polling = true;
+		}
+		snd_soc_update_bits(codec,
+			taiko->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
+		if (mbhc_was_polling)
+			taiko_codec_start_hs_polling(codec);
+		TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+		pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
+			cur_mode_val, reg_mode_val);
+	} else {
+		pr_debug("%s: CFILT Value is already %x\n",
+			__func__, cur_mode_val);
+	}
+}
+
+static void taiko_codec_update_cfilt_usage(struct snd_soc_codec *codec,
+					   u8 cfilt_sel, int inc)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u32 *cfilt_cnt_ptr = NULL;
+	u16 micb_cfilt_reg;
+
+	switch (cfilt_sel) {
+	case TAIKO_CFILT1_SEL:
+		cfilt_cnt_ptr = &taiko->cfilt1_cnt;
+		micb_cfilt_reg = TAIKO_A_MICB_CFILT_1_CTL;
+		break;
+	case TAIKO_CFILT2_SEL:
+		cfilt_cnt_ptr = &taiko->cfilt2_cnt;
+		micb_cfilt_reg = TAIKO_A_MICB_CFILT_2_CTL;
+		break;
+	case TAIKO_CFILT3_SEL:
+		cfilt_cnt_ptr = &taiko->cfilt3_cnt;
+		micb_cfilt_reg = TAIKO_A_MICB_CFILT_3_CTL;
+		break;
+	default:
+		return; /* should not happen */
+	}
+
+	if (inc) {
+		if (!(*cfilt_cnt_ptr)++) {
+			/* Switch CFILT to slow mode if MBHC CFILT being used */
+			if (cfilt_sel == taiko->mbhc_bias_regs.cfilt_sel)
+				taiko_codec_switch_cfilt_mode(codec, 0);
+
+			snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
+		}
+	} else {
+		/* check if count not zero, decrement
+		 * then check if zero, go ahead disable cfilter
+		 */
+		if ((*cfilt_cnt_ptr) && !--(*cfilt_cnt_ptr)) {
+			snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
+
+			/* Switch CFILT to fast mode if MBHC CFILT being used */
+			if (cfilt_sel == taiko->mbhc_bias_regs.cfilt_sel)
+				taiko_codec_switch_cfilt_mode(codec, 1);
+		}
+	}
+}
+
+static int taiko_find_k_value(unsigned int ldoh_v, unsigned int cfilt_mv)
+{
+	int rc = -EINVAL;
+	unsigned min_mv, max_mv;
+
+	switch (ldoh_v) {
+	case TAIKO_LDOH_1P95_V:
+		min_mv = 160;
+		max_mv = 1800;
+		break;
+	case TAIKO_LDOH_2P35_V:
+		min_mv = 200;
+		max_mv = 2200;
+		break;
+	case TAIKO_LDOH_2P75_V:
+		min_mv = 240;
+		max_mv = 2600;
+		break;
+	case TAIKO_LDOH_2P85_V:
+		min_mv = 250;
+		max_mv = 2700;
+		break;
+	default:
+		goto done;
+	}
+
+	if (cfilt_mv < min_mv || cfilt_mv > max_mv)
+		goto done;
+
+	for (rc = 4; rc <= 44; rc++) {
+		min_mv = max_mv * (rc) / 44;
+		if (min_mv >= cfilt_mv) {
+			rc -= 4;
+			break;
+		}
+	}
+done:
+	return rc;
+}
+
+static bool taiko_is_hph_pa_on(struct snd_soc_codec *codec)
+{
+	u8 hph_reg_val = 0;
+	hph_reg_val = snd_soc_read(codec, TAIKO_A_RX_HPH_CNP_EN);
+
+	return (hph_reg_val & 0x30) ? true : false;
+}
+
+static bool taiko_is_hph_dac_on(struct snd_soc_codec *codec, int left)
+{
+	u8 hph_reg_val = 0;
+	if (left)
+		hph_reg_val = snd_soc_read(codec,
+					   TAIKO_A_RX_HPH_L_DAC_CTL);
+	else
+		hph_reg_val = snd_soc_read(codec,
+					   TAIKO_A_RX_HPH_R_DAC_CTL);
+
+	return (hph_reg_val & 0xC0) ? true : false;
+}
+
+static void taiko_turn_onoff_override(struct snd_soc_codec *codec, bool on)
+{
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x04, on << 2);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_drive_v_to_micbias(struct snd_soc_codec *codec,
+					   int usec)
+{
+	int cfilt_k_val;
+	bool set = true;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	if (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
+	    taiko->mbhc_micbias_switched) {
+		pr_debug("%s: set mic V to micbias V\n", __func__);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+		taiko_turn_onoff_override(codec, true);
+		while (1) {
+			cfilt_k_val = taiko_find_k_value(
+						taiko->pdata->micbias.ldoh_v,
+						set ? taiko->mbhc_data.micb_mv :
+						      VDDIO_MICBIAS_MV);
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.cfilt_val,
+					    0xFC, (cfilt_k_val << 2));
+			if (!set)
+				break;
+			usleep_range(usec, usec);
+			set = false;
+		}
+		taiko_turn_onoff_override(codec, false);
+	}
+}
+
+/* called under codec_resource_lock acquisition */
+static void __taiko_codec_switch_micbias(struct snd_soc_codec *codec,
+					 int vddio_switch, bool restartpolling,
+					 bool checkpolling)
+{
+	int cfilt_k_val;
+	bool override;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	if (vddio_switch && !taiko->mbhc_micbias_switched &&
+	    (!checkpolling || taiko->mbhc_polling_active)) {
+		if (restartpolling)
+			taiko_codec_pause_hs_polling(codec);
+		override = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B1_CTL) & 0x04;
+		if (!override)
+			taiko_turn_onoff_override(codec, true);
+		/* Adjust threshold if Mic Bias voltage changes */
+		if (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
+			cfilt_k_val = taiko_find_k_value(
+						   taiko->pdata->micbias.ldoh_v,
+						   VDDIO_MICBIAS_MV);
+			usleep_range(10000, 10000);
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.cfilt_val,
+					    0xFC, (cfilt_k_val << 2));
+			usleep_range(10000, 10000);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B1_CTL,
+				      taiko->mbhc_data.adj_v_ins_hu & 0xFF);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B2_CTL,
+				      (taiko->mbhc_data.adj_v_ins_hu >> 8) &
+				       0xFF);
+			pr_debug("%s: Programmed MBHC thresholds to VDDIO\n",
+				 __func__);
+		}
+
+		/* enable MIC BIAS Switch to VDDIO */
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+				    0x80, 0x80);
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+				    0x10, 0x00);
+		if (!override)
+			taiko_turn_onoff_override(codec, false);
+		if (restartpolling)
+			taiko_codec_start_hs_polling(codec);
+
+		taiko->mbhc_micbias_switched = true;
+		pr_debug("%s: VDDIO switch enabled\n", __func__);
+	} else if (!vddio_switch && taiko->mbhc_micbias_switched) {
+		if ((!checkpolling || taiko->mbhc_polling_active) &&
+		    restartpolling)
+			taiko_codec_pause_hs_polling(codec);
+		/* Reprogram thresholds */
+		if (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
+			cfilt_k_val = taiko_find_k_value(
+						   taiko->pdata->micbias.ldoh_v,
+						   taiko->mbhc_data.micb_mv);
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.cfilt_val,
+					    0xFC, (cfilt_k_val << 2));
+			usleep_range(10000, 10000);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B1_CTL,
+				      taiko->mbhc_data.v_ins_hu & 0xFF);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B2_CTL,
+				      (taiko->mbhc_data.v_ins_hu >> 8) & 0xFF);
+			pr_debug("%s: Programmed MBHC thresholds to MICBIAS\n",
+				 __func__);
+		}
+
+		/* Disable MIC BIAS Switch to VDDIO */
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+				    0x80, 0x00);
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+				    0x10, 0x00);
+
+		if ((!checkpolling || taiko->mbhc_polling_active) &&
+		    restartpolling)
+			taiko_codec_start_hs_polling(codec);
+
+		taiko->mbhc_micbias_switched = false;
+		pr_debug("%s: VDDIO switch disabled\n", __func__);
+	}
+}
+
+static void taiko_codec_switch_micbias(struct snd_soc_codec *codec,
+				       int vddio_switch)
+{
+	return __taiko_codec_switch_micbias(codec, vddio_switch, true, true);
+}
+
+static int taiko_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u16 micb_int_reg;
+	int micb_line;
+	u8 cfilt_sel_val = 0;
+	char *internal1_text = "Internal1";
+	char *internal2_text = "Internal2";
+	char *internal3_text = "Internal3";
+
+	pr_debug("%s %d\n", __func__, event);
+	switch (w->reg) {
+	case TAIKO_A_MICB_1_CTL:
+		micb_int_reg = TAIKO_A_MICB_1_INT_RBIAS;
+		cfilt_sel_val = taiko->pdata->micbias.bias1_cfilt_sel;
+		micb_line = TAIKO_MICBIAS1;
+		break;
+	case TAIKO_A_MICB_2_CTL:
+		micb_int_reg = TAIKO_A_MICB_2_INT_RBIAS;
+		cfilt_sel_val = taiko->pdata->micbias.bias2_cfilt_sel;
+		micb_line = TAIKO_MICBIAS2;
+		break;
+	case TAIKO_A_MICB_3_CTL:
+		micb_int_reg = TAIKO_A_MICB_3_INT_RBIAS;
+		cfilt_sel_val = taiko->pdata->micbias.bias3_cfilt_sel;
+		micb_line = TAIKO_MICBIAS3;
+		break;
+	case TAIKO_A_MICB_4_CTL:
+		micb_int_reg = taiko->reg_addr.micb_4_int_rbias;
+		cfilt_sel_val = taiko->pdata->micbias.bias4_cfilt_sel;
+		micb_line = TAIKO_MICBIAS4;
+		break;
+	default:
+		pr_err("%s: Error, invalid micbias register\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Decide whether to switch the micbias for MBHC */
+		if (w->reg == taiko->mbhc_bias_regs.ctl_reg) {
+			TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+			taiko_codec_switch_micbias(codec, 0);
+			TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+		}
+
+		snd_soc_update_bits(codec, w->reg, 0x0E, 0x0A);
+		taiko_codec_update_cfilt_usage(codec, cfilt_sel_val, 1);
+
+		if (strnstr(w->name, internal1_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
+		else if (strnstr(w->name, internal2_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
+		else if (strnstr(w->name, internal3_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
+
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+
+		usleep_range(20000, 20000);
+
+		if (taiko->mbhc_polling_active &&
+		    taiko->mbhc_cfg.micbias == micb_line) {
+			TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+			taiko_codec_pause_hs_polling(codec);
+			taiko_codec_start_hs_polling(codec);
+			TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+		}
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		if ((w->reg == taiko->mbhc_bias_regs.ctl_reg) &&
+		    taiko_is_hph_pa_on(codec)) {
+			TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+			taiko_codec_switch_micbias(codec, 1);
+			TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+		}
+
+		if (strnstr(w->name, internal1_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
+		else if (strnstr(w->name, internal2_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
+		else if (strnstr(w->name, internal3_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
+
+		taiko_codec_update_cfilt_usage(codec, cfilt_sel_val, 0);
+		break;
+	}
+
+	return 0;
+}
+
+
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work;
+	struct hpf_work *hpf_work;
+	struct taiko_priv *taiko;
+	struct snd_soc_codec *codec;
+	u16 tx_mux_ctl_reg;
+	u8 hpf_cut_of_freq;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	taiko = hpf_work->taiko;
+	codec = hpf_work->taiko->codec;
+	hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+	tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL +
+			(hpf_work->decimator - 1) * 8;
+
+	pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
+		hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+
+	snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
+}
+
+#define  TX_MUX_CTL_CUT_OFF_FREQ_MASK	0x30
+#define  CF_MIN_3DB_4HZ			0x0
+#define  CF_MIN_3DB_75HZ		0x1
+#define  CF_MIN_3DB_150HZ		0x2
+
+static int taiko_codec_enable_dec(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	unsigned int decimator;
+	char *dec_name = NULL;
+	char *widget_name = NULL;
+	char *temp;
+	int ret = 0;
+	u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+	u8 dec_hpf_cut_of_freq;
+	int offset;
+
+
+	pr_debug("%s %d\n", __func__, event);
+
+	widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+	if (!widget_name)
+		return -ENOMEM;
+	temp = widget_name;
+
+	dec_name = strsep(&widget_name, " ");
+	widget_name = temp;
+	if (!dec_name) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
+	if (ret < 0) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+			w->name, dec_name, decimator);
+
+	if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
+		dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B1_CTL;
+		offset = 0;
+	} else if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL) {
+		dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B2_CTL;
+		offset = 8;
+	} else {
+		pr_err("%s: Error, incorrect dec\n", __func__);
+		return -EINVAL;
+	}
+
+	tx_vol_ctl_reg = TAIKO_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
+	tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+
+		/* Enableable TX digital mute */
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+
+		snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
+			1 << w->shift);
+		snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+
+		dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
+
+		dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
+
+		tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+			dec_hpf_cut_of_freq;
+
+		if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
+
+			/* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
+			snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+					    CF_MIN_3DB_150HZ << 4);
+		}
+
+		/* enable HPF */
+		snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
+
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+
+		/* Disable TX digital mute */
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
+
+		if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+				CF_MIN_3DB_150HZ) {
+
+			schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+					msecs_to_jiffies(300));
+		}
+		/* apply the digital gain after the decimator is enabled*/
+		if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+			snd_soc_write(codec,
+				  tx_digital_gain_reg[w->shift + offset],
+				  snd_soc_read(codec,
+				  tx_digital_gain_reg[w->shift + offset])
+				  );
+
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+		cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+			(tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+
+		break;
+	}
+out:
+	kfree(widget_name);
+	return ret;
+}
+
+static int taiko_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_debug("%s %d %s\n", __func__, event, w->name);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
+			1 << w->shift, 1 << w->shift);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
+			1 << w->shift, 0x0);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* apply the digital gain after the interpolator is enabled*/
+		if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+			snd_soc_write(codec,
+				  rx_digital_gain_reg[w->shift],
+				  snd_soc_read(codec,
+				  rx_digital_gain_reg[w->shift])
+				  );
+		break;
+	}
+	return 0;
+}
+
+static int taiko_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+	case SND_SOC_DAPM_POST_PMD:
+		usleep_range(1000, 1000);
+		break;
+	}
+	return 0;
+}
+
+static int taiko_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_debug("%s %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		taiko_enable_rx_bias(codec, 1);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		taiko_enable_rx_bias(codec, 0);
+		break;
+	}
+	return 0;
+}
+static int taiko_hphr_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_debug("%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static void taiko_snd_soc_jack_report(struct taiko_priv *taiko,
+				      struct snd_soc_jack *jack, int status,
+				      int mask)
+{
+	/* XXX: wake_lock_timeout()? */
+	snd_soc_jack_report_no_dapm(jack, status, mask);
+}
+
+static void hphocp_off_report(struct taiko_priv *taiko,
+	u32 jack_status, int irq)
+{
+	struct snd_soc_codec *codec;
+	if (!taiko) {
+		pr_err("%s: Bad taiko private data\n", __func__);
+		return;
+	}
+
+	pr_debug("%s: clear ocp status %x\n", __func__, jack_status);
+	codec = taiko->codec;
+	if (taiko->hph_status & jack_status) {
+		taiko->hph_status &= ~jack_status;
+		if (taiko->mbhc_cfg.headset_jack)
+			taiko_snd_soc_jack_report(taiko,
+						  taiko->mbhc_cfg.headset_jack,
+						  taiko->hph_status,
+						  TAIKO_JACK_MASK);
+		snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10, 0x10);
+		/* reset retry counter as PA is turned off signifying
+		 * start of new OCP detection session
+		 */
+		if (TAIKO_IRQ_HPH_PA_OCPL_FAULT)
+			taiko->hphlocp_cnt = 0;
+		else
+			taiko->hphrocp_cnt = 0;
+		wcd9xxx_enable_irq(codec->control_data, irq);
+	}
+}
+
+static void hphlocp_off_report(struct work_struct *work)
+{
+	struct taiko_priv *taiko = container_of(work, struct taiko_priv,
+		hphlocp_work);
+	hphocp_off_report(taiko, SND_JACK_OC_HPHL, TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+}
+
+static void hphrocp_off_report(struct work_struct *work)
+{
+	struct taiko_priv *taiko = container_of(work, struct taiko_priv,
+		hphrocp_work);
+	hphocp_off_report(taiko, SND_JACK_OC_HPHR, TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+}
+
+static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u8 mbhc_micb_ctl_val;
+	pr_debug("%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mbhc_micb_ctl_val = snd_soc_read(codec,
+				taiko->mbhc_bias_regs.ctl_reg);
+
+		if (!(mbhc_micb_ctl_val & 0x80)) {
+			TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+			taiko_codec_switch_micbias(codec, 1);
+			TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+		}
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		/* schedule work is required because at the time HPH PA DAPM
+		 * event callback is called by DAPM framework, CODEC dapm mutex
+		 * would have been locked while snd_soc_jack_report also
+		 * attempts to acquire same lock.
+		 */
+		if (w->shift == 5) {
+			clear_bit(TAIKO_HPHL_PA_OFF_ACK,
+				  &taiko->hph_pa_dac_state);
+			clear_bit(TAIKO_HPHL_DAC_OFF_ACK,
+				  &taiko->hph_pa_dac_state);
+			if (taiko->hph_status & SND_JACK_OC_HPHL)
+				schedule_work(&taiko->hphlocp_work);
+		} else if (w->shift == 4) {
+			clear_bit(TAIKO_HPHR_PA_OFF_ACK,
+				  &taiko->hph_pa_dac_state);
+			clear_bit(TAIKO_HPHR_DAC_OFF_ACK,
+				  &taiko->hph_pa_dac_state);
+			if (taiko->hph_status & SND_JACK_OC_HPHR)
+				schedule_work(&taiko->hphrocp_work);
+		}
+
+		TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+		taiko_codec_switch_micbias(codec, 0);
+		TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+
+		pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
+				w->name);
+		usleep_range(10000, 10000);
+		break;
+	}
+	return 0;
+}
+
+static void taiko_get_mbhc_micbias_regs(struct snd_soc_codec *codec,
+					struct mbhc_micbias_regs *micbias_regs)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	unsigned int cfilt;
+
+	switch (taiko->mbhc_cfg.micbias) {
+	case TAIKO_MICBIAS1:
+		cfilt = taiko->pdata->micbias.bias1_cfilt_sel;
+		micbias_regs->mbhc_reg = TAIKO_A_MICB_1_MBHC;
+		micbias_regs->int_rbias = TAIKO_A_MICB_1_INT_RBIAS;
+		micbias_regs->ctl_reg = TAIKO_A_MICB_1_CTL;
+		break;
+	case TAIKO_MICBIAS2:
+		cfilt = taiko->pdata->micbias.bias2_cfilt_sel;
+		micbias_regs->mbhc_reg = TAIKO_A_MICB_2_MBHC;
+		micbias_regs->int_rbias = TAIKO_A_MICB_2_INT_RBIAS;
+		micbias_regs->ctl_reg = TAIKO_A_MICB_2_CTL;
+		break;
+	case TAIKO_MICBIAS3:
+		cfilt = taiko->pdata->micbias.bias3_cfilt_sel;
+		micbias_regs->mbhc_reg = TAIKO_A_MICB_3_MBHC;
+		micbias_regs->int_rbias = TAIKO_A_MICB_3_INT_RBIAS;
+		micbias_regs->ctl_reg = TAIKO_A_MICB_3_CTL;
+		break;
+	case TAIKO_MICBIAS4:
+		cfilt = taiko->pdata->micbias.bias4_cfilt_sel;
+		micbias_regs->mbhc_reg = taiko->reg_addr.micb_4_mbhc;
+		micbias_regs->int_rbias = taiko->reg_addr.micb_4_int_rbias;
+		micbias_regs->ctl_reg = taiko->reg_addr.micb_4_ctl;
+		break;
+	default:
+		/* Should never reach here */
+		pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__);
+		return;
+	}
+
+	micbias_regs->cfilt_sel = cfilt;
+
+	switch (cfilt) {
+	case TAIKO_CFILT1_SEL:
+		micbias_regs->cfilt_val = TAIKO_A_MICB_CFILT_1_VAL;
+		micbias_regs->cfilt_ctl = TAIKO_A_MICB_CFILT_1_CTL;
+		taiko->mbhc_data.micb_mv = taiko->pdata->micbias.cfilt1_mv;
+		break;
+	case TAIKO_CFILT2_SEL:
+		micbias_regs->cfilt_val = TAIKO_A_MICB_CFILT_2_VAL;
+		micbias_regs->cfilt_ctl = TAIKO_A_MICB_CFILT_2_CTL;
+		taiko->mbhc_data.micb_mv = taiko->pdata->micbias.cfilt2_mv;
+		break;
+	case TAIKO_CFILT3_SEL:
+		micbias_regs->cfilt_val = TAIKO_A_MICB_CFILT_3_VAL;
+		micbias_regs->cfilt_ctl = TAIKO_A_MICB_CFILT_3_CTL;
+		taiko->mbhc_data.micb_mv = taiko->pdata->micbias.cfilt3_mv;
+		break;
+	}
+}
+static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
+	SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
+	4, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TAIKO_A_CDC_CLK_TX_I2S_CTL, 4,
+	0, NULL, 0),
+};
+
+static int taiko_lineout_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_debug("%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_route audio_i2s_map[] = {
+	{"RX_I2S_CLK", NULL, "CDC_CONN"},
+	{"SLIM RX1", NULL, "RX_I2S_CLK"},
+	{"SLIM RX2", NULL, "RX_I2S_CLK"},
+	{"SLIM RX3", NULL, "RX_I2S_CLK"},
+	{"SLIM RX4", NULL, "RX_I2S_CLK"},
+
+	{"SLIM TX7", NULL, "TX_I2S_CLK"},
+	{"SLIM TX8", NULL, "TX_I2S_CLK"},
+	{"SLIM TX9", NULL, "TX_I2S_CLK"},
+	{"SLIM TX10", NULL, "TX_I2S_CLK"},
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* SLIMBUS Connections */
+
+	{"SLIM TX1", NULL, "SLIM TX1 MUX"},
+	{"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
+
+	{"SLIM TX2", NULL, "SLIM TX2 MUX"},
+	{"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
+
+	{"SLIM TX3", NULL, "SLIM TX3 MUX"},
+	{"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
+
+	{"SLIM TX4", NULL, "SLIM TX4 MUX"},
+	{"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
+
+	{"SLIM TX5", NULL, "SLIM TX5 MUX"},
+	{"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
+
+	{"SLIM TX6", NULL, "SLIM TX6 MUX"},
+	{"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
+
+	{"SLIM TX7", NULL, "SLIM TX7 MUX"},
+	{"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
+	{"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
+	{"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
+	{"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
+	{"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
+	{"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
+
+	{"SLIM TX8", NULL, "SLIM TX8 MUX"},
+	{"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
+	{"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
+	{"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
+	{"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
+	{"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
+
+	{"SLIM TX9", NULL, "SLIM TX9 MUX"},
+	{"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
+	{"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
+	{"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
+	{"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
+	{"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
+
+	{"SLIM TX10", NULL, "SLIM TX10 MUX"},
+	{"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
+	{"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
+	{"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
+	{"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
+	{"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
+
+	/* Earpiece (RX MIX1) */
+	{"EAR", NULL, "EAR PA"},
+	{"EAR PA", NULL, "EAR_PA_MIXER"},
+	{"EAR_PA_MIXER", NULL, "DAC1"},
+	{"DAC1", NULL, "CP"},
+
+	{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
+	{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
+	{"ANC", NULL, "ANC1 FB MUX"},
+
+	/* Headset (RX MIX1 and RX MIX2) */
+	{"HEADPHONE", NULL, "HPHL"},
+	{"HEADPHONE", NULL, "HPHR"},
+
+	{"HPHL", NULL, "HPHL_PA_MIXER"},
+	{"HPHL_PA_MIXER", NULL, "HPHL DAC"},
+
+	{"HPHR", NULL, "HPHR_PA_MIXER"},
+	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
+
+	{"HPHL DAC", NULL, "CP"},
+	{"HPHR DAC", NULL, "CP"},
+
+	{"ANC", NULL, "ANC1 MUX"},
+	{"ANC", NULL, "ANC2 MUX"},
+	{"ANC1 MUX", "ADC1", "ADC1"},
+	{"ANC1 MUX", "ADC2", "ADC2"},
+	{"ANC1 MUX", "ADC3", "ADC3"},
+	{"ANC1 MUX", "ADC4", "ADC4"},
+	{"ANC2 MUX", "ADC1", "ADC1"},
+	{"ANC2 MUX", "ADC2", "ADC2"},
+	{"ANC2 MUX", "ADC3", "ADC3"},
+	{"ANC2 MUX", "ADC4", "ADC4"},
+
+	{"ANC", NULL, "CDC_CONN"},
+
+	{"DAC1", "Switch", "RX1 CHAIN"},
+	{"HPHL DAC", "Switch", "RX1 CHAIN"},
+	{"HPHR DAC", NULL, "RX2 CHAIN"},
+
+	{"LINEOUT1", NULL, "LINEOUT1 PA"},
+	{"LINEOUT2", NULL, "LINEOUT2 PA"},
+	{"LINEOUT3", NULL, "LINEOUT3 PA"},
+	{"LINEOUT4", NULL, "LINEOUT4 PA"},
+
+	{"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
+	{"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
+	{"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
+	{"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
+	{"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
+	{"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
+	{"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
+	{"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
+
+	{"LINEOUT1 DAC", NULL, "RX3 MIX1"},
+
+	{"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
+	{"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
+	{"LINEOUT3 DAC", NULL, "RX4 DSM MUX"},
+
+	{"LINEOUT2 DAC", NULL, "RX5 MIX1"},
+
+	{"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
+	{"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
+	{"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
+
+	{"RX1 CHAIN", NULL, "RX1 MIX2"},
+	{"RX2 CHAIN", NULL, "RX2 MIX2"},
+	{"RX1 CHAIN", NULL, "ANC"},
+	{"RX2 CHAIN", NULL, "ANC"},
+
+	{"CP", NULL, "RX_BIAS"},
+	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
+	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
+	{"LINEOUT3 DAC", NULL, "RX_BIAS"},
+	{"LINEOUT4 DAC", NULL, "RX_BIAS"},
+
+	{"RX1 MIX1", NULL, "COMP1_CLK"},
+	{"RX2 MIX1", NULL, "COMP1_CLK"},
+	{"RX3 MIX1", NULL, "COMP2_CLK"},
+	{"RX5 MIX1", NULL, "COMP2_CLK"},
+
+
+	{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
+	{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
+	{"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
+	{"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
+	{"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
+	{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+	{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+	{"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
+	{"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
+	{"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
+	{"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
+	{"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
+	{"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
+	{"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
+	{"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
+	{"RX1 MIX2", NULL, "RX1 MIX1"},
+	{"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
+	{"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
+	{"RX2 MIX2", NULL, "RX2 MIX1"},
+	{"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
+	{"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
+	{"RX7 MIX2", NULL, "RX7 MIX1"},
+	{"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
+	{"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
+
+	{"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX1 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX1 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
+	{"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
+	{"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
+	{"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
+	{"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
+	{"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX2 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX2 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX3 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX3 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX4 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX4 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX5 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX5 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX6 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX6 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX7 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX7 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX1 MIX2 INP1", "IIR1", "IIR1"},
+	{"RX1 MIX2 INP2", "IIR1", "IIR1"},
+	{"RX2 MIX2 INP1", "IIR1", "IIR1"},
+	{"RX2 MIX2 INP2", "IIR1", "IIR1"},
+	{"RX7 MIX2 INP1", "IIR1", "IIR1"},
+	{"RX7 MIX2 INP2", "IIR1", "IIR1"},
+
+	/* Decimator Inputs */
+	{"DEC1 MUX", "DMIC1", "DMIC1"},
+	{"DEC1 MUX", "ADC6", "ADC6"},
+	{"DEC1 MUX", NULL, "CDC_CONN"},
+	{"DEC2 MUX", "DMIC2", "DMIC2"},
+	{"DEC2 MUX", "ADC5", "ADC5"},
+	{"DEC2 MUX", NULL, "CDC_CONN"},
+	{"DEC3 MUX", "DMIC3", "DMIC3"},
+	{"DEC3 MUX", "ADC4", "ADC4"},
+	{"DEC3 MUX", NULL, "CDC_CONN"},
+	{"DEC4 MUX", "DMIC4", "DMIC4"},
+	{"DEC4 MUX", "ADC3", "ADC3"},
+	{"DEC4 MUX", NULL, "CDC_CONN"},
+	{"DEC5 MUX", "DMIC5", "DMIC5"},
+	{"DEC5 MUX", "ADC2", "ADC2"},
+	{"DEC5 MUX", NULL, "CDC_CONN"},
+	{"DEC6 MUX", "DMIC6", "DMIC6"},
+	{"DEC6 MUX", "ADC1", "ADC1"},
+	{"DEC6 MUX", NULL, "CDC_CONN"},
+	{"DEC7 MUX", "DMIC1", "DMIC1"},
+	{"DEC7 MUX", "DMIC6", "DMIC6"},
+	{"DEC7 MUX", "ADC1", "ADC1"},
+	{"DEC7 MUX", "ADC6", "ADC6"},
+	{"DEC7 MUX", NULL, "CDC_CONN"},
+	{"DEC8 MUX", "DMIC2", "DMIC2"},
+	{"DEC8 MUX", "DMIC5", "DMIC5"},
+	{"DEC8 MUX", "ADC2", "ADC2"},
+	{"DEC8 MUX", "ADC5", "ADC5"},
+	{"DEC8 MUX", NULL, "CDC_CONN"},
+	{"DEC9 MUX", "DMIC4", "DMIC4"},
+	{"DEC9 MUX", "DMIC5", "DMIC5"},
+	{"DEC9 MUX", "ADC2", "ADC2"},
+	{"DEC9 MUX", "ADC3", "ADC3"},
+	{"DEC9 MUX", NULL, "CDC_CONN"},
+	{"DEC10 MUX", "DMIC3", "DMIC3"},
+	{"DEC10 MUX", "DMIC6", "DMIC6"},
+	{"DEC10 MUX", "ADC1", "ADC1"},
+	{"DEC10 MUX", "ADC4", "ADC4"},
+	{"DEC10 MUX", NULL, "CDC_CONN"},
+
+	/* ADC Connections */
+	{"ADC1", NULL, "AMIC1"},
+	{"ADC2", NULL, "AMIC2"},
+	{"ADC3", NULL, "AMIC3"},
+	{"ADC4", NULL, "AMIC4"},
+	{"ADC5", NULL, "AMIC5"},
+	{"ADC6", NULL, "AMIC6"},
+
+	/* AUX PGA Connections */
+	{"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"HPHL_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"HPHL_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+	{"HPHL_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+	{"HPHR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"HPHR_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+	{"HPHR_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+	{"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"LINEOUT1_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"LINEOUT1_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+	{"LINEOUT1_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+	{"LINEOUT2_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"LINEOUT2_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+	{"LINEOUT2_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+	{"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"LINEOUT3_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"LINEOUT3_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+	{"LINEOUT3_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+	{"LINEOUT4_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"LINEOUT4_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+	{"LINEOUT4_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+	{"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"EAR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"EAR_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+	{"EAR_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+	{"AUX_PGA_Left", NULL, "AMIC5"},
+	{"AUX_PGA_Right", NULL, "AMIC6"},
+
+
+	{"IIR1", NULL, "IIR1 INP1 MUX"},
+	{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
+	{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
+	{"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
+	{"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
+	{"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
+	{"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
+	{"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
+	{"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
+	{"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
+	{"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
+
+	{"MIC BIAS1 Internal1", NULL, "LDO_H"},
+	{"MIC BIAS1 Internal2", NULL, "LDO_H"},
+	{"MIC BIAS1 External", NULL, "LDO_H"},
+	{"MIC BIAS2 Internal1", NULL, "LDO_H"},
+	{"MIC BIAS2 Internal2", NULL, "LDO_H"},
+	{"MIC BIAS2 Internal3", NULL, "LDO_H"},
+	{"MIC BIAS2 External", NULL, "LDO_H"},
+	{"MIC BIAS3 Internal1", NULL, "LDO_H"},
+	{"MIC BIAS3 Internal2", NULL, "LDO_H"},
+	{"MIC BIAS3 External", NULL, "LDO_H"},
+	{"MIC BIAS4 External", NULL, "LDO_H"},
+};
+
+static int taiko_readable(struct snd_soc_codec *ssc, unsigned int reg)
+{
+	return taiko_reg_readable[reg];
+}
+
+static bool taiko_is_digital_gain_register(unsigned int reg)
+{
+	bool rtn = false;
+	switch (reg) {
+	case TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL:
+	case TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL:
+	case TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL:
+	case TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL:
+	case TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL:
+	case TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL:
+	case TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL:
+	case TAIKO_A_CDC_TX1_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX2_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX3_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX4_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX5_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX6_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX7_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX8_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX9_VOL_CTL_GAIN:
+	case TAIKO_A_CDC_TX10_VOL_CTL_GAIN:
+		rtn = true;
+		break;
+	default:
+		break;
+	}
+	return rtn;
+}
+
+static int taiko_volatile(struct snd_soc_codec *ssc, unsigned int reg)
+{
+	/* Registers lower than 0x100 are top level registers which can be
+	 * written by the Taiko core driver.
+	 */
+
+	if ((reg >= TAIKO_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
+		return 1;
+
+	/* IIR Coeff registers are not cacheable */
+	if ((reg >= TAIKO_A_CDC_IIR1_COEF_B1_CTL) &&
+		(reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
+		return 1;
+
+	/* Digital gain register is not cacheable so we have to write
+	 * the setting even it is the same
+	 */
+	if (taiko_is_digital_gain_register(reg))
+		return 1;
+
+	/* HPH status registers */
+	if (reg == TAIKO_A_RX_HPH_L_STATUS || reg == TAIKO_A_RX_HPH_R_STATUS)
+		return 1;
+
+	return 0;
+}
+
+#define TAIKO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+static int taiko_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int value)
+{
+	int ret;
+	BUG_ON(reg > TAIKO_MAX_REGISTER);
+
+	if (!taiko_volatile(codec, reg)) {
+		ret = snd_soc_cache_write(codec, reg, value);
+		if (ret != 0)
+			dev_err(codec->dev, "Cache write to %x failed: %d\n",
+				reg, ret);
+	}
+
+	return wcd9xxx_reg_write(codec->control_data, reg, value);
+}
+static unsigned int taiko_read(struct snd_soc_codec *codec,
+				unsigned int reg)
+{
+	unsigned int val;
+	int ret;
+
+	BUG_ON(reg > TAIKO_MAX_REGISTER);
+
+	if (!taiko_volatile(codec, reg) && taiko_readable(codec, reg) &&
+		reg < codec->driver->reg_cache_size) {
+		ret = snd_soc_cache_read(codec, reg, &val);
+		if (ret >= 0) {
+			return val;
+		} else
+			dev_err(codec->dev, "Cache read from %x failed: %d\n",
+				reg, ret);
+	}
+
+	val = wcd9xxx_reg_read(codec->control_data, reg);
+	return val;
+}
+
+static s16 taiko_get_current_v_ins(struct taiko_priv *taiko, bool hu)
+{
+	s16 v_ins;
+	if ((taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) &&
+	    taiko->mbhc_micbias_switched)
+		v_ins = hu ? (s16)taiko->mbhc_data.adj_v_ins_hu :
+			     (s16)taiko->mbhc_data.adj_v_ins_h;
+	else
+		v_ins = hu ? (s16)taiko->mbhc_data.v_ins_hu :
+			     (s16)taiko->mbhc_data.v_ins_h;
+	return v_ins;
+}
+
+static s16 taiko_get_current_v_hs_max(struct taiko_priv *taiko)
+{
+	s16 v_hs_max;
+	struct taiko_mbhc_plug_type_cfg *plug_type;
+
+	plug_type = TAIKO_MBHC_CAL_PLUG_TYPE_PTR(taiko->mbhc_cfg.calibration);
+	if ((taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) &&
+	    taiko->mbhc_micbias_switched)
+		v_hs_max = taiko->mbhc_data.adj_v_hs_max;
+	else
+		v_hs_max = plug_type->v_hs_max;
+	return v_hs_max;
+}
+
+static void taiko_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
+{
+	u8 *n_ready, *n_cic;
+	struct taiko_mbhc_btn_detect_cfg *btn_det;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	const s16 v_ins_hu = taiko_get_current_v_ins(taiko, true);
+
+	btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(taiko->mbhc_cfg.calibration);
+
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B1_CTL,
+		      v_ins_hu & 0xFF);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B2_CTL,
+		      (v_ins_hu >> 8) & 0xFF);
+
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B3_CTL,
+		      taiko->mbhc_data.v_b1_hu & 0xFF);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B4_CTL,
+		      (taiko->mbhc_data.v_b1_hu >> 8) & 0xFF);
+
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B5_CTL,
+		      taiko->mbhc_data.v_b1_h & 0xFF);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B6_CTL,
+		      (taiko->mbhc_data.v_b1_h >> 8) & 0xFF);
+
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B9_CTL,
+		      taiko->mbhc_data.v_brh & 0xFF);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B10_CTL,
+		      (taiko->mbhc_data.v_brh >> 8) & 0xFF);
+
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B11_CTL,
+		      taiko->mbhc_data.v_brl & 0xFF);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B12_CTL,
+		      (taiko->mbhc_data.v_brl >> 8) & 0xFF);
+
+	n_ready = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_READY);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B1_CTL,
+		      n_ready[taiko_codec_mclk_index(taiko)]);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B2_CTL,
+		      taiko->mbhc_data.npoll);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B3_CTL,
+		      taiko->mbhc_data.nbounce_wait);
+	n_cic = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_CIC);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B6_CTL,
+		      n_cic[taiko_codec_mclk_index(taiko)]);
+}
+
+static int taiko_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
+	pr_debug("%s(): substream = %s  stream = %d\n" , __func__,
+		 substream->name, substream->stream);
+	if ((taiko_core != NULL) &&
+	    (taiko_core->dev != NULL) &&
+	    (taiko_core->dev->parent != NULL))
+		pm_runtime_get_sync(taiko_core->dev->parent);
+
+	return 0;
+}
+
+static void taiko_shutdown(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
+	pr_debug("%s(): substream = %s  stream = %d\n" , __func__,
+		 substream->name, substream->stream);
+	if ((taiko_core != NULL) &&
+	    (taiko_core->dev != NULL) &&
+	    (taiko_core->dev->parent != NULL)) {
+		pm_runtime_mark_last_busy(taiko_core->dev->parent);
+		pm_runtime_put(taiko_core->dev->parent);
+	}
+}
+
+int taiko_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: mclk_enable = %u, dapm = %d\n", __func__, mclk_enable,
+		 dapm);
+	if (dapm)
+		TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+	if (mclk_enable) {
+		taiko->mclk_enabled = true;
+
+		if (taiko->mbhc_polling_active) {
+			taiko_codec_pause_hs_polling(codec);
+			taiko_codec_disable_clock_block(codec);
+			taiko_codec_enable_bandgap(codec,
+						   TAIKO_BANDGAP_AUDIO_MODE);
+			taiko_codec_enable_clock_block(codec, 0);
+			taiko_codec_calibrate_hs_polling(codec);
+			taiko_codec_start_hs_polling(codec);
+		} else {
+			taiko_codec_disable_clock_block(codec);
+			taiko_codec_enable_bandgap(codec,
+						   TAIKO_BANDGAP_AUDIO_MODE);
+			taiko_codec_enable_clock_block(codec, 0);
+		}
+	} else {
+
+		if (!taiko->mclk_enabled) {
+			if (dapm)
+				TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+			pr_err("Error, MCLK already diabled\n");
+			return -EINVAL;
+		}
+		taiko->mclk_enabled = false;
+
+		if (taiko->mbhc_polling_active) {
+			taiko_codec_pause_hs_polling(codec);
+			taiko_codec_disable_clock_block(codec);
+			taiko_codec_enable_bandgap(codec,
+						   TAIKO_BANDGAP_MBHC_MODE);
+			taiko_enable_rx_bias(codec, 1);
+			taiko_codec_enable_clock_block(codec, 1);
+			taiko_codec_calibrate_hs_polling(codec);
+			taiko_codec_start_hs_polling(codec);
+			snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1,
+					0x05, 0x01);
+		} else {
+			taiko_codec_disable_clock_block(codec);
+			taiko_codec_enable_bandgap(codec,
+						   TAIKO_BANDGAP_OFF);
+		}
+	}
+	if (dapm)
+		TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+	return 0;
+}
+
+static int taiko_set_dai_sysclk(struct snd_soc_dai *dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	pr_debug("%s\n", __func__);
+	return 0;
+}
+
+static int taiko_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	u8 val = 0;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
+
+	pr_debug("%s\n", __func__);
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		/* CPU is master */
+		if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			if (dai->id == AIF1_CAP)
+				snd_soc_update_bits(dai->codec,
+					TAIKO_A_CDC_CLK_TX_I2S_CTL,
+					TAIKO_I2S_MASTER_MODE_MASK, 0);
+			else if (dai->id == AIF1_PB)
+				snd_soc_update_bits(dai->codec,
+					TAIKO_A_CDC_CLK_RX_I2S_CTL,
+					TAIKO_I2S_MASTER_MODE_MASK, 0);
+		}
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+	/* CPU is slave */
+		if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			val = TAIKO_I2S_MASTER_MODE_MASK;
+			if (dai->id == AIF1_CAP)
+				snd_soc_update_bits(dai->codec,
+					TAIKO_A_CDC_CLK_TX_I2S_CTL, val, val);
+			else if (dai->id == AIF1_PB)
+				snd_soc_update_bits(dai->codec,
+					TAIKO_A_CDC_CLK_RX_I2S_CTL, val, val);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int taiko_set_channel_map(struct snd_soc_dai *dai,
+				unsigned int tx_num, unsigned int *tx_slot,
+				unsigned int rx_num, unsigned int *rx_slot)
+
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
+	u32 i = 0;
+	if (!tx_slot && !rx_slot) {
+		pr_err("%s: Invalid\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n",
+			__func__, dai->name, dai->id, tx_num, rx_num);
+
+	if (dai->id == AIF1_PB || dai->id == AIF2_PB || dai->id == AIF3_PB) {
+		for (i = 0; i < rx_num; i++) {
+			taiko->dai[dai->id - 1].ch_num[i]  = rx_slot[i];
+			taiko->dai[dai->id - 1].ch_act = 0;
+			taiko->dai[dai->id - 1].ch_tot = rx_num;
+		}
+	} else if (dai->id == AIF1_CAP || dai->id == AIF2_CAP ||
+		   dai->id == AIF3_CAP) {
+		for (i = 0; i < tx_num; i++) {
+			taiko->dai[dai->id - 1].ch_num[i]  = tx_slot[i];
+			taiko->dai[dai->id - 1].ch_act = 0;
+			taiko->dai[dai->id - 1].ch_tot = tx_num;
+		}
+	}
+	return 0;
+}
+
+static int taiko_get_channel_map(struct snd_soc_dai *dai,
+				unsigned int *tx_num, unsigned int *tx_slot,
+				unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+	struct wcd9xxx *taiko = dev_get_drvdata(dai->codec->control_data);
+
+	u32 cnt = 0;
+	u32 tx_ch[SLIM_MAX_TX_PORTS];
+	u32 rx_ch[SLIM_MAX_RX_PORTS];
+
+	if (!rx_slot && !tx_slot) {
+		pr_err("%s: Invalid\n", __func__);
+		return -EINVAL;
+	}
+
+	/* for virtual port, codec driver needs to do
+	 * housekeeping, for now should be ok
+	 */
+	wcd9xxx_get_channel(taiko, rx_ch, tx_ch);
+	if (dai->id == AIF1_PB) {
+		*rx_num = taiko_dai[dai->id - 1].playback.channels_max;
+		while (cnt < *rx_num) {
+			rx_slot[cnt] = rx_ch[cnt];
+			cnt++;
+		}
+	} else if (dai->id == AIF1_CAP) {
+		*tx_num = taiko_dai[dai->id - 1].capture.channels_max;
+		while (cnt < *tx_num) {
+			tx_slot[cnt] = tx_ch[6 + cnt];
+			cnt++;
+		}
+	} else if (dai->id == AIF2_PB) {
+		*rx_num = taiko_dai[dai->id - 1].playback.channels_max;
+		while (cnt < *rx_num) {
+			rx_slot[cnt] = rx_ch[5 + cnt];
+			cnt++;
+		}
+	} else if (dai->id == AIF2_CAP) {
+		*tx_num = taiko_dai[dai->id - 1].capture.channels_max;
+		tx_slot[0] = tx_ch[cnt];
+		tx_slot[1] = tx_ch[1 + cnt];
+		tx_slot[2] = tx_ch[5 + cnt];
+		tx_slot[3] = tx_ch[3 + cnt];
+
+	} else if (dai->id == AIF3_PB) {
+		*rx_num = taiko_dai[dai->id - 1].playback.channels_max;
+		rx_slot[0] = rx_ch[3];
+		rx_slot[1] = rx_ch[4];
+
+	} else if (dai->id == AIF3_CAP) {
+		*tx_num = taiko_dai[dai->id - 1].capture.channels_max;
+		tx_slot[cnt] = tx_ch[2 + cnt];
+		tx_slot[cnt + 1] = tx_ch[4 + cnt];
+	}
+	pr_debug("%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n",
+			__func__, dai->name, dai->id, *tx_num, *rx_num);
+
+
+	return 0;
+}
+
+static int taiko_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
+	u8 path, shift;
+	u16 tx_fs_reg, rx_fs_reg;
+	u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
+	u32 compander_fs;
+
+	pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+		 dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	switch (params_rate(params)) {
+	case 8000:
+		tx_fs_rate = 0x00;
+		rx_fs_rate = 0x00;
+		compander_fs = COMPANDER_FS_8KHZ;
+		break;
+	case 16000:
+		tx_fs_rate = 0x01;
+		rx_fs_rate = 0x20;
+		compander_fs = COMPANDER_FS_16KHZ;
+		break;
+	case 32000:
+		tx_fs_rate = 0x02;
+		rx_fs_rate = 0x40;
+		compander_fs = COMPANDER_FS_32KHZ;
+		break;
+	case 48000:
+		tx_fs_rate = 0x03;
+		rx_fs_rate = 0x60;
+		compander_fs = COMPANDER_FS_48KHZ;
+		break;
+	case 96000:
+		tx_fs_rate = 0x04;
+		rx_fs_rate = 0x80;
+		compander_fs = COMPANDER_FS_96KHZ;
+		break;
+	case 192000:
+		tx_fs_rate = 0x05;
+		rx_fs_rate = 0xA0;
+		compander_fs = COMPANDER_FS_192KHZ;
+		break;
+	default:
+		pr_err("%s: Invalid sampling rate %d\n", __func__,
+				params_rate(params));
+		return -EINVAL;
+	}
+
+
+	/**
+	 * If current dai is a tx dai, set sample rate to
+	 * all the txfe paths that are currently not active
+	 */
+	if ((dai->id == AIF1_CAP) || (dai->id == AIF2_CAP) ||
+	    (dai->id == AIF3_CAP)) {
+
+		tx_state = snd_soc_read(codec,
+				TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL);
+
+		for (path = 1, shift = 0;
+				path <= NUM_DECIMATORS; path++, shift++) {
+
+			if (path == BITS_PER_REG + 1) {
+				shift = 0;
+				tx_state = snd_soc_read(codec,
+					TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL);
+			}
+
+			if (!(tx_state & (1 << shift))) {
+				tx_fs_reg = TAIKO_A_CDC_TX1_CLK_FS_CTL
+						+ (BITS_PER_REG*(path-1));
+				snd_soc_update_bits(codec, tx_fs_reg,
+							0x07, tx_fs_rate);
+			}
+		}
+		if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					TAIKO_A_CDC_CLK_TX_I2S_CTL,
+					0x20, 0x20);
+				break;
+			case SNDRV_PCM_FORMAT_S32_LE:
+				snd_soc_update_bits(codec,
+					TAIKO_A_CDC_CLK_TX_I2S_CTL,
+					0x20, 0x00);
+				break;
+			default:
+				pr_err("invalid format\n");
+				break;
+			}
+			snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_I2S_CTL,
+						0x07, tx_fs_rate);
+		} else {
+			taiko->dai[dai->id - 1].rate   = params_rate(params);
+		}
+	}
+	/**
+	 * TODO: Need to handle case where same RX chain takes 2 or more inputs
+	 * with varying sample rates
+	 */
+
+	/**
+	 * If current dai is a rx dai, set sample rate to
+	 * all the rx paths that are currently not active
+	 */
+	if (dai->id == AIF1_PB || dai->id == AIF2_PB || dai->id == AIF3_PB) {
+
+		rx_state = snd_soc_read(codec,
+			TAIKO_A_CDC_CLK_RX_B1_CTL);
+
+		for (path = 1, shift = 0;
+				path <= NUM_INTERPOLATORS; path++, shift++) {
+
+			if (!(rx_state & (1 << shift))) {
+				rx_fs_reg = TAIKO_A_CDC_RX1_B5_CTL
+						+ (BITS_PER_REG*(path-1));
+				snd_soc_update_bits(codec, rx_fs_reg,
+						0xE0, rx_fs_rate);
+				if (comp_rx_path[shift] < COMPANDER_MAX)
+					taiko->comp_fs[comp_rx_path[shift]]
+					= compander_fs;
+			}
+		}
+		if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					TAIKO_A_CDC_CLK_RX_I2S_CTL,
+					0x20, 0x20);
+				break;
+			case SNDRV_PCM_FORMAT_S32_LE:
+				snd_soc_update_bits(codec,
+					TAIKO_A_CDC_CLK_RX_I2S_CTL,
+					0x20, 0x00);
+				break;
+			default:
+				pr_err("invalid format\n");
+				break;
+			}
+			snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_I2S_CTL,
+						0x03, (rx_fs_rate >> 0x05));
+		} else {
+			taiko->dai[dai->id - 1].rate   = params_rate(params);
+		}
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops taiko_dai_ops = {
+	.startup = taiko_startup,
+	.shutdown = taiko_shutdown,
+	.hw_params = taiko_hw_params,
+	.set_sysclk = taiko_set_dai_sysclk,
+	.set_fmt = taiko_set_dai_fmt,
+	.set_channel_map = taiko_set_channel_map,
+	.get_channel_map = taiko_get_channel_map,
+};
+
+static struct snd_soc_dai_driver taiko_dai[] = {
+	{
+		.name = "taiko_rx1",
+		.id = AIF1_PB,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &taiko_dai_ops,
+	},
+	{
+		.name = "taiko_tx1",
+		.id = AIF1_CAP,
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &taiko_dai_ops,
+	},
+	{
+		.name = "taiko_rx2",
+		.id = AIF2_PB,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_min = 8000,
+			.rate_max = 192000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &taiko_dai_ops,
+	},
+	{
+		.name = "taiko_tx2",
+		.id = AIF2_CAP,
+		.capture = {
+			.stream_name = "AIF2 Capture",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &taiko_dai_ops,
+	},
+	{
+		.name = "taiko_tx3",
+		.id = AIF3_CAP,
+		.capture = {
+			.stream_name = "AIF3 Capture",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &taiko_dai_ops,
+	},
+	{
+		.name = "taiko_rx3",
+		.id = AIF3_PB,
+		.playback = {
+			.stream_name = "AIF3 Playback",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_min = 8000,
+			.rate_max = 192000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &taiko_dai_ops,
+	},
+};
+
+static struct snd_soc_dai_driver taiko_i2s_dai[] = {
+	{
+		.name = "taiko_i2s_rx1",
+		.id = 1,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &taiko_dai_ops,
+	},
+	{
+		.name = "taiko_i2s_tx1",
+		.id = 2,
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &taiko_dai_ops,
+	},
+};
+
+static int taiko_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct wcd9xxx *taiko;
+	struct snd_soc_codec *codec = w->codec;
+	struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+	u32  j = 0;
+	u32  ret = 0;
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	taiko = codec->control_data;
+	/* Execute the callback only if interface type is slimbus */
+	if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		return 0;
+
+	pr_debug("%s: %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		for (j = 0; j < ARRAY_SIZE(taiko_dai); j++) {
+			if ((taiko_dai[j].id == AIF1_CAP) ||
+			    (taiko_dai[j].id == AIF2_CAP) ||
+			    (taiko_dai[j].id == AIF3_CAP))
+				continue;
+			if (!strncmp(w->sname,
+				taiko_dai[j].playback.stream_name, 13)) {
+				++taiko_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (taiko_p->dai[j].ch_act == taiko_p->dai[j].ch_tot)
+			ret = wcd9xxx_cfg_slim_sch_rx(taiko,
+					taiko_p->dai[j].ch_num,
+					taiko_p->dai[j].ch_tot,
+					taiko_p->dai[j].rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		for (j = 0; j < ARRAY_SIZE(taiko_dai); j++) {
+			if ((taiko_dai[j].id == AIF1_CAP) ||
+			    (taiko_dai[j].id == AIF2_CAP) ||
+			    (taiko_dai[j].id == AIF3_CAP))
+				continue;
+			if (!strncmp(w->sname,
+				taiko_dai[j].playback.stream_name, 13)) {
+				--taiko_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (!taiko_p->dai[j].ch_act) {
+			ret = wcd9xxx_close_slim_sch_rx(taiko,
+						taiko_p->dai[j].ch_num,
+						taiko_p->dai[j].ch_tot);
+			usleep_range(15000, 15000);
+			taiko_p->dai[j].rate = 0;
+			memset(taiko_p->dai[j].ch_num, 0, (sizeof(u32)*
+					taiko_p->dai[j].ch_tot));
+			taiko_p->dai[j].ch_tot = 0;
+		}
+	}
+	return ret;
+}
+
+static int taiko_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct wcd9xxx *taiko;
+	struct snd_soc_codec *codec = w->codec;
+	struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+	/* index to the DAI ID, for now hardcoding */
+	u32  j = 0;
+	u32  ret = 0;
+
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	taiko = codec->control_data;
+
+	/* Execute the callback only if interface type is slimbus */
+	if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		return 0;
+
+	pr_debug("%s(): %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		for (j = 0; j < ARRAY_SIZE(taiko_dai); j++) {
+			if (taiko_dai[j].id == AIF1_PB ||
+				taiko_dai[j].id == AIF2_PB ||
+				taiko_dai[j].id == AIF3_PB)
+				continue;
+			if (!strncmp(w->sname,
+				taiko_dai[j].capture.stream_name, 13)) {
+				++taiko_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (taiko_p->dai[j].ch_act == taiko_p->dai[j].ch_tot)
+			ret = wcd9xxx_cfg_slim_sch_tx(taiko,
+						taiko_p->dai[j].ch_num,
+						taiko_p->dai[j].ch_tot,
+						taiko_p->dai[j].rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		for (j = 0; j < ARRAY_SIZE(taiko_dai); j++) {
+			if (taiko_dai[j].id == AIF1_PB ||
+				taiko_dai[j].id == AIF2_PB ||
+				taiko_dai[j].id == AIF3_PB)
+				continue;
+			if (!strncmp(w->sname,
+				taiko_dai[j].capture.stream_name, 13)) {
+				--taiko_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (!taiko_p->dai[j].ch_act) {
+			ret = wcd9xxx_close_slim_sch_tx(taiko,
+						taiko_p->dai[j].ch_num,
+						taiko_p->dai[j].ch_tot);
+			taiko_p->dai[j].rate = 0;
+			memset(taiko_p->dai[j].ch_num, 0, (sizeof(u32)*
+					taiko_p->dai[j].ch_tot));
+			taiko_p->dai[j].ch_tot = 0;
+		}
+	}
+	return ret;
+}
+
+/* Todo: Have seperate dapm widgets for I2S and Slimbus.
+ * Might Need to have callbacks registered only for slimbus
+ */
+static const struct snd_soc_dapm_widget taiko_dapm_widgets[] = {
+	/*RX stuff */
+	SND_SOC_DAPM_OUTPUT("EAR"),
+
+	SND_SOC_DAPM_PGA("EAR PA", TAIKO_A_RX_EAR_EN, 4, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER("DAC1", TAIKO_A_RX_EAR_EN, 6, 0, dac1_switch,
+		ARRAY_SIZE(dac1_switch)),
+
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX4", "AIF3 Playback", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX5", "AIF3 Playback", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX6", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX7", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Headphone */
+	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+	SND_SOC_DAPM_PGA_E("HPHL", TAIKO_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+		taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER("HPHL DAC", TAIKO_A_RX_HPH_L_DAC_CTL, 7, 0,
+		hphl_switch, ARRAY_SIZE(hphl_switch)),
+
+	SND_SOC_DAPM_PGA_E("HPHR", TAIKO_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+		taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAIKO_A_RX_HPH_R_DAC_CTL, 7, 0,
+		taiko_hphr_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Speaker */
+	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT3"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT4"),
+
+	SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAIKO_A_RX_LINE_CNP_EN, 0, 0, NULL,
+			0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAIKO_A_RX_LINE_CNP_EN, 1, 0, NULL,
+			0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TAIKO_A_RX_LINE_CNP_EN, 2, 0, NULL,
+			0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TAIKO_A_RX_LINE_CNP_EN, 3, 0, NULL,
+			0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAIKO_A_RX_LINE_1_DAC_CTL, 7, 0
+		, taiko_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAIKO_A_RX_LINE_2_DAC_CTL, 7, 0
+		, taiko_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TAIKO_A_RX_LINE_3_DAC_CTL, 7, 0
+		, taiko_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
+				&lineout3_ground_switch),
+	SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TAIKO_A_RX_LINE_4_DAC_CTL, 7, 0
+		, taiko_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
+				&lineout4_ground_switch),
+
+	SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
+		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX2 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
+		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX7 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
+		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
+		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX6 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
+		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX7 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
+		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX3 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0,
+		&rx4_dsm_mux, taiko_codec_reset_interpolator,
+		SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0,
+		&rx6_dsm_mux, taiko_codec_reset_interpolator,
+		SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MIXER("RX1 CHAIN", TAIKO_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX2 CHAIN", TAIKO_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp3_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx5_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx5_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx6_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx6_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx7_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx7_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+		&rx1_mix2_inp1_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+		&rx1_mix2_inp2_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+		&rx2_mix2_inp1_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+		&rx2_mix2_inp2_mux),
+	SND_SOC_DAPM_MUX("RX7 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+		&rx7_mix2_inp1_mux),
+	SND_SOC_DAPM_MUX("RX7 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+		&rx7_mix2_inp2_mux),
+
+	SND_SOC_DAPM_SUPPLY("CP", TAIKO_A_NCP_EN, 0, 0,
+		taiko_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
+		taiko_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	/* TX */
+
+	SND_SOC_DAPM_SUPPLY("CDC_CONN", TAIKO_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+		0),
+
+	SND_SOC_DAPM_SUPPLY("LDO_H", TAIKO_A_LDO_H_MODE_1, 7, 0,
+		taiko_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 0, 0,
+		taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 1, 0,
+		taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+
+
+	SND_SOC_DAPM_INPUT("AMIC1"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAIKO_A_MICB_1_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAIKO_A_MICB_1_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAIKO_A_MICB_1_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_TX_1_2_EN, 7, 0,
+		taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC3"),
+	SND_SOC_DAPM_ADC_E("ADC3", NULL, TAIKO_A_TX_3_4_EN, 7, 0,
+		taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC4"),
+	SND_SOC_DAPM_ADC_E("ADC4", NULL, TAIKO_A_TX_3_4_EN, 3, 0,
+		taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC5"),
+	SND_SOC_DAPM_ADC_E("ADC5", NULL, TAIKO_A_TX_5_6_EN, 7, 0,
+		taiko_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_INPUT("AMIC6"),
+	SND_SOC_DAPM_ADC_E("ADC6", NULL, TAIKO_A_TX_5_6_EN, 3, 0,
+		taiko_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC1 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+		&dec1_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC2 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+		&dec2_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC3 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+		&dec3_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC4 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+		&dec4_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC5 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
+		&dec5_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC6 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
+		&dec6_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC7 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
+		&dec7_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC8 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
+		&dec8_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC9 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
+		&dec9_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC10 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
+		&dec10_mux, taiko_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
+	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
+
+	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
+		taiko_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
+
+	SND_SOC_DAPM_INPUT("AMIC2"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAIKO_A_MICB_2_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TAIKO_A_MICB_2_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TAIKO_A_MICB_2_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAIKO_A_MICB_2_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAIKO_A_MICB_3_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAIKO_A_MICB_3_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAIKO_A_MICB_3_CTL, 7, 0,
+		taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TAIKO_A_MICB_4_CTL, 7,
+				0, taiko_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_TX_1_2_EN, 3, 0,
+		taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX1", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, 0, 0, &sb_tx2_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX2", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, 0, 0, &sb_tx3_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF3 Capture", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, 0, 0, &sb_tx4_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX4", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX5", "AIF3 Capture", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX6", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX7", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX8", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+				0, taiko_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
+			0, 0, taiko_codec_enable_slimtx,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
+			0, 0, taiko_codec_enable_slimtx,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Digital Mic Inputs */
+	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	/* Sidetone */
+	SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+	SND_SOC_DAPM_PGA("IIR1", TAIKO_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+
+	/* AUX PGA */
+	SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAIKO_A_RX_AUX_SW_CTL, 7, 0,
+		taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("AUX_PGA_Right", NULL, TAIKO_A_RX_AUX_SW_CTL, 6, 0,
+		taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	/* Lineout, ear and HPH PA Mixers */
+
+	SND_SOC_DAPM_MIXER("EAR_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		ear_pa_mix, ARRAY_SIZE(ear_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("HPHL_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		hphl_pa_mix, ARRAY_SIZE(hphl_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("HPHR_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		hphr_pa_mix, ARRAY_SIZE(hphr_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("LINEOUT1_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		lineout1_pa_mix, ARRAY_SIZE(lineout1_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("LINEOUT3_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		lineout3_pa_mix, ARRAY_SIZE(lineout3_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
+
+};
+
+static short taiko_codec_read_sta_result(struct snd_soc_codec *codec)
+{
+	u8 bias_msb, bias_lsb;
+	short bias_value;
+
+	bias_msb = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B3_STATUS);
+	bias_lsb = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B2_STATUS);
+	bias_value = (bias_msb << 8) | bias_lsb;
+	return bias_value;
+}
+
+static short taiko_codec_read_dce_result(struct snd_soc_codec *codec)
+{
+	u8 bias_msb, bias_lsb;
+	short bias_value;
+
+	bias_msb = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B5_STATUS);
+	bias_lsb = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B4_STATUS);
+	bias_value = (bias_msb << 8) | bias_lsb;
+	return bias_value;
+}
+
+static void taiko_turn_onoff_rel_detection(struct snd_soc_codec *codec, bool on)
+{
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x02, on << 1);
+}
+
+static short __taiko_codec_sta_dce(struct snd_soc_codec *codec, int dce,
+				   bool override_bypass, bool noreldetection)
+{
+	short bias_value;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL);
+	if (noreldetection)
+		taiko_turn_onoff_rel_detection(codec, false);
+
+	/* Turn on the override */
+	if (!override_bypass)
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
+	if (dce) {
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+		snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x4);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+		usleep_range(taiko->mbhc_data.t_sta_dce,
+			     taiko->mbhc_data.t_sta_dce);
+		snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x4);
+		usleep_range(taiko->mbhc_data.t_dce,
+			     taiko->mbhc_data.t_dce);
+		bias_value = taiko_codec_read_dce_result(codec);
+	} else {
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+		snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x2);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+		usleep_range(taiko->mbhc_data.t_sta_dce,
+			     taiko->mbhc_data.t_sta_dce);
+		snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x2);
+		usleep_range(taiko->mbhc_data.t_sta,
+			     taiko->mbhc_data.t_sta);
+		bias_value = taiko_codec_read_sta_result(codec);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+		snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x0);
+	}
+	/* Turn off the override after measuring mic voltage */
+	if (!override_bypass)
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
+
+	if (noreldetection)
+		taiko_turn_onoff_rel_detection(codec, true);
+	wcd9xxx_enable_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL);
+
+	return bias_value;
+}
+
+static short taiko_codec_sta_dce(struct snd_soc_codec *codec, int dce,
+				 bool norel)
+{
+	return __taiko_codec_sta_dce(codec, dce, false, norel);
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static short taiko_codec_setup_hs_polling(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	short bias_value;
+	u8 cfilt_mode;
+
+	pr_debug("%s: enter, mclk_enabled %d\n", __func__, taiko->mclk_enabled);
+	if (!taiko->mbhc_cfg.calibration) {
+		pr_err("Error, no taiko calibration\n");
+		return -ENODEV;
+	}
+
+	if (!taiko->mclk_enabled) {
+		taiko_codec_disable_clock_block(codec);
+		taiko_codec_enable_bandgap(codec, TAIKO_BANDGAP_MBHC_MODE);
+		taiko_enable_rx_bias(codec, 1);
+		taiko_codec_enable_clock_block(codec, 1);
+	}
+
+	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x05, 0x01);
+
+	/* Make sure CFILT is in fast mode, save current mode */
+	cfilt_mode = snd_soc_read(codec, taiko->mbhc_bias_regs.cfilt_ctl);
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00);
+
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+	snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x84);
+
+	snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN, 0x80, 0x80);
+	snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN, 0x1F, 0x1C);
+	snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_TEST_CTL, 0x40, 0x40);
+
+	snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN, 0x80, 0x00);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+
+	taiko_codec_calibrate_hs_polling(codec);
+
+	/* don't flip override */
+	bias_value = __taiko_codec_sta_dce(codec, 1, true, true);
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl, 0x40,
+			    cfilt_mode);
+	snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x13, 0x00);
+
+	return bias_value;
+}
+
+static int taiko_cancel_btn_work(struct taiko_priv *taiko)
+{
+	int r = 0;
+	struct wcd9xxx *core = dev_get_drvdata(taiko->codec->dev->parent);
+
+	if (cancel_delayed_work_sync(&taiko->mbhc_btn_dwork)) {
+		/* if scheduled mbhc_btn_dwork is canceled from here,
+		* we have to unlock from here instead btn_work */
+		wcd9xxx_unlock_sleep(core);
+		r = 1;
+	}
+	return r;
+}
+
+/* called under codec_resource_lock acquisition */
+void taiko_set_and_turnoff_hph_padac(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u8 wg_time;
+
+	wg_time = snd_soc_read(codec, TAIKO_A_RX_HPH_CNP_WG_TIME) ;
+	wg_time += 1;
+
+	/* If headphone PA is on, check if userspace receives
+	 * removal event to sync-up PA's state */
+	if (taiko_is_hph_pa_on(codec)) {
+		pr_debug("%s PA is on, setting PA_OFF_ACK\n", __func__);
+		set_bit(TAIKO_HPHL_PA_OFF_ACK, &taiko->hph_pa_dac_state);
+		set_bit(TAIKO_HPHR_PA_OFF_ACK, &taiko->hph_pa_dac_state);
+	} else {
+		pr_debug("%s PA is off\n", __func__);
+	}
+
+	if (taiko_is_hph_dac_on(codec, 1))
+		set_bit(TAIKO_HPHL_DAC_OFF_ACK, &taiko->hph_pa_dac_state);
+	if (taiko_is_hph_dac_on(codec, 0))
+		set_bit(TAIKO_HPHR_DAC_OFF_ACK, &taiko->hph_pa_dac_state);
+
+	snd_soc_update_bits(codec, TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
+	snd_soc_update_bits(codec, TAIKO_A_RX_HPH_L_DAC_CTL,
+			    0xC0, 0x00);
+	snd_soc_update_bits(codec, TAIKO_A_RX_HPH_R_DAC_CTL,
+			    0xC0, 0x00);
+	usleep_range(wg_time * 1000, wg_time * 1000);
+}
+
+static void taiko_clr_and_turnon_hph_padac(struct taiko_priv *taiko)
+{
+	bool pa_turned_on = false;
+	struct snd_soc_codec *codec = taiko->codec;
+	u8 wg_time;
+
+	wg_time = snd_soc_read(codec, TAIKO_A_RX_HPH_CNP_WG_TIME) ;
+	wg_time += 1;
+
+	if (test_and_clear_bit(TAIKO_HPHR_DAC_OFF_ACK,
+			       &taiko->hph_pa_dac_state)) {
+		pr_debug("%s: HPHR clear flag and enable DAC\n", __func__);
+		snd_soc_update_bits(taiko->codec, TAIKO_A_RX_HPH_R_DAC_CTL,
+				    0xC0, 0xC0);
+	}
+	if (test_and_clear_bit(TAIKO_HPHL_DAC_OFF_ACK,
+			       &taiko->hph_pa_dac_state)) {
+		pr_debug("%s: HPHL clear flag and enable DAC\n", __func__);
+		snd_soc_update_bits(taiko->codec, TAIKO_A_RX_HPH_L_DAC_CTL,
+				    0xC0, 0xC0);
+	}
+
+	if (test_and_clear_bit(TAIKO_HPHR_PA_OFF_ACK,
+			       &taiko->hph_pa_dac_state)) {
+		pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
+		snd_soc_update_bits(taiko->codec, TAIKO_A_RX_HPH_CNP_EN, 0x10,
+				    1 << 4);
+		pa_turned_on = true;
+	}
+	if (test_and_clear_bit(TAIKO_HPHL_PA_OFF_ACK,
+			       &taiko->hph_pa_dac_state)) {
+		pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
+		snd_soc_update_bits(taiko->codec, TAIKO_A_RX_HPH_CNP_EN, 0x20,
+				    1 << 5);
+		pa_turned_on = true;
+	}
+
+	if (pa_turned_on) {
+		pr_debug("%s: PA was turned off by MBHC and not by DAPM\n",
+				__func__);
+		usleep_range(wg_time * 1000, wg_time * 1000);
+	}
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_report_plug(struct snd_soc_codec *codec, int insertion,
+				    enum snd_jack_types jack_type)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	if (!insertion) {
+		/* Report removal */
+		taiko->hph_status &= ~jack_type;
+		if (taiko->mbhc_cfg.headset_jack) {
+			/* cancel possibly scheduled btn work and
+			* report release if we reported button press */
+			if (taiko_cancel_btn_work(taiko)) {
+				pr_debug("%s: button press is canceled\n",
+					__func__);
+			} else if (taiko->buttons_pressed) {
+				pr_debug("%s: release of button press%d\n",
+					  __func__, jack_type);
+				taiko_snd_soc_jack_report(taiko,
+						 taiko->mbhc_cfg.button_jack, 0,
+						 taiko->buttons_pressed);
+				taiko->buttons_pressed &=
+							~TAIKO_JACK_BUTTON_MASK;
+			}
+			pr_debug("%s: Reporting removal %d(%x)\n", __func__,
+				 jack_type, taiko->hph_status);
+			taiko_snd_soc_jack_report(taiko,
+						  taiko->mbhc_cfg.headset_jack,
+						  taiko->hph_status,
+						  TAIKO_JACK_MASK);
+		}
+		taiko_set_and_turnoff_hph_padac(codec);
+		hphocp_off_report(taiko, SND_JACK_OC_HPHR,
+				  TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+		hphocp_off_report(taiko, SND_JACK_OC_HPHL,
+				  TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+		taiko->current_plug = PLUG_TYPE_NONE;
+		taiko->mbhc_polling_active = false;
+	} else {
+		/* Report insertion */
+		taiko->hph_status |= jack_type;
+
+		if (jack_type == SND_JACK_HEADPHONE)
+			taiko->current_plug = PLUG_TYPE_HEADPHONE;
+		else if (jack_type == SND_JACK_UNSUPPORTED)
+			taiko->current_plug = PLUG_TYPE_GND_MIC_SWAP;
+		else if (jack_type == SND_JACK_HEADSET) {
+			taiko->mbhc_polling_active = true;
+			taiko->current_plug = PLUG_TYPE_HEADSET;
+		}
+		if (taiko->mbhc_cfg.headset_jack) {
+			pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
+				 jack_type, taiko->hph_status);
+			taiko_snd_soc_jack_report(taiko,
+						  taiko->mbhc_cfg.headset_jack,
+						  taiko->hph_status,
+						  TAIKO_JACK_MASK);
+		}
+		taiko_clr_and_turnon_hph_padac(taiko);
+	}
+}
+
+static int taiko_codec_enable_hs_detect(struct snd_soc_codec *codec,
+					int insertion, int trigger,
+					bool padac_off)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	int central_bias_enabled = 0;
+	const struct taiko_mbhc_general_cfg *generic =
+	    TAIKO_MBHC_CAL_GENERAL_PTR(taiko->mbhc_cfg.calibration);
+	const struct taiko_mbhc_plug_detect_cfg *plug_det =
+	    TAIKO_MBHC_CAL_PLUG_DET_PTR(taiko->mbhc_cfg.calibration);
+
+	if (!taiko->mbhc_cfg.calibration) {
+		pr_err("Error, no taiko calibration\n");
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x1, 0);
+
+	/* Make sure mic bias and Mic line schmitt trigger
+	 * are turned OFF
+	 */
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x01, 0x01);
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
+
+	if (insertion) {
+		taiko_codec_switch_micbias(codec, 0);
+
+		/* DAPM can manipulate PA/DAC bits concurrently */
+		if (padac_off == true)
+			taiko_set_and_turnoff_hph_padac(codec);
+
+		if (trigger & MBHC_USE_HPHL_TRIGGER) {
+			/* Enable HPH Schmitt Trigger */
+			snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x11,
+					    0x11);
+			snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x0C,
+					    plug_det->hph_current << 2);
+			snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x02,
+					    0x02);
+		}
+		if (trigger & MBHC_USE_MB_TRIGGER) {
+			/* enable the mic line schmitt trigger */
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.mbhc_reg,
+					    0x60, plug_det->mic_current << 5);
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.mbhc_reg,
+					    0x80, 0x80);
+			usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.ctl_reg, 0x01,
+					    0x00);
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.mbhc_reg,
+					    0x10, 0x10);
+		}
+
+		/* setup for insetion detection */
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x2, 0);
+	} else {
+		pr_debug("setup for removal detection\n");
+		/* Make sure the HPH schmitt trigger is OFF */
+		snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x12, 0x00);
+
+		/* enable the mic line schmitt trigger */
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg,
+				    0x01, 0x00);
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg, 0x60,
+				    plug_det->mic_current << 5);
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+			0x80, 0x80);
+		usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+			0x10, 0x10);
+
+		/* Setup for low power removal detection */
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x2, 0x2);
+	}
+
+	if (snd_soc_read(codec, TAIKO_A_CDC_MBHC_B1_CTL) & 0x4) {
+		/* called called by interrupt */
+		if (!(taiko->clock_active)) {
+			taiko_codec_enable_config_mode(codec, 1);
+			snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL,
+				0x06, 0);
+			usleep_range(generic->t_shutdown_plug_rem,
+				     generic->t_shutdown_plug_rem);
+			taiko_codec_enable_config_mode(codec, 0);
+		} else
+			snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL,
+				0x06, 0);
+	}
+
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.int_rbias, 0x80, 0);
+
+	/* If central bandgap disabled */
+	if (!(snd_soc_read(codec, TAIKO_A_PIN_CTL_OE1) & 1)) {
+		snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE1, 0x3, 0x3);
+		usleep_range(generic->t_bg_fast_settle,
+			     generic->t_bg_fast_settle);
+		central_bias_enabled = 1;
+	}
+
+	/* If LDO_H disabled */
+	if (snd_soc_read(codec, TAIKO_A_PIN_CTL_OE0) & 0x80) {
+		snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE0, 0x10, 0);
+		snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE0, 0x80, 0x80);
+		usleep_range(generic->t_ldoh, generic->t_ldoh);
+		snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE0, 0x80, 0);
+
+		if (central_bias_enabled)
+			snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE1, 0x1, 0);
+	}
+
+	snd_soc_update_bits(codec, taiko->reg_addr.micb_4_mbhc, 0x3,
+			    taiko->mbhc_cfg.micbias);
+
+	wcd9xxx_enable_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+	return 0;
+}
+
+static u16 taiko_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
+				 s16 vin_mv)
+{
+	struct taiko_priv *taiko;
+	s16 diff, zero;
+	u32 mb_mv, in;
+	u16 value;
+
+	taiko = snd_soc_codec_get_drvdata(codec);
+	mb_mv = taiko->mbhc_data.micb_mv;
+
+	if (mb_mv == 0) {
+		pr_err("%s: Mic Bias voltage is set to zero\n", __func__);
+		return -EINVAL;
+	}
+
+	if (dce) {
+		diff = (taiko->mbhc_data.dce_mb) - (taiko->mbhc_data.dce_z);
+		zero = (taiko->mbhc_data.dce_z);
+	} else {
+		diff = (taiko->mbhc_data.sta_mb) - (taiko->mbhc_data.sta_z);
+		zero = (taiko->mbhc_data.sta_z);
+	}
+	in = (u32) diff * vin_mv;
+
+	value = (u16) (in / mb_mv) + zero;
+	return value;
+}
+
+static s32 taiko_codec_sta_dce_v(struct snd_soc_codec *codec, s8 dce,
+				 u16 bias_value)
+{
+	struct taiko_priv *taiko;
+	s16 value, z, mb;
+	s32 mv;
+
+	taiko = snd_soc_codec_get_drvdata(codec);
+	value = bias_value;
+	if (dce) {
+		z = (taiko->mbhc_data.dce_z);
+		mb = (taiko->mbhc_data.dce_mb);
+		mv = (value - z) * (s32)taiko->mbhc_data.micb_mv / (mb - z);
+	} else {
+		z = (taiko->mbhc_data.sta_z);
+		mb = (taiko->mbhc_data.sta_mb);
+		mv = (value - z) * (s32)taiko->mbhc_data.micb_mv / (mb - z);
+	}
+
+	return mv;
+}
+
+static void btn_lpress_fn(struct work_struct *work)
+{
+	struct delayed_work *delayed_work;
+	struct taiko_priv *taiko;
+	short bias_value;
+	int dce_mv, sta_mv;
+	struct wcd9xxx *core;
+
+	pr_debug("%s:\n", __func__);
+
+	delayed_work = to_delayed_work(work);
+	taiko = container_of(delayed_work, struct taiko_priv, mbhc_btn_dwork);
+	core = dev_get_drvdata(taiko->codec->dev->parent);
+
+	if (taiko) {
+		if (taiko->mbhc_cfg.button_jack) {
+			bias_value = taiko_codec_read_sta_result(taiko->codec);
+			sta_mv = taiko_codec_sta_dce_v(taiko->codec, 0,
+						bias_value);
+			bias_value = taiko_codec_read_dce_result(taiko->codec);
+			dce_mv = taiko_codec_sta_dce_v(taiko->codec, 1,
+						bias_value);
+			pr_debug("%s: Reporting long button press event\n",
+				__func__);
+			pr_debug("%s: STA: %d, DCE: %d\n", __func__, sta_mv,
+					dce_mv);
+			taiko_snd_soc_jack_report(taiko,
+						  taiko->mbhc_cfg.button_jack,
+						  taiko->buttons_pressed,
+						  taiko->buttons_pressed);
+		}
+	} else {
+		pr_err("%s: Bad taiko private data\n", __func__);
+	}
+
+	pr_debug("%s: leave\n", __func__);
+	wcd9xxx_unlock_sleep(core);
+}
+
+void taiko_mbhc_cal(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko;
+	struct taiko_mbhc_btn_detect_cfg *btn_det;
+	u8 cfilt_mode, bg_mode;
+	u8 ncic, nmeas, navg;
+	u32 mclk_rate;
+	u32 dce_wait, sta_wait;
+	u8 *n_cic;
+	void *calibration;
+
+	taiko = snd_soc_codec_get_drvdata(codec);
+	calibration = taiko->mbhc_cfg.calibration;
+
+	wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL);
+	taiko_turn_onoff_rel_detection(codec, false);
+
+	/* First compute the DCE / STA wait times
+	 * depending on tunable parameters.
+	 * The value is computed in microseconds
+	 */
+	btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(calibration);
+	n_cic = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_CIC);
+	ncic = n_cic[taiko_codec_mclk_index(taiko)];
+	nmeas = TAIKO_MBHC_CAL_BTN_DET_PTR(calibration)->n_meas;
+	navg = TAIKO_MBHC_CAL_GENERAL_PTR(calibration)->mbhc_navg;
+	mclk_rate = taiko->mbhc_cfg.mclk_rate;
+	dce_wait = (1000 * 512 * ncic * (nmeas + 1)) / (mclk_rate / 1000);
+	sta_wait = (1000 * 128 * (navg + 1)) / (mclk_rate / 1000);
+
+	taiko->mbhc_data.t_dce = dce_wait;
+	taiko->mbhc_data.t_sta = sta_wait;
+
+	/* LDOH and CFILT are already configured during pdata handling.
+	 * Only need to make sure CFILT and bandgap are in Fast mode.
+	 * Need to restore defaults once calculation is done.
+	 */
+	cfilt_mode = snd_soc_read(codec, taiko->mbhc_bias_regs.cfilt_ctl);
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
+	bg_mode = snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x02,
+				      0x02);
+
+	/* Micbias, CFILT, LDOH, MBHC MUX mode settings
+	 * to perform ADC calibration
+	 */
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x60,
+			    taiko->mbhc_cfg.micbias << 5);
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
+	snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 0x60, 0x60);
+	snd_soc_write(codec, TAIKO_A_TX_7_MBHC_TEST_CTL, 0x78);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
+
+	/* DCE measurement for 0 volts */
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x0A);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x04);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x02);
+	snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x81);
+	usleep_range(100, 100);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x04);
+	usleep_range(taiko->mbhc_data.t_dce, taiko->mbhc_data.t_dce);
+	taiko->mbhc_data.dce_z = taiko_codec_read_dce_result(codec);
+
+	/* DCE measurment for MB voltage */
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x0A);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x02);
+	snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x82);
+	usleep_range(100, 100);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x04);
+	usleep_range(taiko->mbhc_data.t_dce, taiko->mbhc_data.t_dce);
+	taiko->mbhc_data.dce_mb = taiko_codec_read_dce_result(codec);
+
+	/* Sta measuremnt for 0 volts */
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x0A);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x02);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x02);
+	snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x81);
+	usleep_range(100, 100);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x02);
+	usleep_range(taiko->mbhc_data.t_sta, taiko->mbhc_data.t_sta);
+	taiko->mbhc_data.sta_z = taiko_codec_read_sta_result(codec);
+
+	/* STA Measurement for MB Voltage */
+	snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x82);
+	usleep_range(100, 100);
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x02);
+	usleep_range(taiko->mbhc_data.t_sta, taiko->mbhc_data.t_sta);
+	taiko->mbhc_data.sta_mb = taiko_codec_read_sta_result(codec);
+
+	/* Restore default settings. */
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl, 0x40,
+			    cfilt_mode);
+	snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x02, bg_mode);
+
+	snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x84);
+	usleep_range(100, 100);
+
+	wcd9xxx_enable_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL);
+	taiko_turn_onoff_rel_detection(codec, true);
+}
+
+void *taiko_mbhc_cal_btn_det_mp(const struct taiko_mbhc_btn_detect_cfg *btn_det,
+				const enum taiko_mbhc_btn_det_mem mem)
+{
+	void *ret = &btn_det->_v_btn_low;
+
+	switch (mem) {
+	case TAIKO_BTN_DET_GAIN:
+		ret += sizeof(btn_det->_n_cic);
+	case TAIKO_BTN_DET_N_CIC:
+		ret += sizeof(btn_det->_n_ready);
+	case TAIKO_BTN_DET_N_READY:
+		ret += sizeof(btn_det->_v_btn_high[0]) * btn_det->num_btn;
+	case TAIKO_BTN_DET_V_BTN_HIGH:
+		ret += sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn;
+	case TAIKO_BTN_DET_V_BTN_LOW:
+		/* do nothing */
+		break;
+	default:
+		ret = NULL;
+	}
+
+	return ret;
+}
+
+static s16 taiko_scale_v_micb_vddio(struct taiko_priv *taiko, int v,
+				    bool tovddio)
+{
+	int r;
+	int vddio_k, mb_k;
+	vddio_k = taiko_find_k_value(taiko->pdata->micbias.ldoh_v,
+				     VDDIO_MICBIAS_MV);
+	mb_k = taiko_find_k_value(taiko->pdata->micbias.ldoh_v,
+				  taiko->mbhc_data.micb_mv);
+	if (tovddio)
+		r = v * vddio_k / mb_k;
+	else
+		r = v * mb_k / vddio_k;
+	return r;
+}
+
+static void taiko_mbhc_calc_thres(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko;
+	s16 btn_mv = 0, btn_delta_mv;
+	struct taiko_mbhc_btn_detect_cfg *btn_det;
+	struct taiko_mbhc_plug_type_cfg *plug_type;
+	u16 *btn_high;
+	u8 *n_ready;
+	int i;
+
+	taiko = snd_soc_codec_get_drvdata(codec);
+	btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(taiko->mbhc_cfg.calibration);
+	plug_type = TAIKO_MBHC_CAL_PLUG_TYPE_PTR(taiko->mbhc_cfg.calibration);
+
+	n_ready = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_READY);
+	if (taiko->mbhc_cfg.mclk_rate == TAIKO_MCLK_RATE_12288KHZ) {
+		taiko->mbhc_data.npoll = 4;
+		taiko->mbhc_data.nbounce_wait = 30;
+	} else if (taiko->mbhc_cfg.mclk_rate == TAIKO_MCLK_RATE_9600KHZ) {
+		taiko->mbhc_data.npoll = 7;
+		taiko->mbhc_data.nbounce_wait = 23;
+	}
+
+	taiko->mbhc_data.t_sta_dce = ((1000 * 256) /
+				      (taiko->mbhc_cfg.mclk_rate / 1000) *
+				      n_ready[taiko_codec_mclk_index(taiko)]) +
+				     10;
+	taiko->mbhc_data.v_ins_hu =
+	    taiko_codec_v_sta_dce(codec, STA, plug_type->v_hs_max);
+	taiko->mbhc_data.v_ins_h =
+	    taiko_codec_v_sta_dce(codec, DCE, plug_type->v_hs_max);
+
+	taiko->mbhc_data.v_inval_ins_low = TAIKO_MBHC_FAKE_INSERT_LOW;
+	if (taiko->mbhc_cfg.gpio)
+		taiko->mbhc_data.v_inval_ins_high =
+		    TAIKO_MBHC_FAKE_INSERT_HIGH;
+	else
+		taiko->mbhc_data.v_inval_ins_high =
+		    TAIKO_MBHC_FAKE_INS_HIGH_NO_GPIO;
+
+	if (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
+		taiko->mbhc_data.adj_v_hs_max =
+		    taiko_scale_v_micb_vddio(taiko, plug_type->v_hs_max, true);
+		taiko->mbhc_data.adj_v_ins_hu =
+		    taiko_codec_v_sta_dce(codec, STA,
+					  taiko->mbhc_data.adj_v_hs_max);
+		taiko->mbhc_data.adj_v_ins_h =
+		    taiko_codec_v_sta_dce(codec, DCE,
+					  taiko->mbhc_data.adj_v_hs_max);
+		taiko->mbhc_data.v_inval_ins_low =
+		    taiko_scale_v_micb_vddio(taiko,
+					     taiko->mbhc_data.v_inval_ins_low,
+					     false);
+		taiko->mbhc_data.v_inval_ins_high =
+		    taiko_scale_v_micb_vddio(taiko,
+					     taiko->mbhc_data.v_inval_ins_high,
+					     false);
+	}
+
+	btn_high = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_V_BTN_HIGH);
+	for (i = 0; i < btn_det->num_btn; i++)
+		btn_mv = btn_high[i] > btn_mv ? btn_high[i] : btn_mv;
+
+	taiko->mbhc_data.v_b1_h = taiko_codec_v_sta_dce(codec, DCE, btn_mv);
+	btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_sta;
+	taiko->mbhc_data.v_b1_hu =
+	    taiko_codec_v_sta_dce(codec, STA, btn_delta_mv);
+
+	btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_cic;
+
+	taiko->mbhc_data.v_b1_huc =
+	    taiko_codec_v_sta_dce(codec, DCE, btn_delta_mv);
+
+	taiko->mbhc_data.v_brh = taiko->mbhc_data.v_b1_h;
+	taiko->mbhc_data.v_brl = TAIKO_MBHC_BUTTON_MIN;
+
+	taiko->mbhc_data.v_no_mic =
+	    taiko_codec_v_sta_dce(codec, STA, plug_type->v_no_mic);
+}
+
+void taiko_mbhc_init(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko;
+	struct taiko_mbhc_general_cfg *generic;
+	struct taiko_mbhc_btn_detect_cfg *btn_det;
+	int n;
+	u8 *n_cic, *gain;
+
+	taiko = snd_soc_codec_get_drvdata(codec);
+	generic = TAIKO_MBHC_CAL_GENERAL_PTR(taiko->mbhc_cfg.calibration);
+	btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(taiko->mbhc_cfg.calibration);
+
+	for (n = 0; n < 8; n++) {
+			snd_soc_update_bits(codec,
+					    TAIKO_A_CDC_MBHC_FIR_B1_CFG,
+					    0x07, n);
+			snd_soc_write(codec, TAIKO_A_CDC_MBHC_FIR_B2_CFG,
+				      btn_det->c[n]);
+	}
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B2_CTL, 0x07,
+			    btn_det->nc);
+
+	n_cic = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_CIC);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_TIMER_B6_CTL, 0xFF,
+			    n_cic[taiko_codec_mclk_index(taiko)]);
+
+	gain = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_GAIN);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B2_CTL, 0x78,
+			    gain[taiko_codec_mclk_index(taiko)] << 3);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_TIMER_B4_CTL, 0x70,
+			    generic->mbhc_nsa << 4);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_TIMER_B4_CTL, 0x0F,
+			    btn_det->n_meas);
+
+	snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B5_CTL, generic->mbhc_navg);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x80, 0x80);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x78,
+			    btn_det->mbhc_nsc << 3);
+
+	snd_soc_update_bits(codec, taiko->reg_addr.micb_4_mbhc, 0x03,
+			    TAIKO_MICBIAS2);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
+
+	snd_soc_update_bits(codec, TAIKO_A_MBHC_SCALING_MUX_2, 0xF0, 0xF0);
+}
+
+static bool taiko_mbhc_fw_validate(const struct firmware *fw)
+{
+	u32 cfg_offset;
+	struct taiko_mbhc_imped_detect_cfg *imped_cfg;
+	struct taiko_mbhc_btn_detect_cfg *btn_cfg;
+
+	if (fw->size < TAIKO_MBHC_CAL_MIN_SIZE)
+		return false;
+
+	/* previous check guarantees that there is enough fw data up
+	 * to num_btn
+	 */
+	btn_cfg = TAIKO_MBHC_CAL_BTN_DET_PTR(fw->data);
+	cfg_offset = (u32) ((void *) btn_cfg - (void *) fw->data);
+	if (fw->size < (cfg_offset + TAIKO_MBHC_CAL_BTN_SZ(btn_cfg)))
+		return false;
+
+	/* previous check guarantees that there is enough fw data up
+	 * to start of impedance detection configuration
+	 */
+	imped_cfg = TAIKO_MBHC_CAL_IMPED_DET_PTR(fw->data);
+	cfg_offset = (u32) ((void *) imped_cfg - (void *) fw->data);
+
+	if (fw->size < (cfg_offset + TAIKO_MBHC_CAL_IMPED_MIN_SZ))
+		return false;
+
+	if (fw->size < (cfg_offset + TAIKO_MBHC_CAL_IMPED_SZ(imped_cfg)))
+		return false;
+
+	return true;
+}
+
+/* called under codec_resource_lock acquisition */
+static int taiko_determine_button(const struct taiko_priv *priv,
+				  const s32 micmv)
+{
+	s16 *v_btn_low, *v_btn_high;
+	struct taiko_mbhc_btn_detect_cfg *btn_det;
+	int i, btn = -1;
+
+	btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(priv->mbhc_cfg.calibration);
+	v_btn_low = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_V_BTN_LOW);
+	v_btn_high = taiko_mbhc_cal_btn_det_mp(btn_det,
+				TAIKO_BTN_DET_V_BTN_HIGH);
+
+	for (i = 0; i < btn_det->num_btn; i++) {
+		if ((v_btn_low[i] <= micmv) && (v_btn_high[i] >= micmv)) {
+			btn = i;
+			break;
+		}
+	}
+
+	if (btn == -1)
+		pr_debug("%s: couldn't find button number for mic mv %d\n",
+			 __func__, micmv);
+
+	return btn;
+}
+
+static int taiko_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 taiko_dce_handler(int irq, void *data)
+{
+	int i, mask;
+	short dce, sta;
+	s32 mv, mv_s, stamv_s;
+	bool vddio;
+	int btn = -1, meas = 0;
+	struct taiko_priv *priv = data;
+	const struct taiko_mbhc_btn_detect_cfg *d =
+	    TAIKO_MBHC_CAL_BTN_DET_PTR(priv->mbhc_cfg.calibration);
+	short btnmeas[d->n_btn_meas + 1];
+	struct snd_soc_codec *codec = priv->codec;
+	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
+	int n_btn_meas = d->n_btn_meas;
+	u8 mbhc_status = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B1_STATUS) & 0x3E;
+
+	pr_debug("%s: enter\n", __func__);
+
+	TAIKO_ACQUIRE_LOCK(priv->codec_resource_lock);
+	if (priv->mbhc_state == MBHC_STATE_POTENTIAL_RECOVERY) {
+		pr_debug("%s: mbhc is being recovered, skip button press\n",
+			 __func__);
+		goto done;
+	}
+
+	priv->mbhc_state = MBHC_STATE_POTENTIAL;
+
+	if (!priv->mbhc_polling_active) {
+		pr_warn("%s: mbhc polling is not active, skip button press\n",
+			__func__);
+		goto done;
+	}
+
+	dce = taiko_codec_read_dce_result(codec);
+	mv = taiko_codec_sta_dce_v(codec, 1, dce);
+
+	/* If GPIO interrupt already kicked in, ignore button press */
+	if (priv->in_gpio_handler) {
+		pr_debug("%s: GPIO State Changed, ignore button press\n",
+			 __func__);
+		btn = -1;
+		goto done;
+	}
+
+	vddio = (priv->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
+		 priv->mbhc_micbias_switched);
+	mv_s = vddio ? taiko_scale_v_micb_vddio(priv, mv, false) : mv;
+
+	if (mbhc_status != TAIKO_MBHC_STATUS_REL_DETECTION) {
+		if (priv->mbhc_last_resume &&
+		    !time_after(jiffies, priv->mbhc_last_resume + HZ)) {
+			pr_debug("%s: Button is already released shortly after resume\n",
+				__func__);
+			n_btn_meas = 0;
+		} else {
+			pr_debug("%s: Button is already released without resume",
+				__func__);
+			sta = taiko_codec_read_sta_result(codec);
+			stamv_s = taiko_codec_sta_dce_v(codec, 0, sta);
+			if (vddio)
+				stamv_s = taiko_scale_v_micb_vddio(priv,
+								   stamv_s,
+								   false);
+			btn = taiko_determine_button(priv, mv_s);
+			if (btn != taiko_determine_button(priv, stamv_s))
+				btn = -1;
+			goto done;
+		}
+	}
+
+	/* determine pressed button */
+	btnmeas[meas++] = taiko_determine_button(priv, mv_s);
+	pr_debug("%s: meas %d - DCE %d,%d,%d button %d\n", __func__,
+		 meas - 1, dce, mv, mv_s, btnmeas[meas - 1]);
+	if (n_btn_meas == 0)
+		btn = btnmeas[0];
+	for (; ((d->n_btn_meas) && (meas < (d->n_btn_meas + 1))); meas++) {
+		dce = taiko_codec_sta_dce(codec, 1, false);
+		mv = taiko_codec_sta_dce_v(codec, 1, dce);
+		mv_s = vddio ? taiko_scale_v_micb_vddio(priv, mv, false) : mv;
+
+		btnmeas[meas] = taiko_determine_button(priv, mv_s);
+		pr_debug("%s: meas %d - DCE %d,%d,%d button %d\n",
+			 __func__, meas, dce, mv, mv_s, 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;
+			} else if ((n_btn_meas - meas) < (d->n_btn_con - 1)) {
+				/* if left measurements are less than n_btn_con,
+				 * it's impossible to find button number */
+				break;
+			}
+		}
+	}
+
+	if (btn >= 0) {
+		if (priv->in_gpio_handler) {
+			pr_debug(
+			"%s: GPIO already triggered, ignore button press\n",
+			__func__);
+			goto done;
+		}
+		mask = taiko_get_button_mask(btn);
+		priv->buttons_pressed |= mask;
+		wcd9xxx_lock_sleep(core);
+		if (schedule_delayed_work(&priv->mbhc_btn_dwork,
+					  msecs_to_jiffies(400)) == 0) {
+			WARN(1, "Button pressed twice without release event\n");
+			wcd9xxx_unlock_sleep(core);
+		}
+	} else {
+		pr_debug("%s: bogus button press, too short press?\n",
+			 __func__);
+	}
+
+ done:
+	pr_debug("%s: leave\n", __func__);
+	TAIKO_RELEASE_LOCK(priv->codec_resource_lock);
+	return IRQ_HANDLED;
+}
+
+static int taiko_is_fake_press(struct taiko_priv *priv)
+{
+	int i;
+	int r = 0;
+	struct snd_soc_codec *codec = priv->codec;
+	const int dces = MBHC_NUM_DCE_PLUG_DETECT;
+	s16 mb_v, v_ins_hu, v_ins_h;
+
+	v_ins_hu = taiko_get_current_v_ins(priv, true);
+	v_ins_h = taiko_get_current_v_ins(priv, false);
+
+	for (i = 0; i < dces; i++) {
+		usleep_range(10000, 10000);
+		if (i == 0) {
+			mb_v = taiko_codec_sta_dce(codec, 0, true);
+			pr_debug("%s: STA[0]: %d,%d\n", __func__, mb_v,
+				 taiko_codec_sta_dce_v(codec, 0, mb_v));
+			if (mb_v < (s16)priv->mbhc_data.v_b1_hu ||
+			    mb_v > v_ins_hu) {
+				r = 1;
+				break;
+			}
+		} else {
+			mb_v = taiko_codec_sta_dce(codec, 1, true);
+			pr_debug("%s: DCE[%d]: %d,%d\n", __func__, i, mb_v,
+				 taiko_codec_sta_dce_v(codec, 1, mb_v));
+			if (mb_v < (s16)priv->mbhc_data.v_b1_h ||
+			    mb_v > v_ins_h) {
+				r = 1;
+				break;
+			}
+		}
+	}
+
+	return r;
+}
+
+static irqreturn_t taiko_release_handler(int irq, void *data)
+{
+	int ret;
+	struct taiko_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+
+	pr_debug("%s: enter\n", __func__);
+
+	TAIKO_ACQUIRE_LOCK(priv->codec_resource_lock);
+	priv->mbhc_state = MBHC_STATE_RELEASE;
+
+	taiko_codec_drive_v_to_micbias(codec, 10000);
+
+	if (priv->buttons_pressed & TAIKO_JACK_BUTTON_MASK) {
+		ret = taiko_cancel_btn_work(priv);
+		if (ret == 0) {
+			pr_debug("%s: Reporting long button release event\n",
+				 __func__);
+			if (priv->mbhc_cfg.button_jack)
+				taiko_snd_soc_jack_report(priv,
+						  priv->mbhc_cfg.button_jack, 0,
+						  priv->buttons_pressed);
+		} else {
+			if (taiko_is_fake_press(priv)) {
+				pr_debug("%s: Fake button press interrupt\n",
+					 __func__);
+			} else if (priv->mbhc_cfg.button_jack) {
+				if (priv->in_gpio_handler) {
+					pr_debug("%s: GPIO kicked in, ignore\n",
+						 __func__);
+				} else {
+					pr_debug(
+					"%s: Reporting short button press and release\n",
+					 __func__);
+					taiko_snd_soc_jack_report(priv,
+						     priv->mbhc_cfg.button_jack,
+						     priv->buttons_pressed,
+						     priv->buttons_pressed);
+					taiko_snd_soc_jack_report(priv,
+						  priv->mbhc_cfg.button_jack, 0,
+						  priv->buttons_pressed);
+				}
+			}
+		}
+
+		priv->buttons_pressed &= ~TAIKO_JACK_BUTTON_MASK;
+	}
+
+	taiko_codec_calibrate_hs_polling(codec);
+
+	if (priv->mbhc_cfg.gpio)
+		msleep(TAIKO_MBHC_GPIO_REL_DEBOUNCE_TIME_MS);
+
+	taiko_codec_start_hs_polling(codec);
+
+	pr_debug("%s: leave\n", __func__);
+	TAIKO_RELEASE_LOCK(priv->codec_resource_lock);
+	return IRQ_HANDLED;
+}
+
+static void taiko_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	const struct taiko_mbhc_general_cfg *generic =
+	    TAIKO_MBHC_CAL_GENERAL_PTR(taiko->mbhc_cfg.calibration);
+
+	if (!taiko->mclk_enabled && !taiko->mbhc_polling_active)
+		taiko_codec_enable_config_mode(codec, 1);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
+
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
+
+	usleep_range(generic->t_shutdown_plug_rem,
+		     generic->t_shutdown_plug_rem);
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
+	if (!taiko->mclk_enabled && !taiko->mbhc_polling_active)
+		taiko_codec_enable_config_mode(codec, 0);
+
+	snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x00);
+}
+
+static void taiko_codec_cleanup_hs_polling(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	taiko_codec_shutdown_hs_removal_detect(codec);
+
+	if (!taiko->mclk_enabled) {
+		taiko_codec_disable_clock_block(codec);
+		taiko_codec_enable_bandgap(codec, TAIKO_BANDGAP_OFF);
+	}
+
+	taiko->mbhc_polling_active = false;
+	taiko->mbhc_state = MBHC_STATE_NONE;
+}
+
+static irqreturn_t taiko_hphl_ocp_irq(int irq, void *data)
+{
+	struct taiko_priv *taiko = data;
+	struct snd_soc_codec *codec;
+
+	pr_info("%s: received HPHL OCP irq\n", __func__);
+
+	if (taiko) {
+		codec = taiko->codec;
+		if (taiko->hphlocp_cnt++ < TAIKO_OCP_ATTEMPT) {
+			pr_info("%s: retry\n", __func__);
+			snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10,
+					    0x00);
+			snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10,
+					    0x10);
+		} else {
+			wcd9xxx_disable_irq(codec->control_data,
+					  TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+			taiko->hphlocp_cnt = 0;
+			taiko->hph_status |= SND_JACK_OC_HPHL;
+			if (taiko->mbhc_cfg.headset_jack)
+				taiko_snd_soc_jack_report(taiko,
+						   taiko->mbhc_cfg.headset_jack,
+						   taiko->hph_status,
+						   TAIKO_JACK_MASK);
+		}
+	} else {
+		pr_err("%s: Bad taiko private data\n", __func__);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t taiko_hphr_ocp_irq(int irq, void *data)
+{
+	struct taiko_priv *taiko = data;
+	struct snd_soc_codec *codec;
+
+	pr_info("%s: received HPHR OCP irq\n", __func__);
+
+	if (taiko) {
+		codec = taiko->codec;
+		if (taiko->hphrocp_cnt++ < TAIKO_OCP_ATTEMPT) {
+			pr_info("%s: retry\n", __func__);
+			snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10,
+					    0x00);
+			snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10,
+					    0x10);
+		} else {
+			wcd9xxx_disable_irq(codec->control_data,
+					  TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+			taiko->hphrocp_cnt = 0;
+			taiko->hph_status |= SND_JACK_OC_HPHR;
+			if (taiko->mbhc_cfg.headset_jack)
+				taiko_snd_soc_jack_report(taiko,
+						   taiko->mbhc_cfg.headset_jack,
+						   taiko->hph_status,
+						   TAIKO_JACK_MASK);
+		}
+	} else {
+		pr_err("%s: Bad taiko private data\n", __func__);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static bool taiko_is_inval_ins_range(struct snd_soc_codec *codec,
+				     s32 mic_volt, bool highhph, bool *highv)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	bool invalid = false;
+	s16 v_hs_max;
+
+	/* Perform this check only when the high voltage headphone
+	 * needs to be considered as invalid
+	 */
+	v_hs_max = taiko_get_current_v_hs_max(taiko);
+	*highv = mic_volt > v_hs_max;
+	if (!highhph && *highv)
+		invalid = true;
+	else if (mic_volt < taiko->mbhc_data.v_inval_ins_high &&
+		 (mic_volt > taiko->mbhc_data.v_inval_ins_low))
+		invalid = true;
+
+	return invalid;
+}
+
+static bool taiko_is_inval_ins_delta(struct snd_soc_codec *codec,
+				     int mic_volt, int mic_volt_prev,
+				     int threshold)
+{
+	return abs(mic_volt - mic_volt_prev) > threshold;
+}
+
+/* called under codec_resource_lock acquisition */
+void taiko_find_plug_and_report(struct snd_soc_codec *codec,
+				enum taiko_mbhc_plug_type plug_type)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	if (plug_type == PLUG_TYPE_HEADPHONE &&
+	    taiko->current_plug == PLUG_TYPE_NONE) {
+		/* Nothing was reported previously
+		 * report a headphone or unsupported
+		 */
+		taiko_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
+		taiko_codec_cleanup_hs_polling(codec);
+	} else if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
+		if (taiko->current_plug == PLUG_TYPE_HEADSET)
+			taiko_codec_report_plug(codec, 0, SND_JACK_HEADSET);
+		else if (taiko->current_plug == PLUG_TYPE_HEADPHONE)
+			taiko_codec_report_plug(codec, 0, SND_JACK_HEADPHONE);
+
+		taiko_codec_report_plug(codec, 1, SND_JACK_UNSUPPORTED);
+		taiko_codec_cleanup_hs_polling(codec);
+	} else if (plug_type == PLUG_TYPE_HEADSET) {
+		/* If Headphone was reported previously, this will
+		 * only report the mic line
+		 */
+		taiko_codec_report_plug(codec, 1, SND_JACK_HEADSET);
+		msleep(100);
+		taiko_codec_start_hs_polling(codec);
+	} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
+		if (taiko->current_plug == PLUG_TYPE_NONE)
+			taiko_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
+		taiko_codec_cleanup_hs_polling(codec);
+		pr_debug("setup mic trigger for further detection\n");
+		taiko->lpi_enabled = true;
+		taiko_codec_enable_hs_detect(codec, 1,
+					     MBHC_USE_MB_TRIGGER |
+					     MBHC_USE_HPHL_TRIGGER,
+					     false);
+	} else {
+		WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
+		     taiko->current_plug, plug_type);
+	}
+}
+
+/* should be called under interrupt context that hold suspend */
+static void taiko_schedule_hs_detect_plug(struct taiko_priv *taiko)
+{
+	pr_debug("%s: scheduling taiko_hs_correct_gpio_plug\n", __func__);
+	taiko->hs_detect_work_stop = false;
+	wcd9xxx_lock_sleep(taiko->codec->control_data);
+	schedule_work(&taiko->hs_correct_plug_work);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_cancel_hs_detect_plug(struct taiko_priv *taiko)
+{
+	pr_debug("%s: canceling hs_correct_plug_work\n", __func__);
+	taiko->hs_detect_work_stop = true;
+	wmb();
+	TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+	if (cancel_work_sync(&taiko->hs_correct_plug_work)) {
+		pr_debug("%s: hs_correct_plug_work is canceled\n", __func__);
+		wcd9xxx_unlock_sleep(taiko->codec->control_data);
+	}
+	TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+}
+
+static bool taiko_hs_gpio_level_remove(struct taiko_priv *taiko)
+{
+	return (gpio_get_value_cansleep(taiko->mbhc_cfg.gpio) !=
+		taiko->mbhc_cfg.gpio_level_insert);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_hphr_gnd_switch(struct snd_soc_codec *codec, bool on)
+{
+	snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x01, on);
+	if (on)
+		usleep_range(5000, 5000);
+}
+
+/* called under codec_resource_lock acquisition and mbhc override = 1 */
+static enum taiko_mbhc_plug_type
+taiko_codec_get_plug_type(struct snd_soc_codec *codec, bool highhph)
+{
+	int i;
+	bool gndswitch, vddioswitch;
+	int scaled;
+	struct taiko_mbhc_plug_type_cfg *plug_type_ptr;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	const bool vddio = (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV);
+	int num_det = (MBHC_NUM_DCE_PLUG_DETECT + vddio);
+	enum taiko_mbhc_plug_type plug_type[num_det];
+	s16 mb_v[num_det];
+	s32 mic_mv[num_det];
+	bool inval;
+	bool highdelta;
+	bool ahighv = false, highv;
+
+	/* make sure override is on */
+	WARN_ON(!(snd_soc_read(codec, TAIKO_A_CDC_MBHC_B1_CTL) & 0x04));
+
+	/* GND and MIC swap detection requires at least 2 rounds of DCE */
+	BUG_ON(num_det < 2);
+
+	plug_type_ptr =
+	    TAIKO_MBHC_CAL_PLUG_TYPE_PTR(taiko->mbhc_cfg.calibration);
+
+	plug_type[0] = PLUG_TYPE_INVALID;
+
+	/* performs DCEs for N times
+	 * 1st: check if voltage is in invalid range
+	 * 2nd - N-2nd: check voltage range and delta
+	 * N-1st: check voltage range, delta with HPHR GND switch
+	 * Nth: check voltage range with VDDIO switch if micbias V != vddio V*/
+	for (i = 0; i < num_det; i++) {
+		gndswitch = (i == (num_det - 1 - vddio));
+		vddioswitch = (vddio && ((i == num_det - 1) ||
+					 (i == num_det - 2)));
+		if (i == 0) {
+			mb_v[i] = taiko_codec_setup_hs_polling(codec);
+			mic_mv[i] = taiko_codec_sta_dce_v(codec, 1 , mb_v[i]);
+			inval = taiko_is_inval_ins_range(codec, mic_mv[i],
+							 highhph, &highv);
+			ahighv |= highv;
+			scaled = mic_mv[i];
+		} else {
+			if (vddioswitch)
+				__taiko_codec_switch_micbias(taiko->codec, 1,
+							     false, false);
+			if (gndswitch)
+				taiko_codec_hphr_gnd_switch(codec, true);
+			mb_v[i] = __taiko_codec_sta_dce(codec, 1, true, true);
+			mic_mv[i] = taiko_codec_sta_dce_v(codec, 1 , mb_v[i]);
+			if (vddioswitch)
+				scaled = taiko_scale_v_micb_vddio(taiko,
+								  mic_mv[i],
+								  false);
+			else
+				scaled = mic_mv[i];
+			/* !gndswitch & vddioswitch means the previous DCE
+			 * was done with gndswitch, don't compare with DCE
+			 * with gndswitch */
+			highdelta = taiko_is_inval_ins_delta(codec, scaled,
+					mic_mv[i - !gndswitch - vddioswitch],
+					TAIKO_MBHC_FAKE_INS_DELTA_SCALED_MV);
+			inval = (taiko_is_inval_ins_range(codec, mic_mv[i],
+							  highhph, &highv) ||
+				 highdelta);
+			ahighv |= highv;
+			if (gndswitch)
+				taiko_codec_hphr_gnd_switch(codec, false);
+			if (vddioswitch)
+				__taiko_codec_switch_micbias(taiko->codec, 0,
+							     false, false);
+			/* claim UNSUPPORTED plug insertion when
+			 * good headset is detected but HPHR GND switch makes
+			 * delta difference */
+			if (i == (num_det - 2) && highdelta && !ahighv)
+				plug_type[0] = PLUG_TYPE_GND_MIC_SWAP;
+			else if (i == (num_det - 1) && inval)
+				plug_type[0] = PLUG_TYPE_INVALID;
+		}
+		pr_debug("%s: DCE #%d, %04x, V %d, scaled V %d, GND %d, VDDIO %d, inval %d\n",
+			__func__, i + 1, mb_v[i] & 0xffff, mic_mv[i], scaled,
+			gndswitch, vddioswitch, inval);
+		/* don't need to run further DCEs */
+		if (ahighv && inval)
+			break;
+		mic_mv[i] = scaled;
+	}
+
+	for (i = 0; (plug_type[0] != PLUG_TYPE_GND_MIC_SWAP && !inval) &&
+		     i < num_det; i++) {
+		/*
+		 * If we are here, means none of the all
+		 * measurements are fake, continue plug type detection.
+		 * If all three measurements do not produce same
+		 * plug type, restart insertion detection
+		 */
+		if (mic_mv[i] < plug_type_ptr->v_no_mic) {
+			plug_type[i] = PLUG_TYPE_HEADPHONE;
+			pr_debug("%s: Detect attempt %d, detected Headphone\n",
+				 __func__, i);
+		} else if (highhph && (mic_mv[i] > plug_type_ptr->v_hs_max)) {
+			plug_type[i] = PLUG_TYPE_HIGH_HPH;
+			pr_debug(
+			"%s: Detect attempt %d, detected High Headphone\n",
+			__func__, i);
+		} else {
+			plug_type[i] = PLUG_TYPE_HEADSET;
+			pr_debug("%s: Detect attempt %d, detected Headset\n",
+				 __func__, i);
+		}
+
+		if (i > 0 && (plug_type[i - 1] != plug_type[i])) {
+			pr_err("%s: Detect attempt %d and %d are not same",
+			       __func__, i - 1, i);
+			plug_type[0] = PLUG_TYPE_INVALID;
+			inval = true;
+			break;
+		}
+	}
+
+	pr_debug("%s: Detected plug type %d\n", __func__, plug_type[0]);
+	return plug_type[0];
+}
+
+static void taiko_hs_correct_gpio_plug(struct work_struct *work)
+{
+	struct taiko_priv *taiko;
+	struct snd_soc_codec *codec;
+	int retry = 0, pt_gnd_mic_swap_cnt = 0;
+	bool correction = false;
+	enum taiko_mbhc_plug_type plug_type;
+	unsigned long timeout;
+
+	taiko = container_of(work, struct taiko_priv, hs_correct_plug_work);
+	codec = taiko->codec;
+
+	pr_debug("%s: enter\n", __func__);
+	taiko->mbhc_cfg.mclk_cb_fn(codec, 1, false);
+
+	/* Keep override on during entire plug type correction work.
+	 *
+	 * This is okay under the assumption that any GPIO irqs which use
+	 * MBHC block cancel and sync this work so override is off again
+	 * prior to GPIO interrupt handler's MBHC block usage.
+	 * Also while this correction work is running, we can guarantee
+	 * DAPM doesn't use any MBHC block as this work only runs with
+	 * headphone detection.
+	 */
+	taiko_turn_onoff_override(codec, true);
+
+	timeout = jiffies + msecs_to_jiffies(TAIKO_HS_DETECT_PLUG_TIME_MS);
+	while (!time_after(jiffies, timeout)) {
+		++retry;
+		rmb();
+		if (taiko->hs_detect_work_stop) {
+			pr_debug("%s: stop requested\n", __func__);
+			break;
+		}
+
+		msleep(TAIKO_HS_DETECT_PLUG_INERVAL_MS);
+		if (taiko_hs_gpio_level_remove(taiko)) {
+			pr_debug("%s: GPIO value is low\n", __func__);
+			break;
+		}
+
+		/* can race with removal interrupt */
+		TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+		plug_type = taiko_codec_get_plug_type(codec, true);
+		TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+
+		if (plug_type == PLUG_TYPE_INVALID) {
+			pr_debug("Invalid plug in attempt # %d\n", retry);
+			if (retry == NUM_ATTEMPTS_TO_REPORT &&
+			    taiko->current_plug == PLUG_TYPE_NONE) {
+				taiko_codec_report_plug(codec, 1,
+							SND_JACK_HEADPHONE);
+			}
+		} else if (plug_type == PLUG_TYPE_HEADPHONE) {
+			pr_debug("Good headphone detected, continue polling mic\n");
+			if (taiko->current_plug == PLUG_TYPE_NONE)
+				taiko_codec_report_plug(codec, 1,
+							SND_JACK_HEADPHONE);
+		} else {
+			if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
+				pt_gnd_mic_swap_cnt++;
+				if (pt_gnd_mic_swap_cnt <
+				    TAIKO_MBHC_GND_MIC_SWAP_THRESHOLD)
+					continue;
+				else if (pt_gnd_mic_swap_cnt >
+					 TAIKO_MBHC_GND_MIC_SWAP_THRESHOLD) {
+					/* This is due to GND/MIC switch didn't
+					 * work,  Report unsupported plug */
+				} else if (taiko->mbhc_cfg.swap_gnd_mic) {
+					/* if switch is toggled, check again,
+					 * otherwise report unsupported plug */
+					if (taiko->mbhc_cfg.swap_gnd_mic(codec))
+						continue;
+				}
+			} else
+				pt_gnd_mic_swap_cnt = 0;
+
+			TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+			/* Turn off override */
+			taiko_turn_onoff_override(codec, false);
+			/* The valid plug also includes PLUG_TYPE_GND_MIC_SWAP
+			 */
+			taiko_find_plug_and_report(codec, plug_type);
+			TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+			pr_debug("Attempt %d found correct plug %d\n", retry,
+				 plug_type);
+			correction = true;
+			break;
+		}
+	}
+
+	/* Turn off override */
+	if (!correction)
+		taiko_turn_onoff_override(codec, false);
+
+	taiko->mbhc_cfg.mclk_cb_fn(codec, 0, false);
+	pr_debug("%s: leave\n", __func__);
+	/* unlock sleep */
+	wcd9xxx_unlock_sleep(taiko->codec->control_data);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_decide_gpio_plug(struct snd_soc_codec *codec)
+{
+	enum taiko_mbhc_plug_type plug_type;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: enter\n", __func__);
+
+	taiko_turn_onoff_override(codec, true);
+	plug_type = taiko_codec_get_plug_type(codec, true);
+	taiko_turn_onoff_override(codec, false);
+
+	if (taiko_hs_gpio_level_remove(taiko)) {
+		pr_debug("%s: GPIO value is low when determining plug\n",
+			 __func__);
+		return;
+	}
+
+	if (plug_type == PLUG_TYPE_INVALID ||
+	    plug_type == PLUG_TYPE_GND_MIC_SWAP) {
+		taiko_schedule_hs_detect_plug(taiko);
+	} else if (plug_type == PLUG_TYPE_HEADPHONE) {
+		taiko_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
+
+		taiko_schedule_hs_detect_plug(taiko);
+	} else {
+		pr_debug("%s: Valid plug found, determine plug type %d\n",
+			 __func__, plug_type);
+		taiko_find_plug_and_report(codec, plug_type);
+	}
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_detect_plug_type(struct snd_soc_codec *codec)
+{
+	enum taiko_mbhc_plug_type plug_type;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	const struct taiko_mbhc_plug_detect_cfg *plug_det =
+	    TAIKO_MBHC_CAL_PLUG_DET_PTR(taiko->mbhc_cfg.calibration);
+
+	/* Turn on the override,
+	 * taiko_codec_setup_hs_polling requires override on */
+	taiko_turn_onoff_override(codec, true);
+
+	if (plug_det->t_ins_complete > 20)
+		msleep(plug_det->t_ins_complete);
+	else
+		usleep_range(plug_det->t_ins_complete * 1000,
+			     plug_det->t_ins_complete * 1000);
+
+	if (taiko->mbhc_cfg.gpio) {
+		/* Turn off the override */
+		taiko_turn_onoff_override(codec, false);
+		if (taiko_hs_gpio_level_remove(taiko))
+			pr_debug(
+			"%s: GPIO value is low when determining plug\n",
+			__func__);
+		else
+			taiko_codec_decide_gpio_plug(codec);
+		return;
+	}
+
+	plug_type = taiko_codec_get_plug_type(codec, false);
+	taiko_turn_onoff_override(codec, false);
+
+	if (plug_type == PLUG_TYPE_INVALID) {
+		pr_debug("%s: Invalid plug type detected\n", __func__);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
+		taiko_codec_cleanup_hs_polling(codec);
+		taiko_codec_enable_hs_detect(codec, 1,
+					     MBHC_USE_MB_TRIGGER |
+					     MBHC_USE_HPHL_TRIGGER, false);
+	} else if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
+		pr_debug("%s: GND-MIC swapped plug type detected\n", __func__);
+		taiko_codec_report_plug(codec, 1, SND_JACK_UNSUPPORTED);
+		taiko_codec_cleanup_hs_polling(codec);
+		taiko_codec_enable_hs_detect(codec, 0, 0, false);
+	} else if (plug_type == PLUG_TYPE_HEADPHONE) {
+		pr_debug("%s: Headphone Detected\n", __func__);
+		taiko_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
+		taiko_codec_cleanup_hs_polling(codec);
+		taiko_codec_enable_hs_detect(codec, 0, 0, false);
+	} else if (plug_type == PLUG_TYPE_HEADSET) {
+		pr_debug("%s: Headset detected\n", __func__);
+		taiko_codec_report_plug(codec, 1, SND_JACK_HEADSET);
+
+		/* avoid false button press detect */
+		msleep(50);
+		taiko_codec_start_hs_polling(codec);
+	}
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void taiko_hs_insert_irq_gpio(struct taiko_priv *priv, bool is_removal)
+{
+	struct snd_soc_codec *codec = priv->codec;
+
+	if (!is_removal) {
+		pr_debug("%s: MIC trigger insertion interrupt\n", __func__);
+
+		rmb();
+		if (priv->lpi_enabled)
+			msleep(100);
+
+		rmb();
+		if (!priv->lpi_enabled) {
+			pr_debug("%s: lpi is disabled\n", __func__);
+		} else if (gpio_get_value_cansleep(priv->mbhc_cfg.gpio) ==
+			   priv->mbhc_cfg.gpio_level_insert) {
+			pr_debug(
+			"%s: Valid insertion, detect plug type\n", __func__);
+			taiko_codec_decide_gpio_plug(codec);
+		} else {
+			pr_debug(
+			"%s: Invalid insertion stop plug detection\n",
+			__func__);
+		}
+	} else {
+		pr_err("%s: GPIO used, invalid MBHC Removal\n", __func__);
+	}
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void taiko_hs_insert_irq_nogpio(struct taiko_priv *priv, bool is_removal,
+				       bool is_mb_trigger)
+{
+	int ret;
+	struct snd_soc_codec *codec = priv->codec;
+	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
+
+	if (is_removal) {
+		/* cancel possiblely running hs detect work */
+		taiko_cancel_hs_detect_plug(priv);
+
+		/*
+		 * If headphone is removed while playback is in progress,
+		 * it is possible that micbias will be switched to VDDIO.
+		 */
+		taiko_codec_switch_micbias(codec, 0);
+		if (priv->current_plug == PLUG_TYPE_HEADPHONE)
+			taiko_codec_report_plug(codec, 0, SND_JACK_HEADPHONE);
+		else if (priv->current_plug == PLUG_TYPE_GND_MIC_SWAP)
+			taiko_codec_report_plug(codec, 0, SND_JACK_UNSUPPORTED);
+		else
+			WARN(1, "%s: Unexpected current plug type %d\n",
+			     __func__, priv->current_plug);
+		taiko_codec_shutdown_hs_removal_detect(codec);
+		taiko_codec_enable_hs_detect(codec, 1,
+					     MBHC_USE_MB_TRIGGER |
+					     MBHC_USE_HPHL_TRIGGER,
+					     true);
+	} else if (is_mb_trigger && !is_removal) {
+		pr_debug("%s: Waiting for Headphone left trigger\n",
+			__func__);
+		wcd9xxx_lock_sleep(core);
+		if (schedule_delayed_work(&priv->mbhc_insert_dwork,
+					  usecs_to_jiffies(1000000)) == 0) {
+			pr_err("%s: mbhc_insert_dwork is already scheduled\n",
+			       __func__);
+			wcd9xxx_unlock_sleep(core);
+		}
+		taiko_codec_enable_hs_detect(codec, 1, MBHC_USE_HPHL_TRIGGER,
+					     false);
+	} else  {
+		ret = cancel_delayed_work(&priv->mbhc_insert_dwork);
+		if (ret != 0) {
+			pr_debug(
+			"%s: Complete plug insertion, Detecting plug type\n",
+			__func__);
+			taiko_codec_detect_plug_type(codec);
+			wcd9xxx_unlock_sleep(core);
+		} else {
+			wcd9xxx_enable_irq(codec->control_data,
+					   TAIKO_IRQ_MBHC_INSERTION);
+			pr_err("%s: Error detecting plug insertion\n",
+			       __func__);
+		}
+	}
+}
+
+static irqreturn_t taiko_hs_insert_irq(int irq, void *data)
+{
+	bool is_mb_trigger, is_removal;
+	struct taiko_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+
+	pr_debug("%s: enter\n", __func__);
+	TAIKO_ACQUIRE_LOCK(priv->codec_resource_lock);
+	wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION);
+
+	is_mb_trigger = !!(snd_soc_read(codec, priv->mbhc_bias_regs.mbhc_reg) &
+					0x10);
+	is_removal = !!(snd_soc_read(codec, TAIKO_A_CDC_MBHC_INT_CTL) & 0x02);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
+
+	/* Turn off both HPH and MIC line schmitt triggers */
+	snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
+	snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x13, 0x00);
+	snd_soc_update_bits(codec, priv->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
+
+	if (priv->mbhc_cfg.gpio)
+		taiko_hs_insert_irq_gpio(priv, is_removal);
+	else
+		taiko_hs_insert_irq_nogpio(priv, is_removal, is_mb_trigger);
+
+	TAIKO_RELEASE_LOCK(priv->codec_resource_lock);
+	return IRQ_HANDLED;
+}
+
+static bool is_valid_mic_voltage(struct snd_soc_codec *codec, s32 mic_mv)
+{
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	const struct taiko_mbhc_plug_type_cfg *plug_type =
+	    TAIKO_MBHC_CAL_PLUG_TYPE_PTR(taiko->mbhc_cfg.calibration);
+	const s16 v_hs_max = taiko_get_current_v_hs_max(taiko);
+
+	return (!(mic_mv > 10 && mic_mv < 80) && (mic_mv > plug_type->v_no_mic)
+		&& (mic_mv < v_hs_max)) ? true : false;
+}
+
+/* called under codec_resource_lock acquisition
+ * returns true if mic voltage range is back to normal insertion
+ * returns false either if timedout or removed */
+static bool taiko_hs_remove_settle(struct snd_soc_codec *codec)
+{
+	int i;
+	bool timedout, settled = false;
+	s32 mic_mv[MBHC_NUM_DCE_PLUG_DETECT];
+	short mb_v[MBHC_NUM_DCE_PLUG_DETECT];
+	unsigned long retry = 0, timeout;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	const s16 v_hs_max = taiko_get_current_v_hs_max(taiko);
+
+	timeout = jiffies + msecs_to_jiffies(TAIKO_HS_DETECT_PLUG_TIME_MS);
+	while (!(timedout = time_after(jiffies, timeout))) {
+		retry++;
+		if (taiko->mbhc_cfg.gpio && taiko_hs_gpio_level_remove(taiko)) {
+			pr_debug("%s: GPIO indicates removal\n", __func__);
+			break;
+		}
+
+		if (taiko->mbhc_cfg.gpio) {
+			if (retry > 1)
+				msleep(250);
+			else
+				msleep(50);
+		}
+
+		if (taiko->mbhc_cfg.gpio && taiko_hs_gpio_level_remove(taiko)) {
+			pr_debug("%s: GPIO indicates removal\n", __func__);
+			break;
+		}
+
+		for (i = 0; i < MBHC_NUM_DCE_PLUG_DETECT; i++) {
+			mb_v[i] = taiko_codec_sta_dce(codec, 1,  true);
+			mic_mv[i] = taiko_codec_sta_dce_v(codec, 1 , mb_v[i]);
+			pr_debug("%s : DCE run %lu, mic_mv = %d(%x)\n",
+				 __func__, retry, mic_mv[i], mb_v[i]);
+		}
+
+		if (taiko->mbhc_cfg.gpio && taiko_hs_gpio_level_remove(taiko)) {
+			pr_debug("%s: GPIO indicates removal\n", __func__);
+			break;
+		}
+
+		if (taiko->current_plug == PLUG_TYPE_NONE) {
+			pr_debug("%s : headset/headphone is removed\n",
+				 __func__);
+			break;
+		}
+
+		for (i = 0; i < MBHC_NUM_DCE_PLUG_DETECT; i++)
+			if (!is_valid_mic_voltage(codec, mic_mv[i]))
+				break;
+
+		if (i == MBHC_NUM_DCE_PLUG_DETECT) {
+			pr_debug("%s: MIC voltage settled\n", __func__);
+			settled = true;
+			msleep(200);
+			break;
+		}
+
+		/* only for non-GPIO remove irq */
+		if (!taiko->mbhc_cfg.gpio) {
+			for (i = 0; i < MBHC_NUM_DCE_PLUG_DETECT; i++)
+				if (mic_mv[i] < v_hs_max)
+					break;
+			if (i == MBHC_NUM_DCE_PLUG_DETECT) {
+				pr_debug("%s: Headset is removed\n", __func__);
+				break;
+			}
+		}
+	}
+
+	if (timedout)
+		pr_debug("%s: Microphone did not settle in %d seconds\n",
+			 __func__, TAIKO_HS_DETECT_PLUG_TIME_MS);
+	return settled;
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void taiko_hs_remove_irq_gpio(struct taiko_priv *priv)
+{
+	struct snd_soc_codec *codec = priv->codec;
+
+	if (taiko_hs_remove_settle(codec))
+		taiko_codec_start_hs_polling(codec);
+	pr_debug("%s: remove settle done\n", __func__);
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void taiko_hs_remove_irq_nogpio(struct taiko_priv *priv)
+{
+	short bias_value;
+	bool removed = true;
+	struct snd_soc_codec *codec = priv->codec;
+	const struct taiko_mbhc_general_cfg *generic =
+	    TAIKO_MBHC_CAL_GENERAL_PTR(priv->mbhc_cfg.calibration);
+	int min_us = TAIKO_FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
+
+	if (priv->current_plug != PLUG_TYPE_HEADSET) {
+		pr_debug("%s(): Headset is not inserted, ignore removal\n",
+			 __func__);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL,
+				    0x08, 0x08);
+		return;
+	}
+
+	usleep_range(generic->t_shutdown_plug_rem,
+		     generic->t_shutdown_plug_rem);
+
+	do {
+		bias_value = taiko_codec_sta_dce(codec, 1,  true);
+		pr_debug("%s: DCE %d,%d, %d us left\n", __func__, bias_value,
+			 taiko_codec_sta_dce_v(codec, 1, bias_value), min_us);
+		if (bias_value < taiko_get_current_v_ins(priv, false)) {
+			pr_debug("%s: checking false removal\n", __func__);
+			msleep(500);
+			removed = !taiko_hs_remove_settle(codec);
+			pr_debug("%s: headset %sactually removed\n", __func__,
+				 removed ? "" : "not ");
+			break;
+		}
+		min_us -= priv->mbhc_data.t_dce;
+	} while (min_us > 0);
+
+	if (removed) {
+		/* cancel possiblely running hs detect work */
+		taiko_cancel_hs_detect_plug(priv);
+		/*
+		 * If this removal is not false, first check the micbias
+		 * switch status and switch it to LDOH if it is already
+		 * switched to VDDIO.
+		 */
+		taiko_codec_switch_micbias(codec, 0);
+
+		taiko_codec_report_plug(codec, 0, SND_JACK_HEADSET);
+		taiko_codec_cleanup_hs_polling(codec);
+		taiko_codec_enable_hs_detect(codec, 1,
+					     MBHC_USE_MB_TRIGGER |
+					     MBHC_USE_HPHL_TRIGGER,
+					     true);
+	} else {
+		taiko_codec_start_hs_polling(codec);
+	}
+}
+
+static irqreturn_t taiko_hs_remove_irq(int irq, void *data)
+{
+	struct taiko_priv *priv = data;
+	bool vddio;
+	pr_debug("%s: enter, removal interrupt\n", __func__);
+
+	TAIKO_ACQUIRE_LOCK(priv->codec_resource_lock);
+	vddio = (priv->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
+		 priv->mbhc_micbias_switched);
+	if (vddio)
+		__taiko_codec_switch_micbias(priv->codec, 0, false, true);
+
+	if (priv->mbhc_cfg.gpio)
+		taiko_hs_remove_irq_gpio(priv);
+	else
+		taiko_hs_remove_irq_nogpio(priv);
+
+	/* if driver turned off vddio switch and headset is not removed,
+	 * turn on the vddio switch back, if headset is removed then vddio
+	 * switch is off by time now and shouldn't be turn on again from here */
+	if (vddio && priv->current_plug == PLUG_TYPE_HEADSET)
+		__taiko_codec_switch_micbias(priv->codec, 1, true, true);
+	TAIKO_RELEASE_LOCK(priv->codec_resource_lock);
+
+	return IRQ_HANDLED;
+}
+
+static void taiko_mbhc_insert_work(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct taiko_priv *taiko;
+	struct snd_soc_codec *codec;
+	struct wcd9xxx *taiko_core;
+
+	dwork = to_delayed_work(work);
+	taiko = container_of(dwork, struct taiko_priv, mbhc_insert_dwork);
+	codec = taiko->codec;
+	taiko_core = dev_get_drvdata(codec->dev->parent);
+
+	pr_debug("%s:\n", __func__);
+
+	/* Turn off both HPH and MIC line schmitt triggers */
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
+	snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x13, 0x00);
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
+	wcd9xxx_disable_irq_sync(codec->control_data, TAIKO_IRQ_MBHC_INSERTION);
+	taiko_codec_detect_plug_type(codec);
+	wcd9xxx_unlock_sleep(taiko_core);
+}
+
+static void taiko_hs_gpio_handler(struct snd_soc_codec *codec)
+{
+	bool insert;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	bool is_removed = false;
+
+	pr_debug("%s: enter\n", __func__);
+
+	taiko->in_gpio_handler = true;
+	/* Wait here for debounce time */
+	usleep_range(TAIKO_GPIO_IRQ_DEBOUNCE_TIME_US,
+		     TAIKO_GPIO_IRQ_DEBOUNCE_TIME_US);
+
+	TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+
+	/* cancel pending button press */
+	if (taiko_cancel_btn_work(taiko))
+		pr_debug("%s: button press is canceled\n", __func__);
+
+	insert = (gpio_get_value_cansleep(taiko->mbhc_cfg.gpio) ==
+		  taiko->mbhc_cfg.gpio_level_insert);
+	if ((taiko->current_plug == PLUG_TYPE_NONE) && insert) {
+		taiko->lpi_enabled = false;
+		wmb();
+
+		/* cancel detect plug */
+		taiko_cancel_hs_detect_plug(taiko);
+
+		/* Disable Mic Bias pull down and HPH Switch to GND */
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x01,
+				    0x00);
+		snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x01, 0x00);
+		taiko_codec_detect_plug_type(codec);
+	} else if ((taiko->current_plug != PLUG_TYPE_NONE) && !insert) {
+		taiko->lpi_enabled = false;
+		wmb();
+
+		/* cancel detect plug */
+		taiko_cancel_hs_detect_plug(taiko);
+
+		if (taiko->current_plug == PLUG_TYPE_HEADPHONE) {
+			taiko_codec_report_plug(codec, 0, SND_JACK_HEADPHONE);
+			is_removed = true;
+		} else if (taiko->current_plug == PLUG_TYPE_GND_MIC_SWAP) {
+			taiko_codec_report_plug(codec, 0, SND_JACK_UNSUPPORTED);
+			is_removed = true;
+		} else if (taiko->current_plug == PLUG_TYPE_HEADSET) {
+			taiko_codec_pause_hs_polling(codec);
+			taiko_codec_cleanup_hs_polling(codec);
+			taiko_codec_report_plug(codec, 0, SND_JACK_HEADSET);
+			is_removed = true;
+		}
+
+		if (is_removed) {
+			/* Enable Mic Bias pull down and HPH Switch to GND */
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.ctl_reg, 0x01,
+					    0x01);
+			snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x01,
+					    0x01);
+			/* Make sure mic trigger is turned off */
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.ctl_reg,
+					    0x01, 0x01);
+			snd_soc_update_bits(codec,
+					    taiko->mbhc_bias_regs.mbhc_reg,
+					    0x90, 0x00);
+			/* Reset MBHC State Machine */
+			snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL,
+					    0x08, 0x08);
+			snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL,
+					    0x08, 0x00);
+			/* Turn off override */
+			taiko_turn_onoff_override(codec, false);
+		}
+	}
+
+	taiko->in_gpio_handler = false;
+	TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+	pr_debug("%s: leave\n", __func__);
+}
+
+static irqreturn_t taiko_mechanical_plug_detect_irq(int irq, void *data)
+{
+	int r = IRQ_HANDLED;
+	struct snd_soc_codec *codec = data;
+
+	if (unlikely(wcd9xxx_lock_sleep(codec->control_data) == false)) {
+		pr_warn("%s: failed to hold suspend\n", __func__);
+		r = IRQ_NONE;
+	} else {
+		taiko_hs_gpio_handler(codec);
+		wcd9xxx_unlock_sleep(codec->control_data);
+	}
+
+	return r;
+}
+
+static int taiko_mbhc_init_and_calibrate(struct taiko_priv *taiko)
+{
+	int ret = 0;
+	struct snd_soc_codec *codec = taiko->codec;
+
+	taiko->mbhc_cfg.mclk_cb_fn(codec, 1, false);
+	taiko_mbhc_init(codec);
+	taiko_mbhc_cal(codec);
+	taiko_mbhc_calc_thres(codec);
+	taiko->mbhc_cfg.mclk_cb_fn(codec, 0, false);
+	taiko_codec_calibrate_hs_polling(codec);
+	if (!taiko->mbhc_cfg.gpio) {
+		ret = taiko_codec_enable_hs_detect(codec, 1,
+						   MBHC_USE_MB_TRIGGER |
+						   MBHC_USE_HPHL_TRIGGER,
+						   false);
+
+		if (IS_ERR_VALUE(ret))
+			pr_err("%s: Failed to setup MBHC detection\n",
+			       __func__);
+	} else {
+		/* Enable Mic Bias pull down and HPH Switch to GND */
+		snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg,
+				    0x01, 0x01);
+		snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x01, 0x01);
+		INIT_WORK(&taiko->hs_correct_plug_work,
+			  taiko_hs_correct_gpio_plug);
+	}
+
+	if (!IS_ERR_VALUE(ret)) {
+		snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10, 0x10);
+		wcd9xxx_enable_irq(codec->control_data,
+				 TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+		wcd9xxx_enable_irq(codec->control_data,
+				 TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+
+		if (taiko->mbhc_cfg.gpio) {
+			ret = request_threaded_irq(taiko->mbhc_cfg.gpio_irq,
+					       NULL,
+					       taiko_mechanical_plug_detect_irq,
+					       (IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING),
+					       "taiko-gpio", codec);
+			if (!IS_ERR_VALUE(ret)) {
+				ret = enable_irq_wake(taiko->mbhc_cfg.gpio_irq);
+				/* Bootup time detection */
+				taiko_hs_gpio_handler(codec);
+			}
+		}
+	}
+
+	return ret;
+}
+
+static void mbhc_fw_read(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct taiko_priv *taiko;
+	struct snd_soc_codec *codec;
+	const struct firmware *fw;
+	int ret = -1, retry = 0;
+
+	dwork = to_delayed_work(work);
+	taiko = container_of(dwork, struct taiko_priv, mbhc_firmware_dwork);
+	codec = taiko->codec;
+
+	while (retry < MBHC_FW_READ_ATTEMPTS) {
+		retry++;
+		pr_info("%s:Attempt %d to request MBHC firmware\n",
+			__func__, retry);
+		ret = request_firmware(&fw, "wcd9320/wcd9320_mbhc.bin",
+					codec->dev);
+
+		if (ret != 0) {
+			usleep_range(MBHC_FW_READ_TIMEOUT,
+				     MBHC_FW_READ_TIMEOUT);
+		} else {
+			pr_info("%s: MBHC Firmware read succesful\n", __func__);
+			break;
+		}
+	}
+
+	if (ret != 0) {
+		pr_err("%s: Cannot load MBHC firmware use default cal\n",
+			__func__);
+	} else if (taiko_mbhc_fw_validate(fw) == false) {
+		pr_err("%s: Invalid MBHC cal data size use default cal\n",
+			 __func__);
+		release_firmware(fw);
+	} else {
+		taiko->mbhc_cfg.calibration = (void *)fw->data;
+		taiko->mbhc_fw = fw;
+	}
+
+	(void) taiko_mbhc_init_and_calibrate(taiko);
+}
+
+int taiko_hs_detect(struct snd_soc_codec *codec,
+		    const struct taiko_mbhc_config *cfg)
+{
+	struct taiko_priv *taiko;
+	int rc = 0;
+
+	if (!codec || !cfg->calibration) {
+		pr_err("Error: no codec or calibration\n");
+		return -EINVAL;
+	}
+
+	if (cfg->mclk_rate != TAIKO_MCLK_RATE_12288KHZ) {
+		if (cfg->mclk_rate == TAIKO_MCLK_RATE_9600KHZ)
+			pr_err("Error: clock rate %dHz is not yet supported\n",
+			       cfg->mclk_rate);
+		else
+			pr_err("Error: unsupported clock rate %d\n",
+			       cfg->mclk_rate);
+		return -EINVAL;
+	}
+
+	taiko = snd_soc_codec_get_drvdata(codec);
+	taiko->mbhc_cfg = *cfg;
+	taiko->in_gpio_handler = false;
+	taiko->current_plug = PLUG_TYPE_NONE;
+	taiko->lpi_enabled = false;
+	taiko_get_mbhc_micbias_regs(codec, &taiko->mbhc_bias_regs);
+
+	/* Put CFILT in fast mode by default */
+	snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl,
+			    0x40, TAIKO_CFILT_FAST_MODE);
+	INIT_DELAYED_WORK(&taiko->mbhc_firmware_dwork, mbhc_fw_read);
+	INIT_DELAYED_WORK(&taiko->mbhc_btn_dwork, btn_lpress_fn);
+	INIT_WORK(&taiko->hphlocp_work, hphlocp_off_report);
+	INIT_WORK(&taiko->hphrocp_work, hphrocp_off_report);
+	INIT_DELAYED_WORK(&taiko->mbhc_insert_dwork, taiko_mbhc_insert_work);
+
+	if (!taiko->mbhc_cfg.read_fw_bin)
+		rc = taiko_mbhc_init_and_calibrate(taiko);
+	else
+		schedule_delayed_work(&taiko->mbhc_firmware_dwork,
+				      usecs_to_jiffies(MBHC_FW_READ_TIMEOUT));
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(taiko_hs_detect);
+
+static unsigned long slimbus_value;
+
+static irqreturn_t taiko_slimbus_irq(int irq, void *data)
+{
+	struct taiko_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+	int i, j;
+	u8 val;
+
+	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
+		slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
+			TAIKO_SLIM_PGD_PORT_INT_STATUS0 + i);
+		for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
+			val = wcd9xxx_interface_reg_read(codec->control_data,
+				TAIKO_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
+			if (val & 0x1)
+				pr_err_ratelimited(
+				"overflow error on port %x, value %x\n",
+				i*8 + j, val);
+			if (val & 0x2)
+				pr_err_ratelimited(
+				"underflow error on port %x, value %x\n",
+				i*8 + j, val);
+		}
+		wcd9xxx_interface_reg_write(codec->control_data,
+			TAIKO_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int taiko_handle_pdata(struct taiko_priv *taiko)
+{
+	struct snd_soc_codec *codec = taiko->codec;
+	struct wcd9xxx_pdata *pdata = taiko->pdata;
+	int k1, k2, k3, rc = 0;
+	u8 leg_mode = pdata->amic_settings.legacy_mode;
+	u8 txfe_bypass = pdata->amic_settings.txfe_enable;
+	u8 txfe_buff = pdata->amic_settings.txfe_buff;
+	u8 flag = pdata->amic_settings.use_pdata;
+	u8 i = 0, j = 0;
+	u8 val_txfe = 0, value = 0;
+
+	if (!pdata) {
+		rc = -ENODEV;
+		goto done;
+	}
+
+	/* Make sure settings are correct */
+	if ((pdata->micbias.ldoh_v > TAIKO_LDOH_2P85_V) ||
+	    (pdata->micbias.bias1_cfilt_sel > TAIKO_CFILT3_SEL) ||
+	    (pdata->micbias.bias2_cfilt_sel > TAIKO_CFILT3_SEL) ||
+	    (pdata->micbias.bias3_cfilt_sel > TAIKO_CFILT3_SEL) ||
+	    (pdata->micbias.bias4_cfilt_sel > TAIKO_CFILT3_SEL)) {
+		rc = -EINVAL;
+		goto done;
+	}
+
+	/* figure out k value */
+	k1 = taiko_find_k_value(pdata->micbias.ldoh_v,
+		pdata->micbias.cfilt1_mv);
+	k2 = taiko_find_k_value(pdata->micbias.ldoh_v,
+		pdata->micbias.cfilt2_mv);
+	k3 = taiko_find_k_value(pdata->micbias.ldoh_v,
+		pdata->micbias.cfilt3_mv);
+
+	if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
+		rc = -EINVAL;
+		goto done;
+	}
+
+	/* Set voltage level and always use LDO */
+	snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 0x0C,
+		(pdata->micbias.ldoh_v << 2));
+
+	snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_1_VAL, 0xFC,
+		(k1 << 2));
+	snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_2_VAL, 0xFC,
+		(k2 << 2));
+	snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_3_VAL, 0xFC,
+		(k3 << 2));
+
+	snd_soc_update_bits(codec, TAIKO_A_MICB_1_CTL, 0x60,
+		(pdata->micbias.bias1_cfilt_sel << 5));
+	snd_soc_update_bits(codec, TAIKO_A_MICB_2_CTL, 0x60,
+		(pdata->micbias.bias2_cfilt_sel << 5));
+	snd_soc_update_bits(codec, TAIKO_A_MICB_3_CTL, 0x60,
+		(pdata->micbias.bias3_cfilt_sel << 5));
+	snd_soc_update_bits(codec, taiko->reg_addr.micb_4_ctl, 0x60,
+			    (pdata->micbias.bias4_cfilt_sel << 5));
+
+	for (i = 0; i < 6; j++, i += 2) {
+		if (flag & (0x01 << i)) {
+			value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
+			val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
+			val_txfe = val_txfe |
+				((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
+			snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
+				0x10, value);
+			snd_soc_update_bits(codec,
+				TAIKO_A_TX_1_2_TEST_EN + j * 10,
+				0x30, val_txfe);
+		}
+		if (flag & (0x01 << (i + 1))) {
+			value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
+			val_txfe = (txfe_bypass &
+					(0x01 << (i + 1))) ? 0x02 : 0x00;
+			val_txfe |= (txfe_buff &
+					(0x01 << (i + 1))) ? 0x01 : 0x00;
+			snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
+				0x01, value);
+			snd_soc_update_bits(codec,
+				TAIKO_A_TX_1_2_TEST_EN + j * 10,
+				0x03, val_txfe);
+		}
+	}
+	if (flag & 0x40) {
+		value = (leg_mode & 0x40) ? 0x10 : 0x00;
+		value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
+		value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN,
+			0x13, value);
+	}
+
+	if (pdata->ocp.use_pdata) {
+		/* not defined in CODEC specification */
+		if (pdata->ocp.hph_ocp_limit == 1 ||
+			pdata->ocp.hph_ocp_limit == 5) {
+			rc = -EINVAL;
+			goto done;
+		}
+		snd_soc_update_bits(codec, TAIKO_A_RX_COM_OCP_CTL,
+			0x0F, pdata->ocp.num_attempts);
+		snd_soc_write(codec, TAIKO_A_RX_COM_OCP_COUNT,
+			((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
+		snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL,
+			0xE0, (pdata->ocp.hph_ocp_limit << 5));
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+		if (!strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
+			if (pdata->regulator[i].min_uV == 1800000 &&
+			    pdata->regulator[i].max_uV == 1800000) {
+				snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
+					      0x1C);
+			} else if (pdata->regulator[i].min_uV == 2200000 &&
+				   pdata->regulator[i].max_uV == 2200000) {
+				snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
+					      0x1E);
+			} else {
+				pr_err("%s: unsupported CDC_VDDA_RX voltage\n"
+				       "min %d, max %d\n", __func__,
+				       pdata->regulator[i].min_uV,
+				       pdata->regulator[i].max_uV);
+				rc = -EINVAL;
+			}
+			break;
+		}
+	}
+done:
+	return rc;
+}
+
+static const struct taiko_reg_mask_val taiko_1_0_reg_defaults[] = {
+
+	/* Taiko 1.1 MICBIAS changes */
+	TAIKO_REG_VAL(TAIKO_A_MICB_1_INT_RBIAS, 0x24),
+	TAIKO_REG_VAL(TAIKO_A_MICB_2_INT_RBIAS, 0x24),
+	TAIKO_REG_VAL(TAIKO_A_MICB_3_INT_RBIAS, 0x24),
+
+	/* Taiko 1.1 HPH changes */
+	TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x57),
+	TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_LDO, 0x56),
+
+	/* Taiko 1.1 EAR PA changes */
+	TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0xA6),
+	TAIKO_REG_VAL(TAIKO_A_RX_EAR_GAIN, 0x02),
+	TAIKO_REG_VAL(TAIKO_A_RX_EAR_VCM, 0x03),
+
+
+	/* Taiko 1.1 RX Changes */
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B5_CTL, 0x78),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B5_CTL, 0x78),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B5_CTL, 0x78),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B5_CTL, 0x78),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B5_CTL, 0x78),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B5_CTL, 0x78),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B5_CTL, 0x78),
+
+	/* Taiko 1.1 RX1 and RX2 Changes */
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B6_CTL, 0xA0),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B6_CTL, 0xA0),
+
+	/* Taiko 1.1 RX3 to RX7 Changes */
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B6_CTL, 0x80),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B6_CTL, 0x80),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B6_CTL, 0x80),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B6_CTL, 0x80),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
+
+};
+
+static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
+{
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(taiko_1_0_reg_defaults); i++)
+		snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
+				taiko_1_0_reg_defaults[i].val);
+}
+
+static const struct taiko_reg_mask_val taiko_codec_reg_init_val[] = {
+	/* Initialize current threshold to 350MA
+	 * number of wait and run cycles to 4096
+	 */
+	{TAIKO_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
+	{TAIKO_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+
+	{TAIKO_A_QFUSE_CTL, 0xFF, 0x03},
+
+	/* Initialize gain registers to use register gain */
+	{TAIKO_A_RX_HPH_L_GAIN, 0x10, 0x10},
+	{TAIKO_A_RX_HPH_R_GAIN, 0x10, 0x10},
+	{TAIKO_A_RX_LINE_1_GAIN, 0x10, 0x10},
+	{TAIKO_A_RX_LINE_2_GAIN, 0x10, 0x10},
+	{TAIKO_A_RX_LINE_3_GAIN, 0x10, 0x10},
+	{TAIKO_A_RX_LINE_4_GAIN, 0x10, 0x10},
+
+	/* Initialize mic biases to differential mode */
+	{TAIKO_A_MICB_1_INT_RBIAS, 0x24, 0x24},
+	{TAIKO_A_MICB_2_INT_RBIAS, 0x24, 0x24},
+	{TAIKO_A_MICB_3_INT_RBIAS, 0x24, 0x24},
+
+
+	/* Use 16 bit sample size for TX1 to TX6 */
+	{TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
+	{TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
+	{TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
+	{TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
+	{TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
+	{TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
+
+	/* Use 16 bit sample size for TX7 to TX10 */
+	{TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
+	{TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
+	{TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
+	{TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
+
+	/* Use 16 bit sample size for RX */
+	{TAIKO_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
+	{TAIKO_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0xAA},
+
+	/*enable HPF filter for TX paths */
+	{TAIKO_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
+	{TAIKO_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
+
+	/* config Decimator for DMIC CLK_MODE_1(4.8Mhz@9.6Mhz mclk) */
+	{TAIKO_A_CDC_TX1_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX2_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX3_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX4_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX5_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX6_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX7_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX8_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX9_DMIC_CTL, 0x7, 0x0},
+	{TAIKO_A_CDC_TX10_DMIC_CTL, 0x7, 0x0},
+
+	/* config DMIC clk to CLK_MODE_1 (4.8Mhz@9.6Mhz mclk) */
+	{TAIKO_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x0},
+	{TAIKO_A_CDC_CLK_DMIC_B2_CTL, 0xEE, 0x0},
+};
+
+static void taiko_codec_init_reg(struct snd_soc_codec *codec)
+{
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(taiko_codec_reg_init_val); i++)
+		snd_soc_update_bits(codec, taiko_codec_reg_init_val[i].reg,
+				taiko_codec_reg_init_val[i].mask,
+				taiko_codec_reg_init_val[i].val);
+}
+
+static void taiko_update_reg_address(struct taiko_priv *priv)
+{
+	struct taiko_reg_address *reg_addr = &priv->reg_addr;
+	reg_addr->micb_4_mbhc = TAIKO_A_MICB_4_MBHC;
+	reg_addr->micb_4_int_rbias = TAIKO_A_MICB_4_INT_RBIAS;
+	reg_addr->micb_4_ctl = TAIKO_A_MICB_4_CTL;
+
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int codec_debug_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t codec_debug_write(struct file *filp,
+	const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	char lbuf[32];
+	char *buf;
+	int rc;
+	struct taiko_priv *taiko = filp->private_data;
+
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+	buf = (char *)lbuf;
+	taiko->no_mic_headset_override = (*strsep(&buf, " ") == '0') ?
+					     false : true;
+	return rc;
+}
+
+static ssize_t codec_mbhc_debug_read(struct file *file, char __user *buf,
+				     size_t count, loff_t *pos)
+{
+	const int size = 768;
+	char buffer[size];
+	int n = 0;
+	struct taiko_priv *taiko = file->private_data;
+	struct snd_soc_codec *codec = taiko->codec;
+	const struct mbhc_internal_cal_data *p = &taiko->mbhc_data;
+	const s16 v_ins_hu_cur = taiko_get_current_v_ins(taiko, true);
+	const s16 v_ins_h_cur = taiko_get_current_v_ins(taiko, false);
+
+	n = scnprintf(buffer, size - n, "dce_z = %x(%dmv)\n",  p->dce_z,
+		     taiko_codec_sta_dce_v(codec, 1, p->dce_z));
+	n += scnprintf(buffer + n, size - n, "dce_mb = %x(%dmv)\n",
+		       p->dce_mb, taiko_codec_sta_dce_v(codec, 1, p->dce_mb));
+	n += scnprintf(buffer + n, size - n, "sta_z = %x(%dmv)\n",
+		       p->sta_z, taiko_codec_sta_dce_v(codec, 0, p->sta_z));
+	n += scnprintf(buffer + n, size - n, "sta_mb = %x(%dmv)\n",
+		       p->sta_mb, taiko_codec_sta_dce_v(codec, 0, p->sta_mb));
+	n += scnprintf(buffer + n, size - n, "t_dce = %x\n",  p->t_dce);
+	n += scnprintf(buffer + n, size - n, "t_sta = %x\n",  p->t_sta);
+	n += scnprintf(buffer + n, size - n, "micb_mv = %dmv\n",
+		       p->micb_mv);
+	n += scnprintf(buffer + n, size - n, "v_ins_hu = %x(%dmv)%s\n",
+		       p->v_ins_hu,
+		       taiko_codec_sta_dce_v(codec, 0, p->v_ins_hu),
+		       p->v_ins_hu == v_ins_hu_cur ? "*" : "");
+	n += scnprintf(buffer + n, size - n, "v_ins_h = %x(%dmv)%s\n",
+		       p->v_ins_h, taiko_codec_sta_dce_v(codec, 1, p->v_ins_h),
+		       p->v_ins_h == v_ins_h_cur ? "*" : "");
+	n += scnprintf(buffer + n, size - n, "adj_v_ins_hu = %x(%dmv)%s\n",
+		       p->adj_v_ins_hu,
+		       taiko_codec_sta_dce_v(codec, 0, p->adj_v_ins_hu),
+		       p->adj_v_ins_hu == v_ins_hu_cur ? "*" : "");
+	n += scnprintf(buffer + n, size - n, "adj_v_ins_h = %x(%dmv)%s\n",
+		       p->adj_v_ins_h,
+		       taiko_codec_sta_dce_v(codec, 1, p->adj_v_ins_h),
+		       p->adj_v_ins_h == v_ins_h_cur ? "*" : "");
+	n += scnprintf(buffer + n, size - n, "v_b1_hu = %x(%dmv)\n",
+		       p->v_b1_hu, taiko_codec_sta_dce_v(codec, 0, p->v_b1_hu));
+	n += scnprintf(buffer + n, size - n, "v_b1_h = %x(%dmv)\n",
+		       p->v_b1_h, taiko_codec_sta_dce_v(codec, 1, p->v_b1_h));
+	n += scnprintf(buffer + n, size - n, "v_b1_huc = %x(%dmv)\n",
+		       p->v_b1_huc,
+		       taiko_codec_sta_dce_v(codec, 1, p->v_b1_huc));
+	n += scnprintf(buffer + n, size - n, "v_brh = %x(%dmv)\n",
+		       p->v_brh, taiko_codec_sta_dce_v(codec, 1, p->v_brh));
+	n += scnprintf(buffer + n, size - n, "v_brl = %x(%dmv)\n",  p->v_brl,
+		       taiko_codec_sta_dce_v(codec, 0, p->v_brl));
+	n += scnprintf(buffer + n, size - n, "v_no_mic = %x(%dmv)\n",
+		       p->v_no_mic,
+		       taiko_codec_sta_dce_v(codec, 0, p->v_no_mic));
+	n += scnprintf(buffer + n, size - n, "npoll = %d\n",  p->npoll);
+	n += scnprintf(buffer + n, size - n, "nbounce_wait = %d\n",
+		       p->nbounce_wait);
+	n += scnprintf(buffer + n, size - n, "v_inval_ins_low = %d\n",
+		       p->v_inval_ins_low);
+	n += scnprintf(buffer + n, size - n, "v_inval_ins_high = %d\n",
+		       p->v_inval_ins_high);
+	if (taiko->mbhc_cfg.gpio)
+		n += scnprintf(buffer + n, size - n, "GPIO insert = %d\n",
+			       taiko_hs_gpio_level_remove(taiko));
+	buffer[n] = 0;
+
+	return simple_read_from_buffer(buf, count, pos, buffer, n);
+}
+
+static const struct file_operations codec_debug_ops = {
+	.open = codec_debug_open,
+	.write = codec_debug_write,
+};
+
+static const struct file_operations codec_mbhc_debug_ops = {
+	.open = codec_debug_open,
+	.read = codec_mbhc_debug_read,
+};
+#endif
+
+static int taiko_codec_probe(struct snd_soc_codec *codec)
+{
+	struct wcd9xxx *control;
+	struct taiko_priv *taiko;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret = 0;
+	int i;
+	int ch_cnt;
+
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	control = codec->control_data;
+
+	taiko = kzalloc(sizeof(struct taiko_priv), GFP_KERNEL);
+	if (!taiko) {
+		dev_err(codec->dev, "Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	for (i = 0 ; i < NUM_DECIMATORS; i++) {
+		tx_hpf_work[i].taiko = taiko;
+		tx_hpf_work[i].decimator = i + 1;
+		INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+			tx_hpf_corner_freq_callback);
+	}
+
+	/* Make sure mbhc micbias register addresses are zeroed out */
+	memset(&taiko->mbhc_bias_regs, 0,
+		sizeof(struct mbhc_micbias_regs));
+	taiko->mbhc_micbias_switched = false;
+
+	/* Make sure mbhc intenal calibration data is zeroed out */
+	memset(&taiko->mbhc_data, 0,
+		sizeof(struct mbhc_internal_cal_data));
+	taiko->mbhc_data.t_sta_dce = DEFAULT_DCE_STA_WAIT;
+	taiko->mbhc_data.t_dce = DEFAULT_DCE_WAIT;
+	taiko->mbhc_data.t_sta = DEFAULT_STA_WAIT;
+	snd_soc_codec_set_drvdata(codec, taiko);
+
+	taiko->mclk_enabled = false;
+	taiko->bandgap_type = TAIKO_BANDGAP_OFF;
+	taiko->clock_active = false;
+	taiko->config_mode_active = false;
+	taiko->mbhc_polling_active = false;
+	taiko->mbhc_fake_ins_start = 0;
+	taiko->no_mic_headset_override = false;
+	taiko->hs_polling_irq_prepared = false;
+	mutex_init(&taiko->codec_resource_lock);
+	taiko->codec = codec;
+	taiko->mbhc_state = MBHC_STATE_NONE;
+	taiko->mbhc_last_resume = 0;
+	for (i = 0; i < COMPANDER_MAX; i++) {
+		taiko->comp_enabled[i] = 0;
+		taiko->comp_fs[i] = COMPANDER_FS_48KHZ;
+	}
+	taiko->pdata = dev_get_platdata(codec->dev->parent);
+	taiko->intf_type = wcd9xxx_get_intf_type();
+	taiko->aux_pga_cnt = 0;
+	taiko->aux_l_gain = 0x1F;
+	taiko->aux_r_gain = 0x1F;
+	taiko_update_reg_address(taiko);
+	taiko_update_reg_defaults(codec);
+	taiko_codec_init_reg(codec);
+	ret = taiko_handle_pdata(taiko);
+	if (IS_ERR_VALUE(ret)) {
+		pr_err("%s: bad pdata\n", __func__);
+		goto err_pdata;
+	}
+
+	if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+		snd_soc_dapm_new_controls(dapm, taiko_dapm_i2s_widgets,
+			ARRAY_SIZE(taiko_dapm_i2s_widgets));
+		snd_soc_dapm_add_routes(dapm, audio_i2s_map,
+			ARRAY_SIZE(audio_i2s_map));
+	}
+
+	snd_soc_dapm_sync(dapm);
+
+	ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION,
+		taiko_hs_insert_irq, "Headset insert detect", taiko);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TAIKO_IRQ_MBHC_INSERTION);
+		goto err_insert_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION);
+
+	ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_MBHC_REMOVAL,
+		taiko_hs_remove_irq, "Headset remove detect", taiko);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TAIKO_IRQ_MBHC_REMOVAL);
+		goto err_remove_irq;
+	}
+
+	ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL,
+		taiko_dce_handler, "DC Estimation detect", taiko);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TAIKO_IRQ_MBHC_POTENTIAL);
+		goto err_potential_irq;
+	}
+
+	ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_MBHC_RELEASE,
+		taiko_release_handler, "Button Release detect", taiko);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TAIKO_IRQ_MBHC_RELEASE);
+		goto err_release_irq;
+	}
+
+	ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_SLIMBUS,
+		taiko_slimbus_irq, "SLIMBUS Slave", taiko);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TAIKO_IRQ_SLIMBUS);
+		goto err_slimbus_irq;
+	}
+
+	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
+		wcd9xxx_interface_reg_write(codec->control_data,
+			TAIKO_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
+
+	ret = wcd9xxx_request_irq(codec->control_data,
+		TAIKO_IRQ_HPH_PA_OCPL_FAULT, taiko_hphl_ocp_irq,
+		"HPH_L OCP detect", taiko);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+		goto err_hphl_ocp_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+
+	ret = wcd9xxx_request_irq(codec->control_data,
+		TAIKO_IRQ_HPH_PA_OCPR_FAULT, taiko_hphr_ocp_irq,
+		"HPH_R OCP detect", taiko);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+		goto err_hphr_ocp_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+	for (i = 0; i < ARRAY_SIZE(taiko_dai); i++) {
+		switch (taiko_dai[i].id) {
+		case AIF1_PB:
+			ch_cnt = taiko_dai[i].playback.channels_max;
+			break;
+		case AIF1_CAP:
+			ch_cnt = taiko_dai[i].capture.channels_max;
+			break;
+		case AIF2_PB:
+			ch_cnt = taiko_dai[i].playback.channels_max;
+			break;
+		case AIF2_CAP:
+			ch_cnt = taiko_dai[i].capture.channels_max;
+			break;
+		case AIF3_PB:
+			ch_cnt = taiko_dai[i].playback.channels_max;
+			break;
+		case AIF3_CAP:
+			ch_cnt = taiko_dai[i].capture.channels_max;
+			break;
+		default:
+			continue;
+		}
+		taiko->dai[i].ch_num = kzalloc((sizeof(unsigned int)*
+					ch_cnt), GFP_KERNEL);
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	if (ret == 0) {
+		taiko->debugfs_poke =
+		    debugfs_create_file("TRRS", S_IFREG | S_IRUGO, NULL, taiko,
+					&codec_debug_ops);
+		taiko->debugfs_mbhc =
+		    debugfs_create_file("taiko_mbhc", S_IFREG | S_IRUGO,
+					NULL, taiko, &codec_mbhc_debug_ops);
+	}
+#endif
+	codec->ignore_pmdown_time = 1;
+	return ret;
+
+err_hphr_ocp_irq:
+	wcd9xxx_free_irq(codec->control_data,
+			TAIKO_IRQ_HPH_PA_OCPL_FAULT, taiko);
+err_hphl_ocp_irq:
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_SLIMBUS, taiko);
+err_slimbus_irq:
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_RELEASE, taiko);
+err_release_irq:
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL, taiko);
+err_potential_irq:
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_REMOVAL, taiko);
+err_remove_irq:
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION, taiko);
+err_insert_irq:
+err_pdata:
+	mutex_destroy(&taiko->codec_resource_lock);
+	kfree(taiko);
+	return ret;
+}
+static int taiko_codec_remove(struct snd_soc_codec *codec)
+{
+	int i;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_SLIMBUS, taiko);
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_RELEASE, taiko);
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL, taiko);
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_REMOVAL, taiko);
+	wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION, taiko);
+	TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+	taiko_codec_disable_clock_block(codec);
+	TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+	taiko_codec_enable_bandgap(codec, TAIKO_BANDGAP_OFF);
+	if (taiko->mbhc_fw)
+		release_firmware(taiko->mbhc_fw);
+	for (i = 0; i < ARRAY_SIZE(taiko_dai); i++)
+		kfree(taiko->dai[i].ch_num);
+	mutex_destroy(&taiko->codec_resource_lock);
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove(taiko->debugfs_poke);
+	debugfs_remove(taiko->debugfs_mbhc);
+#endif
+	kfree(taiko);
+	return 0;
+}
+static struct snd_soc_codec_driver soc_codec_dev_taiko = {
+	.probe	= taiko_codec_probe,
+	.remove	= taiko_codec_remove,
+
+	.read = taiko_read,
+	.write = taiko_write,
+
+	.readable_register = taiko_readable,
+	.volatile_register = taiko_volatile,
+
+	.reg_cache_size = TAIKO_CACHE_SIZE,
+	.reg_cache_default = taiko_reg_defaults,
+	.reg_word_size = 1,
+
+	.controls = taiko_snd_controls,
+	.num_controls = ARRAY_SIZE(taiko_snd_controls),
+	.dapm_widgets = taiko_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(taiko_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+#ifdef CONFIG_PM
+static int taiko_suspend(struct device *dev)
+{
+	dev_dbg(dev, "%s: system suspend\n", __func__);
+	return 0;
+}
+
+static int taiko_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct taiko_priv *taiko = platform_get_drvdata(pdev);
+	dev_dbg(dev, "%s: system resume\n", __func__);
+	taiko->mbhc_last_resume = jiffies;
+	return 0;
+}
+
+static const struct dev_pm_ops taiko_pm_ops = {
+	.suspend	= taiko_suspend,
+	.resume		= taiko_resume,
+};
+#endif
+
+static int __devinit taiko_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
+			taiko_dai, ARRAY_SIZE(taiko_dai));
+	else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
+			taiko_i2s_dai, ARRAY_SIZE(taiko_i2s_dai));
+	return ret;
+}
+static int __devexit taiko_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+static struct platform_driver taiko_codec_driver = {
+	.probe = taiko_probe,
+	.remove = taiko_remove,
+	.driver = {
+		.name = "taiko_codec",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &taiko_pm_ops,
+#endif
+	},
+};
+
+static int __init taiko_codec_init(void)
+{
+	return platform_driver_register(&taiko_codec_driver);
+}
+
+static void __exit taiko_codec_exit(void)
+{
+	platform_driver_unregister(&taiko_codec_driver);
+}
+
+module_init(taiko_codec_init);
+module_exit(taiko_codec_exit);
+
+MODULE_DESCRIPTION("Taiko codec driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wcd9320.h b/sound/soc/codecs/wcd9320.h
new file mode 100644
index 0000000..739ab17
--- /dev/null
+++ b/sound/soc/codecs/wcd9320.h
@@ -0,0 +1,252 @@
+/* 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 WCD9320_H
+#define WCD9320_H
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+
+#define TAIKO_NUM_REGISTERS 0x400
+#define TAIKO_MAX_REGISTER (TAIKO_NUM_REGISTERS-1)
+#define TAIKO_CACHE_SIZE TAIKO_NUM_REGISTERS
+
+#define TAIKO_REG_VAL(reg, val)		{reg, 0, val}
+
+#define DEFAULT_DCE_STA_WAIT 55
+#define DEFAULT_DCE_WAIT 60000
+#define DEFAULT_STA_WAIT 5000
+#define VDDIO_MICBIAS_MV 1800
+
+#define STA 0
+#define DCE 1
+
+#define TAIKO_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 taiko_reg_readable[TAIKO_CACHE_SIZE];
+extern const u8 taiko_reg_defaults[TAIKO_CACHE_SIZE];
+
+enum taiko_micbias_num {
+	TAIKO_MICBIAS1 = 0,
+	TAIKO_MICBIAS2,
+	TAIKO_MICBIAS3,
+	TAIKO_MICBIAS4,
+};
+
+enum taiko_pid_current {
+	TAIKO_PID_MIC_2P5_UA,
+	TAIKO_PID_MIC_5_UA,
+	TAIKO_PID_MIC_10_UA,
+	TAIKO_PID_MIC_20_UA,
+};
+
+struct taiko_reg_mask_val {
+	u16	reg;
+	u8	mask;
+	u8	val;
+};
+
+enum taiko_mbhc_clk_freq {
+	TAIKO_MCLK_12P2MHZ = 0,
+	TAIKO_MCLK_9P6MHZ,
+	TAIKO_NUM_CLK_FREQS,
+};
+
+enum taiko_mbhc_analog_pwr_cfg {
+	TAIKO_ANALOG_PWR_COLLAPSED = 0,
+	TAIKO_ANALOG_PWR_ON,
+	TAIKO_NUM_ANALOG_PWR_CONFIGS,
+};
+
+enum taiko_mbhc_btn_det_mem {
+	TAIKO_BTN_DET_V_BTN_LOW,
+	TAIKO_BTN_DET_V_BTN_HIGH,
+	TAIKO_BTN_DET_N_READY,
+	TAIKO_BTN_DET_N_CIC,
+	TAIKO_BTN_DET_GAIN
+};
+
+struct taiko_mbhc_general_cfg {
+	u8 t_ldoh;
+	u8 t_bg_fast_settle;
+	u8 t_shutdown_plug_rem;
+	u8 mbhc_nsa;
+	u8 mbhc_navg;
+	u8 v_micbias_l;
+	u8 v_micbias;
+	u8 mbhc_reserved;
+	u16 settle_wait;
+	u16 t_micbias_rampup;
+	u16 t_micbias_rampdown;
+	u16 t_supply_bringup;
+} __packed;
+
+struct taiko_mbhc_plug_detect_cfg {
+	u32 mic_current;
+	u32 hph_current;
+	u16 t_mic_pid;
+	u16 t_ins_complete;
+	u16 t_ins_retry;
+	u16 v_removal_delta;
+	u8 micbias_slow_ramp;
+	u8 reserved0;
+	u8 reserved1;
+	u8 reserved2;
+} __packed;
+
+struct taiko_mbhc_plug_type_cfg {
+	u8 av_detect;
+	u8 mono_detect;
+	u8 num_ins_tries;
+	u8 reserved0;
+	s16 v_no_mic;
+	s16 v_av_min;
+	s16 v_av_max;
+	s16 v_hs_min;
+	s16 v_hs_max;
+	u16 reserved1;
+} __packed;
+
+
+struct taiko_mbhc_btn_detect_cfg {
+	s8 c[8];
+	u8 nc;
+	u8 n_meas;
+	u8 mbhc_nsc;
+	u8 n_btn_meas;
+	u8 n_btn_con;
+	u8 num_btn;
+	u8 reserved0;
+	u8 reserved1;
+	u16 t_poll;
+	u16 t_bounce_wait;
+	u16 t_rel_timeout;
+	s16 v_btn_press_delta_sta;
+	s16 v_btn_press_delta_cic;
+	u16 t_btn0_timeout;
+	s16 _v_btn_low[0]; /* v_btn_low[num_btn] */
+	s16 _v_btn_high[0]; /* v_btn_high[num_btn] */
+	u8 _n_ready[TAIKO_NUM_CLK_FREQS];
+	u8 _n_cic[TAIKO_NUM_CLK_FREQS];
+	u8 _gain[TAIKO_NUM_CLK_FREQS];
+} __packed;
+
+struct taiko_mbhc_imped_detect_cfg {
+	u8 _hs_imped_detect;
+	u8 _n_rload;
+	u8 _hph_keep_on;
+	u8 _repeat_rload_calc;
+	u16 _t_dac_ramp_time;
+	u16 _rhph_high;
+	u16 _rhph_low;
+	u16 _rload[0]; /* rload[n_rload] */
+	u16 _alpha[0]; /* alpha[n_rload] */
+	u16 _beta[3];
+} __packed;
+
+struct taiko_mbhc_config {
+	struct snd_soc_jack *headset_jack;
+	struct snd_soc_jack *button_jack;
+	bool read_fw_bin;
+	/* void* calibration contains:
+	 *  struct taiko_mbhc_general_cfg generic;
+	 *  struct taiko_mbhc_plug_detect_cfg plug_det;
+	 *  struct taiko_mbhc_plug_type_cfg plug_type;
+	 *  struct taiko_mbhc_btn_detect_cfg btn_det;
+	 *  struct taiko_mbhc_imped_detect_cfg imped_det;
+	 * Note: various size depends on btn_det->num_btn
+	 */
+	void *calibration;
+	enum taiko_micbias_num micbias;
+	int (*mclk_cb_fn) (struct snd_soc_codec*, int, bool);
+	unsigned int mclk_rate;
+	unsigned int gpio;
+	unsigned int gpio_irq;
+	int gpio_level_insert;
+	/* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
+	bool (*swap_gnd_mic) (struct snd_soc_codec *);
+};
+
+extern int taiko_hs_detect(struct snd_soc_codec *codec,
+			   const struct taiko_mbhc_config *cfg);
+
+struct anc_header {
+	u32 reserved[3];
+	u32 num_anc_slots;
+};
+
+extern int taiko_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
+			     bool dapm);
+
+extern void *taiko_mbhc_cal_btn_det_mp(const struct taiko_mbhc_btn_detect_cfg
+				       *btn_det,
+				       const enum taiko_mbhc_btn_det_mem mem);
+
+#define TAIKO_MBHC_CAL_SIZE(buttons, rload) ( \
+	sizeof(enum taiko_micbias_num) + \
+	sizeof(struct taiko_mbhc_general_cfg) + \
+	sizeof(struct taiko_mbhc_plug_detect_cfg) + \
+	    ((sizeof(s16) + sizeof(s16)) * buttons) + \
+	sizeof(struct taiko_mbhc_plug_type_cfg) + \
+	sizeof(struct taiko_mbhc_btn_detect_cfg) + \
+	sizeof(struct taiko_mbhc_imped_detect_cfg) + \
+	    ((sizeof(u16) + sizeof(u16)) * rload) \
+	)
+
+#define TAIKO_MBHC_CAL_GENERAL_PTR(cali) ( \
+	    (struct taiko_mbhc_general_cfg *) cali)
+#define TAIKO_MBHC_CAL_PLUG_DET_PTR(cali) ( \
+	    (struct taiko_mbhc_plug_detect_cfg *) \
+	    &(TAIKO_MBHC_CAL_GENERAL_PTR(cali)[1]))
+#define TAIKO_MBHC_CAL_PLUG_TYPE_PTR(cali) ( \
+	    (struct taiko_mbhc_plug_type_cfg *) \
+	    &(TAIKO_MBHC_CAL_PLUG_DET_PTR(cali)[1]))
+#define TAIKO_MBHC_CAL_BTN_DET_PTR(cali) ( \
+	    (struct taiko_mbhc_btn_detect_cfg *) \
+	    &(TAIKO_MBHC_CAL_PLUG_TYPE_PTR(cali)[1]))
+#define TAIKO_MBHC_CAL_IMPED_DET_PTR(cali) ( \
+	    (struct taiko_mbhc_imped_detect_cfg *) \
+	    (((void *)&TAIKO_MBHC_CAL_BTN_DET_PTR(cali)[1]) + \
+	     (TAIKO_MBHC_CAL_BTN_DET_PTR(cali)->num_btn * \
+	      (sizeof(TAIKO_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_low[0]) + \
+	       sizeof(TAIKO_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_high[0])))) \
+	)
+
+/* minimum size of calibration data assuming there is only one button and
+ * one rload.
+ */
+#define TAIKO_MBHC_CAL_MIN_SIZE ( \
+	sizeof(struct taiko_mbhc_general_cfg) + \
+	sizeof(struct taiko_mbhc_plug_detect_cfg) + \
+	sizeof(struct taiko_mbhc_plug_type_cfg) + \
+	sizeof(struct taiko_mbhc_btn_detect_cfg) + \
+	sizeof(struct taiko_mbhc_imped_detect_cfg) + \
+	(sizeof(u16) * 2))
+
+#define TAIKO_MBHC_CAL_BTN_SZ(cfg_ptr) ( \
+	    sizeof(struct taiko_mbhc_btn_detect_cfg) + \
+	    (cfg_ptr->num_btn * (sizeof(cfg_ptr->_v_btn_low[0]) + \
+				 sizeof(cfg_ptr->_v_btn_high[0]))))
+
+#define TAIKO_MBHC_CAL_IMPED_MIN_SZ ( \
+	    sizeof(struct taiko_mbhc_imped_detect_cfg) + \
+	    sizeof(u16) * 2)
+
+#define TAIKO_MBHC_CAL_IMPED_SZ(cfg_ptr) ( \
+	    sizeof(struct taiko_mbhc_imped_detect_cfg) + \
+	    (cfg_ptr->_n_rload * (sizeof(cfg_ptr->_rload[0]) + \
+				 sizeof(cfg_ptr->_alpha[0]))))
+
+#endif
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 36cbb23..1125d20 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -105,6 +105,16 @@
 	help
 	 To add support for SoC audio on MSM8960.
 
+config SND_SOC_MSM_QDSP6V2_INTF
+	bool "SoC Q6 audio driver for MSMCOPPER"
+	depends on MSM_QDSP6_APR
+	help
+	 To add support for SoC audio on MSMCOPPER.
+	 This will enable all the platform specific
+	 interactions towards DSP. It includes asm,
+	 adm and afe interfaces on the DSP.
+
+
 config SND_SOC_VOICE
 	bool "SoC Q6 voice driver for MSM8960"
 	depends on SND_SOC_MSM_QDSP6_INTF
@@ -119,6 +129,15 @@
 	help
 	 To add support for MSM QDSP6 Soc Audio.
 
+config SND_SOC_QDSP6V2
+	tristate "SoC ALSA audio driver for QDSP6V2"
+	select SND_SOC_MSM_QDSP6V2_INTF
+	help
+	 To add support for MSM QDSP6V2 Soc Audio.
+	 This will enable sound soc platform specific
+	 audio drivers. This includes q6asm, q6adm,
+	 q6afe interfaces to DSP using apr.
+
 config SND_SOC_MSM8960
 	tristate "SoC Machine driver for MSM8960 and APQ8064 boards"
 	depends on ARCH_MSM8960 || ARCH_APQ8064
@@ -134,6 +153,20 @@
 	help
 	 To add support for SoC audio on MSM8960 and APQ8064 boards
 
+config SND_SOC_MSM8974
+	tristate "SoC Machine driver for MSMCOPPER boards"
+	depends on ARCH_MSMCOPPER
+	select SND_SOC_QDSP6V2
+	select SND_SOC_MSM_STUB
+	select SND_SOC_MSM_HOSTLESS_PCM
+	select SND_DYNAMIC_MINORS
+	help
+	 To add support for SoC audio on MSMCOPPER.
+	 This will enable sound soc drivers which
+	 interfaces with DSP, also it will enable
+	 the machine drivers and the corresponding
+	 DAI-links.
+
 config SND_SOC_MDM9615
 	tristate "SoC Machine driver for MDM9615 boards"
 	depends on ARCH_MSM9615
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index a7fd38b..2da5c6a 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -18,6 +18,8 @@
 #include <linux/gpio.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/slimbus/slimbus.h>
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
@@ -1417,6 +1419,19 @@
 	return 0;
 }
 
+static int msm_slimbus_1_startup(struct snd_pcm_substream *substream)
+{
+	struct slim_controller *slim = slim_busnum_to_ctrl(1);
+
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+
+	if (slim != NULL)
+		pm_runtime_get_sync(slim->dev.parent);
+
+	return 0;
+}
+
 static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
 {
 
@@ -1433,6 +1448,19 @@
 		rtd->dai_link->cpu_dai_name, rtd->dai_link->codec_dai_name);
 }
 
+static void msm_slimbus_1_shutdown(struct snd_pcm_substream *substream)
+{
+	struct slim_controller *slim = slim_busnum_to_ctrl(1);
+
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+
+	if (slim != NULL) {
+		pm_runtime_mark_last_busy(slim->dev.parent);
+		pm_runtime_put(slim->dev.parent);
+	}
+}
+
 static struct snd_soc_ops msm_be_ops = {
 	.startup = msm_startup,
 	.hw_params = msm_hw_params,
@@ -1445,9 +1473,9 @@
 };
 
 static struct snd_soc_ops msm_slimbus_1_be_ops = {
-	.startup = msm_startup,
+	.startup = msm_slimbus_1_startup,
 	.hw_params = msm_slimbus_1_hw_params,
-	.shutdown = msm_shutdown,
+	.shutdown = msm_slimbus_1_shutdown,
 };
 
 static struct snd_soc_ops msm_slimbus_3_be_ops = {
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index 363635f..90d8723 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -39,8 +39,8 @@
 #define MDM9615_SLIM_0_RX_MAX_CHANNELS		2
 #define MDM9615_SLIM_0_TX_MAX_CHANNELS		4
 
-#define BTSCO_RATE_8KHZ 8000
-#define BTSCO_RATE_16KHZ 16000
+#define SAMPLE_RATE_8KHZ 8000
+#define SAMPLE_RATE_16KHZ 16000
 
 #define BOTTOM_SPK_AMP_POS	0x1
 #define BOTTOM_SPK_AMP_NEG	0x2
@@ -261,9 +261,11 @@
 static int mdm9615_slim_0_rx_ch = 1;
 static int mdm9615_slim_0_tx_ch = 1;
 
-static int mdm9615_btsco_rate = BTSCO_RATE_8KHZ;
+static int mdm9615_btsco_rate = SAMPLE_RATE_8KHZ;
 static int mdm9615_btsco_ch = 1;
 
+static int mdm9615_auxpcm_rate = SAMPLE_RATE_8KHZ;
+
 static struct clk *codec_clk;
 static int clk_users;
 
@@ -679,6 +681,11 @@
 		SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
 };
 
+static const char * const auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
+static const struct soc_enum mdm9615_auxpcm_enum[] = {
+		SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
+};
+
 static int mdm9615_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
@@ -730,19 +737,49 @@
 {
 	switch (ucontrol->value.integer.value[0]) {
 	case 0:
-		mdm9615_btsco_rate = BTSCO_RATE_8KHZ;
+		mdm9615_btsco_rate = SAMPLE_RATE_8KHZ;
 		break;
 	case 1:
-		mdm9615_btsco_rate = BTSCO_RATE_16KHZ;
+		mdm9615_btsco_rate = SAMPLE_RATE_16KHZ;
 		break;
 	default:
-		mdm9615_btsco_rate = BTSCO_RATE_8KHZ;
+		mdm9615_btsco_rate = SAMPLE_RATE_8KHZ;
 		break;
 	}
 	pr_debug("%s: mdm9615_btsco_rate = %d\n", __func__, mdm9615_btsco_rate);
 	return 0;
 }
 
+static int mdm9615_auxpcm_rate_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: mdm9615_auxpcm_rate  = %d", __func__,
+		mdm9615_auxpcm_rate);
+	ucontrol->value.integer.value[0] = mdm9615_auxpcm_rate;
+	return 0;
+}
+
+static int mdm9615_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		mdm9615_auxpcm_rate = SAMPLE_RATE_8KHZ;
+		break;
+	case 1:
+		mdm9615_auxpcm_rate = SAMPLE_RATE_16KHZ;
+		break;
+	default:
+		mdm9615_auxpcm_rate = SAMPLE_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: mdm9615_auxpcm_rate = %d\n"
+		 "ucontrol->value.integer.value[0] = %d\n", __func__,
+		 mdm9615_auxpcm_rate,
+		 (int)ucontrol->value.integer.value[0]);
+	return 0;
+}
+
 static const struct snd_kcontrol_new tabla_mdm9615_controls[] = {
 	SOC_ENUM_EXT("Speaker Function", mdm9615_enum[0], mdm9615_get_spk,
 		mdm9615_set_spk),
@@ -752,6 +789,8 @@
 		mdm9615_slim_0_tx_ch_get, mdm9615_slim_0_tx_ch_put),
 	SOC_ENUM_EXT("Internal BTSCO SampleRate", mdm9615_btsco_enum[0],
 		     mdm9615_btsco_rate_get, mdm9615_btsco_rate_put),
+	SOC_ENUM_EXT("AUX PCM SampleRate", mdm9615_auxpcm_enum[0],
+		mdm9615_auxpcm_rate_get, mdm9615_auxpcm_rate_put),
 };
 
 static void *def_tabla_mbhc_cal(void)
@@ -1554,8 +1593,8 @@
 	struct snd_interval *channels = hw_param_interval(params,
 					SNDRV_PCM_HW_PARAM_CHANNELS);
 
-	/* PCM only supports mono output with 8khz sample rate */
-	rate->min = rate->max = 8000;
+	rate->min = rate->max = mdm9615_auxpcm_rate;
+	/* PCM only supports mono output */
 	channels->min = channels->max = 1;
 
 	return 0;
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 9395e8f..4ecd8df 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1062,7 +1062,8 @@
 		.cpu_dai_name	= "MultiMedia1",
 		.platform_name  = "msm-pcm-dsp",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.ignore_suspend = 1,
@@ -1075,7 +1076,8 @@
 		.cpu_dai_name	= "MultiMedia2",
 		.platform_name  = "msm-multi-ch-pcm-dsp",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.ignore_suspend = 1,
@@ -1088,7 +1090,8 @@
 		.cpu_dai_name   = "CS-VOICE",
 		.platform_name  = "msm-pcm-voice",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1102,7 +1105,8 @@
 		.cpu_dai_name	= "VoIP",
 		.platform_name  = "msm-voip-dsp",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.ignore_suspend = 1,
@@ -1115,7 +1119,8 @@
 		.cpu_dai_name	= "MultiMedia3",
 		.platform_name  = "msm-pcm-dsp",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.ignore_suspend = 1,
@@ -1129,7 +1134,8 @@
 		.cpu_dai_name	= "SLIMBUS0_HOSTLESS",
 		.platform_name  = "msm-pcm-hostless",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1142,7 +1148,8 @@
 		.cpu_dai_name	= "INT_FM_HOSTLESS",
 		.platform_name  = "msm-pcm-hostless",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1178,7 +1185,8 @@
 		.cpu_dai_name   = "MultiMedia4",
 		.platform_name  = "msm-compr-dsp",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.ignore_suspend = 1,
@@ -1191,7 +1199,8 @@
 		.cpu_dai_name = "VOICE_STUB",
 		.platform_name = "msm-pcm-hostless",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1205,7 +1214,8 @@
 		.cpu_dai_name = "HDMI_HOSTLESS",
 		.platform_name = "msm-pcm-hostless",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1219,7 +1229,8 @@
 		.cpu_dai_name = "MI2S_TX_HOSTLESS",
 		.platform_name = "msm-pcm-hostless",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		.codec_dai_name = "snd-soc-dummy-dai",
@@ -1232,7 +1243,8 @@
 		.cpu_dai_name = "SEC_I2S_RX_HOSTLESS",
 		.platform_name = "msm-pcm-hostless",
 		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 6e190b2..56e83d5 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -426,6 +426,30 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "SEC_I2S_RX_HOSTLESS",
 	},
+	{
+		.playback = {
+			.stream_name = "SGLTE Playback",
+			.aif_name = "SGLTE_DL",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min =     8000,
+			.rate_max =     48000,
+		},
+		.capture = {
+			.stream_name = "SGLTE Capture",
+			.aif_name = "SGLTE_UL",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min =     8000,
+			.rate_max =     48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "SGLTE",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index 482cbee..5f3cada 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -32,6 +32,7 @@
 #include <linux/memory_alloc.h>
 #include <mach/msm_subsystem_map.h>
 #include "msm-pcm-afe.h"
+#include "msm-pcm-q6.h"
 
 #define MIN_PERIOD_SIZE (128 * 2)
 #define MAX_PERIOD_SIZE (128 * 2 * 2 * 6)
@@ -58,6 +59,10 @@
 static enum hrtimer_restart afe_hrtimer_callback(struct hrtimer *hrt);
 static enum hrtimer_restart afe_hrtimer_rec_callback(struct hrtimer *hrt);
 
+static void q6asm_event_handler(uint32_t opcode,
+		uint32_t token, uint32_t *payload, void *priv)
+{
+}
 static enum hrtimer_restart afe_hrtimer_callback(struct hrtimer *hrt)
 {
 	struct pcm_afe_info *prtd =
@@ -319,13 +324,22 @@
 	runtime->hw = msm_afe_hardware;
 	prtd->substream = substream;
 	runtime->private_data = prtd;
-	mutex_unlock(&prtd->lock);
+	prtd->audio_client = q6asm_audio_client_alloc(
+				(app_cb)q6asm_event_handler, prtd);
+	if (!prtd->audio_client) {
+		pr_debug("%s: Could not allocate memory\n", __func__);
+		kfree(prtd);
+		mutex_unlock(&prtd->lock);
+		return -ENOMEM;
+	}
 	hrtimer_init(&prtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		prtd->hrt.function = afe_hrtimer_callback;
 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		prtd->hrt.function = afe_hrtimer_rec_callback;
 
+	mutex_unlock(&prtd->lock);
+
 	ret = snd_pcm_hw_constraint_list(runtime, 0,
 				SNDRV_PCM_HW_PARAM_RATE,
 				&constraints_sample_rates);
@@ -348,6 +362,7 @@
 	struct pcm_afe_info *prtd;
 	struct snd_soc_pcm_runtime *rtd = NULL;
 	struct snd_soc_dai *dai = NULL;
+	int dir = IN;
 	int ret = 0;
 
 	pr_debug("%s\n", __func__);
@@ -363,10 +378,12 @@
 	mutex_lock(&prtd->lock);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		dir = IN;
 		ret =  afe_unregister_get_events(dai->id);
 		if (ret < 0)
 			pr_err("AFE unregister for events failed\n");
 	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		dir = OUT;
 		ret =  afe_unregister_get_events(dai->id);
 		if (ret < 0)
 			pr_err("AFE unregister for events failed\n");
@@ -385,17 +402,14 @@
 	}
 
 	if (dma_buf->area) {
-		if (msm_subsystem_unmap_buffer(prtd->mem_buffer) < 0) {
-			pr_err("%s: unmap buffer failed\n", __func__);
-			prtd->mem_buffer = NULL;
 			dma_buf->area = NULL;
 		}
-	}
 
-	if (dma_buf->addr)
-		free_contiguous_memory_by_paddr(dma_buf->addr);
+	q6asm_audio_client_buf_free_contiguous(dir,
+				prtd->audio_client);
 done:
 	pr_debug("%s: dai->id =%x\n", __func__, dai->id);
+	q6asm_audio_client_free(prtd->audio_client);
 	mutex_unlock(&prtd->lock);
 	prtd->prepared--;
 	kfree(prtd);
@@ -470,57 +484,45 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
 	struct pcm_afe_info *prtd = runtime->private_data;
-	int rc;
-	unsigned int flags = 0;
+	struct audio_buffer *buf;
+	int dir, ret;
 
 	pr_debug("%s:\n", __func__);
 
 	mutex_lock(&prtd->lock);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dir = IN;
+	else
+		dir = OUT;
+	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
+			prtd->audio_client,
+			runtime->hw.period_bytes_min,
+			runtime->hw.periods_max);
+	if (ret < 0) {
+		pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
+		mutex_unlock(&prtd->lock);
+		return -ENOMEM;
+	}
+	buf = prtd->audio_client->port[dir].buf;
 
+	if (buf == NULL || buf[0].data == NULL) {
+		mutex_unlock(&prtd->lock);
+		return -ENOMEM;
+	}
+
+	pr_debug("%s:buf = %p\n", __func__, buf);
 	dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
 	dma_buf->dev.dev = substream->pcm->card->dev;
 	dma_buf->private_data = NULL;
-
-	dma_buf->addr = allocate_contiguous_ebi_nomap(
-				runtime->hw.buffer_bytes_max, SZ_4K);
-	if (!dma_buf->addr) {
+	dma_buf->area = buf[0].data;
+	dma_buf->addr =  buf[0].phys;
+	dma_buf->bytes = runtime->hw.buffer_bytes_max;
+	if (!dma_buf->area) {
 		pr_err("%s:MSM AFE physical memory allocation failed\n",
 							__func__);
 		mutex_unlock(&prtd->lock);
 		return -ENOMEM;
 	}
-
-	flags = MSM_SUBSYSTEM_MAP_KADDR | MSM_SUBSYSTEM_MAP_CACHED;
-
-	prtd->mem_buffer = msm_subsystem_map_buffer(dma_buf->addr,
-				runtime->hw.buffer_bytes_max, flags,
-				NULL, 0);
-	if (IS_ERR((void *) prtd->mem_buffer)) {
-		pr_err("%s: map_buffer failed error = %ld\n", __func__,
-				PTR_ERR((void *)prtd->mem_buffer));
-		free_contiguous_memory_by_paddr(dma_buf->addr);
-		mutex_unlock(&prtd->lock);
-		return -ENOMEM;
-	}
-
-	dma_buf->area = prtd->mem_buffer->vaddr;
-
-	pr_debug("%s: dma_buf->area: 0x%p, dma_buf->addr: 0x%x", __func__,
-			(unsigned int *) dma_buf->area, dma_buf->addr);
-
-	if (!dma_buf->area) {
-		pr_err("%s: Invalid Virtual address\n", __func__);
-		if (prtd->mem_buffer) {
-			msm_subsystem_unmap_buffer(prtd->mem_buffer);
-			prtd->mem_buffer = NULL;
-			dma_buf->area = NULL;
-		}
-		free_contiguous_memory_by_paddr(dma_buf->addr);
-		mutex_unlock(&prtd->lock);
-		return -ENOMEM;
-	}
-
-	dma_buf->bytes = runtime->hw.buffer_bytes_max;
 	memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max);
 	prtd->dma_addr = (u32) dma_buf->addr;
 
@@ -528,11 +530,11 @@
 
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
-	rc = afe_cmd_memory_map(dma_buf->addr, dma_buf->bytes);
-	if (rc < 0)
+	ret = afe_cmd_memory_map(dma_buf->addr, dma_buf->bytes);
+	if (ret < 0)
 		pr_err("fail to map memory to DSP\n");
 
-	return rc;
+	return ret;
 }
 static snd_pcm_uframes_t msm_afe_pointer(struct snd_pcm_substream *substream)
 {
diff --git a/sound/soc/msm/msm-pcm-afe.h b/sound/soc/msm/msm-pcm-afe.h
index 38026d5..9be11f3 100644
--- a/sound/soc/msm/msm-pcm-afe.h
+++ b/sound/soc/msm/msm-pcm-afe.h
@@ -30,7 +30,7 @@
 	int prepared;
 	struct hrtimer hrt;
 	int poll_time;
-	struct msm_mapped_buffer *mem_buffer;
+	struct audio_client *audio_client;
 };
 
 
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 3cab34f..269b49b 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -109,15 +109,16 @@
 			break;
 		} else
 			atomic_set(&prtd->pending_buffer, 0);
+
+		buf = prtd->audio_client->port[IN].buf;
 		if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
-			memset((void *)buf[0].phys +
+			memset((void *)buf[0].data +
 				(prtd->out_head * prtd->pcm_count),
 				0, prtd->pcm_count);
 		}
 		pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
 				__func__, prtd->pcm_count);
 
-		buf = prtd->audio_client->port[IN].buf;
 		param.paddr = (unsigned long)buf[0].phys
 				+ (prtd->out_head * prtd->pcm_count);
 		param.len = prtd->pcm_count;
@@ -232,10 +233,12 @@
 		pr_debug("SNDRV_PCM_TRIGGER_START\n");
 		q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
 		atomic_set(&prtd->start, 1);
+		atomic_set(&prtd->stop, 0);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
 		atomic_set(&prtd->start, 0);
+		atomic_set(&prtd->stop, 1);
 		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
 			break;
 		break;
@@ -323,6 +326,7 @@
 
 	prtd->dsp_cnt = 0;
 	atomic_set(&prtd->pending_buffer, 1);
+	atomic_set(&prtd->stop, 1);
 	runtime->private_data = prtd;
 	lpa_audio.prtd = prtd;
 	lpa_set_volume(lpa_audio.volume);
@@ -366,7 +370,8 @@
 	To issue EOS to dsp, we need to be run state otherwise
 	EOS is not honored.
 	*/
-	if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id)) {
+	if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id) &&
+		(!atomic_read(&prtd->stop))) {
 		rc = q6asm_run(prtd->audio_client, 0, 0, 0);
 		atomic_set(&prtd->pending_buffer, 0);
 		prtd->cmd_ack = 0;
@@ -386,6 +391,7 @@
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
 
+	atomic_set(&prtd->stop, 1);
 	pr_debug("%s\n", __func__);
 	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
 		SNDRV_PCM_STREAM_PLAYBACK);
diff --git a/sound/soc/msm/msm-pcm-q6.h b/sound/soc/msm/msm-pcm-q6.h
index e5551ea..9e743a7 100644
--- a/sound/soc/msm/msm-pcm-q6.h
+++ b/sound/soc/msm/msm-pcm-q6.h
@@ -71,6 +71,7 @@
 	int close_ack;
 	int cmd_ack;
 	atomic_t start;
+	atomic_t stop;
 	atomic_t out_count;
 	atomic_t in_count;
 	atomic_t out_needed;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 4219ab6..8051c92 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -48,6 +48,7 @@
 
 static int fm_switch_enable;
 static int fm_pcmrx_switch_enable;
+static int srs_alsa_ctrl_ever_called;
 
 #define INT_RX_VOL_MAX_STEPS 0x2000
 #define INT_RX_VOL_GAIN 0x2000
@@ -120,6 +121,12 @@
 
 static void srs_send_params(int port_id, unsigned int techs,
 		int param_block_idx) {
+
+	/* only send commands to dsp if srs alsa ctrl was used
+	   at least one time */
+	if (!srs_alsa_ctrl_ever_called)
+		return;
+
 	pr_debug("SRS %s: called, port_id = %d, techs flags = %u,"
 			" paramblockidx %d", __func__, port_id, techs,
 			param_block_idx);
@@ -328,6 +335,8 @@
 
 			payload.copp_ids[payload.num_copps++] =
 				msm_bedais[i].port_id;
+			srs_port_id = msm_bedais[i].port_id;
+			srs_send_params(srs_port_id, 1, 0);
 		}
 	}
 	if (payload.num_copps)
@@ -436,6 +445,8 @@
 
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type);
+			srs_port_id = msm_bedais[reg].port_id;
+			srs_send_params(srs_port_id, 1, 0);
 		}
 	} else {
 		if (test_bit(val, &msm_bedais[reg].fe_sessions) &&
@@ -505,6 +516,8 @@
 		session_id = voc_get_session_id(VOICE_SESSION_NAME);
 	else if (val == MSM_FRONTEND_DAI_VOLTE)
 		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+	else if (val == MSM_FRONTEND_DAI_SGLTE)
+		session_id = voc_get_session_id(SGLTE_SESSION_NAME);
 	else
 		session_id = voc_get_session_id(VOIP_SESSION_NAME);
 
@@ -811,6 +824,8 @@
 	unsigned int techs = 0;
 	unsigned short offset, value, max, index;
 
+	srs_alsa_ctrl_ever_called = 1;
+
 	max = sizeof(msm_srs_trumedia_params) >> 1;
 	index = (unsigned short)((ucontrol->value.integer.value[0] &
 			SRS_PARAM_INDEX_MASK) >> 31);
@@ -1303,6 +1318,9 @@
 	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_voice_mixer_controls[] = {
@@ -1315,6 +1333,9 @@
 	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
@@ -1327,6 +1348,9 @@
 	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
@@ -1342,6 +1366,9 @@
 	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_rx_voice_mixer_controls[] = {
@@ -1354,6 +1381,9 @@
 	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
@@ -1369,6 +1399,9 @@
 	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
@@ -1384,6 +1417,9 @@
 	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new sec_aux_pcm_rx_voice_mixer_controls[] = {
@@ -1396,6 +1432,9 @@
 	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
@@ -1408,6 +1447,12 @@
 	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
@@ -1473,6 +1518,29 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new tx_sglte_mixer_controls[] = {
+	SOC_SINGLE_EXT("PRI_TX_SGLTE", MSM_BACKEND_DAI_PRI_I2S_TX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("MI2S_TX_SGLTE", MSM_BACKEND_DAI_MI2S_TX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SLIM_0_TX_SGLTE", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_SGLTE",
+	MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_SGLTE, 1, 0,
+	msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX_SGLTE", MSM_BACKEND_DAI_AFE_PCM_TX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AUX_PCM_TX_SGLTE", MSM_BACKEND_DAI_AUXPCM_TX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_SGLTE", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
 static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
 	SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
@@ -1875,6 +1943,8 @@
 	SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("VoLTE_UL", "VoLTE Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SGLTE_DL", "SGLTE Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("SGLTE_UL", "SGLTE Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
 		0, 0, 0, 0),
@@ -2022,6 +2092,9 @@
 	SND_SOC_DAPM_MIXER("VoLTE_Tx Mixer",
 				SND_SOC_NOPM, 0, 0, tx_volte_mixer_controls,
 				ARRAY_SIZE(tx_volte_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SGLTE_Tx Mixer",
+				SND_SOC_NOPM, 0, 0, tx_sglte_mixer_controls,
+				ARRAY_SIZE(tx_sglte_mixer_controls)),
 	SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -2172,41 +2245,49 @@
 
 	{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+	{"PRI_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"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", "VoLTE", "VoLTE_DL"},
+	{"SEC_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"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", "VoLTE", "VoLTE_DL"},
+	{"SLIM_0_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
 
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+	{"INTERNAL_BT_SCO_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
 
 	{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+	{"AFE_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
 
 	{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+	{"AUX_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
 
 	{"SEC_AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"SEC_AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+	{"SEC_AUX_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"SEC_AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX_Voice Mixer"},
 
 	{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+	{"HDMI_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
 	{"HDMI", NULL, "HDMI_DL_HL"},
@@ -2226,6 +2307,14 @@
 	{"VoLTE_Tx Mixer", "AUX_PCM_TX_VoLTE", "AUX_PCM_TX"},
 	{"VoLTE_Tx Mixer", "SEC_AUX_PCM_TX_VoLTE", "SEC_AUX_PCM_TX"},
 	{"VoLTE_UL", NULL, "VoLTE_Tx Mixer"},
+	{"SGLTE_Tx Mixer", "PRI_TX_SGLTE", "PRI_I2S_TX"},
+	{"SGLTE_Tx Mixer", "MI2S_TX_SGLTE", "MI2S_TX"},
+	{"SGLTE_Tx Mixer", "SLIM_0_TX_SGLTE", "SLIMBUS_0_TX"},
+	{"SGLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_SGLTE", "INT_BT_SCO_TX"},
+	{"SGLTE_Tx Mixer", "AFE_PCM_TX_SGLTE", "PCM_TX"},
+	{"SGLTE_Tx Mixer", "AUX_PCM_TX_SGLTE", "AUX_PCM_TX"},
+	{"SGLTE_Tx Mixer", "SEC_AUX_PCM_TX_SGLTE", "SEC_AUX_PCM_TX"},
+	{"SGLTE_UL", NULL, "SGLTE_Tx Mixer"},
 	{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
 	{"Voip_Tx Mixer", "MI2S_TX_Voip", "MI2S_TX"},
 	{"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
@@ -2313,6 +2402,8 @@
 	{"BE_OUT", NULL, "PCM_RX"},
 	{"PCM_TX", NULL, "BE_IN"},
 	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
+	{"BE_OUT", NULL, "STUB_RX"},
+	{"STUB_TX", NULL, "BE_IN"},
 };
 
 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 d1230ad..2f213e7 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -66,6 +66,7 @@
 	MSM_FRONTEND_DAI_AFE_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB,
 	MSM_FRONTEND_DAI_VOLTE,
+	MSM_FRONTEND_DAI_SGLTE,
 	MSM_FRONTEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index 7bdb4f0..633973e 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -59,6 +59,14 @@
 		return false;
 }
 
+static int is_sglte(struct msm_voice *psglte)
+{
+	if (psglte == &voice_info[SGLTE_SESSION_INDEX])
+		return true;
+	else
+		return false;
+}
+
 static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
@@ -93,6 +101,10 @@
 		voice = &voice_info[VOLTE_SESSION_INDEX];
 		pr_debug("%s: Open VoLTE Substream Id=%s\n",
 				__func__, substream->pcm->id);
+	} else if (!strncmp("SGLTE", substream->pcm->id, 5)) {
+		voice = &voice_info[SGLTE_SESSION_INDEX];
+		pr_debug("%s: Open SGLTE Substream Id=%s\n",
+				__func__, substream->pcm->id);
 	} else {
 		voice = &voice_info[VOICE_SESSION_INDEX];
 		pr_debug("%s: Open VOICE Substream Id=%s\n",
@@ -162,6 +174,8 @@
 		pr_debug("end voice call\n");
 		if (is_volte(prtd))
 			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+		else if (is_sglte(prtd))
+			session_id = voc_get_session_id(SGLTE_SESSION_NAME);
 		else
 			session_id = voc_get_session_id(VOICE_SESSION_NAME);
 		voc_end_voice_call(session_id);
@@ -187,6 +201,8 @@
 	if (prtd->playback_start && prtd->capture_start) {
 		if (is_volte(prtd))
 			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+		else if (is_sglte(prtd))
+			session_id = voc_get_session_id(SGLTE_SESSION_NAME);
 		else
 			session_id = voc_get_session_id(VOICE_SESSION_NAME);
 		voc_start_voice_call(session_id);
@@ -217,6 +233,8 @@
 	pr_debug("%s: cmd = %d\n", __func__, cmd);
 	if (is_volte(prtd))
 		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+	else if (is_sglte(prtd))
+		session_id = voc_get_session_id(SGLTE_SESSION_NAME);
 	else
 		session_id = voc_get_session_id(VOICE_SESSION_NAME);
 
@@ -290,6 +308,23 @@
 	return 0;
 }
 
+static int msm_sglte_volume_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int msm_sglte_volume_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int volume = ucontrol->value.integer.value[0];
+	pr_debug("%s: volume: %d\n", __func__, volume);
+	voc_set_rx_vol_index(voc_get_session_id(SGLTE_SESSION_NAME),
+						RX_PATH, volume);
+	return 0;
+}
+
 static int msm_voice_mute_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -328,6 +363,25 @@
 	return 0;
 }
 
+static int msm_sglte_mute_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int msm_sglte_mute_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_tx_mute(voc_get_session_id(SGLTE_SESSION_NAME), TX_PATH, mute);
+
+	return 0;
+}
+
 static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -368,6 +422,26 @@
 	return 0;
 }
 
+static int msm_sglte_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] =
+		voc_get_rx_device_mute(voc_get_session_id(SGLTE_SESSION_NAME));
+	return 0;
+}
+
+static int msm_sglte_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_rx_device_mute(voc_get_session_id(SGLTE_SESSION_NAME), mute);
+
+	return 0;
+}
+
 static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
 static const struct soc_enum msm_tty_mode_enum[] = {
 		SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -481,6 +555,13 @@
 				msm_volte_mute_get, msm_volte_mute_put),
 	SOC_SINGLE_EXT("VoLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
 				msm_volte_volume_get, msm_volte_volume_put),
+	SOC_SINGLE_EXT("SGLTE Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+				msm_sglte_rx_device_mute_get,
+				msm_sglte_rx_device_mute_put),
+	SOC_SINGLE_EXT("SGLTE Tx Mute", SND_SOC_NOPM, 0, 1, 0,
+				msm_sglte_mute_get, msm_sglte_mute_put),
+	SOC_SINGLE_EXT("SGLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
+				msm_sglte_volume_get, msm_sglte_volume_put),
 };
 
 static struct snd_pcm_ops msm_pcm_ops = {
@@ -543,6 +624,7 @@
 	memset(&voice_info, 0, sizeof(voice_info));
 	mutex_init(&voice_info[VOICE_SESSION_INDEX].lock);
 	mutex_init(&voice_info[VOLTE_SESSION_INDEX].lock);
+	mutex_init(&voice_info[SGLTE_SESSION_INDEX].lock);
 
 	return platform_driver_register(&msm_pcm_driver);
 }
diff --git a/sound/soc/msm/msm-pcm-voice.h b/sound/soc/msm/msm-pcm-voice.h
index aa00577..41aca89 100644
--- a/sound/soc/msm/msm-pcm-voice.h
+++ b/sound/soc/msm/msm-pcm-voice.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
@@ -16,6 +16,7 @@
 enum {
 	VOICE_SESSION_INDEX,
 	VOLTE_SESSION_INDEX,
+	SGLTE_SESSION_INDEX,
 	VOICE_SESSION_INDEX_MAX,
 };
 
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 98cfa6d..2c44b46 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1321,6 +1321,21 @@
 		.codec_name = "snd-soc-dummy",
 		.be_id = MSM_FRONTEND_DAI_VOLTE,
 	},
+	{
+		.name = "SGLTE",
+		.stream_name = "SGLTE",
+		.cpu_dai_name   = "SGLTE",
+		.platform_name  = "msm-pcm-voice",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+					SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,/* this dainlink has playback support */
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.be_id = MSM_FRONTEND_DAI_SGLTE,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index d47910b..4678ea4 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -21,7 +21,6 @@
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
-#include <sound/soc-dsp.h>
 #include <sound/pcm.h>
 #include <sound/jack.h>
 #include <asm/mach-types.h>
@@ -123,8 +122,8 @@
 		}
 		ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
 		if (ret)
-			pr_err("%s: Failed to configure Bottom Spk Ampl"
-				" gpio %u\n", __func__, bottom_spk_pamp_gpio);
+			pr_err("%s: Failed to configure Bottom Spk Ampl gpio %u\n",
+				__func__, bottom_spk_pamp_gpio);
 		else {
 			pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
 			gpio_direction_output(bottom_spk_pamp_gpio, 1);
@@ -140,15 +139,15 @@
 		}
 		ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
 		if (ret)
-			pr_err("%s: Failed to configure Top Spk Ampl"
-				" gpio %u\n", __func__, top_spk_pamp_gpio);
+			pr_err("%s: Failed to configure Top Spk Ampl gpio %u\n",
+				__func__, top_spk_pamp_gpio);
 		else {
 			pr_debug("%s: enable Top spkr amp gpio\n", __func__);
 			gpio_direction_output(top_spk_pamp_gpio, 1);
 		}
 	} else {
-		pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
-			" gpio = %u\n", __func__, spk_amp_gpio);
+		pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO. gpio = %u\n",
+			__func__, spk_amp_gpio);
 		return;
 	}
 }
@@ -160,8 +159,8 @@
 		if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
 			(msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
 
-			pr_debug("%s() External Bottom Speaker Ampl already "
-				"turned on. spk = 0x%08x\n", __func__, spk);
+			pr_debug("%s() External Bottom Speaker Ampl already turned on. spk = 0x%08x\n",
+						__func__, spk);
 			return;
 		}
 
@@ -171,8 +170,8 @@
 			(msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
 
 			msm_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
-			pr_debug("%s: slepping 4 ms after turning on external "
-				" Bottom Speaker Ampl\n", __func__);
+			pr_debug("%s: slepping 4 ms after turning on external Bottom Speaker Ampl\n",
+							__func__);
 			usleep_range(4000, 4000);
 		}
 
@@ -181,8 +180,8 @@
 		if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
 			(msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
 
-			pr_debug("%s() External Top Speaker Ampl already"
-				"turned on. spk = 0x%08x\n", __func__, spk);
+			pr_debug("%s() External Top Speaker Ampl already turned on. spk = 0x%08x\n",
+						__func__, spk);
 			return;
 		}
 
@@ -192,8 +191,8 @@
 			(msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
 
 			msm_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
-			pr_debug("%s: sleeping 4 ms after turning on "
-				" external Top Speaker Ampl\n", __func__);
+			pr_debug("%s: sleeping 4 ms after turning on external Top Speaker Ampl\n",
+						__func__);
 			usleep_range(4000, 4000);
 		}
 	} else  {
@@ -215,8 +214,8 @@
 		gpio_free(bottom_spk_pamp_gpio);
 		msm_ext_bottom_spk_pamp = 0;
 
-		pr_debug("%s: sleeping 4 ms after turning off external Bottom"
-			" Speaker Ampl\n", __func__);
+		pr_debug("%s: sleeping 4 ms after turning off external Bottom Speaker Ampl\n",
+					__func__);
 
 		usleep_range(4000, 4000);
 
@@ -229,8 +228,8 @@
 		gpio_free(top_spk_pamp_gpio);
 		msm_ext_top_spk_pamp = 0;
 
-		pr_debug("%s: sleeping 4 ms after turning off external Top"
-			" Spkaker Ampl\n", __func__);
+		pr_debug("%s: sleeping 4 ms after turning off external Top Spkaker Ampl\n",
+					__func__);
 
 		usleep_range(4000, 4000);
 	} else  {
@@ -442,9 +441,9 @@
 	{"MIC BIAS4 External", NULL, "Digital Mic6"},
 };
 
-static const char *spk_function[] = {"Off", "On"};
-static const char *slim0_rx_ch_text[] = {"One", "Two"};
-static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+static const char *const spk_function[] = {"Off", "On"};
+static const char *const slim0_rx_ch_text[] = {"One", "Two"};
+static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
 
 static const struct soc_enum msm_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, spk_function),
@@ -452,7 +451,7 @@
 	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
 };
 
-static const char *btsco_rate_text[] = {"8000", "16000"};
+static const char *const btsco_rate_text[] = {"8000", "16000"};
 static const struct soc_enum msm_btsco_enum[] = {
 		SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
 };
@@ -537,21 +536,6 @@
 		msm_btsco_rate_get, msm_btsco_rate_put),
 };
 
-static struct snd_soc_dsp_link lpa_fe_media = {
-	.playback = true,
-	.trigger = {
-		SND_SOC_DSP_TRIGGER_POST,
-		SND_SOC_DSP_TRIGGER_POST
-	},
-};
-static struct snd_soc_dsp_link fe_media = {
-	.playback = true,
-	.capture = true,
-	.trigger = {
-		SND_SOC_DSP_TRIGGER_POST,
-		SND_SOC_DSP_TRIGGER_POST
-	},
-};
 static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -654,7 +638,13 @@
 		.cpu_dai_name	= "MultiMedia1",
 		.platform_name  = "msm-pcm-dsp",
 		.dynamic = 1,
-		.dsp_link = &fe_media,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
 	},
 	{
@@ -663,7 +653,13 @@
 		.cpu_dai_name	= "MultiMedia3",
 		.platform_name  = "msm-pcm-lpa",
 		.dynamic = 1,
-		.dsp_link = &lpa_fe_media,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
 	},
 
@@ -679,6 +675,8 @@
 		.be_id = MSM_BACKEND_DAI_AUXPCM_RX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
 		.ops = &msm_auxpcm_be_ops,
+		.ignore_pmdown_time = 1,
+		/* this dainlink has playback support */
 	},
 	{
 		.name = LPASS_BE_AUXPCM_TX,
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 0c30dc9..f66a01c 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -34,6 +34,7 @@
 #define VOC_PATH_PASSIVE 0
 #define VOC_PATH_FULL 1
 #define VOC_PATH_VOLTE_PASSIVE 2
+#define VOC_PATH_SGLTE_PASSIVE 3
 
 /* CVP CAL Size: 245760 = 240 * 1024 */
 #define CVP_CAL_SIZE 245760
@@ -149,6 +150,9 @@
 		else if (!strncmp(name, "VoLTE session", 13))
 			session_id =
 			common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
+		else if (!strncmp(name, "SGLTE session", 13))
+			session_id =
+			common.voice[VOC_PATH_SGLTE_PASSIVE].session_id;
 		else
 			session_id = common.voice[VOC_PATH_FULL].session_id;
 
@@ -189,6 +193,11 @@
 	return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id);
 }
 
+static bool is_sglte_session(u16 session_id)
+{
+	return (session_id == common.voice[VOC_PATH_SGLTE_PASSIVE].session_id);
+}
+
 static int voice_apr_register(void)
 {
 	pr_debug("%s\n", __func__);
@@ -275,8 +284,10 @@
 		pr_err("%s: apr_mvm is NULL.\n", __func__);
 		return -EINVAL;
 	}
-	pr_debug("%s: VoLTE command to MVM\n", __func__);
-	if (is_volte_session(v->session_id)) {
+	pr_debug("%s: VoLTE/SGLTE command to MVM\n", __func__);
+	if (is_volte_session(v->session_id) ||
+			is_sglte_session(v->session_id)) {
+
 		mvm_handle = voice_get_mvm_handle(v);
 		mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
 						APR_MSG_TYPE_SEQ_CMD,
@@ -350,7 +361,8 @@
 
 	if (!mvm_handle) {
 		if (is_voice_session(v->session_id) ||
-				is_volte_session(v->session_id)) {
+				is_volte_session(v->session_id) ||
+				is_sglte_session(v->session_id)) {
 			mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
 						APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -369,11 +381,15 @@
 			if (is_volte_session(v->session_id)) {
 				strlcpy(mvm_session_cmd.mvm_session.name,
 				"default volte voice",
+				sizeof(mvm_session_cmd.mvm_session.name) - 1);
+			} else if (is_sglte_session(v->session_id)) {
+				strlcpy(mvm_session_cmd.mvm_session.name,
+				"default modem voice2",
 				sizeof(mvm_session_cmd.mvm_session.name));
 			} else {
-			strlcpy(mvm_session_cmd.mvm_session.name,
+				strlcpy(mvm_session_cmd.mvm_session.name,
 				"default modem voice",
-				sizeof(mvm_session_cmd.mvm_session.name));
+				sizeof(mvm_session_cmd.mvm_session.name) - 1);
 			}
 
 			v->mvm_state = CMD_STATUS_FAIL;
@@ -432,7 +448,8 @@
 	/* send cmd to create cvs session */
 	if (!cvs_handle) {
 		if (is_voice_session(v->session_id) ||
-			is_volte_session(v->session_id)) {
+			is_volte_session(v->session_id) ||
+			is_sglte_session(v->session_id)) {
 			pr_debug("%s: creating CVS passive session\n",
 				 __func__);
 
@@ -452,11 +469,15 @@
 			if (is_volte_session(v->session_id)) {
 				strlcpy(mvm_session_cmd.mvm_session.name,
 				"default volte voice",
-				sizeof(mvm_session_cmd.mvm_session.name));
-			} else {
-			strlcpy(cvs_session_cmd.cvs_session.name,
-				"default modem voice",
+				sizeof(mvm_session_cmd.mvm_session.name) - 1);
+			} else if (is_sglte_session(v->session_id)) {
+				strlcpy(cvs_session_cmd.cvs_session.name,
+				"default modem voice2",
 				sizeof(cvs_session_cmd.cvs_session.name));
+			} else {
+				strlcpy(cvs_session_cmd.cvs_session.name,
+				"default modem voice",
+				sizeof(cvs_session_cmd.cvs_session.name) - 1);
 			}
 			v->cvs_state = CMD_STATUS_FAIL;
 
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 88ab0d5..468aba8 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -16,7 +16,7 @@
 #include <linux/ion.h>
 
 #define MAX_VOC_PKT_SIZE 642
-#define SESSION_NAME_LEN 20
+#define SESSION_NAME_LEN 21
 
 #define VOC_REC_UPLINK		0x00
 #define VOC_REC_DOWNLINK	0x01
@@ -918,7 +918,7 @@
 	void *buf;
 };
 
-#define MAX_VOC_SESSIONS 3
+#define MAX_VOC_SESSIONS 4
 #define SESSION_ID_BASE 0xFFF0
 
 struct common_data {
@@ -990,6 +990,7 @@
 #define VOICE_SESSION_NAME "Voice session"
 #define VOIP_SESSION_NAME "VoIP session"
 #define VOLTE_SESSION_NAME "VoLTE session"
+#define SGLTE_SESSION_NAME "SGLTE session"
 uint16_t voc_get_session_id(char *name);
 
 int voc_start_playback(uint32_t set);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index daba79d..7723934 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -139,8 +139,7 @@
 		case ASM_SESSION_CMD_RUN_V2: {
 			if (!atomic_read(&prtd->pending_buffer))
 				break;
-			pr_debug("%s:writing %d bytes"
-				" of buffer[%d] to dsp\n",
+			pr_debug("%s:writing %d bytes of buffer[%d] to dsp\n",
 				__func__, prtd->pcm_count, prtd->out_head);
 			buf = prtd->audio_client->port[IN].buf;
 			pr_debug("%s:writing buffer[%d] from 0x%08x\n",
@@ -367,8 +366,8 @@
 		rc = q6asm_set_volume(compressed_audio.prtd->audio_client,
 								 volume);
 		if (rc < 0) {
-			pr_err("%s: Send Volume command failed"
-					" rc=%d\n", __func__, rc);
+			pr_err("%s: Send Volume command failed rc=%d\n",
+						__func__, rc);
 		}
 	}
 	compressed_audio.volume = volume;
@@ -489,8 +488,8 @@
 			runtime->hw.period_bytes_min,
 			runtime->hw.periods_max);
 	if (ret < 0) {
-		pr_err("Audio Start: Buffer Allocation failed "
-					"rc = %d\n", ret);
+		pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
+						ret);
 		return -ENOMEM;
 	}
 	buf = prtd->audio_client->port[dir].buf;
@@ -535,12 +534,9 @@
 		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,
+		pr_debug("%s: bytes_consumed:,timestamp = %lld,\n",
+						__func__,
 			tstamp.timestamp);
 		if (copy_to_user((void *) arg, &tstamp,
 			sizeof(struct snd_compr_tstamp)))
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h
index 2183690..9830300 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h
@@ -15,7 +15,7 @@
 #define _MSM_COMPR_H
 #include <sound/apr_audio-v2.h>
 #include <sound/q6asm-v2.h>
-#include <sound/snd_compress_params.h>
+#include <sound/compress_params.h>
 #include <sound/compress_offload.h>
 #include <sound/compress_driver.h>
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index ee92753..05ef2ce 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -27,7 +27,7 @@
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <linux/android_pmem.h>
-#include <sound/snd_compress_params.h>
+#include <sound/compress_params.h>
 #include <sound/compress_offload.h>
 #include <sound/compress_driver.h>
 #include <sound/timer.h>
@@ -148,8 +148,7 @@
 			if (runtime->status->hw_ptr >=
 				runtime->control->appl_ptr)
 				break;
-			pr_debug("%s:writing %d bytes"
-				" of buffer to dsp\n",
+			pr_debug("%s:writing %d bytes of buffer to dsp\n",
 				__func__, prtd->pcm_count);
 			buf = prtd->audio_client->port[IN].buf;
 			param.paddr = (unsigned long)buf[prtd->out_head].phys;
@@ -340,8 +339,8 @@
 	if (lpa_audio.prtd && lpa_audio.prtd->audio_client) {
 		rc = q6asm_set_volume(lpa_audio.prtd->audio_client, volume);
 		if (rc < 0) {
-			pr_err("%s: Send Volume command failed"
-					" rc=%d\n", __func__, rc);
+			pr_err("%s: Send Volume command failed rc=%d\n",
+					__func__, rc);
 		}
 	}
 	lpa_audio.volume = volume;
@@ -461,8 +460,8 @@
 			runtime->hw.period_bytes_min,
 			runtime->hw.periods_max);
 	if (ret < 0) {
-		pr_err("Audio Start: Buffer Allocation failed "
-					"rc = %d\n", ret);
+		pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
+						ret);
 		return -ENOMEM;
 	}
 	buf = prtd->audio_client->port[dir].buf;
@@ -509,12 +508,9 @@
 		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,
+		pr_debug("%s: bytes_consumed:timestamp = %lld,\n",
+					__func__,
 			tstamp.timestamp);
 		if (copy_to_user((void *) arg, &tstamp,
 			sizeof(struct snd_compr_tstamp)))
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 3a9fbe1..fd3fe6a 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -236,11 +236,24 @@
 	}
 
 	if (codec_dai->driver->ops->startup) {
-		ret = codec_dai->driver->ops->startup(substream, codec_dai);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't open codec %s\n",
-				codec_dai->name);
-			goto codec_dai_err;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			ret = codec_dai->driver->ops->startup(substream,
+								codec_dai);
+			if (ret < 0) {
+				printk(KERN_ERR "asoc: can't open codec %s\n",
+					codec_dai->name);
+				goto codec_dai_err;
+			}
+		} else {
+			if (!codec_dai->capture_active) {
+				ret = codec_dai->driver->ops->startup(substream,
+								codec_dai);
+				if (ret < 0) {
+					printk(KERN_ERR "can't open codec %s\n",
+						codec_dai->name);
+					goto codec_dai_err;
+				}
+			}
 		}
 	}
 
@@ -456,8 +469,15 @@
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		snd_soc_dai_digital_mute(codec_dai, 1);
 
-	if (cpu_dai->driver->ops->shutdown)
-		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
+	if (cpu_dai->driver->ops->shutdown) {
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			codec_dai->driver->ops->shutdown(substream, codec_dai);
+		} else {
+			if (!codec_dai->capture_active)
+				codec_dai->driver->ops->shutdown(substream,
+								codec_dai);
+		}
+	}
 
 	if (codec_dai->driver->ops->shutdown)
 		codec_dai->driver->ops->shutdown(substream, codec_dai);
@@ -485,7 +505,8 @@
 		}
 	} else {
 		/* capture streams can be powered down now */
-		snd_soc_dapm_stream_event(rtd,
+		if (!codec_dai->capture_active)
+			snd_soc_dapm_stream_event(rtd,
 			codec_dai->driver->capture.stream_name,
 			SND_SOC_DAPM_STREAM_STOP);
 	}
@@ -557,11 +578,12 @@
 		snd_soc_dapm_stream_event(rtd,
 					  codec_dai->driver->playback.stream_name,
 					  SND_SOC_DAPM_STREAM_START);
-	else
-		snd_soc_dapm_stream_event(rtd,
+	else {
+		if (codec_dai->capture_active == 1)
+			snd_soc_dapm_stream_event(rtd,
 					  codec_dai->driver->capture.stream_name,
 					  SND_SOC_DAPM_STREAM_START);
-
+	}
 	snd_soc_dai_digital_mute(codec_dai, 0);
 
 out:
@@ -594,11 +616,24 @@
 	}
 
 	if (codec_dai->driver->ops->hw_params) {
-		ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
-				codec_dai->name);
-			goto codec_err;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			ret = codec_dai->driver->ops->hw_params(substream,
+							params, codec_dai);
+			if (ret < 0) {
+				printk(KERN_ERR "not set codec %s hw params\n",
+					codec_dai->name);
+				goto codec_err;
+			}
+		} else {
+			if (codec_dai->capture_active == 1) {
+				ret = codec_dai->driver->ops->hw_params(
+						substream, params, codec_dai);
+				if (ret < 0) {
+					printk(KERN_ERR "fail: %s hw params\n",
+						codec_dai->name);
+					goto codec_err;
+				}
+			}
 		}
 	}
 
@@ -706,9 +741,19 @@
 	int ret;
 
 	if (codec_dai->driver->ops->trigger) {
-		ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
-		if (ret < 0)
-			return ret;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			ret = codec_dai->driver->ops->trigger(substream,
+						cmd, codec_dai);
+			if (ret < 0)
+				return ret;
+		} else {
+			if (codec_dai->capture_active == 1) {
+				ret = codec_dai->driver->ops->trigger(
+						substream, cmd, codec_dai);
+				if (ret < 0)
+					return ret;
+			}
+		}
 	}
 
 	if (platform->driver->ops && platform->driver->ops->trigger) {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 1fcf1bb..28e5548 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -30,6 +30,17 @@
 	return __value(parse_events_text + 1, 16, PE_RAW);
 }
 
+static int sh_raw(void)
+{
+	return __value(parse_events_text + 2, 16, PE_SH_RAW);
+}
+
+static int fab_raw(void)
+{
+	return __value(parse_events_text + 2, 16, PE_FAB_RAW);
+}
+
+
 static int str(int token)
 {
 	parse_events_lval.str = strdup(parse_events_text);
@@ -107,6 +118,8 @@
 
 mem:			{ return PE_PREFIX_MEM; }
 r{num_raw_hex}		{ return raw(); }
+rs{num_raw_hex}		{ return sh_raw(); }
+rm{num_raw_hex}		{ return fab_raw(); }
 {num_dec}		{ return value(10); }
 {num_hex}		{ return value(16); }
 
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index d9637da..07b292d 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -24,7 +24,7 @@
 
 %}
 
-%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM
+%token PE_VALUE PE_VALUE_SYM PE_RAW PE_SH_RAW PE_FAB_RAW PE_TERM
 %token PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
@@ -33,6 +33,8 @@
 %type <num> PE_VALUE
 %type <num> PE_VALUE_SYM
 %type <num> PE_RAW
+%type <num> PE_SH_RAW
+%type <num> PE_FAB_RAW
 %type <num> PE_TERM
 %type <str> PE_NAME
 %type <str> PE_NAME_CACHE_TYPE
@@ -77,7 +79,9 @@
 	   event_legacy_mem |
 	   event_legacy_tracepoint sep_dc |
 	   event_legacy_numeric sep_dc |
-	   event_legacy_raw sep_dc
+	   event_legacy_raw sep_dc |
+	   event_legacy_shared_raw sep_dc |
+	   event_legacy_fabric_raw sep_dc
 
 event_pmu:
 PE_NAME '/' event_config '/'
@@ -149,6 +153,18 @@
 	ABORT_ON(parse_events_add_numeric(list_event, idx, PERF_TYPE_RAW, $1, NULL));
 }
 
+event_legacy_shared_raw:
+PE_SH_RAW
+{
+	ABORT_ON(parse_events_add_numeric(list_event, idx, 6, $1, NULL));
+}
+
+event_legacy_fabric_raw:
+PE_FAB_RAW
+{
+	ABORT_ON(parse_events_add_numeric(list_event, idx, 7, $1, NULL));
+}
+
 event_config:
 event_config ',' event_term
 {