Merge "base: genlock: add magic to protect attach from non-genlock file" into msm-3.4
diff --git a/Documentation/devicetree/bindings/pil/pil-mba.txt b/Documentation/devicetree/bindings/pil/pil-mba.txt
new file mode 100644
index 0000000..7aafd219
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-mba.txt
@@ -0,0 +1,27 @@
+Qualcomm Modem Boot Authenticator Peripheral Image Loader
+
+pil-mba is a peripheral image loader (PIL) driver. It is used for loading
+modem images using the self-authenticating hardware and software features
+of the Modem Boot Authenticator.
+
+Required properties:
+- compatible:	      Must be "qcom,pil-mba"
+- reg:		      Two pairs of physical base addresses and sizes. The
+		      first corresponds to the Relay Message Buffer (RMB)
+		      register base. The second specifies the address at which
+		      the primary modem image metadata should be stored.
+- qcom,firmware-name: Base name of the firmware image. Ex. "modem"
+
+Optional properties:
+- qcom,depends-on:    firmware-name of a prerequisite image that must already
+		      be running.
+
+Example:
+	qcom,mba@fc820000 {
+		compatible = "qcom,pil-mba";
+		reg = <0xfc820000 0x0020>,
+		      <0x0d1f0000 0x4000>;
+
+		qcom,firmware-name = "modem";
+		qcom,depends-on    = "mba";
+	};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
new file mode 100644
index 0000000..95e7f88
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -0,0 +1,32 @@
+Qualcomm MSS QDSP6v5 Peripheral Image Loader
+
+pil-qdsp6v5-mss is a peripheral image loader (PIL) driver. It is used for
+loading QDSP6v5 (Hexagon) firmware images for modem subsystems into memory and
+preparing the subsystem's processor to execute code. It's also responsible for
+shutting down the processor when it's not needed.
+
+Required properties:
+- compatible:	      Must be "qcom,pil-q6v5-mss"
+- reg:		      Four pairs of physical base addresses and region sizes of
+		      memory mapped registers. The first region corresponds to
+		      QDSP6SS_PUB, the second to the bus port halt register
+		      base, the third to the MSS_RELAY_MSG_BUFFER base, and the
+		      fourth to the MSS_RESTART register.
+- vdd_mss-supply:     Reference to the regulator that supplies the processor.
+- qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
+- qcom,pil-self-auth: <0> if the hardware does not require self-authenticating
+		      images and self-authentication is not desired;
+		      <1> if the hardware requires self-authenticating images.
+
+Example:
+	qcom,mss@fc880000 {
+		compatible = "qcom,pil-q6v5-mss";
+		reg = <0xfc880000 0x100>,
+		      <0xfd485000 0x400>,
+		      <0xfc820000 0x020>,
+		      <0xfc401680 0x004>;
+		vdd_mss-supply = <&pm8841_s3>;
+
+		qcom,firmware-name = "mba";
+		qcom,pil-self-auth = <1>;
+	};
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index 523c9b0..b157e95 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -153,13 +153,13 @@
 				status = "disabled";
 
 				qcom,ctl@2600 {
-					reg = <0x2300 0x100>;
+					reg = <0x2600 0x100>;
 				};
 				qcom,ps@2700 {
-					reg = <0x2400 0x100>;
+					reg = <0x2700 0x100>;
 				};
 				qcom,freq@2800 {
-					reg = <0x2500 0x100>;
+					reg = <0x2800 0x100>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/msm9625.dts b/arch/arm/boot/dts/msm9625.dts
index d5aed00..b7b8be2 100644
--- a/arch/arm/boot/dts/msm9625.dts
+++ b/arch/arm/boot/dts/msm9625.dts
@@ -33,9 +33,11 @@
 		reg = <0xfd510000 0x4000>;
 	};
 
-	timer {
+	timer: msm-qtimer@f9021000 {
 		compatible = "qcom,msm-qtimer", "arm,armv7-timer";
+		reg = <0xF9021000 0x1000>;
 		interrupts = <0 7 0>;
+		irq-is-not-percpu;
 		clock-frequency = <5000000>;
 	};
 
diff --git a/arch/arm/boot/dts/msmcopper-rumi.dts b/arch/arm/boot/dts/msmcopper-rumi.dts
index dff1973..3f1a2ac 100644
--- a/arch/arm/boot/dts/msmcopper-rumi.dts
+++ b/arch/arm/boot/dts/msmcopper-rumi.dts
@@ -38,14 +38,6 @@
                 qcom,sdcc-clk-rates = <400000 19200000>;
         };
 
-	qcom,sdcc@f9864000 {
-		status = "disable";
-	};
-
-	qcom,sdcc@f98e4000 {
-		status = "disable";
-	};
-
 	qcom,sps@f998000 {
 		status = "disable";
 	};
diff --git a/arch/arm/boot/dts/msmcopper-sim.dts b/arch/arm/boot/dts/msmcopper-sim.dts
index ae3f2dd..ab6b8ba 100644
--- a/arch/arm/boot/dts/msmcopper-sim.dts
+++ b/arch/arm/boot/dts/msmcopper-sim.dts
@@ -17,22 +17,4 @@
 / {
 	model = "Qualcomm MSM Copper Simulator";
 	compatible = "qcom,msmcopper-sim", "qcom,msmcopper";
-
-	qcom,sdcc@f9824000 {
-		qcom,sdcc-disable_cmd23;
-	};
-
-	qcom,sdcc@f98a4000 {
-		status = "disable";
-	};
-
-	qcom,sdcc@f9864000 {
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-disable_cmd23;
-	};
-
-	qcom,sdcc@f98e4000 {
-		status = "disable";
-	};
 };
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 60f59d3..5b5e646 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -111,6 +111,7 @@
 		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
 		qcom,sdcc-sup-voltages = <1800 1800>;
 		qcom,sdcc-bus-width = <4>;
+		status = "disable";
 	};
 
 	qcom,sdcc@f98e4000 {
@@ -122,6 +123,7 @@
 		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
 		qcom,sdcc-sup-voltages = <1800 1800>;
 		qcom,sdcc-bus-width = <4>;
+		status = "disable";
 	};
 
 	qcom,sps@f9980000 {
@@ -274,6 +276,11 @@
 		compatible = "qcom,dwc-usb3-msm";
 		reg = <0xF9200000 0xCCFF>;
 		interrupts = <0 131 0>;
+		SSUSB_VDDCX-supply = <&pm8841_s2>;
+		SSUSB_1p8-supply = <&pm8941_l6>;
+		HSUSB_VDDCX-supply = <&pm8841_s2>;
+		HSUSB_1p8-supply = <&pm8941_l6>;
+		HSUSB_3p3-supply = <&pm8941_l24>;
 		qcom,dwc-usb3-msm-dbm-eps = <4>;
 	};
 
@@ -289,6 +296,27 @@
 		qcom,firmware-name = "adsp";
 	};
 
+	qcom,mss@fc880000 {
+		compatible = "qcom,pil-q6v5-mss";
+		reg = <0xfc880000 0x100>,
+		      <0xfd485000 0x400>,
+		      <0xfc820000 0x020>,
+		      <0xfc401680 0x004>;
+		vdd_mss-supply = <&pm8841_s3>;
+
+		qcom,firmware-name = "mba";
+		qcom,pil-self-auth = <1>;
+	};
+
+	qcom,mba@fc820000 {
+		compatible = "qcom,pil-mba";
+		reg = <0xfc820000 0x0020>,
+		      <0x0d1fc000 0x4000>;
+
+		qcom,firmware-name = "modem";
+		qcom,depends-on    = "mba";
+	};
+
 	qcom,pronto@fb21b000 {
 		compatible = "qcom,pil-pronto";
 		reg = <0xfb21b000 0x3000>,
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 148f17f..49fae4a 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -45,9 +45,10 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_PIL_LPASS_QDSP6V5=y
-CONFIG_MSM_TZ_LOG=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_MSM_PIL_MBA=y
 CONFIG_MSM_PIL_PRONTO=y
-CONFIG_MSM_IOMMU=y
+CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_OCMEM=y
 CONFIG_NO_HZ=y
@@ -68,14 +69,16 @@
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-# CONFIG_SUSPEND is not set
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
 CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -96,6 +99,7 @@
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_NETDEVICES=y
+CONFIG_KS8851=m
 # CONFIG_MSM_RMNET is not set
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
@@ -107,6 +111,7 @@
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
 CONFIG_DCC_TTY=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -163,6 +168,7 @@
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_MSM_IOMMU=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
@@ -199,4 +205,3 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-CONFIG_HW_RANDOM_MSM=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 447427a..a163829 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -192,6 +192,7 @@
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
+CONFIG_TUN=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 CONFIG_LIBRA_SDIOIF=m
@@ -227,6 +228,7 @@
 CONFIG_BATTERY_MSM=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_MARIMBA_CORE=y
+CONFIG_REGULATOR_MSM_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
@@ -237,13 +239,13 @@
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
 CONFIG_OV5647=y
-CONFIG_OV8825=y
 CONFIG_AD5046_ACT=y
 CONFIG_WEBCAM_OV9726=y
 CONFIG_MT9E013=y
 CONFIG_S5K4E1=y
 CONFIG_DW9712_ACT=y
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_OV8825=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
 CONFIG_OV7692=y
@@ -339,6 +341,5 @@
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 639eb10..d8e2e3c 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -192,6 +192,7 @@
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
+CONFIG_TUN=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 CONFIG_LIBRA_SDIOIF=m
@@ -228,6 +229,7 @@
 CONFIG_BATTERY_MSM=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_MARIMBA_CORE=y
+CONFIG_REGULATOR_MSM_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
@@ -238,13 +240,13 @@
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
 CONFIG_OV5647=y
-CONFIG_OV8825=y
 CONFIG_AD5046_ACT=y
 CONFIG_WEBCAM_OV9726=y
 CONFIG_MT9E013=y
 CONFIG_S5K4E1=y
 CONFIG_DW9712_ACT=y
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_OV8825=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
 CONFIG_OV7692=y
@@ -347,6 +349,5 @@
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 4000a0f..136dc46 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -207,6 +207,7 @@
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_TUN=y
 CONFIG_MSM_RMNET_SDIO=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
@@ -272,6 +273,7 @@
 CONFIG_FB_MSM_TRIPLE_BUFFER=y
 CONFIG_FB_MSM_MDP40=y
 CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
 CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
 CONFIG_FB_MSM_HDMI_ADV7520_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
@@ -369,7 +371,6 @@
 CONFIG_DEBUG_INFO=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index fdcd566..bead86e 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -208,6 +208,7 @@
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_TUN=y
 CONFIG_MSM_RMNET_SDIO=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
@@ -274,6 +275,7 @@
 CONFIG_FB_MSM_TRIPLE_BUFFER=y
 CONFIG_FB_MSM_MDP40=y
 CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
 CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
 CONFIG_FB_MSM_HDMI_ADV7520_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
@@ -377,7 +379,6 @@
 CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index d5b4007..98661be 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -248,6 +248,7 @@
 CONFIG_DM_UEVENT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_TUN=y
 CONFIG_MSM_RMNET_SDIO=y
 CONFIG_SMC91X=y
 CONFIG_SMC911X=y
@@ -443,7 +444,6 @@
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 5e2c1a8..ec7c036 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -249,6 +249,7 @@
 CONFIG_DM_UEVENT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_TUN=y
 CONFIG_MSM_RMNET_SDIO=y
 CONFIG_SMC91X=y
 CONFIG_SMC911X=y
@@ -455,7 +456,6 @@
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_LL=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 74d31b3..47d6ea8 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -66,7 +66,6 @@
 CONFIG_MSM_SMD_PKG4=y
 CONFIG_MSM_PCIE=y
 CONFIG_MSM_BAM_DMUX=y
-CONFIG_MSM_RMNET_SMUX=y
 CONFIG_MSM_DSPS=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
@@ -256,9 +255,11 @@
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_TUN=y
 CONFIG_KS8851=m
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
+CONFIG_MSM_RMNET_SMUX=y
 CONFIG_SMC91X=y
 CONFIG_SMC911X=y
 CONFIG_SMSC911X=y
@@ -308,7 +309,6 @@
 CONFIG_SMB349_CHARGER=y
 CONFIG_PM8921_CHARGER=y
 CONFIG_PM8921_BMS=y
-CONFIG_PM8921_BCL=y
 CONFIG_SENSORS_PM8XXX_ADC=y
 CONFIG_SENSORS_EPM_ADC=y
 CONFIG_THERMAL=y
@@ -475,7 +475,6 @@
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_PID_IN_CONTEXTIDR=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 07a3f91..a0636f9 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -261,6 +261,7 @@
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_TUN=y
 CONFIG_KS8851=m
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
@@ -492,7 +493,6 @@
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_PID_IN_CONTEXTIDR=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 89fb888..1e45f66 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -1,7 +1,7 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
@@ -28,6 +28,7 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM9625=y
 # CONFIG_MSM_STACKED_MEMORY is not set
@@ -51,7 +52,6 @@
 # CONFIG_SUSPEND is not set
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-CONFIG_MISC_DEVICES=y
 # CONFIG_ANDROID_PMEM is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
@@ -67,20 +67,17 @@
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_PARTITION_ADVANCED=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index 2098288..99ee2de 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -4,7 +4,7 @@
 #include <linux/ioport.h>
 
 struct arch_timer {
-	struct resource	res[2];
+	struct resource	res[3];
 };
 
 #ifdef CONFIG_ARM_ARCH_TIMER
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 745a3a4..a6ec7b2 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -59,8 +59,7 @@
  */
 struct msm_mmc_slot_reg_data {
 	struct msm_mmc_reg_data *vdd_data; /* keeps VDD/VCC regulator info */
-	struct msm_mmc_reg_data *vccq_data; /* keeps VCCQ regulator info */
-	struct msm_mmc_reg_data *vddp_data; /* keeps VDD Pad regulator info */
+	struct msm_mmc_reg_data *vdd_io_data; /* keeps VDD IO regulator info */
 };
 
 struct msm_mmc_gpio {
@@ -147,7 +146,6 @@
 	unsigned int msmsdcc_fmid;
 	unsigned int msmsdcc_fmax;
 	bool nonremovable;
-	bool pclk_src_dfab;
 	unsigned int mpm_sdiowakeup_int;
 	unsigned int wpswitch_gpio;
 	unsigned char wpswitch_polarity;
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 81a9a71..88cf368 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -19,6 +19,7 @@
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/of_irq.h>
+#include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 
@@ -32,8 +33,43 @@
 static unsigned long arch_timer_rate;
 static int arch_timer_ppi;
 static int arch_timer_ppi2;
+static int is_irq_percpu;
 
 static struct clock_event_device __percpu **arch_timer_evt;
+static void __iomem *timer_base;
+
+static u32 timer_reg_read_cp15(int reg);
+static void timer_reg_write_cp15(int reg, u32 val);
+static inline cycle_t counter_get_cntpct_cp15(void);
+static inline cycle_t counter_get_cntvct_cp15(void);
+
+static u32 timer_reg_read_mem(int reg);
+static void timer_reg_write_mem(int reg, u32 val);
+static inline cycle_t counter_get_cntpct_mem(void);
+static inline cycle_t counter_get_cntvct_mem(void);
+
+struct arch_timer_operations {
+	void (*reg_write)(int, u32);
+	u32 (*reg_read)(int);
+	cycle_t (*get_cntpct)(void);
+	cycle_t (*get_cntvct)(void);
+};
+
+static struct arch_timer_operations arch_timer_ops_cp15 = {
+	.reg_read = &timer_reg_read_cp15,
+	.reg_write = &timer_reg_write_cp15,
+	.get_cntpct = &counter_get_cntpct_cp15,
+	.get_cntvct = &counter_get_cntvct_cp15,
+};
+
+static struct arch_timer_operations arch_timer_ops_mem = {
+	.reg_read = &timer_reg_read_mem,
+	.reg_write = &timer_reg_write_mem,
+	.get_cntpct = &counter_get_cntpct_mem,
+	.get_cntvct = &counter_get_cntvct_mem,
+};
+
+static struct arch_timer_operations *arch_specific_timer = &arch_timer_ops_cp15;
 
 /*
  * Architected system timer support.
@@ -47,7 +83,29 @@
 #define ARCH_TIMER_REG_FREQ		1
 #define ARCH_TIMER_REG_TVAL		2
 
-static void arch_timer_reg_write(int reg, u32 val)
+/* Iomapped Register Offsets */
+#define QTIMER_CNTP_LOW_REG		0x000
+#define QTIMER_CNTP_HIGH_REG		0x004
+#define QTIMER_CNTV_LOW_REG		0x008
+#define QTIMER_CNTV_HIGH_REG		0x00C
+#define QTIMER_CTRL_REG			0x02C
+#define QTIMER_FREQ_REG			0x010
+#define QTIMER_CNTP_TVAL_REG		0x028
+#define QTIMER_CNTV_TVAL_REG		0x038
+
+static void timer_reg_write_mem(int reg, u32 val)
+{
+	switch (reg) {
+	case ARCH_TIMER_REG_CTRL:
+		__raw_writel(val, timer_base + QTIMER_CTRL_REG);
+		break;
+	case ARCH_TIMER_REG_TVAL:
+		__raw_writel(val, timer_base + QTIMER_CNTP_TVAL_REG);
+		break;
+	}
+}
+
+static void timer_reg_write_cp15(int reg, u32 val)
 {
 	switch (reg) {
 	case ARCH_TIMER_REG_CTRL:
@@ -61,7 +119,28 @@
 	isb();
 }
 
-static u32 arch_timer_reg_read(int reg)
+static u32 timer_reg_read_mem(int reg)
+{
+	u32 val;
+
+	switch (reg) {
+	case ARCH_TIMER_REG_CTRL:
+		val = __raw_readl(timer_base + QTIMER_CTRL_REG);
+		break;
+	case ARCH_TIMER_REG_FREQ:
+		val = __raw_readl(timer_base + QTIMER_FREQ_REG);
+		break;
+	case ARCH_TIMER_REG_TVAL:
+		val = __raw_readl(timer_base + QTIMER_CNTP_TVAL_REG);
+		break;
+	default:
+		BUG();
+	}
+
+	return val;
+}
+
+static u32 timer_reg_read_cp15(int reg)
 {
 	u32 val;
 
@@ -87,10 +166,11 @@
 	struct clock_event_device *evt;
 	unsigned long ctrl;
 
-	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
 	if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
 		ctrl |= ARCH_TIMER_CTRL_IT_MASK;
-		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+		arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL,
+							ctrl);
 		evt = *__this_cpu_ptr(arch_timer_evt);
 		evt->event_handler(evt);
 		return IRQ_HANDLED;
@@ -103,9 +183,9 @@
 {
 	unsigned long ctrl;
 
-	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
 	ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
-	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+	arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
 }
 
 static void arch_timer_set_mode(enum clock_event_mode mode,
@@ -126,12 +206,12 @@
 {
 	unsigned long ctrl;
 
-	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
 	ctrl |= ARCH_TIMER_CTRL_ENABLE;
 	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
 
-	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
-	arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
+	arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+	arch_specific_timer->reg_write(ARCH_TIMER_REG_TVAL, evt);
 
 	return 0;
 }
@@ -168,19 +248,16 @@
 static int local_timer_is_architected(void)
 {
 	return (cpu_architecture() >= CPU_ARCH_ARMv7) &&
-	       ((read_cpuid_ext(CPUID_EXT_PFR1) >> 16) & 0xf) == 1;
+		((read_cpuid_ext(CPUID_EXT_PFR1) >> 16) & 0xf) == 1;
 }
 
 static int arch_timer_available(void)
 {
 	unsigned long freq;
 
-	if (!local_timer_is_architected())
-		return -ENXIO;
-
 	if (arch_timer_rate == 0) {
-		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0);
-		freq = arch_timer_reg_read(ARCH_TIMER_REG_FREQ);
+		arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, 0);
+		freq = arch_specific_timer->reg_read(ARCH_TIMER_REG_FREQ);
 
 		/* Check the timer frequency. */
 		if (freq == 0) {
@@ -196,33 +273,57 @@
 	return 0;
 }
 
-static inline cycle_t arch_counter_get_cntpct(void)
+static inline cycle_t counter_get_cntpct_mem(void)
 {
-	u32 cvall, cvalh;
+	u32 cvall, cvalh, thigh;
 
-	asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
+	do {
+		cvalh = __raw_readl(timer_base + QTIMER_CNTP_HIGH_REG);
+		cvall = __raw_readl(timer_base + QTIMER_CNTP_LOW_REG);
+		thigh = __raw_readl(timer_base + QTIMER_CNTP_HIGH_REG);
+	} while (cvalh != thigh);
 
 	return ((cycle_t) cvalh << 32) | cvall;
 }
 
-static inline cycle_t arch_counter_get_cntvct(void)
+static inline cycle_t counter_get_cntpct_cp15(void)
+{
+	u32 cvall, cvalh;
+
+	asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
+	return ((cycle_t) cvalh << 32) | cvall;
+}
+
+static inline cycle_t counter_get_cntvct_mem(void)
+{
+	u32 cvall, cvalh, thigh;
+
+	do {
+		cvalh = __raw_readl(timer_base + QTIMER_CNTV_HIGH_REG);
+		cvall = __raw_readl(timer_base + QTIMER_CNTV_LOW_REG);
+		thigh = __raw_readl(timer_base + QTIMER_CNTV_HIGH_REG);
+	} while (cvalh != thigh);
+
+	return ((cycle_t) cvalh << 32) | cvall;
+}
+
+static inline cycle_t counter_get_cntvct_cp15(void)
 {
 	u32 cvall, cvalh;
 
 	asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
-
 	return ((cycle_t) cvalh << 32) | cvall;
 }
 
 static cycle_t arch_counter_read(struct clocksource *cs)
 {
-	return arch_counter_get_cntpct();
+	return arch_specific_timer->get_cntpct();
 }
 
 #ifdef ARCH_HAS_READ_CURRENT_TIMER
 int read_current_timer(unsigned long *timer_val)
 {
-	*timer_val = (unsigned long)arch_counter_get_cntpct();
+	*timer_val = (unsigned long)arch_specific_timer->get_cntpct();
 	return 0;
 }
 #endif
@@ -239,7 +340,7 @@
 {
 	cycle_t cntvct;
 
-	cntvct = arch_counter_get_cntvct();
+	cntvct = arch_specific_timer->get_cntvct();
 
 	/*
 	 * The sched_clock infrastructure only knows about counters
@@ -273,6 +374,9 @@
 {
 	int err;
 
+	if (!local_timer_is_architected())
+		arch_specific_timer = &arch_timer_ops_mem;
+
 	err = arch_timer_available();
 	if (err)
 		return err;
@@ -289,8 +393,12 @@
 	set_delay_fn(read_current_timer_delay_loop);
 #endif
 
-	err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
+	if (is_irq_percpu)
+		err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
 				 "arch_timer", arch_timer_evt);
+	else
+		err = request_irq(arch_timer_ppi, arch_timer_handler, 0,
+			"arch_timer", arch_timer_evt);
 	if (err) {
 		pr_err("arch_timer: can't register interrupt %d (%d)\n",
 		       arch_timer_ppi, err);
@@ -298,8 +406,13 @@
 	}
 
 	if (arch_timer_ppi2) {
-		err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler,
-					 "arch_timer", arch_timer_evt);
+		if (is_irq_percpu)
+			err = request_percpu_irq(arch_timer_ppi2,
+					arch_timer_handler, "arch_timer",
+					arch_timer_evt);
+		else
+			err = request_irq(arch_timer_ppi2, arch_timer_handler,
+					0, "arch_timer", arch_timer_evt);
 		if (err) {
 			pr_err("arch_timer: can't register interrupt %d (%d)\n",
 			       arch_timer_ppi2, err);
@@ -336,6 +449,16 @@
 	if (at->res[1].start > 0 && (at->res[1].flags & IORESOURCE_IRQ))
 		arch_timer_ppi2 = at->res[1].start;
 
+	if (at->res[2].start > 0 && at->res[2].end > 0 &&
+					(at->res[2].flags & IORESOURCE_MEM))
+		timer_base = ioremap(at->res[2].start,
+				resource_size(&at->res[2]));
+
+	if (!timer_base) {
+		pr_err("arch_timer: cant map timer base\n");
+		return -ENOMEM;
+	}
+
 	return arch_timer_common_register();
 }
 
@@ -366,6 +489,18 @@
 		pr_err("arch_timer: interrupt not specified in timer node\n");
 		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_property(np, "irq-is-not-percpu", NULL))
+		is_irq_percpu = 0;
+	else
+		is_irq_percpu = 1;
+
 	arch_timer_ppi = ret;
 	ret = irq_of_parse_and_map(np, 1);
 	if (ret > 0)
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index cbdb51a..3554b56 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -227,7 +227,7 @@
 config ARCH_MSMCOPPER
 	bool "MSM Copper"
 	select ARCH_MSM_KRAITMP
-	select GPIO_MSM_V2
+	select GPIO_MSM_V3
 	select ARM_GIC
 	select CPU_V7
 	select MSM_SCM if SMP
@@ -1841,8 +1841,22 @@
        tristate "LPASS QDSP6v5 (Hexagon) Boot Support"
        depends on MSM_PIL
        help
-         Support for booting and shutting down QDSP6v5 processors (Hexagon)
-	 processors in low power audio subsystems.
+         Support for booting and shutting down QDSP6v5 (Hexagon) processors
+	 in low power audio subsystems.
+
+config MSM_PIL_MSS_QDSP6V5
+       tristate "MSS QDSP6v5 (Hexagon) Boot Support"
+       depends on MSM_PIL
+       help
+         Support for booting and shutting down QDSP6v5 (Hexagon) processors
+	 in modem subsystems.
+
+config MSM_PIL_MBA
+	tristate "Support for modem self-authentication"
+	depends on MSM_PIL_MSS_QDSP6V5
+	help
+	  Support for booting self-authenticating modems using the Modem Boot
+	  Authenticator.
 
 config MSM_PIL_RIVA
 	tristate "RIVA (WCNSS) Boot Support"
@@ -2243,6 +2257,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
@@ -2264,6 +2288,16 @@
 
 	  For production builds, you should probably say 'N' here.
 
+config MSM_L1_ERR_LOG
+	bool "Log CPU ERP events to system memory"
+	depends on MSM_CACHE_ERP
+	help
+	  Enable logging CPU ERP events to an area of memory that will be
+	  preserved across a system reset. This may be useful for detecting and
+	  troubleshooting ERP-related system crashes in the field.
+
+	  For production builds, you may want to say 'Y' here.
+
 config MSM_L2_ERP_PRINT_ACCESS_ERRORS
 	bool "Report L2 master port slave/decode errors in kernel log"
 	depends on MSM_CACHE_ERP
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 44bef1b..3043b78 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -70,6 +70,8 @@
 obj-$(CONFIG_MSM_PIL_QDSP6V3) += pil-q6v3.o
 obj-$(CONFIG_MSM_PIL_QDSP6V4) += pil-q6v4.o
 obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
+obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-q6v5-mss.o
+obj-$(CONFIG_MSM_PIL_MBA) += pil-mba.o
 obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
 obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
 obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
@@ -286,7 +288,7 @@
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
 obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o board-copper-gpiomux.o
 obj-$(CONFIG_ARCH_MSMCOPPER) += acpuclock-krait.o acpuclock-copper.o
-obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o clock-pll.o clock-copper.o
+obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o clock-pll.o clock-copper.o clock-rpm.o clock-voter.o
 obj-$(CONFIG_ARCH_MSMCOPPER) += gdsc.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
 
@@ -328,7 +330,7 @@
 ifdef CONFIG_VCM
 obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
 endif
-obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.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
@@ -362,6 +364,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-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index f467aba..a58eb6e 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -105,6 +105,14 @@
 	HFPLL_VDD_NOM
 };
 
+enum pvs {
+	PVS_SLOW,
+	PVS_NOM,
+	PVS_FAST,
+	PVS_FASTER,
+	NUM_PVS
+};
+
 struct vreg {
 	const char name[15];
 	const unsigned int max_vdd;
@@ -602,7 +610,7 @@
 };
 
 /* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl_8064[] = {
+static struct acpu_level acpu_freq_tbl_8064_slow[] = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
 	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   975000 },
@@ -629,6 +637,60 @@
 	{ 0, { 0 } }
 };
 
+static struct acpu_level acpu_freq_tbl_8064_nom[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
+	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   925000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),   950000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),   975000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),   975000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),  1025000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),  1025000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1050000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1050000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1075000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1075000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1125000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1125000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1150000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1150000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1175000 },
+	{ 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 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_8064_fast[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   850000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   850000 },
+	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   875000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),   900000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),   925000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),   975000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),   975000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1000000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1000000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1025000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1025000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1075000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1075000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1100000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1100000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1125000 },
+	{ 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 },
+	{ 0, { 0 } }
+};
+
 /* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
 #undef L2
 #define L2(x) (&l2_freq_tbl_8930[(x)])
@@ -711,6 +773,26 @@
 	{ 0, { 0 } }
 };
 
+static struct acpu_level *acpu_freq_tbl_8960_v1[NUM_PVS] __initdata = {
+	[PVS_SLOW] = acpu_freq_tbl_8960_kraitv1_slow,
+	[PVS_NOM] = acpu_freq_tbl_8960_kraitv1_nom_fast,
+	[PVS_FAST] = acpu_freq_tbl_8960_kraitv1_nom_fast,
+};
+
+static struct acpu_level *acpu_freq_tbl_8960_v2[NUM_PVS] __initdata = {
+	[PVS_SLOW] = acpu_freq_tbl_8960_kraitv2_slow,
+	[PVS_NOM] = acpu_freq_tbl_8960_kraitv2_nom,
+	[PVS_FAST] = acpu_freq_tbl_8960_kraitv2_fast,
+};
+
+/* TODO: update the faster table when data is available */
+static struct acpu_level *acpu_freq_tbl_8064[NUM_PVS] __initdata = {
+	[PVS_SLOW] = acpu_freq_tbl_8064_slow,
+	[PVS_NOM] = acpu_freq_tbl_8064_nom,
+	[PVS_FAST] = acpu_freq_tbl_8064_fast,
+	[PVS_FASTER] = acpu_freq_tbl_8064_fast,
+};
+
 static unsigned long acpuclk_8960_get_rate(int cpu)
 {
 	return scalable[cpu].current_speed->khz;
@@ -1416,57 +1498,60 @@
 			tbl->vdd_core = 1150000;
 }
 
+static enum pvs __init get_pvs(void)
+{
+	uint32_t pte_efuse, pvs;
+
+	pte_efuse = readl_relaxed(QFPROM_PTE_EFUSE_ADDR);
+	pvs = (pte_efuse >> 10) & 0x7;
+	if (pvs == 0x7)
+		pvs = (pte_efuse >> 13) & 0x7;
+
+	switch (pvs) {
+	case 0x0:
+	case 0x7:
+		pr_info("ACPU PVS: Slow\n");
+		return PVS_SLOW;
+	case 0x1:
+		pr_info("ACPU PVS: Nominal\n");
+		return PVS_NOM;
+	case 0x3:
+		pr_info("ACPU PVS: Fast\n");
+		return PVS_FAST;
+	case 0x4:
+		if (cpu_is_apq8064()) {
+			pr_info("ACPU PVS: Faster\n");
+			return  PVS_FASTER;
+		}
+	default:
+		pr_warn("ACPU PVS: Unknown. Defaulting to slow\n");
+		return PVS_SLOW;
+	}
+}
+
 static struct acpu_level * __init select_freq_plan(void)
 {
 	struct acpu_level *l, *max_acpu_level = NULL;
 
 	/* Select frequency tables. */
 	if (cpu_is_msm8960()) {
-		uint32_t pte_efuse, pvs;
-		struct acpu_level *v1, *v2;
-
-		pte_efuse = readl_relaxed(QFPROM_PTE_EFUSE_ADDR);
-		pvs = (pte_efuse >> 10) & 0x7;
-		if (pvs == 0x7)
-			pvs = (pte_efuse >> 13) & 0x7;
-
-		switch (pvs) {
-		case 0x0:
-		case 0x7:
-			pr_info("ACPU PVS: Slow\n");
-			v1 = acpu_freq_tbl_8960_kraitv1_slow;
-			v2 = acpu_freq_tbl_8960_kraitv2_slow;
-			break;
-		case 0x1:
-			pr_info("ACPU PVS: Nominal\n");
-			v1 = acpu_freq_tbl_8960_kraitv1_nom_fast;
-			v2 = acpu_freq_tbl_8960_kraitv2_nom;
-			break;
-		case 0x3:
-			pr_info("ACPU PVS: Fast\n");
-			v1 = acpu_freq_tbl_8960_kraitv1_nom_fast;
-			v2 = acpu_freq_tbl_8960_kraitv2_fast;
-			break;
-		default:
-			pr_warn("ACPU PVS: Unknown. Defaulting to slow.\n");
-			v1 = acpu_freq_tbl_8960_kraitv1_slow;
-			v2 = acpu_freq_tbl_8960_kraitv2_slow;
-			break;
-		}
+		enum pvs pvs_id = get_pvs();
 
 		scalable = scalable_8960;
 		if (cpu_is_krait_v1()) {
-			acpu_freq_tbl = v1;
+			acpu_freq_tbl = acpu_freq_tbl_8960_v1[pvs_id];
 			l2_freq_tbl = l2_freq_tbl_8960_kraitv1;
 			l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv1);
 		} else {
-			acpu_freq_tbl = v2;
+			acpu_freq_tbl = acpu_freq_tbl_8960_v2[pvs_id];
 			l2_freq_tbl = l2_freq_tbl_8960_kraitv2;
 			l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv2);
 		}
 	} else if (cpu_is_apq8064()) {
+		enum pvs pvs_id = get_pvs();
+
 		scalable = scalable_8064;
-		acpu_freq_tbl = acpu_freq_tbl_8064;
+		acpu_freq_tbl = acpu_freq_tbl_8064[pvs_id];
 		l2_freq_tbl = l2_freq_tbl_8064;
 		l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8064);
 	} else if (cpu_is_msm8627()) {
@@ -1482,6 +1567,7 @@
 	} else {
 		BUG();
 	}
+	BUG_ON(!acpu_freq_tbl);
 	if (krait_needs_vmin())
 		kraitv2_apply_vmin(acpu_freq_tbl);
 
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 71ad49a..7368f6e 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -58,11 +58,15 @@
 };
 
 #define LVDS_CHIMEI_PANEL_NAME "lvds_chimei_wxga"
+#define LVDS_FRC_PANEL_NAME "lvds_frc_fhd"
 #define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
 #define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
 #define HDMI_PANEL_NAME "hdmi_msm"
 #define TVOUT_PANEL_NAME "tvout_msm"
 
+#define LVDS_PIXEL_MAP_PATTERN_1	1
+#define LVDS_PIXEL_MAP_PATTERN_2	2
+
 #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
 static unsigned char hdmi_is_primary = 1;
 #else
@@ -98,12 +102,18 @@
 			strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
 				PANEL_NAME_MAX_LEN)))
 			return 0;
-	} else if (machine_is_apq8064_cdp() ||
-		       machine_is_mpq8064_dtv()) {
+	} else if (machine_is_apq8064_cdp()) {
 		if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
 			strnlen(LVDS_CHIMEI_PANEL_NAME,
 				PANEL_NAME_MAX_LEN)))
 			return 0;
+	} else if (machine_is_mpq8064_dtv()) {
+		if (!strncmp(name, LVDS_FRC_PANEL_NAME,
+			strnlen(LVDS_FRC_PANEL_NAME,
+			PANEL_NAME_MAX_LEN))) {
+			set_mdp_clocks_for_wuxga();
+			return 0;
+		}
 	}
 
 	if (!strncmp(name, HDMI_PANEL_NAME,
@@ -599,7 +609,9 @@
 		u32 ver = socinfo_get_version();
 		if ((SOCINFO_VERSION_MAJOR(ver) == 1) &&
 		    (SOCINFO_VERSION_MINOR(ver) == 0))
-			return 1;
+			return LVDS_PIXEL_MAP_PATTERN_1;
+	} else if (machine_is_mpq8064_dtv()) {
+		return LVDS_PIXEL_MAP_PATTERN_2;
 	}
 	return 0;
 }
@@ -624,6 +636,23 @@
 	}
 };
 
+#define FRC_GPIO_UPDATE	(SX150X_EXP4_GPIO_BASE + 8)
+#define FRC_GPIO_RESET	(SX150X_EXP4_GPIO_BASE + 9)
+#define FRC_GPIO_PWR	(SX150X_EXP4_GPIO_BASE + 10)
+
+static int lvds_frc_gpio[] = {FRC_GPIO_UPDATE, FRC_GPIO_RESET, FRC_GPIO_PWR};
+static struct lvds_panel_platform_data lvds_frc_pdata = {
+	.gpio = lvds_frc_gpio,
+};
+
+static struct platform_device lvds_frc_panel_device = {
+	.name = "lvds_frc_fhd",
+	.id = 0,
+	.dev = {
+		.platform_data = &lvds_frc_pdata,
+	}
+};
+
 static int dsi2lvds_gpio[2] = {
 	LPM_CHANNEL,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
 	0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
@@ -921,6 +950,8 @@
 		platform_device_register(&mipi_dsi2lvds_bridge_device);
 	if (machine_is_apq8064_mtp())
 		platform_device_register(&mipi_dsi_toshiba_panel_device);
+	if (machine_is_mpq8064_dtv())
+		platform_device_register(&lvds_frc_panel_device);
 
 	msm_fb_register_device("mdp", &mdp_pdata);
 	msm_fb_register_device("lvds", &lvds_pdata);
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 877c9fc..bef5cdc 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -126,7 +126,6 @@
 	PM8921_GPIO_INPUT(38, PM_GPIO_PULL_UP_30),
 	/* TABLA CODEC RESET */
 	PM8921_GPIO_OUTPUT(34, 1, MED),
-	PM8921_GPIO_INPUT(31, PM_GPIO_PULL_NO),
 	PM8921_GPIO_OUTPUT(13, 0, HIGH),               /* PCIE_CLK_PWR_EN */
 };
 
@@ -237,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[] = {
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 40222b8..f7d5403 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -54,7 +54,7 @@
 };
 VREG_CONSUMERS(L7) = {
 	REGULATOR_SUPPLY("8921_l7",		NULL),
-	REGULATOR_SUPPLY("sdc_vddp",		"msm_sdcc.3"),
+	REGULATOR_SUPPLY("sdc_vdd_io",		"msm_sdcc.3"),
 };
 VREG_CONSUMERS(L8) = {
 	REGULATOR_SUPPLY("8921_l8",		NULL),
@@ -162,7 +162,7 @@
 };
 VREG_CONSUMERS(S4) = {
 	REGULATOR_SUPPLY("8921_s4",		NULL),
-	REGULATOR_SUPPLY("sdc_vccq",		"msm_sdcc.1"),
+	REGULATOR_SUPPLY("sdc_vdd_io",		"msm_sdcc.1"),
 	REGULATOR_SUPPLY("VDDIO_CDC",		"tabla-slim"),
 	REGULATOR_SUPPLY("CDC_VDD_CP",		"tabla-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_TX",		"tabla-slim"),
@@ -265,9 +265,6 @@
 	REGULATOR_SUPPLY("ext_ts_sw",		NULL),
 	REGULATOR_SUPPLY("vdd_ana",		"3-005b"),
 };
-VREG_CONSUMERS(FRC_5V) = {
-	REGULATOR_SUPPLY("frc_5v",	NULL),
-};
 VREG_CONSUMERS(AVC_1P2V) = {
 	REGULATOR_SUPPLY("avc_1p2v",	NULL),
 };
@@ -519,7 +516,6 @@
 
 struct gpio_regulator_platform_data
 mpq8064_gpio_regulator_pdata[] __devinitdata = {
-	GPIO_VREG(FRC_5V, "frc_5v", "frc_5v_en", SX150X_GPIO(4, 10), NULL),
 	GPIO_VREG(AVC_1P2V, "avc_1p2v", "avc_1p2v_en", SX150X_GPIO(4, 2), NULL),
 	GPIO_VREG(AVC_1P8V, "avc_1p8v", "avc_1p8v_en", SX150X_GPIO(4, 4), NULL),
 	GPIO_VREG(AVC_2P2V, "avc_2p2v", "avc_2p2v_en",
@@ -532,15 +528,15 @@
 /* SAW regulator constraints */
 struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5 =
 	/*	      ID  vreg_name	       min_uV   max_uV */
-	SAW_VREG_INIT(S5, "8921_s5",	       950000, 1300000);
+	SAW_VREG_INIT(S5, "8921_s5",	       850000, 1300000);
 struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6 =
-	SAW_VREG_INIT(S6, "8921_s6",	       950000, 1300000);
+	SAW_VREG_INIT(S6, "8921_s6",	       850000, 1300000);
 
 struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0 =
 	/*	      ID       vreg_name	min_uV  max_uV */
-	SAW_VREG_INIT(8821_S0, "8821_s0",       950000, 1300000);
+	SAW_VREG_INIT(8821_S0, "8821_s0",       850000, 1300000);
 struct regulator_init_data msm8064_saw_regulator_pdata_8821_s1 =
-	SAW_VREG_INIT(8821_S1, "8821_s1",       950000, 1300000);
+	SAW_VREG_INIT(8821_S1, "8821_s1",       850000, 1300000);
 
 /* PM8921 regulator constraints */
 struct pm8xxx_regulator_platform_data
@@ -589,7 +585,7 @@
 	RPM_LDO(L22, 0, 1, 0, 2600000, 2600000, NULL,          0,     0),
 	RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL,          0,     0),
 	RPM_LDO(L24, 0, 1, 1,  750000, 1150000, "8921_s1", 10000, 10000),
-	RPM_LDO(L25, 1, 1, 0, 1225000, 1225000, "8921_s1", 10000, 10000),
+	RPM_LDO(L25, 1, 1, 0, 1250000, 1250000, "8921_s1", 10000, 10000),
 	RPM_LDO(L27, 0, 1, 0, 1100000, 1100000, "8921_s7",     0,     0),
 	RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7",     0,     0),
 	RPM_LDO(L29, 0, 1, 0, 2000000, 2000000, NULL,          0,     0),
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 193fc4a..fe4beab 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -56,23 +56,19 @@
 	}
 };
 
-/* Only slots having eMMC card will require VCCQ voltage */
-static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
+/* SDCC controllers may require voting for VDD IO voltage */
+static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
-		.name = "sdc_vccq",
+		.name = "sdc_vdd_io",
 		.always_on = 1,
 		.high_vol_level = 1800000,
 		.low_vol_level = 1800000,
 		.hpm_uA = 200000, /* 200mA */
-	}
-};
-
-/* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+	},
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
-		.name = "sdc_vddp",
+		.name = "sdc_vdd_io",
 		.high_vol_level = 2950000,
 		.low_vol_level = 1850000,
 		.always_on = 1,
@@ -92,12 +88,12 @@
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
 		.vdd_data = &mmc_vdd_reg_data[SDCC1],
-		.vccq_data = &mmc_vccq_reg_data[SDCC1],
+		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
 	},
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.vdd_data = &mmc_vdd_reg_data[SDCC3],
-		.vddp_data = &mmc_vddp_reg_data[SDCC3],
+		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
 	}
 };
 
@@ -251,7 +247,6 @@
 #endif
 	.sup_clk_table	= sdc1_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc1_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 	.nonremovable	= 1,
 	.pin_data	= &mmc_slot_pin_data[SDCC1],
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
@@ -274,7 +269,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table	= sdc2_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc2_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 	.pin_data	= &mmc_slot_pin_data[SDCC2],
 	.sdiowakeup_irq = MSM_GPIO_TO_INT(61),
 	.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
@@ -294,7 +288,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table	= sdc3_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc3_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 	.pin_data	= &mmc_slot_pin_data[SDCC3],
 	.vreg_data	= &mmc_slot_vreg_data[SDCC3],
 	.wpswitch_gpio	= PM8921_GPIO_PM_TO_SYS(17),
@@ -326,7 +319,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table	= sdc4_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc4_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 	.pin_data	= &mmc_slot_pin_data[SDCC4],
 	.sdiowakeup_irq = MSM_GPIO_TO_INT(65),
 	.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
@@ -366,10 +358,29 @@
 		}
 		if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
 			machine_is_mpq8064_dtv()) {
+			int rc;
+			struct pm_gpio sd_card_det_init_cfg = {
+				.direction      = PM_GPIO_DIR_IN,
+				.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+				.pull           = PM_GPIO_PULL_UP_30,
+				.vin_sel        = PM_GPIO_VIN_S4,
+				.out_strength   = PM_GPIO_STRENGTH_NO,
+				.function       = PM_GPIO_FUNC_NORMAL,
+			};
+
 			apq8064_sdc3_pdata->status_gpio =
 				PM8921_GPIO_PM_TO_SYS(31);
 			apq8064_sdc3_pdata->status_irq =
 				PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 31);
+			rc = pm8xxx_gpio_config(apq8064_sdc3_pdata->status_gpio,
+					&sd_card_det_init_cfg);
+			if (rc) {
+				pr_info("%s: SD_CARD_DET GPIO%d config "
+					"failed(%d)\n", __func__,
+					apq8064_sdc3_pdata->status_gpio, rc);
+				apq8064_sdc3_pdata->status_gpio = 0;
+				apq8064_sdc3_pdata->status_irq = 0;
+			}
 		}
 		apq8064_add_sdcc(3, apq8064_sdc3_pdata);
 	}
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 806bbd8..5f1a57d 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1027,13 +1027,13 @@
 	{
 		.name = "VDDD_CDC_D",
 		.min_uV = 1225000,
-		.max_uV = 1225000,
+		.max_uV = 1250000,
 		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
 	},
 	{
 		.name = "CDC_VDDA_A_1P2V",
 		.min_uV = 1225000,
-		.max_uV = 1225000,
+		.max_uV = 1250000,
 		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
 	},
 	},
@@ -1094,13 +1094,13 @@
 	{
 		.name = "VDDD_CDC_D",
 		.min_uV = 1225000,
-		.max_uV = 1225000,
+		.max_uV = 1250000,
 		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
 	},
 	{
 		.name = "CDC_VDDA_A_1P2V",
 		.min_uV = 1225000,
-		.max_uV = 1225000,
+		.max_uV = 1250000,
 		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
 	},
 	},
@@ -2187,8 +2187,10 @@
 	&apq_cpudai_stub,
 	&apq_cpudai_slimbus_1_rx,
 	&apq_cpudai_slimbus_1_tx,
+	&apq_cpudai_slimbus_2_rx,
 	&apq_cpudai_slimbus_2_tx,
 	&apq_cpudai_slimbus_3_rx,
+	&apq_cpudai_slimbus_3_tx,
 	&apq8064_rpm_device,
 	&apq8064_rpm_log_device,
 	&apq8064_rpm_stat_device,
@@ -2247,16 +2249,6 @@
 };
 
 static struct platform_device
-mpq8064_device_ext_5v_frc_vreg __devinitdata = {
-	.name	= GPIO_REGULATOR_DEV_NAME,
-	.id	= SX150X_GPIO(4, 10),
-	.dev	= {
-		.platform_data =
-			&mpq8064_gpio_regulator_pdata[GPIO_VREG_ID_FRC_5V],
-	},
-};
-
-static struct platform_device
 mpq8064_device_ext_1p2_buck_vreg __devinitdata = {
 	.name	= GPIO_REGULATOR_DEV_NAME,
 	.id	= SX150X_GPIO(4, 2),
@@ -2345,7 +2337,6 @@
 	&msm_rotator_device,
 #endif
 	&gpio_ir_recv_pdev,
-	&mpq8064_device_ext_5v_frc_vreg,
 	&mpq8064_device_ext_1p2_buck_vreg,
 	&mpq8064_device_ext_1p8_buck_vreg,
 	&mpq8064_device_ext_2p2_buck_vreg,
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 39c367f..a241ab3 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -45,12 +45,11 @@
 #define GPIO_VREG_ID_EXT_TS_SW		2
 #define GPIO_VREG_ID_EXT_MPP8		3
 
-#define GPIO_VREG_ID_FRC_5V		0
-#define GPIO_VREG_ID_AVC_1P2V		1
-#define GPIO_VREG_ID_AVC_1P8V		2
-#define GPIO_VREG_ID_AVC_2P2V		3
-#define GPIO_VREG_ID_AVC_5V		4
-#define GPIO_VREG_ID_AVC_3P3V		5
+#define GPIO_VREG_ID_AVC_1P2V		0
+#define GPIO_VREG_ID_AVC_1P8V		1
+#define GPIO_VREG_ID_AVC_2P2V		2
+#define GPIO_VREG_ID_AVC_5V		3
+#define GPIO_VREG_ID_AVC_3P3V		4
 
 #define APQ8064_EXT_3P3V_REG_EN_GPIO	77
 
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index c7ab260..000f080 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -624,6 +624,22 @@
 	},
 };
 
+static struct gpiomux_setting sd_det_line = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm8930_sd_det_config[] __initdata = {
+	{
+		.gpio = 94,	/* SD Card Detect Line */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &sd_det_line,
+			[GPIOMUX_ACTIVE] = &sd_det_line,
+		},
+	},
+};
+
 int __init msm8930_init_gpiomux(void)
 {
 	int rc = msm_gpiomux_init(NR_GPIO_IRQS);
@@ -687,5 +703,9 @@
 
 	msm_gpiomux_install(msm8960_mdp_vsync_configs,
 			ARRAY_SIZE(msm8960_mdp_vsync_configs));
+
+	msm_gpiomux_install(msm8930_sd_det_config,
+			ARRAY_SIZE(msm8930_sd_det_config));
+
 	return 0;
 }
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index cf7a829..188cf39 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[] = {
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 2f24c95..cb8903c 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -80,7 +80,7 @@
 	REGULATOR_SUPPLY("vdd_dig",		"3-004a"),
 	REGULATOR_SUPPLY("iris_vddio",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
-	REGULATOR_SUPPLY("sdc_vccq",		"msm_sdcc.1"),
+	REGULATOR_SUPPLY("sdc_vdd_io",		"msm_sdcc.1"),
 	REGULATOR_SUPPLY("VDDIO_CDC",		"sitar-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_TX",		"sitar-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_RX",		"sitar-slim"),
@@ -129,7 +129,7 @@
 };
 VREG_CONSUMERS(L22) = {
 	REGULATOR_SUPPLY("8038_l22",		NULL),
-	REGULATOR_SUPPLY("sdc_vddp",		"msm_sdcc.3"),
+	REGULATOR_SUPPLY("sdc_vdd_io",		"msm_sdcc.3"),
 };
 VREG_CONSUMERS(L23) = {
 	REGULATOR_SUPPLY("8038_l23",		NULL),
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index 52a11bc..65da578 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -53,27 +53,35 @@
 		.name = "sdc_vdd",
 		.high_vol_level = 2950000,
 		.low_vol_level = 2950000,
-		.hpm_uA = 800000, /* 800mA */
-	}
-};
-
-/* Only slots having eMMC card will require VCCQ voltage */
-static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
-	/* SDCC1 : eMMC card connected */
-	[SDCC1] = {
-		.name = "sdc_vccq",
+		/*
+		 * Normally this is not an always ON regulator. On this
+		 * platform, unfortunately the sd detect line is connected
+		 * to this via esd circuit and so turn this off/on while card
+		 * is not present causes the sd detect line to toggle
+		 * continuously. This is expected to be fixed in the newer
+		 * hardware revisions - maybe once that is done, this can be
+		 * reverted.
+		 */
 		.always_on = 1,
-		.high_vol_level = 1800000,
-		.low_vol_level = 1800000,
-		.hpm_uA = 200000, /* 200mA */
+		.lpm_sup = 1,
+		.hpm_uA = 800000, /* 800mA */
+		.lpm_uA = 9000,
 	}
 };
 
 /* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
+	/* SDCC1 : eMMC card connected */
+	[SDCC1] = {
+		.name = "sdc_vdd_io",
+		.always_on = 1,
+		.high_vol_level = 1800000,
+		.low_vol_level = 1800000,
+		.hpm_uA = 200000, /* 200mA */
+	},
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
-		.name = "sdc_vddp",
+		.name = "sdc_vdd_io",
 		.high_vol_level = 2950000,
 		.low_vol_level = 1850000,
 		.always_on = 1,
@@ -93,12 +101,12 @@
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
 		.vdd_data = &mmc_vdd_reg_data[SDCC1],
-		.vccq_data = &mmc_vccq_reg_data[SDCC1],
+		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
 	},
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.vdd_data = &mmc_vdd_reg_data[SDCC3],
-		.vddp_data = &mmc_vddp_reg_data[SDCC3],
+		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
 	}
 };
 
@@ -231,7 +239,6 @@
 #endif
 	.sup_clk_table	= sdc1_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc1_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 	.nonremovable	= 1,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
 	.pin_data	= &mmc_slot_pin_data[SDCC1],
@@ -246,7 +253,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table	= sdc3_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc3_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 #ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
 /*TODO: Insert right replacement for PM8038 */
 #ifndef MSM8930_PHASE_2
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 98d9f3a..338cb84 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -126,6 +126,7 @@
 #define MSM_LIQUID_PMEM_SIZE 0x4000000 /* 64 Mbytes */
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#define HOLE_SIZE	0x20000
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x65000
 #ifdef CONFIG_MSM_IOMMU
 #define MSM_ION_MM_SIZE            0x3800000 /* Need to be multiple of 64K */
@@ -138,7 +139,7 @@
 #define MSM_ION_QSECOM_SIZE	0x600000 /* (6MB) */
 #define MSM_ION_HEAP_NUM	8
 #endif
-#define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
+#define MSM_ION_MM_FW_SIZE	(0x200000 - HOLE_SIZE) /* 2MB - 128Kb */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 
@@ -146,10 +147,11 @@
 #define MSM_LIQUID_ION_SF_SIZE MSM_LIQUID_PMEM_SIZE
 #define MSM_HDMI_PRIM_ION_SF_SIZE MSM_HDMI_PRIM_PMEM_SIZE
 
-#define MSM8930_FIXED_AREA_START 0xa0000000
+#define MSM_MM_FW_SIZE	(0x200000 - HOLE_SIZE) /*2MB -128Kb */
+#define MSM8930_FIXED_AREA_START (0xa0000000 - (MSM_ION_MM_FW_SIZE + \
+								HOLE_SIZE))
 #define MAX_FIXED_AREA_SIZE	0x10000000
-#define MSM_MM_FW_SIZE		0x200000
-#define MSM8930_FW_START	(MSM8930_FIXED_AREA_START - MSM_MM_FW_SIZE)
+#define MSM8930_FW_START	MSM8930_FIXED_AREA_START
 
 #else
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x110C000
@@ -560,7 +562,8 @@
 		return;
 
 	if (msm8930_fmem_pdata.size) {
-		msm8930_fmem_pdata.reserved_size_low = fixed_low_size;
+		msm8930_fmem_pdata.reserved_size_low = fixed_low_size +
+							HOLE_SIZE;
 		msm8930_fmem_pdata.reserved_size_high = fixed_high_size;
 	}
 
@@ -572,7 +575,7 @@
 	msm8930_reserve_fixed_area(fixed_size);
 
 	fixed_low_start = MSM8930_FIXED_AREA_START;
-	fixed_middle_start = fixed_low_start + fixed_low_size;
+	fixed_middle_start = fixed_low_start + fixed_low_size + HOLE_SIZE;
 	fixed_high_start = fixed_middle_start + fixed_middle_size;
 
 	for (i = 0; i < msm8930_ion_pdata.nr; ++i) {
@@ -580,11 +583,13 @@
 
 		if (heap->extra_data) {
 			int fixed_position = NOT_FIXED;
+			struct ion_cp_heap_pdata *pdata = NULL;
 
 			switch (heap->type) {
 			case ION_HEAP_TYPE_CP:
-				fixed_position = ((struct ion_cp_heap_pdata *)
-					heap->extra_data)->fixed_position;
+				pdata =
+				(struct ion_cp_heap_pdata *)heap->extra_data;
+				fixed_position = pdata->fixed_position;
 				break;
 			case ION_HEAP_TYPE_CARVEOUT:
 				fixed_position = ((struct ion_co_heap_pdata *)
@@ -600,6 +605,9 @@
 				break;
 			case FIXED_MIDDLE:
 				heap->base = fixed_middle_start;
+				pdata->secure_base = fixed_middle_start
+							- HOLE_SIZE;
+				pdata->secure_size = HOLE_SIZE + heap->size;
 				break;
 			case FIXED_HIGH:
 				heap->base = fixed_high_start;
@@ -1194,6 +1202,7 @@
 	[23] = MSM_GPIO_TO_INT(85),
 	[24] = MSM_GPIO_TO_INT(83),
 	[25] = USB1_HS_IRQ,
+	[26] = MSM_GPIO_TO_INT(6),
 	[27] = HDMI_IRQ,
 	[29] = MSM_GPIO_TO_INT(10),
 	[30] = MSM_GPIO_TO_INT(102),
@@ -1207,15 +1216,15 @@
 	[38] = MSM_GPIO_TO_INT(50),
 	[39] = MSM_GPIO_TO_INT(42),
 	[41] = MSM_GPIO_TO_INT(62),
-	[42] = MSM_GPIO_TO_INT(76),
-	[43] = MSM_GPIO_TO_INT(75),
+	[42] = MSM_GPIO_TO_INT(8),
+	[43] = MSM_GPIO_TO_INT(33),
 	[44] = MSM_GPIO_TO_INT(70),
 	[45] = MSM_GPIO_TO_INT(69),
 	[46] = MSM_GPIO_TO_INT(67),
 	[47] = MSM_GPIO_TO_INT(65),
-	[48] = MSM_GPIO_TO_INT(58),
-	[49] = MSM_GPIO_TO_INT(54),
-	[50] = MSM_GPIO_TO_INT(52),
+	[48] = MSM_GPIO_TO_INT(55),
+	[49] = MSM_GPIO_TO_INT(74),
+	[50] = MSM_GPIO_TO_INT(98),
 	[51] = MSM_GPIO_TO_INT(49),
 	[52] = MSM_GPIO_TO_INT(40),
 	[53] = MSM_GPIO_TO_INT(37),
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index ea1ab58..977dbb2 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -529,11 +529,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[] = {
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 93c72ea..bc5a892 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -53,7 +53,7 @@
 };
 VREG_CONSUMERS(L7) = {
 	REGULATOR_SUPPLY("8921_l7",		NULL),
-	REGULATOR_SUPPLY("sdc_vddp",		"msm_sdcc.3"),
+	REGULATOR_SUPPLY("sdc_vdd_io",		"msm_sdcc.3"),
 };
 VREG_CONSUMERS(L8) = {
 	REGULATOR_SUPPLY("8921_l8",		NULL),
@@ -162,9 +162,9 @@
 };
 VREG_CONSUMERS(S4) = {
 	REGULATOR_SUPPLY("8921_s4",		NULL),
-	REGULATOR_SUPPLY("sdc_vccq",		"msm_sdcc.1"),
+	REGULATOR_SUPPLY("sdc_vdd_io",		"msm_sdcc.1"),
 	REGULATOR_SUPPLY("sdc_vdd",		"msm_sdcc.2"),
-	REGULATOR_SUPPLY("sdc_vddp",            "msm_sdcc.4"),
+	REGULATOR_SUPPLY("sdc_vdd_io",            "msm_sdcc.4"),
 	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("hdmi_vcc",		"hdmi_msm.0"),
 	REGULATOR_SUPPLY("VDDIO_CDC",		"tabla-slim"),
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index 1279b75..e674e91 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -65,23 +65,19 @@
 	}
 };
 
-/* Only slots having eMMC card will require VCCQ voltage */
-static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
+/* SDCC controllers may require voting for IO operating voltage */
+static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
-		.name = "sdc_vccq",
+		.name = "sdc_vdd_io",
 		.always_on = 1,
 		.high_vol_level = 1800000,
 		.low_vol_level = 1800000,
 		.hpm_uA = 200000, /* 200mA */
-	}
-};
-
-/* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+	},
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
-		.name = "sdc_vddp",
+		.name = "sdc_vdd_io",
 		.high_vol_level = 2950000,
 		.low_vol_level = 1850000,
 		.always_on = 1,
@@ -97,7 +93,7 @@
 	},
 	/* SDCC4 : SDIO slot connected */
 	[SDCC4] = {
-		.name = "sdc_vddp",
+		.name = "sdc_vdd_io",
 		.high_vol_level = 1800000,
 		.low_vol_level = 1800000,
 		.always_on = 1,
@@ -111,7 +107,7 @@
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
 		.vdd_data = &mmc_vdd_reg_data[SDCC1],
-		.vccq_data = &mmc_vccq_reg_data[SDCC1],
+		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
 	},
 	/* SDCC2 : SDIO card slot connected */
 	[SDCC2] = {
@@ -120,11 +116,11 @@
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.vdd_data = &mmc_vdd_reg_data[SDCC3],
-		.vddp_data = &mmc_vddp_reg_data[SDCC3],
+		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
 	},
 	/* SDCC4 : SDIO card slot connected */
 	[SDCC4] = {
-		.vddp_data = &mmc_vddp_reg_data[SDCC4],
+		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC4],
 	},
 };
 
@@ -294,7 +290,6 @@
 #endif
 	.sup_clk_table	= sdc1_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc1_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 	.nonremovable	= 1,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
 	.pin_data	= &mmc_slot_pin_data[SDCC1],
@@ -313,7 +308,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table  = sdc2_sup_clk_rates,
 	.sup_clk_cnt    = ARRAY_SIZE(sdc2_sup_clk_rates),
-	.pclk_src_dfab  = 1,
 	.vreg_data      = &mmc_slot_vreg_data[SDCC2],
 	.pin_data       = &mmc_slot_pin_data[SDCC2],
 	.sdiowakeup_irq = MSM_GPIO_TO_INT(90),
@@ -327,7 +321,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table	= sdc3_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc3_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 #ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
 	.wpswitch_gpio	= PM8921_GPIO_PM_TO_SYS(16),
 #endif
@@ -358,7 +351,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table  = sdc4_sup_clk_rates,
 	.sup_clk_cnt    = ARRAY_SIZE(sdc4_sup_clk_rates),
-	.pclk_src_dfab  = 1,
 	.vreg_data      = &mmc_slot_vreg_data[SDCC4],
 	.pin_data       = &mmc_slot_pin_data[SDCC4],
 	.sdiowakeup_irq = MSM_GPIO_TO_INT(85),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index e0831fb..9c096b7 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -50,6 +50,7 @@
 #include <asm/mach/mmc.h>
 
 #include <mach/board.h>
+#include <mach/msm_tspp.h>
 #include <mach/msm_iomap.h>
 #include <mach/msm_spi.h>
 #include <mach/msm_serial_hs.h>
@@ -144,6 +145,7 @@
 #define MSM_HDMI_PRIM_PMEM_SIZE 0x4000000 /* 64 Mbytes */
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#define HOLE_SIZE	0x20000
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x65000
 #ifdef CONFIG_MSM_IOMMU
 #define MSM_ION_MM_SIZE            0x3800000 /* Need to be multiple of 64K */
@@ -156,7 +158,7 @@
 #define MSM_ION_QSECOM_SIZE        0x600000 /* (6MB) */
 #define MSM_ION_HEAP_NUM	8
 #endif
-#define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
+#define MSM_ION_MM_FW_SIZE	(0x200000 - HOLE_SIZE) /* 128kb */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 
@@ -164,10 +166,11 @@
 #define MSM_LIQUID_ION_SF_SIZE MSM_LIQUID_PMEM_SIZE
 #define MSM_HDMI_PRIM_ION_SF_SIZE MSM_HDMI_PRIM_PMEM_SIZE
 
-#define MSM8960_FIXED_AREA_START 0xa0000000
+#define MSM_MM_FW_SIZE		(0x200000 - HOLE_SIZE) /* 2mb -128kb*/
+#define MSM8960_FIXED_AREA_START (0xa0000000 - (MSM_ION_MM_FW_SIZE + \
+							HOLE_SIZE))
 #define MAX_FIXED_AREA_SIZE	0x10000000
-#define MSM_MM_FW_SIZE		0x200000
-#define MSM8960_FW_START	(MSM8960_FIXED_AREA_START - MSM_MM_FW_SIZE)
+#define MSM8960_FW_START	MSM8960_FIXED_AREA_START
 
 static unsigned msm_ion_sf_size = MSM_ION_SF_SIZE;
 #else
@@ -640,7 +643,8 @@
 		return;
 
 	if (msm8960_fmem_pdata.size) {
-		msm8960_fmem_pdata.reserved_size_low = fixed_low_size;
+		msm8960_fmem_pdata.reserved_size_low = fixed_low_size +
+							HOLE_SIZE;
 		msm8960_fmem_pdata.reserved_size_high = fixed_high_size;
 	}
 
@@ -652,7 +656,7 @@
 	msm8960_reserve_fixed_area(fixed_size);
 
 	fixed_low_start = MSM8960_FIXED_AREA_START;
-	fixed_middle_start = fixed_low_start + fixed_low_size;
+	fixed_middle_start = fixed_low_start + fixed_low_size + HOLE_SIZE;
 	fixed_high_start = fixed_middle_start + fixed_middle_size;
 
 	for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
@@ -660,11 +664,13 @@
 
 		if (heap->extra_data) {
 			int fixed_position = NOT_FIXED;
+			struct ion_cp_heap_pdata *pdata = NULL;
 
 			switch (heap->type) {
 			case ION_HEAP_TYPE_CP:
-				fixed_position = ((struct ion_cp_heap_pdata *)
-					heap->extra_data)->fixed_position;
+				pdata =
+				(struct ion_cp_heap_pdata *)heap->extra_data;
+				fixed_position = pdata->fixed_position;
 				break;
 			case ION_HEAP_TYPE_CARVEOUT:
 				fixed_position = ((struct ion_co_heap_pdata *)
@@ -680,6 +686,9 @@
 				break;
 			case FIXED_MIDDLE:
 				heap->base = fixed_middle_start;
+				pdata->secure_base = fixed_middle_start
+							- HOLE_SIZE;
+				pdata->secure_size = HOLE_SIZE + heap->size;
 				break;
 			case FIXED_HIGH:
 				heap->base = fixed_high_start;
@@ -1284,6 +1293,87 @@
 	.peripheral_platform_device = NULL,
 };
 
+#define MSM_TSIF0_PHYS			(0x18200000)
+#define MSM_TSIF1_PHYS			(0x18201000)
+#define MSM_TSIF_SIZE			(0x200)
+#define MSM_TSPP_PHYS			(0x18202000)
+#define MSM_TSPP_SIZE			(0x1000)
+#define MSM_TSPP_BAM_PHYS		(0x18204000)
+#define MSM_TSPP_BAM_SIZE		(0x2000)
+
+#define TSIF_0_CLK       GPIO_CFG(75, 1, GPIO_CFG_INPUT, \
+	GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_0_EN        GPIO_CFG(76, 1, GPIO_CFG_INPUT, \
+	GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_0_DATA      GPIO_CFG(77, 1, GPIO_CFG_INPUT, \
+	GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_0_SYNC      GPIO_CFG(82, 1, GPIO_CFG_INPUT, \
+	GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_1_CLK       GPIO_CFG(79, 1, GPIO_CFG_INPUT, \
+	GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_1_EN        GPIO_CFG(80, 1, GPIO_CFG_INPUT, \
+	GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_1_DATA      GPIO_CFG(81, 1, GPIO_CFG_INPUT, \
+	GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_1_SYNC      GPIO_CFG(78, 1, GPIO_CFG_INPUT, \
+	GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+
+static const struct msm_gpio tsif_gpios[] = {
+	{ .gpio_cfg = TSIF_0_CLK,  .label =  "tsif0_clk", },
+	{ .gpio_cfg = TSIF_0_EN,   .label =  "tsif0_en", },
+	{ .gpio_cfg = TSIF_0_DATA, .label =  "tsif0_data", },
+	{ .gpio_cfg = TSIF_0_SYNC, .label =  "tsif0_sync", },
+	{ .gpio_cfg = TSIF_1_CLK,  .label =  "tsif1_clk", },
+	{ .gpio_cfg = TSIF_1_EN,   .label =  "tsif1_en", },
+	{ .gpio_cfg = TSIF_1_DATA, .label =  "tsif1_data", },
+	{ .gpio_cfg = TSIF_1_SYNC, .label =  "tsif1_sync", },
+};
+
+static struct resource tspp_resources[] = {
+	[0] = {
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF_TSPP_IRQ,
+		.end   = TSIF1_IRQ,
+	},
+	[1] = {
+		.flags = IORESOURCE_MEM,
+		.start = MSM_TSIF0_PHYS,
+		.end   = MSM_TSIF0_PHYS + MSM_TSIF_SIZE - 1,
+	},
+	[2] = {
+		.flags = IORESOURCE_MEM,
+		.start = MSM_TSIF1_PHYS,
+		.end   = MSM_TSIF1_PHYS + MSM_TSIF_SIZE - 1,
+	},
+	[3] = {
+		.flags = IORESOURCE_MEM,
+		.start = MSM_TSPP_PHYS,
+		.end   = MSM_TSPP_PHYS + MSM_TSPP_SIZE - 1,
+	},
+	[4] = {
+		.flags = IORESOURCE_MEM,
+		.start = MSM_TSPP_BAM_PHYS,
+		.end   = MSM_TSPP_BAM_PHYS + MSM_TSPP_BAM_SIZE - 1,
+	},
+};
+
+static struct msm_tspp_platform_data tspp_platform_data = {
+	.num_gpios = ARRAY_SIZE(tsif_gpios),
+	.gpios = tsif_gpios,
+	.tsif_pclk = "tsif_pclk",
+	.tsif_ref_clk = "tsif_ref_clk",
+};
+
+static struct platform_device msm_device_tspp = {
+	.name          = "msm_tspp",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(tspp_resources),
+	.resource      = tspp_resources,
+	.dev = {
+		.platform_data = &tspp_platform_data
+	},
+};
+
 #define MSM_SHARED_RAM_PHYS 0x80000000
 
 static void __init msm8960_map_io(void)
@@ -2466,7 +2556,6 @@
 	&msm_device_vidc,
 	&msm_device_bam_dmux,
 	&msm_fm_platform_init,
-
 #if defined(CONFIG_TSIF) || defined(CONFIG_TSIF_MODULE)
 #ifdef CONFIG_MSM_USE_TSIF1
 	&msm_device_tsif[1],
@@ -2474,7 +2563,7 @@
 	&msm_device_tsif[0],
 #endif
 #endif
-
+	&msm_device_tspp,
 #ifdef CONFIG_HW_RANDOM_MSM
 	&msm_device_rng,
 #endif
@@ -2521,6 +2610,7 @@
 	&msm_pcm_routing,
 	&msm_cpudai0,
 	&msm_cpudai1,
+	&msm8960_cpudai_slimbus_2_rx,
 	&msm8960_cpudai_slimbus_2_tx,
 	&msm_cpudai_hdmi_rx,
 	&msm_cpudai_bt_rx,
@@ -2558,6 +2648,9 @@
 #ifdef CONFIG_MSM_GEMINI
 	&msm8960_gemini_device,
 #endif
+#ifdef CONFIG_MSM_MERCURY
+	&msm8960_mercury_device,
+#endif
 };
 
 static struct platform_device *cdp_devices[] __initdata = {
@@ -2577,6 +2670,7 @@
 	&msm_pcm_routing,
 	&msm_cpudai0,
 	&msm_cpudai1,
+	&msm8960_cpudai_slimbus_2_rx,
 	&msm8960_cpudai_slimbus_2_tx,
 	&msm_cpudai_hdmi_rx,
 	&msm_cpudai_bt_rx,
@@ -2595,6 +2689,9 @@
 #ifdef CONFIG_MSM_GEMINI
 	&msm8960_gemini_device,
 #endif
+#ifdef CONFIG_MSM_MERCURY
+	&msm8960_mercury_device,
+#endif
 	&msm_voice,
 	&msm_voip,
 	&msm_lpa_pcm,
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index 7ed350d..1122ed9 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -61,7 +61,7 @@
 };
 VREG_CONSUMERS(L13) = {
 	REGULATOR_SUPPLY("8018_l13",		NULL),
-	REGULATOR_SUPPLY("sdc_vddp",		"msm_sdcc.1"),
+	REGULATOR_SUPPLY("sdc_vdd_io",		"msm_sdcc.1"),
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8018_l14",		NULL),
@@ -316,7 +316,7 @@
 
 	/*	 ID    a_on pd ss min_uV   max_uV  supply  sys_uA init_ip */
 	RPM_LDO(L2,      1, 1, 0, 1800000, 1800000, NULL,      0, 10000),
-	RPM_LDO(L3,      0, 1, 0, 1800000, 1800000, NULL,      0, 0),
+	RPM_LDO(L3,      1, 1, 0, 1800000, 1800000, NULL,      0, 0),
 	RPM_LDO(L4,      0, 1, 0, 3075000, 3075000, NULL,      0, 0),
 	RPM_LDO(L5,      0, 1, 0, 2850000, 2850000, NULL,      0, 0),
 	RPM_LDO(L6,      0, 1, 0, 1800000, 2850000, NULL,      0, 0),
diff --git a/arch/arm/mach-msm/board-9615-storage.c b/arch/arm/mach-msm/board-9615-storage.c
index 5bdeb94..2025bd0 100644
--- a/arch/arm/mach-msm/board-9615-storage.c
+++ b/arch/arm/mach-msm/board-9615-storage.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -54,10 +54,10 @@
 };
 
 /* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
 	/* SDCC1 : External card slot connected */
 	[SDCC1] = {
-		.name = "sdc_vddp",
+		.name = "sdc_vdd_io",
 		.high_vol_level = 2950000,
 		.low_vol_level = 1850000,
 		.always_on = true,
@@ -77,7 +77,7 @@
 	/* SDCC1 : External card slot connected */
 	[SDCC1] = {
 		.vdd_data = &mmc_vdd_reg_data[SDCC1],
-		.vddp_data = &mmc_vddp_reg_data[SDCC1],
+		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
 	}
 };
 
@@ -176,7 +176,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table	= sdc1_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc1_sup_clk_rates),
-	.pclk_src_dfab	= true,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
 	.pin_data	= &mmc_slot_pin_data[SDCC1],
 #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
@@ -205,7 +204,6 @@
 	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
 	.sup_clk_table	= sdc2_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc2_sup_clk_rates),
-	.pclk_src_dfab	= 1,
 	.pin_data	= &mmc_slot_pin_data[SDCC2],
 	.sdiowakeup_irq = MSM_GPIO_TO_INT(GPIO_SDC2_DAT1_WAKEUP),
 	.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index df114a3..dc376b5 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -471,14 +471,6 @@
 	},
 };
 
-static struct i2c_registry msm9615_i2c_devices[] __initdata = {
-	{
-		I2C_SURF | I2C_FFA | I2C_FLUID,
-		MSM_9615_GSBI5_QUP_I2C_BUS_ID,
-		wcd9xxx_device_info,
-		ARRAY_SIZE(wcd9xxx_device_info),
-	},
-};
 /*
  * MDM9x15 I2S.
  */
@@ -561,6 +553,17 @@
 };
 #endif
 
+static struct i2c_registry msm9615_i2c_devices[] __initdata = {
+#ifdef CONFIG_WCD9310_CODEC
+	{
+		I2C_SURF | I2C_FFA | I2C_FLUID,
+		MSM_9615_GSBI5_QUP_I2C_BUS_ID,
+		wcd9xxx_device_info,
+		ARRAY_SIZE(wcd9xxx_device_info),
+	},
+#endif
+};
+
 static struct slim_boardinfo msm_slim_devices[] = {
 	/* add slimbus slaves as needed */
 #ifdef CONFIG_WCD9310_CODEC
@@ -897,6 +900,8 @@
 	&msm_pcm_afe,
 	&msm_cpudai_auxpcm_rx,
 	&msm_cpudai_auxpcm_tx,
+	&msm_cpudai_sec_auxpcm_rx,
+	&msm_cpudai_sec_auxpcm_tx,
 
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index a8094e1..f83b403 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -421,33 +421,6 @@
 	platform_device_register(&copper_device_tz_log);
 }
 
-/*
- * Used to satisfy dependencies for devices that need to be
- * run early or in a particular order. Most likely your device doesn't fall
- * into this category, and thus the driver should not be added here. The
- * EPROBE_DEFER can satisfy most dependency problems.
- */
-void __init msm_copper_add_drivers(void)
-{
-	msm_smd_init();
-	msm_rpm_driver_init();
-	rpm_regulator_smd_driver_init();
-	msm_spm_device_init();
-	regulator_stub_init();
-}
-
-static struct of_device_id irq_match[] __initdata  = {
-	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
-	{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
-	{ .compatible = "qcom,spmi-pmic-arb", .data = qpnpint_of_init, },
-	{}
-};
-
-void __init msm_copper_init_irq(void)
-{
-	of_irq_init(irq_match);
-}
-
 static struct clk_lookup msm_clocks_dummy[] = {
 	CLK_DUMMY("xo",		XO_CLK,		NULL,	OFF),
 	CLK_DUMMY("xo",		XO_CLK,		"pil_pronto",		OFF),
@@ -476,11 +449,44 @@
 	.size = ARRAY_SIZE(msm_clocks_dummy),
 };
 
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init msm_copper_add_drivers(void)
+{
+	msm_smd_init();
+	msm_rpm_driver_init();
+	rpm_regulator_smd_driver_init();
+	msm_spm_device_init();
+	regulator_stub_init();
+	if (machine_is_copper_rumi())
+		msm_clock_init(&msm_dummy_clock_init_data);
+	else
+		msm_clock_init(&msmcopper_clock_init_data);
+}
+
+static struct of_device_id irq_match[] __initdata  = {
+	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
+	{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
+	{ .compatible = "qcom,spmi-pmic-arb", .data = qpnpint_of_init, },
+	{}
+};
+
+void __init msm_copper_init_irq(void)
+{
+	of_irq_init(irq_match);
+}
+
 static struct of_dev_auxdata msm_copper_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
 			"msm_serial_hsl.0", NULL),
 	OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
 			"msm_otg", NULL),
+	OF_DEV_AUXDATA("qcom,dwc-usb3-msm", 0xF9200000, \
+			"msm_dwc3", NULL),
 	OF_DEV_AUXDATA("qcom,spi-qup-v2", 0xF9924000, \
 			"spi_qsd.1", NULL),
 	OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
@@ -495,6 +501,8 @@
 			"msm_sdcc.4", NULL),
 	OF_DEV_AUXDATA("qcom,pil-q6v5-lpass",   0xFE200000, \
 			"pil-q6v5-lpass", NULL),
+	OF_DEV_AUXDATA("qcom,pil-q6v5-mss", 0xFC880000, "pil-q6v5-mss", NULL),
+	OF_DEV_AUXDATA("qcom,pil-mba",     0xFC820000, "pil-mba", NULL),
 	OF_DEV_AUXDATA("qcom,pil-pronto", 0xFB21B000, \
 			"pil_pronto", NULL),
 	OF_DEV_AUXDATA("qcom,msm-rng", 0xF9BFF000, \
@@ -506,11 +514,6 @@
 {
 	msm_copper_init_gpiomux();
 
-	if (machine_is_copper_rumi())
-		msm_clock_init(&msm_dummy_clock_init_data);
-	else
-		msm_clock_init(&msmcopper_clock_init_data);
-
 	*adata = msm_copper_auxdata_lookup;
 
 	regulator_has_full_constraints();
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index bd38f30..c2b7b9d 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -1140,6 +1140,7 @@
 static int mipi_dsi_panel_qrd3_power(int on)
 {
 	int rc = 0;
+	static struct regulator *gpio_reg_2p85v, *gpio_reg_1p8v;
 
 	if (!qrd3_dsi_gpio_initialized) {
 		rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
@@ -1147,47 +1148,21 @@
 		if (rc < 0)
 			return rc;
 
-		rc = gpio_request(GPIO_QRD3_LCD_EXT_2V85_EN,
-			"qrd3_gpio_ext_2v85_en");
-		if (rc < 0)
-			return rc;
-
-		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0,
-			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
-			GPIO_CFG_ENABLE);
-		if (rc < 0) {
-			pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_2V85_EN tlmm config\n");
-			return rc;
+		gpio_reg_2p85v = regulator_get(&msm8625_mipi_dsi_device.dev,
+								"lcd_vdd");
+		if (IS_ERR(gpio_reg_2p85v)) {
+			pr_err("%s:ext_2p85v regulator get failed", __func__);
+			return -EINVAL;
 		}
 
-		rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_2V85_EN, 1);
-		if (rc < 0) {
-			pr_err("failed to enable external 2V85\n");
-			gpio_free(GPIO_QRD3_LCD_EXT_2V85_EN);
-			return rc;
+		gpio_reg_1p8v = regulator_get(&msm8625_mipi_dsi_device.dev,
+								"lcd_vddi");
+		if (IS_ERR(gpio_reg_1p8v)) {
+			pr_err("%s:ext_1p8v regulator get failed", __func__);
+			return -EINVAL;
 		}
 
-		rc = gpio_request(GPIO_QRD3_LCD_EXT_1V8_EN,
-			"qrd3_gpio_ext_1v8_en");
-		if (rc < 0)
-			return rc;
-
-		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0,
-			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
-			GPIO_CFG_ENABLE);
-		if (rc < 0) {
-			pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_1V8_EN tlmm config\n");
-			return rc;
-		}
-
-		rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_1V8_EN, 1);
-		if (rc < 0) {
-			pr_err("failed to enable external 1v8\n");
-			gpio_free(GPIO_QRD3_LCD_EXT_1V8_EN);
-			return rc;
-		}
-
-			qrd3_dsi_gpio_initialized = 1;
+		qrd3_dsi_gpio_initialized = 1;
 	}
 
 	if (on) {
@@ -1204,7 +1179,7 @@
 			gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
 			return rc;
 		}
-
+		/*Toggle Backlight GPIO*/
 		gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
 		udelay(190);
 		gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 0);
@@ -1212,18 +1187,17 @@
 		gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
 		/* 1 wire mode starts from this low to high transition */
 		udelay(50);
-	} else {
-		gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
-			GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
-			GPIO_CFG_DISABLE);
-	}
 
-	gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
-	gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
+		/*Enable EXT_2.85 and 1.8 regulators*/
+		rc = regulator_enable(gpio_reg_2p85v);
+		if (rc < 0)
+			pr_err("%s: reg enable failed\n", __func__);
+		rc = regulator_enable(gpio_reg_1p8v);
+		if (rc < 0)
+			pr_err("%s: reg enable failed\n", __func__);
 
-	if (on) {
+		/*Configure LCD Bridge reset*/
 		rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
-
 		if (rc < 0) {
 			pr_err("Failed to enable LCD Bridge reset enable\n");
 			return rc;
@@ -1237,18 +1211,32 @@
 			return rc;
 		}
 
+		/*Toggle Bridge Reset GPIO*/
 		msleep(20);
 		gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 0);
 		msleep(20);
 		gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
 		msleep(20);
+
 	} else {
+		gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
+			GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+			GPIO_CFG_DISABLE);
+
 		gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0,
 			GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
 			GPIO_CFG_DISABLE);
+
+		rc = regulator_disable(gpio_reg_2p85v);
+		if (rc < 0)
+			pr_err("%s: reg disable failed\n", __func__);
+		rc = regulator_disable(gpio_reg_1p8v);
+		if (rc < 0)
+			pr_err("%s: reg disable failed\n", __func__);
+
 	}
 
-		return rc;
+	return rc;
 }
 
 static int mipi_dsi_panel_power(int on)
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 8abcef0..7ac0c9a 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -95,15 +95,31 @@
 
 #define MSM_PMEM_SF_SIZE	0x1700000
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE            0x780000
+#define MSM_FB_PRIM_BUF_SIZE   (864 * 480 * 4 * 3) /* 4bpp * 3 Pages */
 #else
-#define MSM_FB_SIZE            0x500000
+#define MSM_FB_PRIM_BUF_SIZE   (864 * 480 * 4 * 2) /* 4bpp * 2 Pages */
 #endif
 /*
  * Reserve space for double buffered full screen
  * res V4L2 video overlay - i.e. 1280x720x1.5x2
  */
 #define MSM_V4L2_VIDEO_OVERLAY_BUF_SIZE 2764800
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+#define MSM_FB_EXT_BUF_SIZE (1280 * 720 * 2 * 1) /* 2 bpp x 1 page */
+#else
+#define MSM_FB_EXT_BUF_SIZE    0
+#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK
+/* width x height x 3 bpp x 2 frame buffer */
+#define MSM_FB_OVERLAY0_WRITEBACK_SIZE roundup((864 * 480 * 3 * 2), 4096)
+#else
+#define MSM_FB_OVERLAY0_WRITEBACK_SIZE  0
+#endif
+
+#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE, 4096)
+
 #define MSM_PMEM_ADSP_SIZE      0x1E00000
 #define MSM_FLUID_PMEM_ADSP_SIZE	0x2800000
 #define PMEM_KERNEL_EBI0_SIZE   0x600000
@@ -4533,6 +4549,7 @@
 	.mdp_core_clk_table = mdp_core_clk_rate_table,
 	.num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
 	.mdp_rev = MDP_REV_40,
+	.mem_hid = MEMTYPE_EBI0,
 };
 
 static int lcd_panel_spi_gpio_num[] = {
@@ -7095,7 +7112,7 @@
 }
 early_param("pmem_sf_size", pmem_sf_size_setup);
 
-static unsigned fb_size = MSM_FB_SIZE;
+static unsigned fb_size;
 static int __init fb_size_setup(char *p)
 {
 	fb_size = memparse(p, NULL);
@@ -7176,10 +7193,17 @@
 #endif
 }
 
+static void __init reserve_mdp_memory(void)
+{
+	mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
+	msm7x30_reserve_table[mdp_pdata.mem_hid].size += mdp_pdata.ov0_wb_size;
+}
+
 static void __init msm7x30_calculate_reserve_sizes(void)
 {
 	size_pmem_devices();
 	reserve_pmem_memory();
+	reserve_mdp_memory();
 }
 
 static int msm7x30_paddr_to_memtype(unsigned int paddr)
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 57f2077..3488fb3 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2650,11 +2650,19 @@
 #define USER_SMI_SIZE         (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
 #define MSM_PMEM_SMIPOOL_SIZE USER_SMI_SIZE
 
+#define MSM_ION_HOLE_SIZE	SZ_128K /* (128KB) */
+#define MSM_MM_FW_SIZE		(0x200000 - MSM_ION_HOLE_SIZE) /*(2MB-128KB)*/
+#define MSM_ION_MM_SIZE		0x3800000  /* (56MB) */
+#define MSM_ION_MFC_SIZE	SZ_8K
+
+#define MSM_MM_FW_BASE		MSM_SMI_BASE
+#define MSM_ION_HOLE_BASE	(MSM_MM_FW_BASE + MSM_MM_FW_SIZE)
+#define MSM_ION_MM_BASE		(MSM_ION_HOLE_BASE + MSM_ION_HOLE_SIZE)
+#define MSM_ION_MFC_BASE	(MSM_ION_MM_BASE + MSM_ION_MM_SIZE)
+
 #define MSM_ION_SF_SIZE		0x4000000 /* 64MB */
 #define MSM_ION_CAMERA_SIZE     MSM_PMEM_ADSP_SIZE
-#define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
-#define MSM_ION_MM_SIZE		0x3c00000 /* (60MB) Must be a multiple of 64K */
-#define MSM_ION_MFC_SIZE	SZ_8K
+
 #ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
 #define MSM_ION_WB_SIZE		0xC00000 /* 12MB */
 #else
@@ -5289,6 +5297,8 @@
 	.request_region = request_smi_region,
 	.release_region = release_smi_region,
 	.setup_region = setup_smi_region,
+	.secure_base = MSM_ION_HOLE_BASE,
+	.secure_size = MSM_ION_HOLE_SIZE + MSM_ION_MM_SIZE,
 	.iommu_map_all = 1,
 	.iommu_2x_map_domain = VIDEO_DOMAIN,
 };
@@ -5306,9 +5316,8 @@
 	.align = PAGE_SIZE,
 };
 
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
+static struct ion_co_heap_pdata hole_co_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
-	.align = SZ_128K,
 };
 
 static struct ion_co_heap_pdata co_ion_pdata = {
@@ -5341,6 +5350,7 @@
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
+			.base   = MSM_ION_MM_BASE,
 			.size	= MSM_ION_MM_SIZE,
 			.memory_type = ION_SMI_TYPE,
 			.extra_data = (void *) &cp_mm_ion_pdata,
@@ -5349,14 +5359,16 @@
 			.id	= ION_MM_FIRMWARE_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
 			.name	= ION_MM_FIRMWARE_HEAP_NAME,
-			.size	= MSM_ION_MM_FW_SIZE,
+			.base	= MSM_ION_HOLE_BASE,
+			.size	= MSM_ION_HOLE_SIZE,
 			.memory_type = ION_SMI_TYPE,
-			.extra_data = (void *) &fw_co_ion_pdata,
+			.extra_data = (void *) &hole_co_ion_pdata,
 		},
 		{
 			.id	= ION_CP_MFC_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MFC_HEAP_NAME,
+			.base	= MSM_ION_MFC_BASE,
 			.size	= MSM_ION_MFC_SIZE,
 			.memory_type = ION_SMI_TYPE,
 			.extra_data = (void *) &cp_mfc_ion_pdata,
@@ -5425,12 +5437,7 @@
 		.size	=	KERNEL_SMI_SIZE,
 		.flags	=	MEMTYPE_FLAGS_FIXED,
 	},
-	/* User space SMI memory pool for video core */
-	/* used for encoder, decoder input & output buffers  */
 	[MEMTYPE_SMI] = {
-		.start	=	USER_SMI_BASE,
-		.limit	=	USER_SMI_SIZE,
-		.flags	=	MEMTYPE_FLAGS_FIXED,
 	},
 	[MEMTYPE_EBI0] = {
 		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
@@ -5475,9 +5482,6 @@
 	}
 
 	msm8x60_reserve_table[MEMTYPE_EBI1].size += msm_ion_sf_size;
-	msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MM_FW_SIZE;
-	msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MM_SIZE;
-	msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MFC_SIZE;
 	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_CAMERA_SIZE;
 	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_WB_SIZE;
 	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
@@ -8385,7 +8389,6 @@
 	.msmsdcc_fmid	= 24000000,
 	.msmsdcc_fmax	= 48000000,
 	.nonremovable	= 1,
-	.pclk_src_dfab	= 1,
 	.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
 };
 #endif
@@ -8400,7 +8403,6 @@
 	.msmsdcc_fmid	= 24000000,
 	.msmsdcc_fmax	= 48000000,
 	.nonremovable	= 0,
-	.pclk_src_dfab  = 1,
 	.register_status_notify = sdc2_register_status_notify,
 #ifdef CONFIG_MSM_SDIO_AL
 	.is_sdio_al_client = 1,
@@ -8425,7 +8427,6 @@
 	.msmsdcc_fmid	= 24000000,
 	.msmsdcc_fmax	= 48000000,
 	.nonremovable	= 0,
-	.pclk_src_dfab  = 1,
 	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1,
 	.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
 };
@@ -8440,7 +8441,6 @@
 	.msmsdcc_fmid	= 24000000,
 	.msmsdcc_fmax	= 48000000,
 	.nonremovable	= 0,
-	.pclk_src_dfab  = 1,
 	.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC4_DAT1,
 	.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
 };
@@ -8456,7 +8456,6 @@
 	.msmsdcc_fmid	= 24000000,
 	.msmsdcc_fmax	= 48000000,
 	.nonremovable	= 0,
-	.pclk_src_dfab  = 1,
 	.register_status_notify = sdc5_register_status_notify,
 #ifdef CONFIG_MSM_SDIO_AL
 	.is_sdio_al_client = 1,
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 7708310..c8f8b10 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -32,6 +32,7 @@
 #include <linux/input/ft5x06_ts.h>
 #include <linux/msm_adc.h>
 #include <linux/fmem.h>
+#include <linux/regulator/msm-gpio-regulator.h>
 #include <asm/mach/mmc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -631,6 +632,64 @@
 	.dev = { .platform_data = &fmem_pdata },
 };
 
+#define GPIO_VREG_INIT(_id, _reg_name, _gpio_label, _gpio, _active_low) \
+	[GPIO_VREG_ID_##_id] = { \
+		.init_data = { \
+			.constraints = { \
+				.valid_ops_mask	= REGULATOR_CHANGE_STATUS, \
+			}, \
+			.num_consumer_supplies	= \
+					ARRAY_SIZE(vreg_consumers_##_id), \
+			.consumer_supplies	= vreg_consumers_##_id, \
+		}, \
+		.regulator_name	= _reg_name, \
+		.active_low	= _active_low, \
+		.gpio_label	= _gpio_label, \
+		.gpio		= _gpio, \
+	}
+
+#define GPIO_VREG_ID_EXT_2P85V	0
+#define GPIO_VREG_ID_EXT_1P8V	1
+
+static struct regulator_consumer_supply vreg_consumers_EXT_2P85V[] = {
+	REGULATOR_SUPPLY("cam_ov5647_avdd", "0-006c"),
+	REGULATOR_SUPPLY("cam_ov7692_avdd", "0-0078"),
+	REGULATOR_SUPPLY("cam_ov8825_avdd", "0-000d"),
+	REGULATOR_SUPPLY("lcd_vdd", "mipi_dsi.1"),
+};
+
+static struct regulator_consumer_supply vreg_consumers_EXT_1P8V[] = {
+	REGULATOR_SUPPLY("cam_ov5647_vdd", "0-006c"),
+	REGULATOR_SUPPLY("cam_ov7692_vdd", "0-0078"),
+	REGULATOR_SUPPLY("cam_ov8825_vdd", "0-000d"),
+	REGULATOR_SUPPLY("lcd_vddi", "mipi_dsi.1"),
+};
+
+/* GPIO regulator constraints */
+static struct gpio_regulator_platform_data msm_gpio_regulator_pdata[] = {
+	GPIO_VREG_INIT(EXT_2P85V, "ext_2p85v", "ext_2p85v_en", 35, 0),
+	GPIO_VREG_INIT(EXT_1P8V, "ext_1p8v", "ext_1p8v_en", 40, 0),
+};
+
+/* GPIO regulator */
+static struct platform_device qrd_msm8625_vreg_gpio_ext_2p85v __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= 35,
+	.dev	= {
+		.platform_data =
+			&msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_2P85V],
+	},
+};
+
+static struct platform_device qrd_msm8625_vreg_gpio_ext_1p8v __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= 40,
+	.dev	= {
+		.platform_data =
+			&msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_1P8V],
+	},
+};
+
 static struct platform_device *common_devices[] __initdata = {
 	&android_usb_device,
 	&android_pmem_device,
@@ -672,6 +731,8 @@
 	&msm8625_device_otg,
 	&msm8625_device_gadget_peripheral,
 	&msm8625_kgsl_3d0,
+	&qrd_msm8625_vreg_gpio_ext_2p85v,
+	&qrd_msm8625_vreg_gpio_ext_1p8v,
 };
 
 static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index 97225ac..4d7ce12 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -35,6 +35,9 @@
 /* Print a message for everything but TLB MH events */
 #define CESR_PRINT_MASK		0x000000FF
 
+/* Log everything but TLB MH events */
+#define CESR_LOG_EVENT_MASK	0x000000FF
+
 #define L2ESR_IND_ADDR		0x204
 #define L2ESYNR0_IND_ADDR	0x208
 #define L2ESYNR1_IND_ADDR	0x209
@@ -87,6 +90,9 @@
 
 #define MODULE_NAME "msm_cache_erp"
 
+#define ERP_LOG_MAGIC_ADDR	0x748
+#define ERP_LOG_MAGIC		0x11C39893
+
 struct msm_l1_err_stats {
 	unsigned int dctpe;
 	unsigned int dcdpe;
@@ -114,6 +120,10 @@
 static int l1_erp_irq, l2_erp_irq;
 static struct proc_dir_entry *procfs_entry;
 
+#ifdef CONFIG_MSM_L1_ERR_LOG
+static struct proc_dir_entry *procfs_log_entry;
+#endif
+
 static inline unsigned int read_cesr(void)
 {
 	unsigned int cesr;
@@ -192,6 +202,48 @@
 	return len;
 }
 
+#ifdef CONFIG_MSM_L1_ERR_LOG
+static int proc_read_log(char *page, char **start, off_t off, int count,
+	int *eof, void *data)
+{
+	char *p = page;
+	int len, log_value;
+	log_value = __raw_readl(MSM_IMEM_BASE + ERP_LOG_MAGIC_ADDR) ==
+			ERP_LOG_MAGIC ? 1 : 0;
+
+	p += snprintf(p, PAGE_SIZE, "%d\n", log_value);
+
+	len = (p - page) - off;
+	if (len < 0)
+		len = 0;
+
+	*eof = (len <= count) ? 1 : 0;
+	*start = page + off;
+
+	return len;
+}
+
+static void log_cpu_event(void)
+{
+	__raw_writel(ERP_LOG_MAGIC, MSM_IMEM_BASE + ERP_LOG_MAGIC_ADDR);
+	mb();
+}
+
+static int procfs_event_log_init(void)
+{
+	procfs_log_entry = create_proc_entry("cpu/msm_erp_log", S_IRUGO, NULL);
+
+	if (!procfs_log_entry)
+		return -ENODEV;
+	procfs_log_entry->read_proc = proc_read_log;
+	return 0;
+}
+
+#else
+static inline void log_cpu_event(void) { }
+static inline int procfs_event_log_init(void) { return 0; }
+#endif
+
 static irqreturn_t msm_l1_erp_irq(int irq, void *dev_id)
 {
 	struct msm_l1_err_stats *l1_stats = dev_id;
@@ -199,6 +251,7 @@
 	unsigned int i_cesynr, d_cesynr;
 	unsigned int cpu = smp_processor_id();
 	int print_regs = cesr & CESR_PRINT_MASK;
+	int log_event = cesr & CESR_LOG_EVENT_MASK;
 
 	void *const saw_bases[] = {
 		MSM_SAW0_BASE,
@@ -271,6 +324,9 @@
 		pr_alert("D-side CESYNR = 0x%08x\n", d_cesynr);
 	}
 
+	if (log_event)
+		log_cpu_event();
+
 	/* Clear the interrupt bits we processed */
 	write_cesr(cesr);
 
@@ -459,6 +515,11 @@
 	put_online_cpus();
 
 	procfs_entry->read_proc = proc_read_status;
+
+	ret = procfs_event_log_init();
+	if (ret)
+		pr_err("Failed to create procfs node for ERP log access\n");
+
 	return 0;
 
 fail_l2:
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 7b4ca29..aca2a3b 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -934,6 +934,7 @@
 	.c = {
 		.dbg_name = "gfx2d0_p_clk",
 		.ops = &clk_ops_branch,
+		.flags = CLKFLAG_SKIP_HANDOFF,
 		CLK_INIT(gfx2d0_p_clk.c),
 	},
 };
@@ -952,6 +953,7 @@
 	.c = {
 		.dbg_name = "gfx2d1_p_clk",
 		.ops = &clk_ops_branch,
+		.flags = CLKFLAG_SKIP_HANDOFF,
 		CLK_INIT(gfx2d1_p_clk.c),
 	},
 };
@@ -3346,6 +3348,7 @@
 	.c = {
 		.dbg_name = "gfx2d0_clk",
 		.ops = &clk_ops_rcg,
+		.flags = CLKFLAG_SKIP_HANDOFF,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(gfx2d0_clk.c),
@@ -3390,6 +3393,7 @@
 	.c = {
 		.dbg_name = "gfx2d1_clk",
 		.ops = &clk_ops_rcg,
+		.flags = CLKFLAG_SKIP_HANDOFF,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(gfx2d1_clk.c),
@@ -4605,6 +4609,11 @@
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c, 0);
 
+static DEFINE_CLK_VOTER(ebi1_acpu_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ebi1_msmbus_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(afab_acpu_a_clk, &afab_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(afab_msmbus_a_clk, &afab_a_clk.c, LONG_MAX);
+
 #ifdef CONFIG_DEBUG_FS
 struct measure_sel {
 	u32 test_vector;
@@ -5030,8 +5039,25 @@
 	CLK_LOOKUP("pll4",		pll4_clk.c,	NULL),
 	CLK_LOOKUP("measure",		measure_clk.c,	"debug"),
 
+	CLK_LOOKUP("bus_clk",		afab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		afab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_a_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_a_clk.c,	""),
+
 	CLK_LOOKUP("bus_clk",		afab_clk.c,		"msm_apps_fab"),
-	CLK_LOOKUP("bus_a_clk",		afab_a_clk.c,		"msm_apps_fab"),
+	CLK_LOOKUP("bus_a_clk",		afab_msmbus_a_clk.c,	"msm_apps_fab"),
 	CLK_LOOKUP("bus_clk",		cfpb_clk.c,		"msm_cpss_fpb"),
 	CLK_LOOKUP("bus_a_clk",		cfpb_a_clk.c,		"msm_cpss_fpb"),
 	CLK_LOOKUP("bus_clk",		sfab_clk.c,		"msm_sys_fab"),
@@ -5041,7 +5067,7 @@
 	CLK_LOOKUP("bus_clk",		mmfab_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("bus_a_clk",		mmfab_a_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
-	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
+	CLK_LOOKUP("mem_a_clk",		ebi1_msmbus_a_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 
@@ -5313,6 +5339,8 @@
 	CLK_LOOKUP("smmu_iface_clk",	smmu_p_clk.c,  "pil_vidc"),
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
+	CLK_LOOKUP("mem_clk",		ebi1_acpu_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk",		afab_acpu_a_clk.c, ""),
 
 	CLK_LOOKUP("l2_mclk",		l2_m_clk,     ""),
 	CLK_LOOKUP("krait0_mclk",	krait0_m_clk, ""),
@@ -5336,8 +5364,25 @@
 	CLK_LOOKUP("pll4",		pll4_clk.c,	NULL),
 	CLK_LOOKUP("measure",		measure_clk.c,	"debug"),
 
+	CLK_LOOKUP("bus_clk",		afab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		afab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_a_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_a_clk.c,	""),
+
 	CLK_LOOKUP("bus_clk",		afab_clk.c,		"msm_apps_fab"),
-	CLK_LOOKUP("bus_a_clk",		afab_a_clk.c,		"msm_apps_fab"),
+	CLK_LOOKUP("bus_a_clk",		afab_msmbus_a_clk.c,	"msm_apps_fab"),
 	CLK_LOOKUP("bus_clk",		cfpb_clk.c,		"msm_cpss_fpb"),
 	CLK_LOOKUP("bus_a_clk",		cfpb_a_clk.c,		"msm_cpss_fpb"),
 	CLK_LOOKUP("bus_clk",		sfab_clk.c,		"msm_sys_fab"),
@@ -5347,7 +5392,7 @@
 	CLK_LOOKUP("bus_clk",		mmfab_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("bus_a_clk",		mmfab_a_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
-	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
+	CLK_LOOKUP("mem_a_clk",		ebi1_msmbus_a_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 
@@ -5486,7 +5531,8 @@
 	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,	"msm_gemini.0"),
 	CLK_LOOKUP("core_clk",          ijpeg_clk.c,    "msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
-	CLK_LOOKUP("core_clk",		jpegd_clk.c,		""),
+	CLK_LOOKUP("core_clk",		jpegd_clk.c, "msm_mercury.0"),
+	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c, "msm_mercury.0"),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("vsync_clk",	mdp_vsync_clk.c,	"mdp.0"),
@@ -5611,6 +5657,8 @@
 	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, ""),
+	CLK_LOOKUP("bus_clk",		afab_acpu_a_clk.c, ""),
 
 	CLK_LOOKUP("l2_mclk",		l2_m_clk,     ""),
 	CLK_LOOKUP("krait0_mclk",	krait0_m_clk, ""),
@@ -5633,8 +5681,25 @@
 	CLK_LOOKUP("pll4",		pll4_clk.c,	NULL),
 	CLK_LOOKUP("measure",		measure_clk.c,	"debug"),
 
+	CLK_LOOKUP("bus_clk",		afab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		afab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_a_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_a_clk.c,	""),
+
 	CLK_LOOKUP("bus_clk",		afab_clk.c,		"msm_apps_fab"),
-	CLK_LOOKUP("bus_a_clk",		afab_a_clk.c,		"msm_apps_fab"),
+	CLK_LOOKUP("bus_a_clk",		afab_msmbus_a_clk.c,	"msm_apps_fab"),
 	CLK_LOOKUP("bus_clk",		cfpb_clk.c,		"msm_cpss_fpb"),
 	CLK_LOOKUP("bus_a_clk",		cfpb_a_clk.c,		"msm_cpss_fpb"),
 	CLK_LOOKUP("bus_clk",		sfab_clk.c,		"msm_sys_fab"),
@@ -5644,7 +5709,7 @@
 	CLK_LOOKUP("bus_clk",		mmfab_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("bus_a_clk",		mmfab_a_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
-	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
+	CLK_LOOKUP("mem_a_clk",		ebi1_msmbus_a_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 
@@ -5885,6 +5950,8 @@
 	CLK_LOOKUP("bus_clk",		dfab_qseecom_clk.c,	"qseecom"),
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
+	CLK_LOOKUP("mem_clk",		ebi1_acpu_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk",		afab_acpu_a_clk.c, ""),
 
 	CLK_LOOKUP("l2_mclk",		l2_m_clk,     ""),
 	CLK_LOOKUP("krait0_mclk",	krait0_m_clk, ""),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 7aed579..74d71a2 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -700,6 +700,7 @@
 	.c = {
 		.dbg_name = "gfx2d0_p_clk",
 		.ops = &clk_ops_branch,
+		.flags = CLKFLAG_SKIP_HANDOFF,
 		CLK_INIT(gfx2d0_p_clk.c),
 	},
 };
@@ -716,6 +717,7 @@
 	.c = {
 		.dbg_name = "gfx2d1_p_clk",
 		.ops = &clk_ops_branch,
+		.flags = CLKFLAG_SKIP_HANDOFF,
 		CLK_INIT(gfx2d1_p_clk.c),
 	},
 };
@@ -2178,6 +2180,7 @@
 	.c = {
 		.dbg_name = "gfx2d0_clk",
 		.ops = &clk_ops_rcg,
+		.flags = CLKFLAG_SKIP_HANDOFF,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(gfx2d0_clk.c),
@@ -2222,6 +2225,7 @@
 	.c = {
 		.dbg_name = "gfx2d1_clk",
 		.ops = &clk_ops_rcg,
+		.flags = CLKFLAG_SKIP_HANDOFF,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(gfx2d1_clk.c),
@@ -3117,6 +3121,11 @@
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ebi1_adm0_clk,   &ebi1_clk.c, 0);
 static DEFINE_CLK_VOTER(ebi1_adm1_clk,   &ebi1_clk.c, 0);
+static DEFINE_CLK_VOTER(ebi1_acpu_a_clk,   &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ebi1_msmbus_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(afab_acpu_a_clk,   &afab_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(afab_msmbus_a_clk, &afab_a_clk.c, LONG_MAX);
+
 static DEFINE_CLK_MEASURE(sc0_m_clk);
 static DEFINE_CLK_MEASURE(sc1_m_clk);
 static DEFINE_CLK_MEASURE(l2_m_clk);
@@ -3479,8 +3488,27 @@
 	CLK_LOOKUP("pll4",		pll4_clk.c,	"pil_qdsp6v3"),
 	CLK_LOOKUP("measure",		measure_clk.c,	"debug"),
 
+	CLK_LOOKUP("bus_clk",		afab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		afab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_a_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		mmfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_a_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		smi_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		smi_a_clk.c,	""),
+
 	CLK_LOOKUP("bus_clk",		afab_clk.c,	"msm_apps_fab"),
-	CLK_LOOKUP("bus_a_clk",		afab_a_clk.c,	"msm_apps_fab"),
+	CLK_LOOKUP("bus_a_clk",		afab_msmbus_a_clk.c, "msm_apps_fab"),
 	CLK_LOOKUP("bus_clk",		sfab_clk.c,	"msm_sys_fab"),
 	CLK_LOOKUP("bus_a_clk",		sfab_a_clk.c,	"msm_sys_fab"),
 	CLK_LOOKUP("bus_clk",		sfpb_clk.c,	"msm_sys_fpb"),
@@ -3490,16 +3518,10 @@
 	CLK_LOOKUP("bus_clk",		cfpb_clk.c,	"msm_cpss_fpb"),
 	CLK_LOOKUP("bus_a_clk",		cfpb_a_clk.c,	"msm_cpss_fpb"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c, "msm_bus"),
-	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,	"msm_bus"),
+	CLK_LOOKUP("mem_a_clk",		ebi1_msmbus_a_clk.c, "msm_bus"),
 	CLK_LOOKUP("smi_clk",		smi_clk.c,	"msm_bus"),
 	CLK_LOOKUP("smi_a_clk",		smi_a_clk.c,	"msm_bus"),
 
-	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,	NULL),
-	CLK_LOOKUP("dfab_clk",		dfab_clk.c,	NULL),
-	CLK_LOOKUP("dfab_a_clk",	dfab_a_clk.c,	NULL),
-	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,	NULL),
-	CLK_LOOKUP("mmfpb_a_clk",	mmfpb_a_clk.c,	NULL),
-
 	CLK_LOOKUP("core_clk",		gp0_clk.c,		""),
 	CLK_LOOKUP("core_clk",		gp1_clk.c,		""),
 	CLK_LOOKUP("core_clk",		gp2_clk.c,		""),
@@ -3713,6 +3735,8 @@
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm0_clk.c, "msm_dmov.0"),
 	CLK_LOOKUP("mem_clk",		ebi1_adm1_clk.c, "msm_dmov.1"),
+	CLK_LOOKUP("mem_clk",		ebi1_acpu_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk",		afab_acpu_a_clk.c, ""),
 
 	CLK_LOOKUP("sc0_mclk",		sc0_m_clk, ""),
 	CLK_LOOKUP("sc1_mclk",		sc1_m_clk, ""),
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 66d849a..834deb6 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -135,6 +135,9 @@
 #define LCC_PCM_MD_REG				REG_LPA(0x0058)
 #define LCC_PCM_NS_REG				REG_LPA(0x0054)
 #define LCC_PCM_STATUS_REG			REG_LPA(0x005C)
+#define LCC_SEC_PCM_MD_REG			REG_LPA(0x00F4)
+#define LCC_SEC_PCM_NS_REG			REG_LPA(0x00F0)
+#define LCC_SEC_PCM_STATUS_REG			REG_LPA(0x00F8)
 #define LCC_PLL0_STATUS_REG			REG_LPA(0x0018)
 #define LCC_SPARE_I2S_MIC_MD_REG		REG_LPA(0x007C)
 #define LCC_SPARE_I2S_MIC_NS_REG		REG_LPA(0x0078)
@@ -1267,6 +1270,32 @@
 	},
 };
 
+static struct rcg_clk sec_pcm_clk = {
+	.b = {
+		.ctl_reg = LCC_SEC_PCM_NS_REG,
+		.en_mask = BIT(11),
+		.reset_reg = LCC_SEC_PCM_NS_REG,
+		.reset_mask = BIT(13),
+		.halt_reg = LCC_SEC_PCM_STATUS_REG,
+		.halt_check = ENABLE,
+		.halt_bit = 0,
+	},
+	.ns_reg = LCC_SEC_PCM_NS_REG,
+	.md_reg = LCC_SEC_PCM_MD_REG,
+	.root_en_mask = BIT(9),
+	.ns_mask = BM(31, 16) | BIT(10) | BM(6, 0),
+	.mnd_en_mask = BIT(8),
+	.set_rate = set_rate_mnd,
+	.freq_tbl = clk_tbl_pcm,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "sec_pcm_clk",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 24576000),
+		CLK_INIT(sec_pcm_clk.c),
+	},
+};
+
 static struct rcg_clk audio_slimbus_clk = {
 	.b = {
 		.ctl_reg = LCC_SLIMBUS_NS_REG,
@@ -1338,7 +1367,11 @@
 static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c, 0);
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ebi1_msmbus_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ebi1_acpu_a_clk, &ebi1_a_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c, 0);
+static DEFINE_CLK_VOTER(sfab_msmbus_a_clk, &sfab_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(sfab_acpu_a_clk, &sfab_a_clk.c, LONG_MAX);
 
 #ifdef CONFIG_DEBUG_FS
 struct measure_sel {
@@ -1588,19 +1621,24 @@
 
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
 
+	CLK_LOOKUP("bus_clk",		cfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		cfpb_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		dfab_a_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		ebi1_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfab_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_clk.c,	""),
+	CLK_LOOKUP("bus_clk",		sfpb_a_clk.c,	""),
+
 	CLK_LOOKUP("bus_clk",		sfab_clk.c,		"msm_sys_fab"),
-	CLK_LOOKUP("bus_a_clk",		sfab_a_clk.c,		"msm_sys_fab"),
+	CLK_LOOKUP("bus_a_clk",		sfab_msmbus_a_clk.c,	"msm_sys_fab"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
-	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
+	CLK_LOOKUP("mem_a_clk",		ebi1_msmbus_a_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 
-	CLK_LOOKUP("bus_clk",		sfpb_clk.c,	NULL),
-	CLK_LOOKUP("bus_a_clk",		sfpb_a_clk.c,	NULL),
-	CLK_LOOKUP("bus_clk",		cfpb_clk.c,	NULL),
-	CLK_LOOKUP("bus_a_clk",		cfpb_a_clk.c,	NULL),
-	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,	NULL),
-
 	CLK_LOOKUP("core_clk",		gp0_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gp1_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gp2_clk.c,	""),
@@ -1673,6 +1711,8 @@
 			   "msm-dai-q6.4"),
 	CLK_LOOKUP("pcm_clk",		pcm_clk.c,	"msm-dai-q6.2"),
 	CLK_LOOKUP("pcm_clk",		pcm_clk.c,	"msm-dai-q6.3"),
+	CLK_LOOKUP("sec_pcm_clk",	sec_pcm_clk.c,	"msm-dai-q6.12"),
+	CLK_LOOKUP("sec_pcm_clk",	sec_pcm_clk.c,	"msm-dai-q6.13"),
 
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
@@ -1682,6 +1722,8 @@
 	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,		"msm_sps"),
 	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
+	CLK_LOOKUP("mem_clk",		ebi1_acpu_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk",		sfab_acpu_a_clk.c, ""),
 
 	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		"qce.0"),
 	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		"qcrypto.0"),
diff --git a/arch/arm/mach-msm/clock-copper.c b/arch/arm/mach-msm/clock-copper.c
index fc0b0af..72424f2 100644
--- a/arch/arm/mach-msm/clock-copper.c
+++ b/arch/arm/mach-msm/clock-copper.c
@@ -23,6 +23,8 @@
 
 #include "clock-local2.h"
 #include "clock-pll.h"
+#include "clock-rpm.h"
+#include "clock-voter.h"
 
 enum {
 	GCC_BASE,
@@ -713,6 +715,37 @@
 	},
 };
 
+#define RPM_BUS_CLK_TYPE  0x316b6c63
+#define RPM_MEM_CLK_TYPE  0x326b6c63
+
+#define PNOC_ID		0x0
+#define SNOC_ID		0x1
+#define CNOC_ID		0x2
+
+#define BIMC_ID		0x0
+#define OCMEM_ID	0x1
+
+DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(cnoc_clk, cnoc_a_clk, RPM_BUS_CLK_TYPE, CNOC_ID, NULL);
+
+DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
+DEFINE_CLK_RPM_SMD(ocmemgx_clk, ocmemgx_a_clk, RPM_MEM_CLK_TYPE, OCMEM_ID,
+			NULL);
+
+static DEFINE_CLK_VOTER(pnoc_msmbus_clk, &pnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_clk, &cnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, &pnoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, &cnoc_a_clk.c, LONG_MAX);
+
+static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_acpu_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_msmbus_clk, &ocmemgx_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
+
 static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
 	F(125000000,  gpll0,   1,   5,  24),
 	F_END
@@ -2199,28 +2232,6 @@
 	},
 };
 
-static struct clk_freq_tbl ftbl_mmss_ahb_clk[] = {
-	F_MM(19200000,    cxo,   1,   0,   0),
-	F_MM(40000000,  gpll0,  15,   0,   0),
-	F_MM(80000000, mmpll0,  10,   0,   0),
-	F_END,
-};
-
-/* TODO: This may go away (may be controlled by the RPM). */
-static struct rcg_clk ahb_clk_src = {
-	.cmd_rcgr_reg = 0x5000,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_mmss_ahb_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[MMSS_BASE],
-	.c = {
-		.dbg_name = "ahb_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 40000000, NOMINAL, 80000000),
-		CLK_INIT(ahb_clk_src.c),
-	},
-};
-
 static struct clk_freq_tbl ftbl_mmss_axi_clk[] = {
 	F_MM( 19200000,    cxo,   1,   0,   0),
 	F_MM(150000000,  gpll0,   4,   0,   0),
@@ -2244,6 +2255,29 @@
 	},
 };
 
+static struct clk_freq_tbl ftbl_ocmemnoc_clk[] = {
+	F_MM( 19200000,    cxo,   1,   0,   0),
+	F_MM(150000000,  gpll0,   4,   0,   0),
+	F_MM(333330000, mmpll1,   3,   0,   0),
+	F_MM(400000000, mmpll0,   2,   0,   0),
+	F_END
+};
+
+struct rcg_clk ocmemnoc_clk_src = {
+	.cmd_rcgr_reg = OCMEMNOC_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_ocmemnoc_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "ocmemnoc_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 150000000, NOMINAL, 333330000,
+				  HIGH, 400000000),
+		CLK_INIT(ocmemnoc_clk_src.c),
+	},
+};
+
 static struct clk_freq_tbl ftbl_camss_csi0_3_clk[] = {
 	F_MM(100000000,  gpll0,   6,   0,   0),
 	F_MM(200000000, mmpll0,   4,   0,   0),
@@ -2869,7 +2903,6 @@
 
 static struct branch_clk camss_cci_cci_ahb_clk = {
 	.cbcr_reg = CAMSS_CCI_CCI_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2893,7 +2926,6 @@
 
 static struct branch_clk camss_csi0_ahb_clk = {
 	.cbcr_reg = CAMSS_CSI0_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2953,7 +2985,6 @@
 
 static struct branch_clk camss_csi1_ahb_clk = {
 	.cbcr_reg = CAMSS_CSI1_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3013,7 +3044,6 @@
 
 static struct branch_clk camss_csi2_ahb_clk = {
 	.cbcr_reg = CAMSS_CSI2_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3073,7 +3103,6 @@
 
 static struct branch_clk camss_csi3_ahb_clk = {
 	.cbcr_reg = CAMSS_CSI3_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3181,7 +3210,6 @@
 
 static struct branch_clk camss_ispif_ahb_clk = {
 	.cbcr_reg = CAMSS_ISPIF_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3229,7 +3257,6 @@
 
 static struct branch_clk camss_jpeg_jpeg_ahb_clk = {
 	.cbcr_reg = CAMSS_JPEG_JPEG_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3253,6 +3280,7 @@
 
 static struct branch_clk camss_jpeg_jpeg_ocmemnoc_clk = {
 	.cbcr_reg = CAMSS_JPEG_JPEG_OCMEMNOC_CBCR,
+	.parent = &ocmemnoc_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3312,7 +3340,6 @@
 
 static struct branch_clk camss_micro_ahb_clk = {
 	.cbcr_reg = CAMSS_MICRO_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3360,7 +3387,6 @@
 
 static struct branch_clk camss_top_ahb_clk = {
 	.cbcr_reg = CAMSS_TOP_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3372,7 +3398,6 @@
 
 static struct branch_clk camss_vfe_cpp_ahb_clk = {
 	.cbcr_reg = CAMSS_VFE_CPP_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3420,7 +3445,6 @@
 
 static struct branch_clk camss_vfe_vfe_ahb_clk = {
 	.cbcr_reg = CAMSS_VFE_VFE_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3444,6 +3468,7 @@
 
 static struct branch_clk camss_vfe_vfe_ocmemnoc_clk = {
 	.cbcr_reg = CAMSS_VFE_VFE_OCMEMNOC_CBCR,
+	.parent = &ocmemnoc_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3455,7 +3480,6 @@
 
 static struct branch_clk mdss_ahb_clk = {
 	.cbcr_reg = MDSS_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3575,7 +3599,6 @@
 
 static struct branch_clk mdss_hdmi_ahb_clk = {
 	.cbcr_reg = MDSS_HDMI_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3659,7 +3682,6 @@
 
 static struct branch_clk mmss_misc_ahb_clk = {
 	.cbcr_reg = MMSS_MISC_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3671,7 +3693,6 @@
 
 static struct branch_clk mmss_mmssnoc_ahb_clk = {
 	.cbcr_reg = MMSS_MMSSNOC_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3683,7 +3704,6 @@
 
 static struct branch_clk mmss_mmssnoc_bto_ahb_clk = {
 	.cbcr_reg = MMSS_MMSSNOC_BTO_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3717,9 +3737,21 @@
 	},
 };
 
+struct branch_clk ocmemnoc_clk = {
+	.cbcr_reg = OCMEMNOC_CBCR,
+	.parent = &ocmemnoc_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = 0x50b0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "ocmemnoc_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(ocmemnoc_clk.c),
+	},
+};
+
 static struct branch_clk venus0_ahb_clk = {
 	.cbcr_reg = VENUS0_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3743,6 +3775,7 @@
 
 static struct branch_clk venus0_ocmemnoc_clk = {
 	.cbcr_reg = VENUS0_OCMEMNOC_CBCR,
+	.parent = &ocmemnoc_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3777,7 +3810,6 @@
 
 static struct branch_clk oxilicx_ahb_clk = {
 	.cbcr_reg = OXILICX_AHB_CBCR,
-	.parent = &ahb_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -4310,6 +4342,7 @@
 	{&gcc_usb_hsic_system_clk.c,		GCC_BASE, 0x0061},
 	{&mmss_mmssnoc_ahb_clk.c,		MMSS_BASE, 0x0001},
 	{&mmss_mmssnoc_axi_clk.c,		MMSS_BASE, 0x0004},
+	{&ocmemnoc_clk.c,			MMSS_BASE, 0x0007},
 	{&camss_cci_cci_ahb_clk.c,		MMSS_BASE, 0x002e},
 	{&camss_cci_cci_clk.c,			MMSS_BASE, 0x002d},
 	{&camss_csi0_ahb_clk.c,			MMSS_BASE, 0x0042},
@@ -4577,6 +4610,8 @@
 static struct clk_lookup msm_clocks_copper[] = {
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"msm_otg"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-lpass"),
+	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-mss"),
+	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-mba"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil_pronto"),
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
 
@@ -4650,18 +4685,17 @@
 	CLK_LOOKUP("iface_clk", gcc_tsif_ahb_clk.c, ""),
 	CLK_LOOKUP("ref_clk", gcc_tsif_ref_clk.c, ""),
 
-	CLK_LOOKUP("core_clk", gcc_usb30_master_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_usb30_mock_utmi_clk.c, ""),
-	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "msm_otg"),
-	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, ""),
-	CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_usb_hsic_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_usb_hsic_io_cal_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_usb30_master_clk.c,    "msm_dwc3"),
+	CLK_LOOKUP("utmi_clk", gcc_usb30_mock_utmi_clk.c, "msm_dwc3"),
+	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c,     "msm_otg"),
+	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c,   "msm_otg"),
+	CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c,	  "msm_hsic_host"),
+	CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c,	  "msm_hsic_host"),
+	CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c,  "msm_hsic_host"),
+	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
 
 	/* Multimedia clocks */
 	CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
-	CLK_LOOKUP("bus_clk_src", ahb_clk_src.c, ""),
 	CLK_LOOKUP("bus_clk", mmss_mmssnoc_ahb_clk.c, ""),
 	CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, ""),
 	CLK_LOOKUP("core_clk", mdss_edpaux_clk.c, ""),
@@ -4773,20 +4807,45 @@
 	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
 	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
 
-	CLK_LOOKUP("core_clk",       mss_xo_q6_clk.c, ""),
-	CLK_LOOKUP("bus_clk",       mss_bus_q6_clk.c, ""),
+	CLK_LOOKUP("core_clk",       mss_xo_q6_clk.c, "pil-q6v5-mss"),
+	CLK_LOOKUP("bus_clk",       mss_bus_q6_clk.c, "pil-q6v5-mss"),
+	CLK_LOOKUP("bus_clk",  gcc_mss_cfg_ahb_clk.c, ""),
+	CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "pil-q6v5-mss"),
 	CLK_LOOKUP("core_clk",         q6ss_xo_clk.c, "pil-q6v5-lpass"),
 	CLK_LOOKUP("bus_clk",  q6ss_ahb_lfabif_clk.c, "pil-q6v5-lpass"),
-	CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, ""),
-	CLK_LOOKUP("bus_clk",  gcc_mss_cfg_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
 
 	/* TODO: Remove dummy clocks as soon as they become unnecessary */
-	CLK_DUMMY("phy_clk",       NULL,    "msm_otg", OFF),
-	CLK_DUMMY("core_clk",      NULL,    "msm_otg", OFF),
 	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_LOOKUP("bus_clk", snoc_clk.c, ""),
+	CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
+	CLK_LOOKUP("bus_clk", cnoc_clk.c, ""),
+	CLK_LOOKUP("mem_clk", bimc_clk.c, ""),
+	CLK_LOOKUP("mem_clk", ocmemgx_clk.c, ""),
+	CLK_LOOKUP("bus_clk", snoc_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk", pnoc_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk", cnoc_a_clk.c, ""),
+	CLK_LOOKUP("mem_clk", bimc_a_clk.c, ""),
+	CLK_LOOKUP("mem_clk", ocmemgx_a_clk.c, ""),
+
+	CLK_LOOKUP("bus_clk",	cnoc_msmbus_clk.c,	"msm_config_noc"),
+	CLK_LOOKUP("bus_a_clk",	cnoc_msmbus_a_clk.c,	"msm_config_noc"),
+	CLK_LOOKUP("bus_clk",	snoc_msmbus_clk.c,	"msm_sys_noc"),
+	CLK_LOOKUP("bus_a_clk",	snoc_msmbus_a_clk.c,	"msm_sys_noc"),
+	CLK_LOOKUP("bus_clk",	pnoc_msmbus_clk.c,	"msm_periph_noc"),
+	CLK_LOOKUP("bus_a_clk",	pnoc_msmbus_a_clk.c,	"msm_periph_noc"),
+	CLK_LOOKUP("mem_clk",	bimc_msmbus_clk.c,	"msm_bimc"),
+	CLK_LOOKUP("mem_a_clk",	bimc_msmbus_a_clk.c,	"msm_bimc"),
+	CLK_LOOKUP("mem_clk",	bimc_acpu_a_clk.c,	""),
+	CLK_LOOKUP("ocmem_clk",	ocmemgx_msmbus_clk.c,	  "msm_bus"),
+	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"),
 };
 
 static struct pll_config_regs gpll0_regs __initdata = {
@@ -4981,7 +5040,6 @@
 
 static void __init msmcopper_clock_post_init(void)
 {
-	clk_set_rate(&ahb_clk_src.c, 80000000);
 	clk_set_rate(&axi_clk_src.c, 333330000);
 
 	/* Set rates for single-rate clocks. */
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 4f365fa..b5ae4ab 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -464,10 +464,7 @@
 	if (nf->freq_hz == FREQ_END)
 		return -EINVAL;
 
-	/* Check if frequency is actually changed. */
 	cf = clk->current_freq;
-	if (nf == cf)
-		return 0;
 
 	if (clk->enabled) {
 		/* Enable source clock dependency for the new freq. */
@@ -613,10 +610,8 @@
 	ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
 	for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
 		if ((freq->ns_val & ns_mask) == ns_val &&
-		    (!freq->md_val || freq->md_val == md_val)) {
-			pr_info("%s rate=%d\n", clk->c.dbg_name, freq->freq_hz);
+		    (!freq->md_val || freq->md_val == md_val))
 			break;
-		}
 	}
 	if (freq->freq_hz == FREQ_END)
 		return HANDOFF_UNKNOWN_RATE;
@@ -881,9 +876,6 @@
 
 	if (rate > clk->max_div)
 		return -EINVAL;
-	/* Check if frequency is actually changed. */
-	if (rate == clk->cur_div)
-		return 0;
 
 	spin_lock(&local_clock_reg_lock);
 	reg_val = readl_relaxed(clk->ns_reg);
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index cf45e63..467d5d1 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -166,10 +166,7 @@
 	if (nf->freq_hz == FREQ_END)
 		return -EINVAL;
 
-	/* Check if frequency is actually changed. */
 	cf = rcg->current_freq;
-	if (nf == cf)
-		return 0;
 
 	if (rcg->c.count) {
 		/* TODO: Modify to use the prepare API */
@@ -285,7 +282,6 @@
 			if (freq->d_val != d_regval)
 				continue;
 		}
-		pr_info("%s rate=%lu\n", rcg->c.dbg_name, freq->freq_hz);
 		break;
 	}
 
@@ -451,7 +447,6 @@
 	cbcr_regval = readl_relaxed(CBCR_REG(branch));
 	if ((cbcr_regval & CBCR_BRANCH_OFF_BIT))
 		return HANDOFF_DISABLED_CLK;
-	pr_info("%s enabled.\n", branch->c.dbg_name);
 
 	if (branch->parent) {
 		if (branch->parent->ops->handoff)
@@ -462,17 +457,12 @@
 }
 
 static int __branch_clk_reset(void __iomem *bcr_reg,
-				enum clk_reset_action action, const char *name)
+				enum clk_reset_action action)
 {
 	int ret = 0;
 	unsigned long flags;
 	u32 reg_val;
 
-	if (!bcr_reg) {
-		WARN("clk_reset called on an unsupported clock (%s)\n", name);
-		return -EPERM;
-	}
-
 	spin_lock_irqsave(&local_clock_reg_lock, flags);
 	reg_val = readl_relaxed(bcr_reg);
 	switch (action) {
@@ -497,7 +487,13 @@
 static int branch_clk_reset(struct clk *c, enum clk_reset_action action)
 {
 	struct branch_clk *branch = to_branch_clk(c);
-	return __branch_clk_reset(BCR_REG(branch), action, c->dbg_name);
+
+	if (!branch->bcr_reg) {
+		WARN("clk_reset called on an unsupported clock (%s)\n",
+			c->dbg_name);
+		return -EPERM;
+	}
+	return __branch_clk_reset(BCR_REG(branch), action);
 }
 
 /*
@@ -506,7 +502,13 @@
 static int local_vote_clk_reset(struct clk *c, enum clk_reset_action action)
 {
 	struct local_vote_clk *vclk = to_local_vote_clk(c);
-	return __branch_clk_reset(BCR_REG(vclk), action, c->dbg_name);
+
+	if (!vclk->bcr_reg) {
+		WARN("clk_reset called on an unsupported clock (%s)\n",
+			c->dbg_name);
+		return -EPERM;
+	}
+	return __branch_clk_reset(BCR_REG(vclk), action);
 }
 
 static int local_vote_clk_enable(struct clk *c)
@@ -549,7 +551,6 @@
 	vote_regval = readl_relaxed(VOTE_REG(vclk));
 	if (!(vote_regval & vclk->en_mask))
 		return HANDOFF_DISABLED_CLK;
-	pr_info("%s enabled.\n", vclk->c.dbg_name);
 
 	return HANDOFF_ENABLED_CLK;
 }
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index ae87bb7..e0707fc 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -18,13 +18,89 @@
 #include "clock.h"
 #include "clock-rpm.h"
 
+#define __clk_rpmrs_set_rate(r, value, ctx, noirq) \
+	((r)->rpmrs_data->set_rate_fn((r), (value), (ctx), (noirq)))
+
+#define clk_rpmrs_set_rate_sleep(r, value) \
+	    __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_sleep_id, 0)
+
+#define clk_rpmrs_set_rate_sleep_noirq(r, value) \
+	    __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_sleep_id, 1)
+
+#define clk_rpmrs_set_rate_active(r, value) \
+	   __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_active_id, 0)
+
+#define clk_rpmrs_set_rate_active_noirq(r, value) \
+	   __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_active_id, 1)
+
+static int clk_rpmrs_set_rate(struct rpm_clk *r, uint32_t value,
+			   uint32_t context, int noirq)
+{
+	struct msm_rpm_iv_pair iv = {
+		.id = r->rpm_clk_id,
+		.value = value,
+	};
+	if (noirq)
+		return msm_rpmrs_set_noirq(context, &iv, 1);
+	else
+		return msm_rpmrs_set(context, &iv, 1);
+}
+
+static int clk_rpmrs_get_rate(struct rpm_clk *r)
+{
+	int rc;
+	struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
+	rc = msm_rpm_get_status(&iv, 1);
+	return (rc < 0) ? rc : iv.value * 1000;
+}
+
+#define RPM_SMD_KEY_CLOCK_SET_RATE	0x007A484B
+
+static int clk_rpmrs_set_rate_smd(struct rpm_clk *r, uint32_t value,
+				uint32_t context, int noirq)
+{
+	struct msm_rpm_kvp kvp = {
+		.key = RPM_SMD_KEY_CLOCK_SET_RATE,
+		.data = (void *)&value,
+		.length = sizeof(value),
+	};
+
+	if (noirq)
+		return msm_rpm_send_message_noirq(context,
+				r->rpm_res_type, r->rpm_clk_id, &kvp, 1);
+	else
+		return msm_rpm_send_message(context, r->rpm_res_type,
+						r->rpm_clk_id, &kvp, 1);
+}
+
+struct clk_rpmrs_data {
+	int (*set_rate_fn)(struct rpm_clk *r, uint32_t value,
+				uint32_t context, int noirq);
+	int (*get_rate_fn)(struct rpm_clk *r);
+	int ctx_active_id;
+	int ctx_sleep_id;
+};
+
+struct clk_rpmrs_data clk_rpmrs_data = {
+	.set_rate_fn = clk_rpmrs_set_rate,
+	.get_rate_fn = clk_rpmrs_get_rate,
+	.ctx_active_id = MSM_RPM_CTX_SET_0,
+	.ctx_sleep_id = MSM_RPM_CTX_SET_SLEEP,
+};
+
+struct clk_rpmrs_data clk_rpmrs_data_smd = {
+	.set_rate_fn = clk_rpmrs_set_rate_smd,
+	.ctx_active_id = MSM_RPM_CTX_ACTIVE_SET,
+	.ctx_sleep_id = MSM_RPM_CTX_SLEEP_SET,
+};
+
 static DEFINE_SPINLOCK(rpm_clock_lock);
 
 static int rpm_clk_enable(struct clk *clk)
 {
 	unsigned long flags;
 	struct rpm_clk *r = to_rpm_clk(clk);
-	struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
+	uint32_t value;
 	int rc = 0;
 	unsigned long this_khz, this_sleep_khz;
 	unsigned long peer_khz = 0, peer_sleep_khz = 0;
@@ -45,21 +121,23 @@
 		peer_sleep_khz = peer->last_set_sleep_khz;
 	}
 
-	iv.value = max(this_khz, peer_khz);
+	value = max(this_khz, peer_khz);
 	if (r->branch)
-		iv.value = !!iv.value;
+		value = !!value;
 
-	rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
+	rc = clk_rpmrs_set_rate_active_noirq(r, value);
 	if (rc)
 		goto out;
 
-	iv.value = max(this_sleep_khz, peer_sleep_khz);
+	value = max(this_sleep_khz, peer_sleep_khz);
 	if (r->branch)
-		iv.value = !!iv.value;
-	rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
+		value = !!value;
+
+	rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
 	if (rc) {
-		iv.value = peer_khz;
-		msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
+		/* Undo the active set vote and restore it to peer_khz */
+		value = peer_khz;
+		rc = clk_rpmrs_set_rate_active_noirq(r, value);
 	}
 
 out:
@@ -79,7 +157,7 @@
 	spin_lock_irqsave(&rpm_clock_lock, flags);
 
 	if (r->last_set_khz) {
-		struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
+		uint32_t value;
 		struct rpm_clk *peer = r->peer;
 		unsigned long peer_khz = 0, peer_sleep_khz = 0;
 		int rc;
@@ -90,13 +168,13 @@
 			peer_sleep_khz = peer->last_set_sleep_khz;
 		}
 
-		iv.value = r->branch ? !!peer_khz : peer_khz;
-		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
+		value = r->branch ? !!peer_khz : peer_khz;
+		rc = clk_rpmrs_set_rate_active_noirq(r, value);
 		if (rc)
 			goto out;
 
-		iv.value = r->branch ? !!peer_sleep_khz : peer_sleep_khz;
-		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
+		value = r->branch ? !!peer_sleep_khz : peer_sleep_khz;
+		rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
 	}
 	r->enabled = false;
 out:
@@ -116,10 +194,6 @@
 
 	spin_lock_irqsave(&rpm_clock_lock, flags);
 
-	/* Ignore duplicate requests. */
-	if (r->last_set_khz == this_khz)
-		goto out;
-
 	/* Active-only clocks don't care what the rate is during sleep. So,
 	 * they vote for zero. */
 	if (r->active_only)
@@ -128,25 +202,23 @@
 		this_sleep_khz = this_khz;
 
 	if (r->enabled) {
-		struct msm_rpm_iv_pair iv;
+		uint32_t value;
 		struct rpm_clk *peer = r->peer;
 		unsigned long peer_khz = 0, peer_sleep_khz = 0;
 
-		iv.id = r->rpm_clk_id;
-
 		/* Take peer clock's rate into account only if it's enabled. */
 		if (peer->enabled) {
 			peer_khz = peer->last_set_khz;
 			peer_sleep_khz = peer->last_set_sleep_khz;
 		}
 
-		iv.value = max(this_khz, peer_khz);
-		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
+		value = max(this_khz, peer_khz);
+		rc = clk_rpmrs_set_rate_active_noirq(r, value);
 		if (rc)
 			goto out;
 
-		iv.value = max(this_sleep_khz, peer_sleep_khz);
-		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
+		value = max(this_sleep_khz, peer_sleep_khz);
+		rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
 	}
 	if (!rc) {
 		r->last_set_khz = this_khz;
@@ -162,13 +234,10 @@
 static unsigned long rpm_clk_get_rate(struct clk *clk)
 {
 	struct rpm_clk *r = to_rpm_clk(clk);
-	struct msm_rpm_iv_pair iv = { r->rpm_status_id };
-	int rc;
-
-	rc  = msm_rpm_get_status(&iv, 1);
-	if (rc < 0)
-		return rc;
-	return iv.value * 1000;
+	if (r->rpmrs_data->get_rate_fn)
+		return r->rpmrs_data->get_rate_fn(r);
+	else
+		return 0;
 }
 
 static int rpm_clk_is_enabled(struct clk *clk)
@@ -187,6 +256,29 @@
 	return false;
 }
 
+static enum handoff rpm_clk_handoff(struct clk *clk)
+{
+	struct rpm_clk *r = to_rpm_clk(clk);
+	struct msm_rpm_iv_pair iv = { r->rpm_status_id };
+	int rc;
+
+	/*
+	 * Querying an RPM clock's status will return 0 unless the clock's
+	 * rate has previously been set through the RPM. When handing off,
+	 * assume these clocks are enabled (unless the RPM call fails) so
+	 * child clocks of these RPM clocks can still be handed off.
+	 */
+	rc  = msm_rpm_get_status(&iv, 1);
+	if (rc < 0)
+		return HANDOFF_DISABLED_CLK;
+
+	r->last_set_khz = iv.value;
+	r->last_set_sleep_khz = iv.value;
+	clk->rate = iv.value * 1000;
+
+	return HANDOFF_ENABLED_CLK;
+}
+
 struct clk_ops clk_ops_rpm = {
 	.enable = rpm_clk_enable,
 	.disable = rpm_clk_disable,
@@ -195,10 +287,12 @@
 	.is_enabled = rpm_clk_is_enabled,
 	.round_rate = rpm_clk_round_rate,
 	.is_local = rpm_clk_is_local,
+	.handoff = rpm_clk_handoff,
 };
 
 struct clk_ops clk_ops_rpm_branch = {
 	.enable = rpm_clk_enable,
 	.disable = rpm_clk_disable,
 	.is_local = rpm_clk_is_local,
+	.handoff = rpm_clk_handoff,
 };
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index b0d5693..b2358bc 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -15,12 +15,15 @@
 #define __ARCH_ARM_MACH_MSM_CLOCK_RPM_H
 
 #include <mach/rpm.h>
+#include <mach/rpm-smd.h>
 
 struct clk_ops;
+struct clk_rpmrs_data;
 extern struct clk_ops clk_ops_rpm;
 extern struct clk_ops clk_ops_rpm_branch;
 
 struct rpm_clk {
+	const int rpm_res_type;
 	const int rpm_clk_id;
 	const int rpm_status_id;
 	const bool active_only;
@@ -29,6 +32,7 @@
 	unsigned last_set_sleep_khz;
 	bool enabled;
 	bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
+	struct clk_rpmrs_data *rpmrs_data;
 
 	struct rpm_clk *peer;
 	struct clk c;
@@ -39,12 +43,17 @@
 	return container_of(clk, struct rpm_clk, c);
 }
 
-#define DEFINE_CLK_RPM(name, active, r_id, dep) \
+extern struct clk_rpmrs_data clk_rpmrs_data;
+extern struct clk_rpmrs_data clk_rpmrs_data_smd;
+
+#define __DEFINE_CLK_RPM(name, active, type, r_id, stat_id, dep, rpmrsdata) \
 	static struct rpm_clk active; \
 	static struct rpm_clk name = { \
-		.rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
-		.rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+		.rpm_res_type = (type), \
+		.rpm_clk_id = (r_id), \
+		.rpm_status_id = (stat_id), \
 		.peer = &active, \
+		.rpmrs_data = (rpmrsdata),\
 		.c = { \
 			.ops = &clk_ops_rpm, \
 			.flags = CLKFLAG_SKIP_AUTO_OFF, \
@@ -54,10 +63,12 @@
 		}, \
 	}; \
 	static struct rpm_clk active = { \
-		.rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
-		.rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+		.rpm_res_type = (type), \
+		.rpm_clk_id = (r_id), \
+		.rpm_status_id = (stat_id), \
 		.peer = &name, \
 		.active_only = true, \
+		.rpmrs_data = (rpmrsdata),\
 		.c = { \
 			.ops = &clk_ops_rpm, \
 			.flags = CLKFLAG_SKIP_AUTO_OFF, \
@@ -67,15 +78,18 @@
 		}, \
 	};
 
-#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
+#define __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, stat_id, r, \
+					rpmrsdata) \
 	static struct rpm_clk active; \
 	static struct rpm_clk name = { \
-		.rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
-		.rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+		.rpm_res_type = (type), \
+		.rpm_clk_id = (r_id), \
+		.rpm_status_id = (stat_id), \
 		.peer = &active, \
 		.last_set_khz = ((r) / 1000), \
 		.last_set_sleep_khz = ((r) / 1000), \
 		.branch = true, \
+		.rpmrs_data = (rpmrsdata),\
 		.c = { \
 			.ops = &clk_ops_rpm_branch, \
 			.flags = CLKFLAG_SKIP_AUTO_OFF, \
@@ -86,12 +100,14 @@
 		}, \
 	}; \
 	static struct rpm_clk active = { \
-		.rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
-		.rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+		.rpm_res_type = (type), \
+		.rpm_clk_id = (r_id), \
+		.rpm_status_id = (stat_id), \
 		.peer = &name, \
 		.last_set_khz = ((r) / 1000), \
 		.active_only = true, \
 		.branch = true, \
+		.rpmrs_data = (rpmrsdata),\
 		.c = { \
 			.ops = &clk_ops_rpm_branch, \
 			.flags = CLKFLAG_SKIP_AUTO_OFF, \
@@ -102,4 +118,19 @@
 		}, \
 	};
 
+#define DEFINE_CLK_RPM(name, active, r_id, dep) \
+	__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
+		MSM_RPM_STATUS_ID_##r_id##_CLK, dep, &clk_rpmrs_data)
+
+#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
+	__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
+			MSM_RPM_STATUS_ID_##r_id##_CLK, r, &clk_rpmrs_data)
+
+#define DEFINE_CLK_RPM_SMD(name, active, type, r_id, dep) \
+	__DEFINE_CLK_RPM(name, active, type, r_id, 0, dep, &clk_rpmrs_data_smd)
+
+#define DEFINE_CLK_RPM_SMD_BRANCH(name, active, type, r_id, dep) \
+	__DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, 0, dep, \
+					&clk_rpmrs_data_smd)
+
 #endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index fb5b580..8bf98fa 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -21,10 +21,17 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/list.h>
 #include <trace/events/power.h>
 
 #include "clock.h"
 
+struct handoff_clk {
+	struct list_head list;
+	struct clk *clk;
+};
+static LIST_HEAD(handoff_list);
+
 /* Find the voltage level required for a given rate. */
 static int find_vdd_level(struct clk *clk, unsigned long rate)
 {
@@ -203,18 +210,8 @@
 			ret = clk->ops->enable(clk);
 		if (ret)
 			goto err_enable_clock;
-	} else if (clk->flags & CLKFLAG_HANDOFF_RATE) {
-		/*
-		 * The clock was already enabled by handoff code so there is no
-		 * need to enable it again here. Clearing the handoff flag will
-		 * prevent the lateinit handoff code from disabling the clock if
-		 * a client driver still has it enabled.
-		 */
-		clk->flags &= ~CLKFLAG_HANDOFF_RATE;
-		goto out;
 	}
 	clk->count++;
-out:
 	spin_unlock_irqrestore(&clk->lock, flags);
 
 	return 0;
@@ -320,7 +317,7 @@
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long start_rate, flags;
-	int rc;
+	int rc = 0;
 
 	if (IS_ERR_OR_NULL(clk))
 		return -EINVAL;
@@ -329,6 +326,11 @@
 		return -ENOSYS;
 
 	spin_lock_irqsave(&clk->lock, flags);
+
+	/* Return early if the rate isn't going to change */
+	if (clk->rate == rate)
+		goto out;
+
 	trace_clock_set_rate(clk->dbg_name, rate, smp_processor_id());
 	if (clk->count) {
 		start_rate = clk->rate;
@@ -347,7 +349,7 @@
 
 	if (!rc)
 		clk->rate = rate;
-
+out:
 	spin_unlock_irqrestore(&clk->lock, flags);
 	return rc;
 
@@ -417,6 +419,58 @@
 
 static struct clock_init_data __initdata *clk_init_data;
 
+static enum handoff __init __handoff_clk(struct clk *clk)
+{
+	enum handoff ret;
+	struct handoff_clk *h;
+	unsigned long rate;
+	int err = 0;
+
+	/*
+	 * Tree roots don't have parents, but need to be handed off. So,
+	 * terminate recursion by returning "enabled". Also return "enabled"
+	 * for clocks with non-zero enable counts since they must have already
+	 * been handed off.
+	 */
+	if (clk == NULL || clk->count)
+		return HANDOFF_ENABLED_CLK;
+
+	/* Clocks without handoff functions are assumed to be disabled. */
+	if (!clk->ops->handoff || (clk->flags & CLKFLAG_SKIP_HANDOFF))
+		return HANDOFF_DISABLED_CLK;
+
+	/*
+	 * Handoff functions for children must be called before their parents'
+	 * so that the correct parent is returned by the clk_get_parent() below.
+	 */
+	ret = clk->ops->handoff(clk);
+	if (ret == HANDOFF_ENABLED_CLK) {
+		ret = __handoff_clk(clk_get_parent(clk));
+		if (ret == HANDOFF_ENABLED_CLK) {
+			h = kmalloc(sizeof(*h), GFP_KERNEL);
+			if (!h) {
+				err = -ENOMEM;
+				goto out;
+			}
+			err = clk_prepare_enable(clk);
+			if (err)
+				goto out;
+			rate = clk_get_rate(clk);
+			if (rate)
+				pr_debug("%s rate=%lu\n", clk->dbg_name, rate);
+			h->clk = clk;
+			list_add_tail(&h->list, &handoff_list);
+		}
+	}
+out:
+	if (err) {
+		pr_err("%s handoff failed (%d)\n", clk->dbg_name, err);
+		kfree(h);
+		ret = HANDOFF_DISABLED_CLK;
+	}
+	return ret;
+}
+
 void __init msm_clock_init(struct clock_init_data *data)
 {
 	unsigned n;
@@ -443,14 +497,8 @@
 	 * Detect and preserve initial clock state until clock_late_init() or
 	 * a driver explicitly changes it, whichever is first.
 	 */
-	for (n = 0; n < num_clocks; n++) {
-		clk = clock_tbl[n].clk;
-		if (clk->ops->handoff && !(clk->flags & CLKFLAG_HANDOFF_RATE) &&
-		    (clk->ops->handoff(clk) == HANDOFF_ENABLED_CLK)) {
-			clk->flags |= CLKFLAG_HANDOFF_RATE;
-			clk_prepare_enable(clk);
-		}
-	}
+	for (n = 0; n < num_clocks; n++)
+		__handoff_clk(clock_tbl[n].clk);
 
 	clkdev_add_table(clock_tbl, num_clocks);
 
@@ -466,13 +514,13 @@
 static int __init clock_late_init(void)
 {
 	unsigned n, count = 0;
+	struct handoff_clk *h, *h_temp;
 	unsigned long flags;
 	int ret = 0;
 
 	clock_debug_init(clk_init_data);
 	for (n = 0; n < clk_init_data->size; n++) {
 		struct clk *clk = clk_init_data->table[n].clk;
-		bool handoff = false;
 
 		clock_debug_add(clk);
 		spin_lock_irqsave(&clk->lock, flags);
@@ -482,19 +530,16 @@
 				clk->ops->auto_off(clk);
 			}
 		}
-		if (clk->flags & CLKFLAG_HANDOFF_RATE) {
-			clk->flags &= ~CLKFLAG_HANDOFF_RATE;
-			handoff = true;
-		}
 		spin_unlock_irqrestore(&clk->lock, flags);
-		/*
-		 * Calling this outside the lock is safe since
-		 * it doesn't need to be atomic with the flag change.
-		 */
-		if (handoff)
-			clk_disable_unprepare(clk);
 	}
 	pr_info("clock_late_init() disabled %d unused clocks\n", count);
+
+	list_for_each_entry_safe(h, h_temp, &handoff_list, list) {
+		clk_disable_unprepare(h->clk);
+		list_del(&h->list);
+		kfree(h);
+	}
+
 	if (clk_init_data->late_init)
 		ret = clk_init_data->late_init();
 	return ret;
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 1be05ad..03d5790 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -29,10 +29,10 @@
 #define CLKFLAG_NOINVERT		0x00000002
 #define CLKFLAG_NONEST			0x00000004
 #define CLKFLAG_NORESET			0x00000008
-#define CLKFLAG_HANDOFF_RATE		0x00000010
 #define CLKFLAG_HWCG			0x00000020
 #define CLKFLAG_RETAIN			0x00000040
 #define CLKFLAG_NORETAIN		0x00000080
+#define CLKFLAG_SKIP_HANDOFF		0x00000100
 #define CLKFLAG_SKIP_AUTO_OFF		0x00000200
 #define CLKFLAG_MIN			0x00000400
 #define CLKFLAG_MAX			0x00000800
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 1382632..b9617f3 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -608,6 +608,11 @@
 	.id = 0x4003,
 };
 
+struct platform_device apq_cpudai_slimbus_2_rx = {
+	.name = "msm-dai-q6",
+	.id = 0x4004,
+};
+
 struct platform_device apq_cpudai_slimbus_2_tx = {
 	.name = "msm-dai-q6",
 	.id = 0x4005,
@@ -618,6 +623,11 @@
 	.id = 0x4006,
 };
 
+struct platform_device apq_cpudai_slimbus_3_tx = {
+	.name = "msm-dai-q6",
+	.id = 0x4007,
+};
+
 static struct resource resources_ssbi_pmic1[] = {
 	{
 		.start  = MSM_PMIC1_SSBI_CMD_PHYS,
@@ -1663,6 +1673,21 @@
 	.bus_port0 = MSM_BUS_MASTER_JPEG_ENC,
 };
 
+static struct fs_driver_data mdp_fs_data = {
+	.clks = (struct fs_clk_data[]){
+		{ .name = "core_clk" },
+		{ .name = "iface_clk" },
+		{ .name = "bus_clk" },
+		{ .name = "vsync_clk" },
+		{ .name = "lut_clk" },
+		{ .name = "tv_src_clk" },
+		{ .name = "tv_clk" },
+		{ 0 }
+	},
+	.bus_port0 = MSM_BUS_MASTER_MDP_PORT0,
+	.bus_port1 = MSM_BUS_MASTER_MDP_PORT1,
+};
+
 static struct fs_driver_data rot_fs_data = {
 	.clks = (struct fs_clk_data[]){
 		{ .name = "core_clk" },
@@ -1715,6 +1740,7 @@
 };
 
 struct platform_device *apq8064_footswitch[] __initdata = {
+	FS_8X60(FS_MDP,    "vdd",       "mdp.0",        &mdp_fs_data),
 	FS_8X60(FS_ROT,    "vdd",	"msm_rotator.0", &rot_fs_data),
 	FS_8X60(FS_IJPEG,  "vdd",	"msm_gemini.0",	&ijpeg_fs_data),
 	FS_8X60(FS_VFE,    "fs_vfe",	NULL,	&vfe_fs_data),
@@ -2018,6 +2044,16 @@
 
 /* Sensors DSPS platform data */
 
+#define PPSS_DSPS_TCM_CODE_BASE 0x12000000
+#define PPSS_DSPS_TCM_CODE_SIZE 0x28000
+#define PPSS_DSPS_TCM_BUF_BASE  0x12040000
+#define PPSS_DSPS_TCM_BUF_SIZE  0x4000
+#define PPSS_DSPS_PIPE_BASE     0x12800000
+#define PPSS_DSPS_PIPE_SIZE     0x4000
+#define PPSS_DSPS_DDR_BASE      0x8fe00000
+#define PPSS_DSPS_DDR_SIZE      0x100000
+#define PPSS_SMEM_BASE          0x80000000
+#define PPSS_SMEM_SIZE          0x200000
 #define PPSS_REG_PHYS_BASE	0x12080000
 
 static struct dsps_clk_info dsps_clks[] = {};
@@ -2036,6 +2072,16 @@
 	.regs = dsps_regs,
 	.regs_num = ARRAY_SIZE(dsps_regs),
 	.dsps_pwr_ctl_en = 1,
+	.tcm_code_start = PPSS_DSPS_TCM_CODE_BASE,
+	.tcm_code_size = PPSS_DSPS_TCM_CODE_SIZE,
+	.tcm_buf_start = PPSS_DSPS_TCM_BUF_BASE,
+	.tcm_buf_size = PPSS_DSPS_TCM_BUF_SIZE,
+	.pipe_start = PPSS_DSPS_PIPE_BASE,
+	.pipe_size = PPSS_DSPS_PIPE_SIZE,
+	.ddr_start = PPSS_DSPS_DDR_BASE,
+	.ddr_size = PPSS_DSPS_DDR_SIZE,
+	.smem_start = PPSS_SMEM_BASE,
+	.smem_size  = PPSS_SMEM_SIZE,
 	.signature = DSPS_SIGNATURE,
 };
 
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 2c4687f..c480bba 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -127,7 +127,6 @@
 		MSM_RPM_MAP(8930, CXO_BUFFERS, CXO_BUFFERS, 1),
 		MSM_RPM_MAP(8930, USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
 		MSM_RPM_MAP(8930, HDMI_SWITCH, HDMI_SWITCH, 1),
-		MSM_RPM_MAP(8930, DDR_DMM_0, DDR_DMM, 2),
 		MSM_RPM_MAP(8930, QDSS_CLK, QDSS_CLK, 1),
 		MSM_RPM_MAP(8930, VOLTAGE_CORNER, VOLTAGE_CORNER, 1),
 	},
@@ -232,8 +231,6 @@
 		MSM_RPM_STATUS_ID_MAP(8930, CXO_BUFFERS),
 		MSM_RPM_STATUS_ID_MAP(8930, USB_OTG_SWITCH),
 		MSM_RPM_STATUS_ID_MAP(8930, HDMI_SWITCH),
-		MSM_RPM_STATUS_ID_MAP(8930, DDR_DMM_0),
-		MSM_RPM_STATUS_ID_MAP(8930, DDR_DMM_1),
 		MSM_RPM_STATUS_ID_MAP(8930, QDSS_CLK),
 		MSM_RPM_STATUS_ID_MAP(8930, VOLTAGE_CORNER),
 	},
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index be364e7..db55d14 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -577,6 +577,58 @@
 		.ib  = 10000000,
 	},
 };
+static struct msm_bus_vectors vidc_venc_1080p_turbo_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_HD_CODEC_PORT0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 222298112,
+		.ib  = 3522000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_HD_CODEC_PORT1,
+		.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_HD_CODEC_PORT0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 222298112,
+		.ib  = 3522000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_HD_CODEC_PORT1,
+		.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[] = {
 	{
@@ -607,6 +659,14 @@
 		ARRAY_SIZE(vidc_vdec_1080p_vectors),
 		vidc_vdec_1080p_vectors,
 	},
+	{
+		ARRAY_SIZE(vidc_venc_1080p_turbo_vectors),
+		vidc_vdec_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 = {
@@ -1841,6 +1901,11 @@
 	.id	= 0x4001,
 };
 
+struct platform_device msm8960_cpudai_slimbus_2_rx = {
+	.name = "msm-dai-q6",
+	.id = 0x4004,
+};
+
 struct platform_device msm8960_cpudai_slimbus_2_tx = {
 	.name = "msm-dai-q6",
 	.id = 0x4005,
@@ -2939,6 +3004,27 @@
 };
 #endif
 
+#ifdef CONFIG_MSM_MERCURY
+static struct resource msm_mercury_resources[] = {
+	{
+		.start  = 0x05000000,
+		.end  = 0x05000000 + SZ_1M - 1,
+		.name   = "mercury_resource_base",
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = JPEGD_IRQ,
+		.end  = JPEGD_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+struct platform_device msm8960_mercury_device = {
+	.name       = "msm_mercury",
+	.resource     = msm_mercury_resources,
+	.num_resources  = ARRAY_SIZE(msm_mercury_resources),
+};
+#endif
+
 struct msm_rpm_platform_data msm8960_rpm_data __initdata = {
 	.reg_base_addrs = {
 		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
@@ -3246,6 +3332,16 @@
 /* Sensors DSPS platform data */
 #ifdef CONFIG_MSM_DSPS
 
+#define PPSS_DSPS_TCM_CODE_BASE 0x12000000
+#define PPSS_DSPS_TCM_CODE_SIZE 0x28000
+#define PPSS_DSPS_TCM_BUF_BASE  0x12040000
+#define PPSS_DSPS_TCM_BUF_SIZE  0x4000
+#define PPSS_DSPS_PIPE_BASE     0x12800000
+#define PPSS_DSPS_PIPE_SIZE     0x4000
+#define PPSS_DSPS_DDR_BASE      0x8fe00000
+#define PPSS_DSPS_DDR_SIZE      0x100000
+#define PPSS_SMEM_BASE          0x80000000
+#define PPSS_SMEM_SIZE          0x200000
 #define PPSS_REG_PHYS_BASE	0x12080000
 
 static struct dsps_clk_info dsps_clks[] = {};
@@ -3264,6 +3360,16 @@
 	.regs = dsps_regs,
 	.regs_num = ARRAY_SIZE(dsps_regs),
 	.dsps_pwr_ctl_en = 1,
+	.tcm_code_start = PPSS_DSPS_TCM_CODE_BASE,
+	.tcm_code_size = PPSS_DSPS_TCM_CODE_SIZE,
+	.tcm_buf_start = PPSS_DSPS_TCM_BUF_BASE,
+	.tcm_buf_size = PPSS_DSPS_TCM_BUF_SIZE,
+	.pipe_start = PPSS_DSPS_PIPE_BASE,
+	.pipe_size = PPSS_DSPS_PIPE_SIZE,
+	.ddr_start = PPSS_DSPS_DDR_BASE,
+	.ddr_size = PPSS_DSPS_DDR_SIZE,
+	.smem_start = PPSS_SMEM_BASE,
+	.smem_size  = PPSS_SMEM_SIZE,
 	.signature = DSPS_SIGNATURE,
 };
 
@@ -3274,7 +3380,6 @@
 		.name  = "ppss_reg",
 		.flags = IORESOURCE_MEM,
 	},
-
 	{
 		.start = PPSS_WDOG_TIMER_IRQ,
 		.end   = PPSS_WDOG_TIMER_IRQ,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 85d00eb..4677a1c 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -492,6 +492,44 @@
 	},
 };
 
+struct msm_dai_auxpcm_pdata sec_auxpcm_pdata = {
+	.clk = "sec_pcm_clk",
+	.mode_8k = {
+		.mode = AFE_PCM_CFG_MODE_PCM,
+		.sync = AFE_PCM_CFG_SYNC_INT,
+		.frame = AFE_PCM_CFG_FRM_256BPF,
+		.quant = AFE_PCM_CFG_QUANT_LINEAR_NOPAD,
+		.slot = 0,
+		.data = AFE_PCM_CFG_CDATAOE_MASTER,
+		.pcm_clk_rate = 2048000,
+	},
+	.mode_16k = {
+		.mode = AFE_PCM_CFG_MODE_PCM,
+		.sync = AFE_PCM_CFG_SYNC_INT,
+		.frame = AFE_PCM_CFG_FRM_256BPF,
+		.quant = AFE_PCM_CFG_QUANT_LINEAR_NOPAD,
+		.slot = 0,
+		.data = AFE_PCM_CFG_CDATAOE_MASTER,
+		.pcm_clk_rate = 4096000,
+	}
+};
+
+struct platform_device msm_cpudai_sec_auxpcm_rx = {
+	.name = "msm-dai-q6",
+	.id = 12,
+	.dev = {
+		.platform_data = &sec_auxpcm_pdata,
+	},
+};
+
+struct platform_device msm_cpudai_sec_auxpcm_tx = {
+	.name = "msm-dai-q6",
+	.id = 13,
+	.dev = {
+		.platform_data = &sec_auxpcm_pdata,
+	},
+};
+
 struct platform_device msm_cpu_fe = {
 	.name	= "msm-dai-fe",
 	.id	= -1,
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 4654606..adc9169 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1445,7 +1445,7 @@
 	},
 };
 
-static struct platform_device msm8625_mipi_dsi_device = {
+struct platform_device msm8625_mipi_dsi_device = {
 	.name   = "mipi_dsi",
 	.id     = 1,
 	.num_resources  = ARRAY_SIZE(msm8625_mipi_dsi_resources),
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index d622af2..37844c1 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -1568,6 +1568,16 @@
 /* Sensors DSPS platform data */
 #ifdef CONFIG_MSM_DSPS
 
+#define PPSS_DSPS_TCM_CODE_BASE 0x12000000
+#define PPSS_DSPS_TCM_CODE_SIZE 0x28000
+#define PPSS_DSPS_TCM_BUF_BASE  0x12040000
+#define PPSS_DSPS_TCM_BUF_SIZE  0x4000
+#define PPSS_DSPS_PIPE_BASE     0x12800000
+#define PPSS_DSPS_PIPE_SIZE     0x0 /* 8660 V2 does not use PIPE memory */
+#define PPSS_DSPS_DDR_BASE      0x8fe00000
+#define PPSS_DSPS_DDR_SIZE      0x0 /* 8660 V2 does not use DDR memory */
+#define PPSS_SMEM_BASE          0x40000000
+#define PPSS_SMEM_SIZE          0x4000
 #define PPSS_REG_PHYS_BASE	0x12080000
 
 #define MHZ (1000*1000)
@@ -1631,6 +1641,16 @@
 	.regs = dsps_regs,
 	.regs_num = ARRAY_SIZE(dsps_regs),
 	.init = dsps_init1,
+	.tcm_code_start = PPSS_DSPS_TCM_CODE_BASE,
+	.tcm_code_size = PPSS_DSPS_TCM_CODE_SIZE,
+	.tcm_buf_start = PPSS_DSPS_TCM_BUF_BASE,
+	.tcm_buf_size = PPSS_DSPS_TCM_BUF_SIZE,
+	.pipe_start = PPSS_DSPS_PIPE_BASE,
+	.pipe_size = PPSS_DSPS_PIPE_SIZE,
+	.ddr_start = PPSS_DSPS_DDR_BASE,
+	.ddr_size = PPSS_DSPS_DDR_SIZE,
+	.smem_start = PPSS_SMEM_BASE,
+	.smem_size  = PPSS_SMEM_SIZE,
 	.signature = DSPS_SIGNATURE,
 };
 
@@ -2266,7 +2286,8 @@
 #endif
 	.disable_dmx = 0,
 	.disable_fullhd = 0,
-	.cont_mode_dpb_count = 8
+	.cont_mode_dpb_count = 8,
+	.disable_turbo = 1,
 };
 
 struct platform_device msm_device_vidc = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index f180aa5..2b2fcc7 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -65,6 +65,7 @@
 extern struct platform_device msm8960_device_qup_i2c_gsbi12;
 extern struct platform_device msm8960_device_qup_spi_gsbi1;
 extern struct platform_device msm8960_gemini_device;
+extern struct platform_device msm8960_mercury_device;
 extern struct platform_device msm8960_device_i2c_mux_gsbi4;
 extern struct platform_device msm8960_device_csiphy0;
 extern struct platform_device msm8960_device_csiphy1;
@@ -202,6 +203,7 @@
 extern struct platform_device msm_cpudai0;
 extern struct platform_device msm_cpudai1;
 extern struct platform_device mpq_cpudai_sec_i2s_rx;
+extern struct platform_device msm8960_cpudai_slimbus_2_rx;
 extern struct platform_device msm8960_cpudai_slimbus_2_tx;
 extern struct platform_device msm_cpudai_hdmi_rx;
 extern struct platform_device msm_cpudai_bt_rx;
@@ -210,6 +212,8 @@
 extern struct platform_device msm_cpudai_fm_tx;
 extern struct platform_device msm_cpudai_auxpcm_rx;
 extern struct platform_device msm_cpudai_auxpcm_tx;
+extern struct platform_device msm_cpudai_sec_auxpcm_rx;
+extern struct platform_device msm_cpudai_sec_auxpcm_tx;
 extern struct platform_device msm_cpu_fe;
 extern struct platform_device msm_stub_codec;
 extern struct platform_device msm_voice;
@@ -267,8 +271,10 @@
 extern struct platform_device apq_cpudai_stub;
 extern struct platform_device apq_cpudai_slimbus_1_rx;
 extern struct platform_device apq_cpudai_slimbus_1_tx;
+extern struct platform_device apq_cpudai_slimbus_2_rx;
 extern struct platform_device apq_cpudai_slimbus_2_tx;
 extern struct platform_device apq_cpudai_slimbus_3_rx;
+extern struct platform_device apq_cpudai_slimbus_3_tx;
 extern struct platform_device apq_cpudai_slim_4_rx;
 extern struct platform_device apq_cpudai_slim_4_tx;
 
@@ -294,6 +300,7 @@
 extern struct platform_device msm_kgsl_2d1;
 
 extern struct platform_device msm_mipi_dsi1_device;
+extern struct platform_device msm8625_mipi_dsi_device;
 extern struct platform_device msm_lvds_device;
 extern struct platform_device msm_ebi2_lcdc_device;
 
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/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 5e2eaf1..bae5cbc 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -524,6 +524,7 @@
 	struct msm_bus_scale_pdata *vidc_bus_client_pdata;
 #endif
 	int cont_mode_dpb_count;
+	int disable_turbo;
 };
 
 struct vcap_platform_data {
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index 8aed079..1d32003 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -178,7 +178,7 @@
 	TLMM_PULL_SDC1_DATA,
 };
 
-#ifdef CONFIG_GPIO_MSM_V2
+#if defined(CONFIG_GPIO_MSM_V2) || defined(CONFIG_GPIO_MSM_V3)
 void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt, int drv_str);
 void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull);
 
diff --git a/arch/arm/mach-msm/include/mach/irqs-copper.h b/arch/arm/mach-msm/include/mach/irqs-copper.h
index 6d27d69..8cd8620 100644
--- a/arch/arm/mach-msm/include/mach/irqs-copper.h
+++ b/arch/arm/mach-msm/include/mach/irqs-copper.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
@@ -35,7 +35,7 @@
 #define SPS_BAM_DMA_IRQ			(GIC_SPI_START + 105)
 
 #define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
-#define NR_GPIO_IRQS 156
+#define NR_GPIO_IRQS 146
 #define NR_QPNP_IRQS 32768 /* SPARSE_IRQ is required to support this */
 #define NR_BOARD_IRQS NR_QPNP_IRQS
 #define NR_TLMM_MSM_DIR_CONN_IRQ 8
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index fdf6786..d630799 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -41,7 +41,7 @@
 #define NR_MSM_IRQS 288
 #define NR_GPIO_IRQS 152
 #define NR_PM8921_IRQS 256
-#define NR_PM8821_IRQS 64
+#define NR_PM8821_IRQS 112
 #define NR_WCD9XXX_IRQS 49
 #define NR_TABLA_IRQS NR_WCD9XXX_IRQS
 #define NR_GPIO_EXPANDER_IRQS 64
diff --git a/arch/arm/mach-msm/include/mach/msm_dsps.h b/arch/arm/mach-msm/include/mach/msm_dsps.h
index cfb2024..32a4f15 100644
--- a/arch/arm/mach-msm/include/mach/msm_dsps.h
+++ b/arch/arm/mach-msm/include/mach/msm_dsps.h
@@ -75,6 +75,16 @@
  * @regs_num - number of regulators.
  * @dsps_pwr_ctl_en - to enable DSPS to do power control if set 1
  *  otherwise the apps will do power control
+ * @tcm_code_start - start of the TCM code region as physical address
+ * @tcm_code_size - size of the TCM code region in bytes
+ * @tcm_buf_start - start of the TCM buf region as physical address
+ * @tcm_buf_size - size of the TCM buf region in bytes
+ * @pipe_start - start of the PIPE region as physical address
+ * @pipe_size - size of the PIPE region in bytes
+ * @ddr_start - start of the DDR region as physical address
+ * @ddr_size - size of the DDR region in bytes
+ * @smem_start - start of the smem region as physical address
+ * @smem_size - size of the smem region in bytes
  * @signature - signature for validity check.
  */
 struct msm_dsps_platform_data {
@@ -87,6 +97,16 @@
 	int regs_num;
 	int dsps_pwr_ctl_en;
 	void (*init)(struct msm_dsps_platform_data *data);
+	int tcm_code_start;
+	int tcm_code_size;
+	int tcm_buf_start;
+	int tcm_buf_size;
+	int pipe_start;
+	int pipe_size;
+	int ddr_start;
+	int ddr_size;
+	int smem_start;
+	int smem_size;
 	u32 signature;
 };
 
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index daf32a5..dd3a318 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -78,4 +78,8 @@
 int free_head(struct ocmem_zone *, unsigned long, unsigned long);
 unsigned long allocate_tail(struct ocmem_zone *, unsigned long);
 int free_tail(struct ocmem_zone *, unsigned long, unsigned long);
+
+int ocmem_notifier_init(void);
+int check_notifier(int);
+int dispatch_notification(int, enum ocmem_notif_type, struct ocmem_buf *);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
index bd303b2..f747a80 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
@@ -68,12 +68,23 @@
 #define USF_POINT_EPOS_FORMAT	0
 #define USF_RAW_FORMAT		1
 
+/* Indexes of event types, produced by the calculators */
+#define USF_TSC_EVENT_IND      0
+#define USF_TSC_PTR_EVENT_IND  1
+#define USF_MOUSE_EVENT_IND    2
+#define USF_KEYBOARD_EVENT_IND 3
+#define USF_MAX_EVENT_IND      4
+
 /* Types of events, produced by the calculators */
 #define USF_NO_EVENT 0
-#define USF_TSC_EVENT 1
-#define USF_MOUSE_EVENT 2
-#define USF_KEYBOARD_EVENT 4
-#define USF_ALL_EVENTS (USF_TSC_EVENT | USF_MOUSE_EVENT | USF_KEYBOARD_EVENT)
+#define USF_TSC_EVENT      (1 << USF_TSC_EVENT_IND)
+#define USF_TSC_PTR_EVENT  (1 << USF_TSC_PTR_EVENT_IND)
+#define USF_MOUSE_EVENT    (1 << USF_MOUSE_EVENT_IND)
+#define USF_KEYBOARD_EVENT (1 << USF_KEYBOARD_EVENT_IND)
+#define USF_ALL_EVENTS         (USF_TSC_EVENT |\
+				USF_TSC_PTR_EVENT |\
+				USF_MOUSE_EVENT |\
+				USF_KEYBOARD_EVENT)
 
 /* min, max array dimension */
 #define MIN_MAX_DIM 2
@@ -152,9 +163,6 @@
 	/* Info specific for RX*/
 };
 
-
-#define	USF_PIX_COORDINATE  0 /* unit is pixel */
-#define	USF_CMM_COORDINATE  1 /* unit is 0.01 mm */
 struct point_event_type {
 /* Pen coordinates (x, y, z) in units, defined by <coordinates_type>  */
 	int coordinates[COORDINATES_DIM];
@@ -162,8 +170,6 @@
 	int inclinations[TILTS_DIM];
 /* [0-1023] (10bits); 0 - pen up */
 	uint32_t pressure;
-/* 0 - mapped in the display pixel. 1 - raw in 0.01 mm (only for log); */
-	uint8_t coordinates_type;
 };
 
 /* Mouse buttons, supported by USF */
@@ -189,8 +195,8 @@
 	uint32_t seq_num;
 /* Event generation system time */
 	uint32_t timestamp;
-/* Destination input event type (e.g. touch screen, mouse, key) */
-	uint16_t event_type;
+/* Destination input event type index (e.g. touch screen, mouse, key) */
+	uint16_t event_type_ind;
 	union {
 		struct point_event_type point_event;
 		struct mouse_event_type mouse_event;
diff --git a/arch/arm/mach-msm/include/mach/rpm-8930.h b/arch/arm/mach-msm/include/mach/rpm-8930.h
index 5ec3a74..6fd9cf4 100644
--- a/arch/arm/mach-msm/include/mach/rpm-8930.h
+++ b/arch/arm/mach-msm/include/mach/rpm-8930.h
@@ -240,10 +240,8 @@
 	MSM_RPM_8930_ID_CXO_BUFFERS	= 164,
 	MSM_RPM_8930_ID_USB_OTG_SWITCH	= 165,
 	MSM_RPM_8930_ID_HDMI_SWITCH	= 166,
-	MSM_RPM_8930_ID_DDR_DMM_0		= 167,
-	MSM_RPM_8930_ID_DDR_DMM_1		= 168,
-	MSM_RPM_8930_ID_QDSS_CLK	= 168,
-	MSM_RPM_8930_ID_VOLTAGE_CORNER	= 169,
+	MSM_RPM_8930_ID_QDSS_CLK	= 167,
+	MSM_RPM_8930_ID_VOLTAGE_CORNER	= 168,
 	MSM_RPM_8930_ID_LAST = MSM_RPM_8930_ID_VOLTAGE_CORNER,
 };
 
@@ -353,10 +351,8 @@
 	MSM_RPM_8930_STATUS_ID_CXO_BUFFERS			= 105,
 	MSM_RPM_8930_STATUS_ID_USB_OTG_SWITCH			= 106,
 	MSM_RPM_8930_STATUS_ID_HDMI_SWITCH			= 107,
-	MSM_RPM_8930_STATUS_ID_DDR_DMM_0			= 108,
-	MSM_RPM_8930_STATUS_ID_DDR_DMM_1			= 109,
-	MSM_RPM_8930_STATUS_ID_QDSS_CLK				= 110,
-	MSM_RPM_8930_STATUS_ID_VOLTAGE_CORNER			= 111,
+	MSM_RPM_8930_STATUS_ID_QDSS_CLK				= 108,
+	MSM_RPM_8930_STATUS_ID_VOLTAGE_CORNER			= 109,
 	MSM_RPM_8930_STATUS_ID_LAST = MSM_RPM_8930_STATUS_ID_VOLTAGE_CORNER,
 };
 
diff --git a/arch/arm/mach-msm/include/mach/rpm-smd.h b/arch/arm/mach-msm/include/mach/rpm-smd.h
index ff58fed..0239e36 100644
--- a/arch/arm/mach-msm/include/mach/rpm-smd.h
+++ b/arch/arm/mach-msm/include/mach/rpm-smd.h
@@ -236,6 +236,20 @@
 	return 0;
 
 }
+
+static inline int msm_rpm_send_message(enum msm_rpm_set set, uint32_t rsc_type,
+		uint32_t rsc_id, struct msm_rpm_kvp *kvp, int nelems)
+{
+	return 0;
+}
+
+static inline int msm_rpm_send_message_noirq(enum msm_rpm_set set,
+		uint32_t rsc_type, uint32_t rsc_id, struct msm_rpm_kvp *kvp,
+		int nelems)
+{
+	return 0;
+}
+
 static inline int msm_rpm_wait_for_ack(uint32_t msg_id)
 {
 	return 0;
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index 98621be..de4c9d9 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -899,6 +899,8 @@
 extern struct msm_rpm_platform_data msm8930_rpm_data;
 extern struct msm_rpm_platform_data apq8064_rpm_data;
 
+#if defined(CONFIG_MSM_RPM)
+
 int msm_rpm_local_request_is_outstanding(void);
 int msm_rpm_get_status(struct msm_rpm_iv_pair *status, int count);
 int msm_rpm_set(int ctx, struct msm_rpm_iv_pair *req, int count);
@@ -938,4 +940,70 @@
 int msm_rpm_unregister_notification(struct msm_rpm_notification *n);
 int msm_rpm_init(struct msm_rpm_platform_data *data);
 
+#else
+
+static inline int msm_rpm_local_request_is_outstanding(void)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_get_status(struct msm_rpm_iv_pair *status, int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_set(int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_set_noirq(int ctx, struct msm_rpm_iv_pair *req,
+					int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_set_nosleep(
+	int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_clear(int ctx, struct msm_rpm_iv_pair *req,
+				int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_clear_noirq(int ctx, struct msm_rpm_iv_pair *req,
+					int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_clear_nosleep(
+	int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_register_notification(struct msm_rpm_notification *n,
+	struct msm_rpm_iv_pair *req, int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_unregister_notification(
+					struct msm_rpm_notification *n)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpm_init(struct msm_rpm_platform_data *data)
+{
+	return -ENODEV;
+}
+
+#endif /* CONFIG_RPM */
+
 #endif /* __ARCH_ARM_MACH_MSM_RPM_H */
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 86e06a4..e35d99b 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -34,7 +34,7 @@
 		.virtual = (unsigned long) MSM_##name##_BASE, \
 		.pfn = __phys_to_pfn(chip##_##name##_PHYS), \
 		.length = chip##_##name##_SIZE, \
-		.type = MT_DEVICE_NONSHARED, \
+		.type = MT_DEVICE, \
 	 }
 
 #define MSM_DEVICE(name) MSM_CHIP_DEVICE(name, MSM)
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index e7287c1..a7e06ba 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -99,6 +99,8 @@
 {
 	int ret;
 	struct scatterlist *sglist;
+	int prot = IOMMU_WRITE | IOMMU_READ;
+	prot |= cached ? IOMMU_CACHE : 0;
 
 	sglist = vmalloc(sizeof(*sglist));
 	if (!sglist) {
@@ -111,7 +113,7 @@
 	sglist->offset = 0;
 	sglist->dma_address = phys;
 
-	ret = iommu_map_range(domain, iova, sglist, size, cached);
+	ret = iommu_map_range(domain, iova, sglist, size, prot);
 	if (ret) {
 		pr_err("%s: could not map extra %lx in domain %p\n",
 			__func__, iova, domain);
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 6fa435a..c15e8b1 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -2023,7 +2023,7 @@
 }
 
 int msm_ipc_router_lookup_server_name(struct msm_ipc_port_name *srv_name,
-				struct msm_ipc_port_addr *srv_addr,
+				struct msm_ipc_server_info *srv_info,
 				int num_entries_in_array,
 				uint32_t lookup_mask)
 {
@@ -2036,8 +2036,8 @@
 		return -EINVAL;
 	}
 
-	if (num_entries_in_array && !srv_addr) {
-		pr_err("%s: srv_addr NULL\n", __func__);
+	if (num_entries_in_array && !srv_info) {
+		pr_err("%s: srv_info NULL\n", __func__);
 		return -EINVAL;
 	}
 
@@ -2054,10 +2054,14 @@
 			list_for_each_entry(server_port,
 				&server->server_port_list, list) {
 				if (i < num_entries_in_array) {
-					srv_addr[i].node_id =
+					srv_info[i].node_id =
 					  server_port->server_addr.node_id;
-					srv_addr[i].port_id =
+					srv_info[i].port_id =
 					  server_port->server_addr.port_id;
+					srv_info[i].service =
+					  server->name.service;
+					srv_info[i].instance =
+					  server->name.instance;
 				}
 				i++;
 			}
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index a90be23..07bc5e0 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -185,7 +185,7 @@
 int msm_ipc_router_get_curr_pkt_size(struct msm_ipc_port *port_ptr);
 int msm_ipc_router_bind_control_port(struct msm_ipc_port *port_ptr);
 int msm_ipc_router_lookup_server_name(struct msm_ipc_port_name *srv_name,
-				      struct msm_ipc_port_addr *port_addr,
+				      struct msm_ipc_server_info *srv_info,
 				      int num_entries_in_array,
 				      uint32_t lookup_mask);
 int msm_ipc_router_close_port(struct msm_ipc_port *port_ptr);
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index d82ffe5..d3917f1 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -367,8 +367,8 @@
 	struct sock *sk = sock->sk;
 	struct msm_ipc_port *port_ptr;
 	struct server_lookup_args server_arg;
-	struct msm_ipc_port_addr *port_addr = NULL;
-	unsigned int n, port_addr_sz = 0;
+	struct msm_ipc_server_info *srv_info = NULL;
+	unsigned int n, srv_info_sz = 0;
 	int ret;
 
 	if (!sk)
@@ -409,33 +409,33 @@
 			break;
 		}
 		if (server_arg.num_entries_in_array) {
-			port_addr_sz = server_arg.num_entries_in_array *
-					sizeof(*port_addr);
-			port_addr = kmalloc(port_addr_sz, GFP_KERNEL);
-			if (!port_addr) {
+			srv_info_sz = server_arg.num_entries_in_array *
+					sizeof(*srv_info);
+			srv_info = kmalloc(srv_info_sz, GFP_KERNEL);
+			if (!srv_info) {
 				ret = -ENOMEM;
 				break;
 			}
 		}
 		ret = msm_ipc_router_lookup_server_name(&server_arg.port_name,
-				port_addr, server_arg.num_entries_in_array,
+				srv_info, server_arg.num_entries_in_array,
 				server_arg.lookup_mask);
 		if (ret < 0) {
 			pr_err("%s: Server not found\n", __func__);
 			ret = -ENODEV;
-			kfree(port_addr);
+			kfree(srv_info);
 			break;
 		}
 		server_arg.num_entries_found = ret;
 
 		ret = copy_to_user((void *)arg, &server_arg,
 				   sizeof(server_arg));
-		if (port_addr_sz) {
+		if (srv_info_sz) {
 			ret = copy_to_user((void *)(arg + sizeof(server_arg)),
-					   port_addr, port_addr_sz);
+					   srv_info, srv_info_sz);
 			if (ret)
 				ret = -EFAULT;
-			kfree(port_addr);
+			kfree(srv_info);
 		}
 		break;
 
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index 4922007..5d02bda 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -63,6 +63,12 @@
 	wmb();
 }
 
+static void restart_modem(void)
+{
+	log_modem_sfr();
+	subsystem_restart("modem");
+}
+
 static void modem_wdog_check(struct work_struct *work)
 {
 	void __iomem *q6_sw_wdog_addr;
@@ -75,8 +81,7 @@
 	regval = readl_relaxed(q6_sw_wdog_addr);
 	if (!regval) {
 		pr_err("modem-8960: Modem watchdog wasn't activated!. Restarting the modem now.\n");
-		log_modem_sfr();
-		subsystem_restart("modem");
+		restart_modem();
 	}
 
 	iounmap(q6_sw_wdog_addr);
@@ -84,47 +89,6 @@
 
 static DECLARE_DELAYED_WORK(modem_wdog_check_work, modem_wdog_check);
 
-static void modem_sw_fatal_fn(struct work_struct *work)
-{
-	uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
-	uint32_t reset_smsm_states = SMSM_SYSTEM_REBOOT_USR |
-					SMSM_SYSTEM_PWRDWN_USR;
-	uint32_t modem_state;
-
-	pr_err("Watchdog bite received from modem SW!\n");
-
-	modem_state = smsm_get_state(SMSM_MODEM_STATE);
-
-	if (modem_state & panic_smsm_states) {
-
-		pr_err("Modem SMSM state changed to SMSM_RESET.\n"
-			"Probable err_fatal on the modem. "
-			"Calling subsystem restart...\n");
-		log_modem_sfr();
-		subsystem_restart("modem");
-
-	} else if (modem_state & reset_smsm_states) {
-
-		pr_err("%s: User-invoked system reset/powerdown. "
-			"Resetting the SoC now.\n",
-			__func__);
-		kernel_restart(NULL);
-	} else {
-		log_modem_sfr();
-		subsystem_restart("modem");
-	}
-}
-
-static void modem_fw_fatal_fn(struct work_struct *work)
-{
-	pr_err("Watchdog bite received from modem FW!\n");
-	log_modem_sfr();
-	subsystem_restart("modem");
-}
-
-static DECLARE_WORK(modem_sw_fatal_work, modem_sw_fatal_fn);
-static DECLARE_WORK(modem_fw_fatal_work, modem_fw_fatal_fn);
-
 static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
 {
 	/* Ignore if we're the one that set SMSM_RESET */
@@ -133,8 +97,7 @@
 
 	if (new_state & SMSM_RESET) {
 		pr_err("Probable fatal error on the modem.\n");
-		log_modem_sfr();
-		subsystem_restart("modem");
+		restart_modem();
 	}
 }
 
@@ -252,19 +215,15 @@
 
 static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
 {
-	int ret;
-
 	switch (irq) {
 
 	case Q6SW_WDOG_EXPIRED_IRQ:
-		ret = schedule_work(&modem_sw_fatal_work);
-		disable_irq_nosync(Q6SW_WDOG_EXPIRED_IRQ);
-		disable_irq_nosync(Q6FW_WDOG_EXPIRED_IRQ);
+		pr_err("Watchdog bite received from modem software!\n");
+		restart_modem();
 		break;
 	case Q6FW_WDOG_EXPIRED_IRQ:
-		ret = schedule_work(&modem_fw_fatal_work);
-		disable_irq_nosync(Q6SW_WDOG_EXPIRED_IRQ);
-		disable_irq_nosync(Q6FW_WDOG_EXPIRED_IRQ);
+		pr_err("Watchdog bite received from modem firmware!\n");
+		restart_modem();
 		break;
 	break;
 
diff --git a/arch/arm/mach-msm/msm_dsps.c b/arch/arm/mach-msm/msm_dsps.c
index 057665b..eda22e1 100644
--- a/arch/arm/mach-msm/msm_dsps.c
+++ b/arch/arm/mach-msm/msm_dsps.c
@@ -15,6 +15,8 @@
  *
  */
 
+#include <asm/atomic.h>
+
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -39,10 +41,11 @@
 #include <mach/subsystem_restart.h>
 #include <mach/subsystem_notif.h>
 
+#include "ramdump.h"
 #include "timer.h"
 
 #define DRV_NAME	"msm_dsps"
-#define DRV_VERSION	"3.02"
+#define DRV_VERSION	"4.01"
 
 #define PPSS_PAUSE_REG	0x1804
 
@@ -58,8 +61,14 @@
  *  @cdev - character device for user interface.
  *  @pdata - platform data.
  *  @pil - handle to DSPS Firmware loader.
+ *  @dspsfw_ramdump_dev - handle to ramdump device for DSPS
+ *  @dspsfw_ramdump_segments - Ramdump segment information for DSPS
+ *  @smem_ramdump_dev - handle to ramdump device for smem
+ *  @smem_ramdump_segments - Ramdump segment information for smem
  *  @is_on - DSPS is on.
  *  @ref_count - open/close reference count.
+ *  @wdog_irq - DSPS Watchdog IRQ
+ *  @crash_in_progress - 1 if crash recovery is in progress
  *  @ppss_base - ppss registers virtual base address.
  */
 struct dsps_drv {
@@ -73,9 +82,17 @@
 
 	void *pil;
 
+	void *dspsfw_ramdump_dev;
+	struct ramdump_segment dspsfw_ramdump_segments[4];
+
+	void *smem_ramdump_dev;
+	struct ramdump_segment smem_ramdump_segments[1];
+
 	int is_on;
 	int ref_count;
+	int wdog_irq;
 
+	atomic_t crash_in_progress;
 	void __iomem *ppss_base;
 };
 
@@ -89,8 +106,7 @@
  */
 static int dsps_crash_shutdown_g;
 
-
-static void dsps_fatal_handler(struct work_struct *work);
+static void dsps_restart_handler(void);
 
 /**
  *  Load DSPS Firmware.
@@ -210,7 +226,7 @@
 
 		}
 
-		ret = clk_enable(clock);
+		ret = clk_prepare_enable(clock);
 		if (ret) {
 			pr_err("%s: enable clk %s err %d.",
 			       __func__, name, ret);
@@ -299,7 +315,7 @@
 		if (clock == NULL)
 			continue;
 
-		clk_disable(clock);
+		clk_disable_unprepare(clock);
 	}
 
 	return -ENODEV;
@@ -329,7 +345,7 @@
 			const char *name = drv->pdata->clks[i].name;
 
 			pr_debug("%s: set clk %s off.", __func__, name);
-			clk_disable(drv->pdata->clks[i].clock);
+			clk_disable_unprepare(drv->pdata->clks[i].clock);
 		}
 
 	for (i = 0; i < drv->pdata->regs_num; i++)
@@ -360,7 +376,28 @@
 	return 0;
 }
 
-static DECLARE_WORK(dsps_fatal_work, dsps_fatal_handler);
+/**
+ *
+ * Log subsystem restart failure reason
+ */
+static void dsps_log_sfr(void)
+{
+	const char dflt_reason[] = "Died too early due to unknown reason";
+	char *smem_reset_reason;
+	unsigned smem_reset_size;
+
+	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_DSPS0,
+		&smem_reset_size);
+	if (smem_reset_reason != NULL && smem_reset_reason[0] != 0) {
+		smem_reset_reason[smem_reset_size-1] = 0;
+		pr_err("%s: DSPS failure: %s\nResetting DSPS\n",
+			__func__, smem_reset_reason);
+		memset(smem_reset_reason, 0, smem_reset_size);
+		wmb();
+	} else
+		pr_err("%s: DSPS failure: %s\nResetting DSPS\n",
+			__func__, dflt_reason);
+}
 
 /**
  *  Watchdog interrupt handler
@@ -368,9 +405,9 @@
  */
 static irqreturn_t dsps_wdog_bite_irq(int irq, void *dev_id)
 {
-	pr_debug("%s\n", __func__);
-	(void)schedule_work(&dsps_fatal_work);
-	disable_irq_nosync(irq);
+	pr_err("%s\n", __func__);
+	dsps_log_sfr();
+	dsps_restart_handler();
 	return IRQ_HANDLED;
 }
 
@@ -406,7 +443,9 @@
 		ret = put_user(val, (u32 __user *) arg);
 		break;
 	case DSPS_IOCTL_RESET:
-		dsps_fatal_handler(NULL);
+		pr_err("%s: User-initiated DSPS reset.\nResetting DSPS\n",
+		       __func__);
+		dsps_restart_handler();
 		ret = 0;
 		break;
 	default:
@@ -498,21 +537,52 @@
 	ppss_wdog = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
 						"ppss_wdog");
 	if (ppss_wdog) {
-		ret = request_irq(ppss_wdog->start, dsps_wdog_bite_irq,
+		drv->wdog_irq = ppss_wdog->start;
+		ret = request_irq(drv->wdog_irq, dsps_wdog_bite_irq,
 				  IRQF_TRIGGER_RISING, "dsps_wdog", NULL);
 		if (ret) {
 			pr_err("%s: request_irq fail %d\n", __func__, ret);
 			goto request_irq_err;
 		}
 	} else {
+		drv->wdog_irq = -1;
 		pr_debug("%s: ppss_wdog not supported.\n", __func__);
 	}
 
+	drv->dspsfw_ramdump_segments[0].address = drv->pdata->tcm_code_start;
+	drv->dspsfw_ramdump_segments[0].size =  drv->pdata->tcm_code_size;
+	drv->dspsfw_ramdump_segments[1].address = drv->pdata->tcm_buf_start;
+	drv->dspsfw_ramdump_segments[1].size =  drv->pdata->tcm_buf_size;
+	drv->dspsfw_ramdump_segments[2].address = drv->pdata->pipe_start;
+	drv->dspsfw_ramdump_segments[2].size =  drv->pdata->pipe_size;
+	drv->dspsfw_ramdump_segments[3].address = drv->pdata->ddr_start;
+	drv->dspsfw_ramdump_segments[3].size =  drv->pdata->ddr_size;
+
+	drv->dspsfw_ramdump_dev = create_ramdump_device("dsps");
+	if (!drv->dspsfw_ramdump_dev) {
+		pr_err("%s: create_ramdump_device(\"dsps\") fail\n",
+			      __func__);
+		goto create_ramdump_err;
+	}
+
+	drv->smem_ramdump_segments[0].address = drv->pdata->smem_start;
+	drv->smem_ramdump_segments[0].size =  drv->pdata->smem_size;
+	drv->smem_ramdump_dev = create_ramdump_device("smem");
+	if (!drv->smem_ramdump_dev) {
+		pr_err("%s: create_ramdump_device(\"smem\") fail\n",
+		       __func__);
+		goto create_ramdump_err;
+	}
+
 	if (drv->pdata->init)
 		drv->pdata->init(drv->pdata);
 
 	return 0;
 
+create_ramdump_err:
+	disable_irq_nosync(drv->wdog_irq);
+	free_irq(drv->wdog_irq, NULL);
+
 request_irq_err:
 	iounmap(drv->ppss_base);
 
@@ -600,6 +670,8 @@
 		}
 	}
 
+	free_irq(drv->wdog_irq, NULL);
+
 	iounmap(drv->ppss_base);
 }
 
@@ -646,22 +718,16 @@
  *  Fatal error handler
  *  Resets DSPS.
  */
-static void dsps_fatal_handler(struct work_struct *work)
+static void dsps_restart_handler(void)
 {
-	uint32_t dsps_state;
+	pr_debug("%s: Restart lvl %d\n",
+		__func__, get_restart_level());
 
-	dsps_state = smsm_get_state(SMSM_DSPS_STATE);
-
-	pr_debug("%s: DSPS state 0x%x\n", __func__, dsps_state);
-
-	if (dsps_state & SMSM_RESET) {
-		pr_err("%s: DSPS fatal error detected. Resetting\n",
-		       __func__);
-		panic("DSPS fatal error detected.");
+	if (atomic_add_return(1, &drv->crash_in_progress) > 1) {
+		pr_err("%s: DSPS already resetting. Count %d\n", __func__,
+		       atomic_read(&drv->crash_in_progress));
 	} else {
-		pr_debug("%s: User-initiated DSPS reset. Resetting\n",
-			 __func__);
-		panic("User-initiated DSPS reset.");
+		subsystem_restart("dsps");
 	}
 }
 
@@ -680,12 +746,9 @@
 		dsps_crash_shutdown_g = 0;
 		return;
 	}
-
 	if (new_state & SMSM_RESET) {
-		pr_err
-		    ("%s: SMSM_RESET state detected. restarting the DSPS\n",
-		     __func__);
-		panic("SMSM_RESET state detected.");
+		dsps_log_sfr();
+		dsps_restart_handler();
 	}
 }
 
@@ -697,7 +760,10 @@
 static int dsps_shutdown(const struct subsys_data *subsys)
 {
 	pr_debug("%s\n", __func__);
-	dsps_unload();
+	disable_irq_nosync(drv->wdog_irq);
+	dsps_suspend();
+	pil_force_shutdown(drv->pdata->pil_name);
+	dsps_power_off_handler();
 	return 0;
 }
 
@@ -709,11 +775,11 @@
 static int dsps_powerup(const struct subsys_data *subsys)
 {
 	pr_debug("%s\n", __func__);
-	if (dsps_load(drv->pdata->pil_name) != 0) {
-		pr_err("%s: fail to restart DSPS after reboot\n",
-		       __func__);
-		return 1;
-	}
+	dsps_power_on_handler();
+	pil_force_boot(drv->pdata->pil_name);
+	atomic_set(&drv->crash_in_progress, 0);
+	enable_irq(drv->wdog_irq);
+	dsps_resume();
 	return 0;
 }
 
@@ -736,8 +802,34 @@
  */
 static int dsps_ramdump(int enable, const struct subsys_data *subsys)
 {
+	int ret = 0;
 	pr_debug("%s\n", __func__);
-	return 0;
+
+	if (enable) {
+		if (drv->dspsfw_ramdump_dev != NULL) {
+			ret = do_ramdump(drv->dspsfw_ramdump_dev,
+				drv->dspsfw_ramdump_segments,
+				ARRAY_SIZE(drv->dspsfw_ramdump_segments));
+			if (ret < 0) {
+				pr_err("%s: Unable to dump DSPS memory (rc = %d).\n",
+				       __func__, ret);
+				goto dsps_ramdump_out;
+			}
+		}
+		if (drv->smem_ramdump_dev != NULL) {
+			ret = do_ramdump(drv->smem_ramdump_dev,
+				drv->smem_ramdump_segments,
+				ARRAY_SIZE(drv->smem_ramdump_segments));
+			if (ret < 0) {
+				pr_err("%s: Unable to dump smem memory (rc = %d).\n",
+				       __func__, ret);
+				goto dsps_ramdump_out;
+			}
+		}
+	}
+
+dsps_ramdump_out:
+	return ret;
 }
 
 static struct subsys_data dsps_ssrops = {
@@ -768,6 +860,8 @@
 		pr_err("%s: kzalloc fail.\n", __func__);
 		goto alloc_err;
 	}
+	atomic_set(&drv->crash_in_progress, 0);
+
 	drv->pdata = pdev->dev.platform_data;
 
 	drv->dev_class = class_create(THIS_MODULE, DRV_NAME);
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index 2cff7f0..7ac3f74 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -247,29 +247,6 @@
 		schedule_delayed_work_on(0, &dogwork_struct, delay_time);
 }
 
-static int msm_watchdog_remove(struct platform_device *pdev)
-{
-	if (enable) {
-		__raw_writel(0, msm_tmr0_base + WDT0_EN);
-		mb();
-		if (has_vic) {
-			free_irq(WDT0_ACCSCSSNBARK_INT, 0);
-		} else {
-			disable_percpu_irq(WDT0_ACCSCSSNBARK_INT);
-			if (!appsbark_fiq) {
-				free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
-						percpu_pdata);
-				free_percpu(percpu_pdata);
-			}
-		}
-		enable = 0;
-		/* In case we got suspended mid-exit */
-		__raw_writel(0, msm_tmr0_base + WDT0_EN);
-	}
-	printk(KERN_INFO "MSM Watchdog Exit - Deactivated\n");
-	return 0;
-}
-
 static irqreturn_t wdog_bark_handler(int irq, void *dev_id)
 {
 	unsigned long nanosec_rem;
@@ -445,7 +422,6 @@
 
 static struct platform_driver msm_watchdog_driver = {
 	.probe = msm_watchdog_probe,
-	.remove = msm_watchdog_remove,
 	.driver = {
 		.name = MODULE_NAME,
 		.owner = THIS_MODULE,
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 69e39df..ddfc906 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -273,6 +273,9 @@
 	if (ocmem_zone_init(pdev))
 		return -EBUSY;
 
+	if (ocmem_notifier_init())
+		return -EBUSY;
+
 	dev_info(dev, "initialized successfully\n");
 	return 0;
 }
diff --git a/arch/arm/mach-msm/ocmem_notifier.c b/arch/arm/mach-msm/ocmem_notifier.c
new file mode 100644
index 0000000..58ad3d9
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_notifier.c
@@ -0,0 +1,137 @@
+/* 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 <mach/ocmem_priv.h>
+#include <linux/hardirq.h>
+
+static unsigned notifier_threshold;
+
+/* Protect the notifier structure below */
+DEFINE_MUTEX(nc_lock);
+
+struct ocmem_notifier {
+	int owner;
+	struct atomic_notifier_head nc;
+	unsigned listeners;
+} notifiers[OCMEM_CLIENT_MAX];
+
+static int check_id(int id)
+{
+	return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
+}
+
+int check_notifier(int id)
+{
+	int ret = 0;
+
+	if (!check_id(id))
+		return 0;
+
+	mutex_lock(&nc_lock);
+	ret = notifiers[id].listeners;
+	mutex_unlock(&nc_lock);
+	return ret;
+}
+
+int ocmem_notifier_init(void)
+{
+	int id;
+	/* Maximum notifiers for each subsystem */
+	notifier_threshold = 1;
+	mutex_lock(&nc_lock);
+	for (id = 0; id < OCMEM_CLIENT_MAX; id++) {
+		notifiers[id].owner = id;
+		ATOMIC_INIT_NOTIFIER_HEAD(&notifiers[id].nc);
+		notifiers[id].listeners = 0;
+	}
+	mutex_unlock(&nc_lock);
+	return 0;
+}
+
+/* Broadcast a notification to listeners */
+int dispatch_notification(int id, enum ocmem_notif_type notif,
+				struct ocmem_buf *buf)
+{
+	int ret = 0;
+	struct ocmem_notifier *nc_hndl = NULL;
+	mutex_lock(&nc_lock);
+	nc_hndl = &notifiers[id];
+	if (nc_hndl->listeners == 0) {
+		/* Send an error so that the scheduler can clean up */
+		mutex_unlock(&nc_lock);
+		return -EINVAL;
+	}
+	ret = atomic_notifier_call_chain(&notifiers[id].nc, notif, buf);
+	mutex_unlock(&nc_lock);
+	return ret;
+}
+
+void *ocmem_notifier_register(int client_id, struct notifier_block *nb)
+{
+
+	int ret = 0;
+	struct ocmem_notifier *nc_hndl = NULL;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid Client id\n");
+		return NULL;
+	}
+
+	if (!nb) {
+		pr_err("ocmem: Invalid Notifier Block\n");
+		return NULL;
+	}
+
+	mutex_lock(&nc_lock);
+
+	nc_hndl = &notifiers[client_id];
+
+	if (nc_hndl->listeners >= notifier_threshold) {
+		pr_err("ocmem: Max notifiers already registered\n");
+		mutex_unlock(&nc_lock);
+		return NULL;
+	}
+
+	ret = atomic_notifier_chain_register(&nc_hndl->nc, nb);
+
+	if (ret < 0) {
+		mutex_unlock(&nc_lock);
+		return NULL;
+	}
+
+	nc_hndl->listeners++;
+	pr_info("ocmem: Notifier registered for %d\n", client_id);
+	mutex_unlock(&nc_lock);
+	return nc_hndl;
+}
+EXPORT_SYMBOL(ocmem_notifier_register);
+
+int ocmem_notifier_unregister(void *hndl, struct notifier_block *nb)
+{
+
+	int ret = 0;
+
+	struct ocmem_notifier *nc_hndl = (struct ocmem_notifier *) hndl;
+
+	if (!nc_hndl) {
+		pr_err("ocmem: Invalid notification handle\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&nc_lock);
+	ret = atomic_notifier_chain_unregister(&nc_hndl->nc, nb);
+	nc_hndl->listeners--;
+	mutex_unlock(&nc_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(ocmem_notifier_unregister);
diff --git a/arch/arm/mach-msm/pil-mba.c b/arch/arm/mach-msm/pil-mba.c
new file mode 100644
index 0000000..7405ab9
--- /dev/null
+++ b/arch/arm/mach-msm/pil-mba.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/elf.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/of.h>
+
+#include "peripheral-loader.h"
+
+#define RMB_MBA_COMMAND			0x08
+#define RMB_MBA_STATUS			0x0C
+#define RMB_PMI_META_DATA		0x10
+#define RMB_PMI_CODE_START		0x14
+#define RMB_PMI_CODE_LENGTH		0x18
+
+#define CMD_META_DATA_READY		0x1
+#define CMD_LOAD_READY			0x2
+
+#define STATUS_META_DATA_AUTH_SUCCESS	0x3
+#define STATUS_AUTH_COMPLETE		0x4
+#define STATUS_ERROR_MASK		BIT(31)
+
+#define AUTH_TIMEOUT_US			10000000
+#define PROXY_TIMEOUT_MS		10000
+#define POLL_INTERVAL_US		50
+
+struct mba_data {
+	void __iomem *reg_base;
+	void __iomem *metadata_base;
+	unsigned long metadata_phys;
+	struct pil_device *pil;
+	struct clk *xo;
+	u32 img_length;
+};
+
+static int pil_mba_make_proxy_votes(struct pil_desc *pil)
+{
+	int ret;
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable XO\n");
+		return ret;
+	}
+	return 0;
+}
+
+static void pil_mba_remove_proxy_votes(struct pil_desc *pil)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	clk_disable_unprepare(drv->xo);
+}
+
+static int pil_mba_init_image(struct pil_desc *pil,
+			      const u8 *metadata, size_t size)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	u32 status;
+	int ret;
+
+	/* Copy metadata to assigned shared buffer location */
+	memcpy(drv->metadata_base, metadata, size);
+
+	/* Initialize length counter to 0 */
+	writel_relaxed(0, drv->reg_base + RMB_PMI_CODE_LENGTH);
+	drv->img_length = 0;
+
+	/* Pass address of meta-data to the MBA and perform authentication */
+	writel_relaxed(drv->metadata_phys, drv->reg_base + RMB_PMI_META_DATA);
+	writel_relaxed(CMD_META_DATA_READY, drv->reg_base + RMB_MBA_COMMAND);
+	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
+		status == STATUS_META_DATA_AUTH_SUCCESS,
+		POLL_INTERVAL_US, AUTH_TIMEOUT_US);
+	if (ret)
+		dev_err(pil->dev, "MBA authentication timed out\n");
+
+	return ret;
+}
+
+static int pil_mba_verify_blob(struct pil_desc *pil, u32 phy_addr,
+			       size_t size)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+
+	/* Begin image authentication */
+	if (drv->img_length == 0) {
+		writel_relaxed(phy_addr, drv->reg_base + RMB_PMI_CODE_START);
+		writel_relaxed(CMD_LOAD_READY, drv->reg_base + RMB_MBA_COMMAND);
+	}
+	/* Increment length counter */
+	drv->img_length += size;
+	writel_relaxed(drv->img_length, drv->reg_base + RMB_PMI_CODE_LENGTH);
+
+	return readl_relaxed(drv->reg_base + RMB_MBA_STATUS)
+			& STATUS_ERROR_MASK;
+}
+
+static int pil_mba_auth(struct pil_desc *pil)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+	u32 status;
+
+	/* Wait for all segments to be authenticated or an error to occur */
+	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
+			status == STATUS_AUTH_COMPLETE ||
+			status & STATUS_ERROR_MASK,
+			50, AUTH_TIMEOUT_US);
+	if (ret)
+		return ret;
+
+	if (status & STATUS_ERROR_MASK)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int pil_mba_shutdown(struct pil_desc *pil)
+{
+	return 0;
+}
+
+static struct pil_reset_ops pil_mba_ops = {
+	.init_image = pil_mba_init_image,
+	.proxy_vote = pil_mba_make_proxy_votes,
+	.proxy_unvote = pil_mba_remove_proxy_votes,
+	.verify_blob = pil_mba_verify_blob,
+	.auth_and_reset = pil_mba_auth,
+	.shutdown = pil_mba_shutdown,
+};
+
+static int __devinit pil_mba_driver_probe(struct platform_device *pdev)
+{
+	struct mba_data *drv;
+	struct resource *res;
+	struct pil_desc *desc;
+	int ret;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, drv);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+	drv->reg_base = devm_ioremap(&pdev->dev, res->start,
+				     resource_size(res));
+	if (!drv->reg_base)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res) {
+		drv->metadata_base = devm_ioremap(&pdev->dev, res->start,
+						  resource_size(res));
+		if (!drv->metadata_base)
+			return -ENOMEM;
+		drv->metadata_phys = res->start;
+	}
+
+	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
+
+	ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
+				      &desc->name);
+	if (ret)
+		return ret;
+
+	of_property_read_string(pdev->dev.of_node, "qcom,depends-on",
+				      &desc->depends_on);
+
+	drv->xo = devm_clk_get(&pdev->dev, "xo");
+	if (IS_ERR(drv->xo))
+		return PTR_ERR(drv->xo);
+
+	desc->dev = &pdev->dev;
+	desc->ops = &pil_mba_ops;
+	desc->owner = THIS_MODULE;
+	desc->proxy_timeout = PROXY_TIMEOUT_MS;
+
+	drv->pil = msm_pil_register(desc);
+	if (IS_ERR(drv->pil))
+		return PTR_ERR(drv->pil);
+
+	return 0;
+}
+
+static int __devexit pil_mba_driver_exit(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id mba_match_table[] = {
+	{ .compatible = "qcom,pil-mba" },
+	{}
+};
+
+struct platform_driver pil_mba_driver = {
+	.probe = pil_mba_driver_probe,
+	.remove = __devexit_p(pil_mba_driver_exit),
+	.driver = {
+		.name = "pil-mba",
+		.of_match_table = mba_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pil_mba_init(void)
+{
+	return platform_driver_register(&pil_mba_driver);
+}
+module_init(pil_mba_init);
+
+static void __exit pil_mba_exit(void)
+{
+	platform_driver_unregister(&pil_mba_driver);
+}
+module_exit(pil_mba_exit);
+
+MODULE_DESCRIPTION("Support for modem boot using the Modem Boot Authenticator");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
new file mode 100644
index 0000000..e279f99
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/elf.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/clk.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+
+/* Q6 Register Offsets */
+#define QDSP6SS_RST_EVB			0x010
+
+/* AXI Halting Registers */
+#define MSS_Q6_HALT_BASE		0x180
+#define MSS_MODEM_HALT_BASE		0x200
+#define MSS_NC_HALT_BASE		0x280
+
+/* RMB Status Register Values */
+#define STATUS_PBL_SUCCESS		0x1
+#define STATUS_XPU_UNLOCKED		0x1
+#define STATUS_XPU_UNLOCKED_SCRIBBLED	0x2
+
+/* PBL/MBA interface registers */
+#define RMB_MBA_IMAGE			0x00
+#define RMB_PBL_STATUS			0x04
+#define RMB_MBA_STATUS			0x0C
+
+#define PBL_MBA_WAIT_TIMEOUT_US		100000
+#define PROXY_TIMEOUT_MS		10000
+#define POLL_INTERVAL_US		50
+
+static int pil_mss_power_up(struct device *dev)
+{
+	int ret;
+	struct q6v5_data *drv = dev_get_drvdata(dev);
+
+	ret = regulator_enable(drv->vreg);
+	if (ret)
+		dev_err(dev, "Failed to enable regulator.\n");
+
+	return ret;
+}
+
+static int pil_mss_power_down(struct device *dev)
+{
+	struct q6v5_data *drv = dev_get_drvdata(dev);
+
+	return regulator_disable(drv->vreg);
+}
+
+static int wait_for_mba_ready(struct device *dev)
+{
+	struct q6v5_data *drv = dev_get_drvdata(dev);
+	int ret;
+	u32 status;
+
+	/* Wait for PBL completion. */
+	ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status,
+		status != 0, POLL_INTERVAL_US, PBL_MBA_WAIT_TIMEOUT_US);
+	if (ret) {
+		dev_err(dev, "PBL boot timed out\n");
+		return ret;
+	}
+	if (status != STATUS_PBL_SUCCESS) {
+		dev_err(dev, "PBL returned unexpected status %d\n", status);
+		return -EINVAL;
+	}
+
+	/* Wait for MBA completion. */
+	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+		status != 0, POLL_INTERVAL_US, PBL_MBA_WAIT_TIMEOUT_US);
+	if (ret) {
+		dev_err(dev, "MBA boot timed out\n");
+		return ret;
+	}
+	if (status != STATUS_XPU_UNLOCKED &&
+	    status != STATUS_XPU_UNLOCKED_SCRIBBLED) {
+		dev_err(dev, "MBA returned unexpected status %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int pil_mss_shutdown(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_Q6_HALT_BASE);
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_MODEM_HALT_BASE);
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_NC_HALT_BASE);
+
+	/*
+	 * If the shutdown function is called before the reset function, clocks
+	 * and power will not be enabled yet. Enable them here so that register
+	 * writes performed during the shutdown succeed.
+	 */
+	if (drv->is_booted == false) {
+		pil_mss_power_up(pil->dev);
+		pil_q6v5_enable_clks(pil);
+	}
+	pil_q6v5_shutdown(pil);
+
+	pil_q6v5_disable_clks(pil);
+	pil_mss_power_down(pil->dev);
+
+	writel_relaxed(1, drv->restart_reg);
+
+	drv->is_booted = false;
+
+	return 0;
+}
+
+static int pil_mss_reset(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+
+	writel_relaxed(0, drv->restart_reg);
+	mb();
+
+	/*
+	 * Bring subsystem out of reset and enable required
+	 * regulators and clocks.
+	 */
+	ret = pil_mss_power_up(pil->dev);
+	if (ret)
+		goto err_power;
+
+	ret = pil_q6v5_enable_clks(pil);
+	if (ret)
+		goto err_clks;
+
+	/* Program Image Address */
+	if (drv->self_auth)
+		writel_relaxed(drv->start_addr, drv->rmb_base + RMB_MBA_IMAGE);
+	else
+		writel_relaxed((drv->start_addr >> 4) & 0x0FFFFFF0,
+				drv->reg_base + QDSP6SS_RST_EVB);
+
+	ret = pil_q6v5_reset(pil);
+	if (ret)
+		goto err_q6v5_reset;
+
+	/* Wait for MBA to start. Check for PBL and MBA errors while waiting. */
+	if (drv->self_auth) {
+		ret = wait_for_mba_ready(pil->dev);
+		if (ret)
+			goto err_auth;
+	}
+
+	drv->is_booted = true;
+
+	return 0;
+
+err_auth:
+	pil_q6v5_shutdown(pil);
+err_q6v5_reset:
+	pil_q6v5_disable_clks(pil);
+err_clks:
+	pil_mss_power_down(pil->dev);
+err_power:
+	return ret;
+}
+
+static struct pil_reset_ops pil_mss_ops = {
+	.init_image = pil_q6v5_init_image,
+	.proxy_vote = pil_q6v5_make_proxy_votes,
+	.proxy_unvote = pil_q6v5_remove_proxy_votes,
+	.auth_and_reset = pil_mss_reset,
+	.shutdown = pil_mss_shutdown,
+};
+
+static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
+{
+	struct q6v5_data *drv;
+	struct pil_desc *desc;
+	struct resource *res;
+	int ret;
+
+	desc = pil_q6v5_init(pdev);
+	if (IS_ERR(desc))
+		return PTR_ERR(desc);
+	drv = platform_get_drvdata(pdev);
+	if (drv == NULL)
+		return -ENODEV;
+
+	desc->ops = &pil_mss_ops;
+	desc->owner = THIS_MODULE;
+	desc->proxy_timeout = PROXY_TIMEOUT_MS;
+
+	of_property_read_u32(pdev->dev.of_node, "qcom,pil-self-auth",
+			     &drv->self_auth);
+	if (drv->self_auth) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+		drv->rmb_base = devm_ioremap(&pdev->dev, res->start,
+					     resource_size(res));
+		if (!drv->rmb_base)
+			return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+	drv->restart_reg = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+	if (!drv->restart_reg)
+		return -ENOMEM;
+
+	drv->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
+	if (IS_ERR(drv->vreg))
+		return PTR_ERR(drv->vreg);
+
+	ret = regulator_set_voltage(drv->vreg, 1150000, 1150000);
+	if (ret)
+		dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
+
+	ret = regulator_set_optimum_mode(drv->vreg, 100000);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to set regulator's mode.\n");
+		return ret;
+	}
+
+	drv->mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
+	if (IS_ERR(drv->mem_clk))
+		return PTR_ERR(drv->mem_clk);
+
+	drv->pil = msm_pil_register(desc);
+	if (IS_ERR(drv->pil))
+		return PTR_ERR(drv->pil);
+
+	return 0;
+}
+
+static int __devexit pil_mss_driver_exit(struct platform_device *pdev)
+{
+	struct q6v5_data *drv = platform_get_drvdata(pdev);
+	msm_pil_unregister(drv->pil);
+	return 0;
+}
+
+static struct of_device_id mss_match_table[] = {
+	{ .compatible = "qcom,pil-q6v5-mss" },
+	{}
+};
+
+static struct platform_driver pil_mss_driver = {
+	.probe = pil_mss_driver_probe,
+	.remove = __devexit_p(pil_mss_driver_exit),
+	.driver = {
+		.name = "pil-q6v5-mss",
+		.of_match_table = mss_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pil_mss_init(void)
+{
+	return platform_driver_register(&pil_mss_driver);
+}
+module_init(pil_mss_init);
+
+static void __exit pil_mss_exit(void)
+{
+	platform_driver_unregister(&pil_mss_driver);
+}
+module_exit(pil_mss_exit);
+
+MODULE_DESCRIPTION("Support for booting modem subsystems with QDSP6v5 Hexagon processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 6a96990..a362a7e3 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -121,9 +121,16 @@
 	ret = clk_prepare_enable(drv->bus_clk);
 	if (ret)
 		goto err_bus_clk;
+	if (drv->mem_clk) {
+		ret = clk_prepare_enable(drv->mem_clk);
+		if (ret)
+			goto err_mem_clk;
+	}
 
 	return 0;
 
+err_mem_clk:
+	clk_disable_unprepare(drv->bus_clk);
 err_bus_clk:
 	clk_disable_unprepare(drv->core_clk);
 err_core_clk:
@@ -139,6 +146,7 @@
 
 	clk_disable_unprepare(drv->bus_clk);
 	clk_disable_unprepare(drv->core_clk);
+	clk_disable_unprepare(drv->mem_clk);
 	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
 }
 EXPORT_SYMBOL(pil_q6v5_disable_clks);
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index a9a8d07..e0d7a20 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -24,8 +24,10 @@
 	struct clk *xo;
 	struct clk *bus_clk;
 	struct clk *core_clk;
+	struct clk *mem_clk;
 	void __iomem *axi_halt_base;
 	void __iomem *rmb_base;
+	void __iomem *restart_reg;
 	unsigned long start_addr;
 	struct regulator *vreg;
 	bool is_booted;
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index f6105af1..079ed9c 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -41,7 +41,7 @@
 }
 
 #ifdef CONFIG_MSM_SCM
-static int __init msm_pm_tz_boot_init(void)
+static int __devinit msm_pm_tz_boot_init(void)
 {
 	int flag = 0;
 	if (num_possible_cpus() == 1)
@@ -72,7 +72,7 @@
 		unsigned long entry) {}
 #endif
 
-static int __init msm_pm_boot_reset_vector_init(uint32_t *reset_vector)
+static int __devinit msm_pm_boot_reset_vector_init(uint32_t *reset_vector)
 {
 	if (!reset_vector)
 		return -ENODEV;
@@ -110,7 +110,7 @@
 }
 #define BOOT_REMAP_ENABLE  BIT(0)
 
-int __init msm_pm_boot_init(struct msm_pm_boot_platform_data *pdata)
+int __devinit msm_pm_boot_init(struct msm_pm_boot_platform_data *pdata)
 {
 	int ret = 0;
 	unsigned long entry;
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index 6f5ccbf..b485058 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -865,7 +865,8 @@
 	unsigned msg_id;
 	unsigned msg_length;
 #ifdef CONFIG_DEBUG_FS
-	uint16_t *ptr;
+	uint16_t *ptr16;
+	uint32_t *ptr32;
 	int ii;
 #endif /* CONFIG_DEBUG_FS */
 	void (*func)(void *, size_t);
@@ -909,12 +910,20 @@
 		return 0;
 	}
 #ifdef CONFIG_DEBUG_FS
-	if (rdump > 0) {
-		ptr = read_event_addr;
+	if (rdump > 0 &&
+		(dsp_addr >= (void *)(MSM_AD5_BASE + QDSP_RAMC_OFFSET))) {
+		ptr32 = read_event_addr;
+		pr_info("D->A\n");
+		pr_info("m_id = %x id = %x\n", module->id, msg_id);
+		for (ii = 0; ii < msg_length/4; ii++)
+			pr_info("%x ", ptr32[ii]);
+		pr_info("\n");
+	} else if (rdump > 0) {
+		ptr16 = read_event_addr;
 		pr_info("D->A\n");
 		pr_info("m_id = %x id = %x\n", module->id, msg_id);
 		for (ii = 0; ii < msg_length/2; ii++)
-			pr_info("%x ", ptr[ii]);
+			pr_info("%x ", ptr16[ii]);
 		pr_info("\n");
 	}
 #endif /* CONFIG_DEBUG_FS */
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
index 2011c42..03dd295 100644
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
@@ -387,9 +387,10 @@
 		msm_rpc_setup_req(&rhdr, audio->rpc_prog, audio->rpc_ver,
 				SND_VOC_REC_STOP_PROC);
 		rc = msm_rpc_write(audio->sndept, &rhdr, sizeof(rhdr));
-		wait_event_timeout(audio->wait, audio->stopped == 0,
+		rc = wait_event_timeout(audio->wait, audio->stopped == 1,
 				1 * HZ);
-		audio->stopped = 1;
+		if (rc == 0)
+			audio->stopped = 1;
 		wake_up(&audio->read_wait);
 		audmgr_disable(&audio->audmgr);
 		audio->enabled = 0;
@@ -456,7 +457,9 @@
 		if ((rec_status == RPC_VOC_REC_STAT_DATA) ||
 		(rec_status == RPC_VOC_REC_STAT_DONE)) {
 			if (datacb_data->pkt.fw_data.fw_ptr_status &&
-			be32_to_cpu(datacb_data->pkt.fw_data.rec_length)) {
+			be32_to_cpu(datacb_data->pkt.fw_data.rec_length) &&
+			be32_to_cpu(datacb_data->pkt.fw_data.rec_length)
+			<= MAX_FRAME_SIZE) {
 
 				MM_DBG("Copy FW link:rec_buf_size \
 				= 0x%08x, rec_length=0x%08x\n",
@@ -479,7 +482,10 @@
 				datacb_data->pkt.fw_data.rec_num_frames);
 				mutex_unlock(&audio->dsp_lock);
 			} else if (datacb_data->pkt.rw_data.rw_ptr_status &&
-			be32_to_cpu(datacb_data->pkt.rw_data.rec_length)) {
+			be32_to_cpu(datacb_data->pkt.rw_data.rec_length) &&
+			be32_to_cpu(datacb_data->pkt.rw_data.rec_length)
+			<= MAX_FRAME_SIZE) {
+
 				MM_DBG("Copy RW link:rec_buf_size \
 				=0x%08x, rec_length=0x%08x\n",
 				be32_to_cpu( \
@@ -500,6 +506,15 @@
 				be32_to_cpu(
 				datacb_data->pkt.rw_data.rec_num_frames);
 				mutex_unlock(&audio->dsp_lock);
+			} else {
+				MM_ERR("FW: ptr_status %d, rec_length=0x%08x,"
+				"RW: ptr_status %d, rec_length=0x%08x\n",
+				datacb_data->pkt.rw_data.fw_ptr_status, \
+				be32_to_cpu( \
+				datacb_data->pkt.fw_data.rec_length), \
+				datacb_data->pkt.rw_data.fw_ptr_status, \
+				be32_to_cpu( \
+				datacb_data->pkt.fw_data.rec_length));
 			}
 			if (rec_status != RPC_VOC_REC_STAT_DONE) {
 				/* Not end of record */
@@ -521,6 +536,7 @@
 			} else {
 				/* Indication record stopped gracefully */
 				MM_DBG("End Of Voice Record\n");
+				audio->stopped = 1;
 				wake_up(&audio->wait);
 			}
 		} else if (rec_status == RPC_VOC_REC_STAT_PAUSED) {
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
index db0a96e..0591a71 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
@@ -840,6 +840,10 @@
 				.step = SOFT_VOLUME_STEP,
 				.rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
 			};
+			if (softpause.rampingcurve == SOFT_PAUSE_CURVE_LINEAR)
+				softpause.step = SOFT_PAUSE_STEP_LINEAR;
+			if (softvol.rampingcurve == SOFT_VOLUME_CURVE_LINEAR)
+				softvol.step = SOFT_VOLUME_STEP_LINEAR;
 			audio->out_enabled = 1;
 			audio->out_needed = 1;
 			rc = q6asm_set_volume(audio->ac, audio->volume);
diff --git a/arch/arm/mach-msm/qdsp6v2/snddev_ecodec.c b/arch/arm/mach-msm/qdsp6v2/snddev_ecodec.c
index f75af16..0b38ec2 100644
--- a/arch/arm/mach-msm/qdsp6v2/snddev_ecodec.c
+++ b/arch/arm/mach-msm/qdsp6v2/snddev_ecodec.c
@@ -220,7 +220,7 @@
 		goto err_clk;
 	}
 
-	clk_enable(drv->ecodec_clk);
+	clk_prepare_enable(drv->ecodec_clk);
 
 	clk_reset(drv->ecodec_clk, CLK_RESET_DEASSERT);
 
@@ -260,7 +260,7 @@
 
 		pr_info("%s: closing all devices\n", __func__);
 
-		clk_disable(drv->ecodec_clk);
+		clk_disable_unprepare(drv->ecodec_clk);
 		aux_pcm_gpios_free();
 
 		afe_close(PCM_RX);
diff --git a/arch/arm/mach-msm/qdsp6v2/snddev_icodec.c b/arch/arm/mach-msm/qdsp6v2/snddev_icodec.c
index 41ef88c..e266d7a 100644
--- a/arch/arm/mach-msm/qdsp6v2/snddev_icodec.c
+++ b/arch/arm/mach-msm/qdsp6v2/snddev_icodec.c
@@ -325,7 +325,7 @@
 		goto error_invalid_freq;
 	}
 
-	clk_enable(drv->rx_osrclk);
+	clk_prepare_enable(drv->rx_osrclk);
 	drv->rx_bitclk = clk_get_sys(NULL, "i2s_spkr_bit_clk");
 	if (IS_ERR(drv->rx_bitclk))
 		pr_err("%s clock Error\n", __func__);
@@ -345,7 +345,7 @@
 		pr_err("ERROR setting m clock1\n");
 		goto error_adie;
 	}
-	clk_enable(drv->rx_bitclk);
+	clk_prepare_enable(drv->rx_bitclk);
 
 	if (icodec->data->voltage_on)
 		icodec->data->voltage_on();
@@ -412,7 +412,7 @@
 
 error_pamp:
 error_adie:
-	clk_disable(drv->rx_osrclk);
+	clk_disable_unprepare(drv->rx_osrclk);
 error_invalid_freq:
 
 	pr_err("%s: encounter error\n", __func__);
@@ -455,7 +455,7 @@
 		goto error_invalid_freq;
 	}
 
-	clk_enable(drv->tx_osrclk);
+	clk_prepare_enable(drv->tx_osrclk);
 	drv->tx_bitclk = clk_get_sys(NULL, "i2s_mic_bit_clk");
 	if (IS_ERR(drv->tx_bitclk))
 		pr_err("%s clock Error\n", __func__);
@@ -471,7 +471,7 @@
 	} else
 		trc =  clk_set_rate(drv->tx_bitclk, 8);
 
-	clk_enable(drv->tx_bitclk);
+	clk_prepare_enable(drv->tx_bitclk);
 
 	/* Enable ADIE */
 	trc = adie_codec_open(icodec->data->profile, &icodec->adie_path);
@@ -580,8 +580,8 @@
 	if (icodec->data->voltage_off)
 		icodec->data->voltage_off();
 
-	clk_disable(drv->rx_bitclk);
-	clk_disable(drv->rx_osrclk);
+	clk_disable_unprepare(drv->rx_bitclk);
+	clk_disable_unprepare(drv->rx_osrclk);
 
 	msm_snddev_rx_mclk_free();
 
@@ -611,8 +611,8 @@
 
 	afe_close(icodec->data->copp_id);
 
-	clk_disable(drv->tx_bitclk);
-	clk_disable(drv->tx_osrclk);
+	clk_disable_unprepare(drv->tx_bitclk);
+	clk_disable_unprepare(drv->tx_osrclk);
 
 	msm_snddev_tx_mclk_free();
 
diff --git a/arch/arm/mach-msm/qdsp6v2/snddev_mi2s.c b/arch/arm/mach-msm/qdsp6v2/snddev_mi2s.c
index 75a7411..4cf18b3 100644
--- a/arch/arm/mach-msm/qdsp6v2/snddev_mi2s.c
+++ b/arch/arm/mach-msm/qdsp6v2/snddev_mi2s.c
@@ -194,7 +194,7 @@
 		pr_err("ERROR setting osr clock\n");
 		return -ENODEV;
 	}
-	clk_enable(drv->tx_osrclk);
+	clk_prepare_enable(drv->tx_osrclk);
 
 	/* set up bit clk */
 	drv->tx_bitclk = clk_get_sys(NULL, "mi2s_bit_clk");
@@ -204,10 +204,10 @@
 	rc =  clk_set_rate(drv->tx_bitclk, 8);
 	if (IS_ERR_VALUE(rc)) {
 		pr_err("ERROR setting bit clock\n");
-		clk_disable(drv->tx_osrclk);
+		clk_disable_unprepare(drv->tx_osrclk);
 		return -ENODEV;
 	}
-	clk_enable(drv->tx_bitclk);
+	clk_prepare_enable(drv->tx_bitclk);
 
 	afe_config.mi2s.bitwidth = 16;
 
@@ -336,8 +336,8 @@
 
 error_invalid_data:
 
-	clk_disable(drv->tx_bitclk);
-	clk_disable(drv->tx_osrclk);
+	clk_disable_unprepare(drv->tx_bitclk);
+	clk_disable_unprepare(drv->tx_osrclk);
 	return -EINVAL;
 }
 
@@ -358,8 +358,8 @@
 		return -EIO;
 	}
 	afe_close(snddev_mi2s_data->copp_id);
-	clk_disable(mi2s_drv->tx_bitclk);
-	clk_disable(mi2s_drv->tx_osrclk);
+	clk_disable_unprepare(mi2s_drv->tx_bitclk);
+	clk_disable_unprepare(mi2s_drv->tx_osrclk);
 
 	mi2s_gpios_free();
 
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
index 614339b..a8773ea 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -27,7 +27,8 @@
 #include "usfcdev.h"
 
 /* The driver version*/
-#define DRV_VERSION "1.3.1"
+#define DRV_VERSION "1.4.0"
+#define USF_VERSION_ID 0x0140
 
 /* Standard timeout in the asynchronous ops */
 #define USF_TIMEOUT_JIFFIES (1*HZ) /* 1 sec */
@@ -108,8 +109,8 @@
 	uint16_t dev_ind;
 	/* Event types, supported by device */
 	uint16_t event_types;
-	/*  The device is "input" module registered client */
-	struct input_dev *input_if;
+	/*  The input devices are "input" module registered clients */
+	struct input_dev *input_ifs[USF_MAX_EVENT_IND];
 	/*  The event source */
 	int event_src;
 	/* Bitmap of types of events, conflicting to USF's ones */
@@ -118,6 +119,23 @@
 	uint16_t conflicting_event_filters;
 };
 
+struct usf_input_dev_type {
+	/* Input event type, supported by the input device */
+	uint16_t event_type;
+	/* Input device name */
+	const char *input_dev_name;
+	/* Input device registration function */
+	int (*prepare_dev)(uint16_t, struct usf_type *,
+			    struct us_input_info_type *,
+			   const char *);
+	/* Input event notification function */
+	void (*notify_event)(struct usf_type *,
+			     uint16_t,
+			     struct usf_event_type *
+			     );
+};
+
+
 /* The MAX number of the supported devices */
 #define MAX_DEVS_NUMBER	1
 
@@ -131,9 +149,197 @@
 /* The opened devices container */
 static int s_opened_devs[MAX_DEVS_NUMBER];
 
-#define USF_NAME_PREFIX "USF_"
+#define USF_NAME_PREFIX "usf_"
 #define USF_NAME_PREFIX_SIZE 4
 
+
+static struct input_dev *allocate_dev(uint16_t ind, const char *name)
+{
+	struct input_dev *in_dev = input_allocate_device();
+
+	if (in_dev == NULL) {
+		pr_err("%s: input_allocate_device() failed\n", __func__);
+	} else {
+		/* Common part configuration */
+		in_dev->name = name;
+		in_dev->phys = NULL;
+		in_dev->id.bustype = BUS_HOST;
+		in_dev->id.vendor  = 0x0001;
+		in_dev->id.product = 0x0001;
+		in_dev->id.version = USF_VERSION_ID;
+	}
+	return in_dev;
+}
+
+static int prepare_tsc_input_device(uint16_t ind,
+				struct usf_type *usf_info,
+				struct us_input_info_type *input_info,
+				const char *name)
+{
+	struct input_dev *in_dev = allocate_dev(ind, name);
+
+	if (in_dev == NULL)
+		return -ENOMEM;
+
+	usf_info->input_ifs[ind] = in_dev;
+	in_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	in_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_set_abs_params(in_dev, ABS_X,
+			     input_info->tsc_x_dim[MIN_IND],
+			     input_info->tsc_x_dim[MAX_IND],
+			     0, 0);
+	input_set_abs_params(in_dev, ABS_Y,
+			     input_info->tsc_y_dim[MIN_IND],
+			     input_info->tsc_y_dim[MAX_IND],
+			     0, 0);
+	input_set_abs_params(in_dev, ABS_DISTANCE,
+			     input_info->tsc_z_dim[MIN_IND],
+			     input_info->tsc_z_dim[MAX_IND],
+			     0, 0);
+
+	input_set_abs_params(in_dev, ABS_PRESSURE,
+			     input_info->tsc_pressure[MIN_IND],
+			     input_info->tsc_pressure[MAX_IND],
+			     0, 0);
+
+	input_set_abs_params(in_dev, ABS_TILT_X,
+			     input_info->tsc_x_tilt[MIN_IND],
+			     input_info->tsc_x_tilt[MAX_IND],
+			     0, 0);
+	input_set_abs_params(in_dev, ABS_TILT_Y,
+			     input_info->tsc_y_tilt[MIN_IND],
+			     input_info->tsc_y_tilt[MAX_IND],
+			     0, 0);
+
+	return 0;
+}
+
+static int prepare_mouse_input_device(uint16_t ind, struct usf_type *usf_info,
+			struct us_input_info_type *input_info,
+			const char *name)
+{
+	struct input_dev *in_dev = allocate_dev(ind, name);
+
+	if (in_dev == NULL)
+		return -ENOMEM;
+
+	usf_info->input_ifs[ind] = in_dev;
+	in_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+
+	in_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+						BIT_MASK(BTN_RIGHT) |
+						BIT_MASK(BTN_MIDDLE);
+	in_dev->relbit[0] =  BIT_MASK(REL_X) |
+				BIT_MASK(REL_Y) |
+				BIT_MASK(REL_Z);
+
+	return 0;
+}
+
+static int prepare_keyboard_input_device(
+					uint16_t ind,
+					struct usf_type *usf_info,
+					struct us_input_info_type *input_info,
+					const char *name)
+{
+	struct input_dev *in_dev = allocate_dev(ind, name);
+
+	if (in_dev == NULL)
+		return -ENOMEM;
+
+	usf_info->input_ifs[ind] = in_dev;
+	in_dev->evbit[0] |= BIT_MASK(EV_KEY);
+	/* All keys are permitted */
+	memset(in_dev->keybit, 0xff, sizeof(in_dev->keybit));
+
+	return 0;
+}
+
+static void notify_tsc_event(struct usf_type *usf_info,
+			     uint16_t if_ind,
+			     struct usf_event_type *event)
+
+{
+	struct input_dev *input_if = usf_info->input_ifs[if_ind];
+	struct point_event_type *pe = &(event->event_data.point_event);
+
+	input_report_abs(input_if, ABS_X, pe->coordinates[X_IND]);
+	input_report_abs(input_if, ABS_Y, pe->coordinates[Y_IND]);
+	input_report_abs(input_if, ABS_DISTANCE, pe->coordinates[Z_IND]);
+
+	input_report_abs(input_if, ABS_TILT_X, pe->inclinations[X_IND]);
+	input_report_abs(input_if, ABS_TILT_Y, pe->inclinations[Y_IND]);
+
+	input_report_abs(input_if, ABS_PRESSURE, pe->pressure);
+	input_report_key(input_if, BTN_TOUCH, !!(pe->pressure));
+
+	if (usf_info->event_src)
+		input_report_key(input_if, usf_info->event_src, 1);
+
+	input_sync(input_if);
+
+	pr_debug("%s: TSC event: xyz[%d;%d;%d], incl[%d;%d], pressure[%d]\n",
+		 __func__,
+		 pe->coordinates[X_IND],
+		 pe->coordinates[Y_IND],
+		 pe->coordinates[Z_IND],
+		 pe->inclinations[X_IND],
+		 pe->inclinations[Y_IND],
+		 pe->pressure);
+}
+
+static void notify_mouse_event(struct usf_type *usf_info,
+			       uint16_t if_ind,
+			       struct usf_event_type *event)
+{
+	struct input_dev *input_if = usf_info->input_ifs[if_ind];
+	struct mouse_event_type *me = &(event->event_data.mouse_event);
+
+	input_report_rel(input_if, REL_X, me->rels[X_IND]);
+	input_report_rel(input_if, REL_Y, me->rels[Y_IND]);
+	input_report_rel(input_if, REL_Z, me->rels[Z_IND]);
+
+	input_report_key(input_if, BTN_LEFT,
+			 me->buttons_states & USF_BUTTON_LEFT_MASK);
+	input_report_key(input_if, BTN_MIDDLE,
+			 me->buttons_states & USF_BUTTON_MIDDLE_MASK);
+	input_report_key(input_if, BTN_RIGHT,
+			 me->buttons_states & USF_BUTTON_RIGHT_MASK);
+
+	input_sync(input_if);
+
+	pr_debug("%s: mouse event: dx[%d], dy[%d], buttons_states[%d]\n",
+		 __func__, me->rels[X_IND],
+		 me->rels[Y_IND], me->buttons_states);
+}
+
+static void notify_key_event(struct usf_type *usf_info,
+			     uint16_t if_ind,
+			     struct usf_event_type *event)
+{
+	struct input_dev *input_if = usf_info->input_ifs[if_ind];
+	struct key_event_type *ke = &(event->event_data.key_event);
+
+	input_report_key(input_if, ke->key, ke->key_state);
+	input_sync(input_if);
+	pr_debug("%s: key event: key[%d], state[%d]\n",
+		 __func__,
+		 ke->key,
+		 ke->key_state);
+
+}
+
+static struct usf_input_dev_type s_usf_input_devs[] = {
+	{USF_TSC_EVENT, "usf_tsc",
+		prepare_tsc_input_device, notify_tsc_event},
+	{USF_TSC_PTR_EVENT, "usf_tsc_ptr",
+		prepare_tsc_input_device, notify_tsc_event},
+	{USF_MOUSE_EVENT, "usf_mouse",
+		prepare_mouse_input_device, notify_mouse_event},
+	{USF_KEYBOARD_EVENT, "usf_kb",
+		prepare_keyboard_input_device, notify_key_event},
+};
+
 static void usf_rx_cb(uint32_t opcode, uint32_t token,
 		      uint32_t *payload, void *priv)
 {
@@ -386,8 +592,8 @@
 				 struct us_input_info_type *input_info)
 {
 	int rc = 0;
-	struct input_dev *input_dev = NULL;
 	bool ret = true;
+	uint16_t ind = 0;
 
 	if ((usf_info == NULL) ||
 	    (input_info == NULL) ||
@@ -396,194 +602,75 @@
 		return -EINVAL;
 	}
 
-	if (usf_info->input_if != NULL) {
-		pr_err("%s: input_if is already allocated\n", __func__);
-		return -EFAULT;
-	}
-
-	input_dev = input_allocate_device();
-	if (input_dev == NULL) {
-		pr_err("%s: input_allocate_device() failed\n", __func__);
-		return -ENOMEM;
-	}
-
-	/* Common part configuration */
-	input_dev->name = (const char *)(usf_info->usf_tx.client_name);
-	input_dev->phys = NULL;
-	input_dev->id.bustype = BUS_HOST;
-	input_dev->id.vendor  = 0x0001;
-	input_dev->id.product = 0x0001;
-	input_dev->id.version = 0x0001;
-
-	if (input_info->event_types & USF_TSC_EVENT) {
-		/* TSC part configuration */
-		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-		input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-		input_set_abs_params(input_dev, ABS_X,
-				     input_info->tsc_x_dim[MIN_IND],
-				     input_info->tsc_x_dim[MAX_IND],
-				     0, 0);
-		input_set_abs_params(input_dev, ABS_Y,
-				     input_info->tsc_y_dim[MIN_IND],
-				     input_info->tsc_y_dim[MAX_IND],
-				     0, 0);
-		input_set_abs_params(input_dev, ABS_DISTANCE,
-				     input_info->tsc_z_dim[MIN_IND],
-				     input_info->tsc_z_dim[MAX_IND],
-				     0, 0);
-
-		input_set_abs_params(input_dev, ABS_PRESSURE,
-				     input_info->tsc_pressure[MIN_IND],
-				     input_info->tsc_pressure[MAX_IND], 0, 0);
-
-		input_set_abs_params(input_dev, ABS_TILT_X,
-				     input_info->tsc_x_tilt[MIN_IND],
-				     input_info->tsc_x_tilt[MAX_IND],
-				     0, 0);
-		input_set_abs_params(input_dev, ABS_TILT_Y,
-				     input_info->tsc_y_tilt[MIN_IND],
-				     input_info->tsc_y_tilt[MAX_IND],
-				     0, 0);
-	}
-
-	if (input_info->event_types & USF_MOUSE_EVENT) {
-		/* Mouse part configuration */
-		input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
-
-		input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
-							BIT_MASK(BTN_RIGHT) |
-							BIT_MASK(BTN_MIDDLE);
-		input_dev->relbit[0] =  BIT_MASK(REL_X) |
-					BIT_MASK(REL_Y) |
-					BIT_MASK(REL_Z);
-	}
-
-	if (input_info->event_types & USF_KEYBOARD_EVENT) {
-		/* Keyboard part configuration */
-		input_dev->evbit[0] |= BIT_MASK(EV_KEY);
-
-		/* All keys are permitted */
-		memset(input_dev->keybit, 0xff, sizeof(input_dev->keybit));
-	}
-
 	if (input_info->event_src < ARRAY_SIZE(s_event_src_map))
-		usf_info->event_src = s_event_src_map[input_info->event_src];
+		usf_info->event_src =
+			s_event_src_map[input_info->event_src];
 	else
 		usf_info->event_src = 0;
 
-	if (usf_info->event_src)
-		input_set_capability(input_dev, EV_KEY, usf_info->event_src);
+	for (ind = 0; ind < USF_MAX_EVENT_IND; ++ind) {
+		if (usf_info->input_ifs[ind] != NULL) {
+			pr_err("%s: input_if[%d] is already allocated\n",
+				__func__, ind);
+			return -EFAULT;
+		}
+		if ((input_info->event_types &
+			s_usf_input_devs[ind].event_type) &&
+		     s_usf_input_devs[ind].prepare_dev) {
+			rc = (*s_usf_input_devs[ind].prepare_dev)(
+				ind,
+				usf_info,
+				input_info,
+				s_usf_input_devs[ind].input_dev_name);
+			if (rc)
+				return rc;
 
-	rc = input_register_device(input_dev);
-	if (rc) {
-		pr_err("%s: input_register_device() failed; rc=%d\n",
-		       __func__, rc);
-		input_free_device(input_dev);
-	} else {
-		usf_info->input_if = input_dev;
-		usf_info->event_types = input_info->event_types;
-		pr_debug("%s: input device[%s] was registered\n",
-			__func__, input_dev->name);
-		ret = usf_register_conflicting_events(
-					input_info->conflicting_event_types);
-		if (ret)
-			usf_info->conflicting_event_types =
-				input_info->conflicting_event_types;
-	}
 
-	return rc;
+			if (usf_info->event_src)
+				input_set_capability(usf_info->input_ifs[ind],
+						     EV_KEY,
+						     usf_info->event_src);
+
+			rc = input_register_device(usf_info->input_ifs[ind]);
+			if (rc) {
+				pr_err("%s: input_reg_dev() failed; rc=%d\n",
+					__func__, rc);
+				input_free_device(usf_info->input_ifs[ind]);
+				usf_info->input_ifs[ind] = NULL;
+			} else {
+				usf_info->event_types |=
+					s_usf_input_devs[ind].event_type;
+				pr_debug("%s: input device[%s] was registered\n",
+					__func__,
+					s_usf_input_devs[ind].input_dev_name);
+			}
+		} /* supported event */
+	} /* event types loop */
+
+	ret = usf_register_conflicting_events(
+			input_info->conflicting_event_types);
+	if (ret)
+		usf_info->conflicting_event_types =
+			input_info->conflicting_event_types;
+
+	return 0;
 }
 
-static void notify_tsc_event(struct usf_type *usf_info,
-			     struct point_event_type *pe)
-{
-	struct input_dev *input_if = usf_info->input_if;
-
-	input_report_abs(input_if, ABS_X, pe->coordinates[X_IND]);
-	input_report_abs(input_if, ABS_Y, pe->coordinates[Y_IND]);
-	input_report_abs(input_if, ABS_DISTANCE, pe->coordinates[Z_IND]);
-
-	input_report_abs(input_if, ABS_TILT_X, pe->inclinations[X_IND]);
-	input_report_abs(input_if, ABS_TILT_Y, pe->inclinations[Y_IND]);
-
-	input_report_abs(input_if, ABS_PRESSURE, pe->pressure);
-	input_report_key(input_if, BTN_TOUCH, !!(pe->pressure));
-
-	if (usf_info->event_src)
-		input_report_key(input_if, usf_info->event_src, 1);
-
-	input_sync(input_if);
-
-	pr_debug("%s: TSC event: xyz[%d;%d;%d], incl[%d;%d], pressure[%d]\n",
-		 __func__,
-		 pe->coordinates[X_IND],
-		 pe->coordinates[Y_IND],
-		 pe->coordinates[Z_IND],
-		 pe->inclinations[X_IND],
-		 pe->inclinations[Y_IND],
-		 pe->pressure);
-}
-
-static void notify_mouse_event(struct input_dev *input_if,
-			       struct mouse_event_type *me)
-{
-	if (me == NULL) {
-		pr_err("%s: mouse event is NULL\n", __func__);
-		return;
-	}
-
-	input_report_rel(input_if, REL_X, me->rels[X_IND]);
-	input_report_rel(input_if, REL_Y, me->rels[Y_IND]);
-	input_report_rel(input_if, REL_Z, me->rels[Z_IND]);
-
-	input_report_key(input_if, BTN_LEFT,
-			 me->buttons_states & USF_BUTTON_LEFT_MASK);
-	input_report_key(input_if, BTN_MIDDLE,
-			 me->buttons_states & USF_BUTTON_MIDDLE_MASK);
-	input_report_key(input_if, BTN_RIGHT,
-			 me->buttons_states & USF_BUTTON_RIGHT_MASK);
-
-	input_sync(input_if);
-
-	pr_debug("%s: mouse event: dx[%d], dy[%d], buttons_states[%d]\n",
-		 __func__, me->rels[X_IND],
-		 me->rels[Y_IND], me->buttons_states);
-}
-
-static void notify_key_event(struct input_dev *input_if,
-			       struct key_event_type *ke)
-{
-	if (ke == NULL) {
-		pr_err("%s: key event is NULL\n", __func__);
-		return;
-	}
-
-	input_report_key(input_if, ke->key, ke->key_state);
-	input_sync(input_if);
-	pr_debug("%s: key event: key[%d], state[%d]\n",
-		 __func__,
-		 ke->key,
-		 ke->key_state);
-
-}
 
 static void handle_input_event(struct usf_type *usf_info,
 			       uint16_t event_counter,
 			       struct usf_event_type *event)
 {
-	struct input_dev *input_if = NULL;
 	uint16_t ind = 0;
 	uint16_t events_num = 0;
 	struct usf_event_type usf_events[USF_EVENTS_PORTION_SIZE];
 	int rc = 0;
 
-	if ((usf_info == NULL) || (usf_info->input_if == NULL) ||
+	if ((usf_info == NULL) ||
 	    (event == NULL) || (!event_counter)) {
 		return;
 	}
 
-	input_if = usf_info->input_if;
-
 	while (event_counter > 0) {
 		if (event_counter > USF_EVENTS_PORTION_SIZE) {
 			events_num = USF_EVENTS_PORTION_SIZE;
@@ -602,26 +689,17 @@
 		}
 		for (ind = 0; ind < events_num; ++ind) {
 			struct usf_event_type *p_event = &usf_events[ind];
-			if (p_event->event_type & USF_TSC_EVENT) {
-				struct point_event_type *pe =
-					&(p_event->event_data.point_event);
-				if (pe->coordinates_type ==
-					USF_PIX_COORDINATE)
-					notify_tsc_event(usf_info, pe);
-				else
-					pr_debug("%s: wrong coord type: %d",
-						__func__,
-						pe->coordinates_type);
-				continue;
-			}
-			if (p_event->event_type & USF_MOUSE_EVENT) {
-				notify_mouse_event(input_if,
-					&(p_event->event_data.mouse_event));
-				continue;
-			}
-			if (p_event->event_type & USF_KEYBOARD_EVENT)
-				notify_key_event(input_if,
-					&(p_event->event_data.key_event));
+			uint16_t if_ind = p_event->event_type_ind;
+
+			if ((if_ind >= USF_MAX_EVENT_IND) ||
+			    (usf_info->input_ifs[if_ind] == NULL))
+				continue; /* event isn't supported */
+
+			if (s_usf_input_devs[if_ind].notify_event)
+				(*s_usf_input_devs[if_ind].notify_event)(
+								usf_info,
+								if_ind,
+								p_event);
 		} /* loop in the portion */
 	} /* all events loop */
 }
@@ -1051,13 +1129,20 @@
 
 static void usf_release_input(struct usf_type *usf)
 {
-	if (usf->input_if != NULL) {
+	uint16_t ind = 0;
+
+	for (ind = 0; ind < USF_MAX_EVENT_IND; ++ind) {
+		if (usf->input_ifs[ind] == NULL)
+			continue;
+
 		usf_unregister_conflicting_events(
 						usf->conflicting_event_types);
 		usf->conflicting_event_types = 0;
-		input_unregister_device(usf->input_if);
-		usf->input_if = NULL;
-		pr_debug("%s input_unregister_device\n",  __func__);
+		input_unregister_device(usf->input_ifs[ind]);
+		usf->input_ifs[ind] = NULL;
+		pr_debug("%s input_unregister_device[%s]\n",
+			 __func__,
+			 s_usf_input_devs[ind].input_dev_name);
 	}
 } /* usf_release_input */
 
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
index d594405..46d6d94 100644
--- a/arch/arm/mach-msm/rpm_resources.h
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -102,6 +102,8 @@
 	unsigned int rpmrs_target_id[MSM_RPMRS_ID_LAST];
 };
 
+#if defined(CONFIG_MSM_RPM)
+
 int msm_rpmrs_set(int ctx, struct msm_rpm_iv_pair *req, int count);
 int msm_rpmrs_set_noirq(int ctx, struct msm_rpm_iv_pair *req, int count);
 int msm_rpmrs_set_bits_noirq(int ctx, struct msm_rpm_iv_pair *req, int count,
@@ -139,4 +141,74 @@
 void msm_rpmrs_show_resources(void);
 int msm_rpmrs_levels_init(struct msm_rpmrs_platform_data *data);
 
+#else
+
+static inline int msm_rpmrs_set(int ctx, struct msm_rpm_iv_pair *req,
+				int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_noirq(int ctx, struct msm_rpm_iv_pair *req,
+					int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_bits_noirq(int ctx, struct msm_rpm_iv_pair *req,
+			int count, int *mask)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_nosleep(
+	int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear(int ctx, struct msm_rpm_iv_pair *req,
+					int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear_noirq(int ctx, struct msm_rpm_iv_pair *req,
+						int count)
+{
+	return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear_nosleep(
+	int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+	return -ENODEV;
+}
+
+static inline struct msm_rpmrs_limits *msm_rpmrs_lowest_limits(
+	bool from_idle, enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
+	uint32_t sleep_us)
+{
+	return NULL;
+}
+
+static inline int msm_rpmrs_enter_sleep(uint32_t sclk_count,
+	struct msm_rpmrs_limits *limits, bool from_idle, bool notify_rpm)
+{
+	return -ENODEV;
+}
+
+static inline void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+		bool from_idle, bool notify_rpm, bool collapsed)
+{
+	return;
+}
+
+static inline int msm_rpmrs_levels_init(struct msm_rpmrs_platform_data *data)
+{
+	return -ENODEV;
+}
+
+#endif /* CONFIG_MSM_RPM */
+
 #endif /* __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H */
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index b9cba8c..8d567f8 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -76,6 +76,7 @@
 	struct wake_lock pa_wake_lock;		/* Packet Arrival Wake lock*/
 	struct work_struct packet_arrival_work;
 	struct spinlock pa_spinlock;
+	int wakelock_locked;
 } *smd_pkt_devp[NUM_SMD_PKT_PORTS];
 
 struct class *smd_pkt_classp;
@@ -233,16 +234,19 @@
 static void packet_arrival_worker(struct work_struct *work)
 {
 	struct smd_pkt_dev *smd_pkt_devp;
+	unsigned long flags;
 
 	smd_pkt_devp = container_of(work, struct smd_pkt_dev,
 				    packet_arrival_work);
 	mutex_lock(&smd_pkt_devp->ch_lock);
-	if (smd_pkt_devp->ch) {
+	spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
+	if (smd_pkt_devp->ch && smd_pkt_devp->wakelock_locked) {
 		D_READ("%s locking smd_pkt_dev id:%d wakelock\n",
 			__func__, smd_pkt_devp->i);
 		wake_lock_timeout(&smd_pkt_devp->pa_wake_lock,
 				  WAKELOCK_TIMEOUT);
 	}
+	spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
 	mutex_unlock(&smd_pkt_devp->ch_lock);
 }
 
@@ -398,6 +402,7 @@
 	if (smd_pkt_devp->poll_mode &&
 	    !smd_cur_packet_size(smd_pkt_devp->ch)) {
 		wake_unlock(&smd_pkt_devp->pa_wake_lock);
+		smd_pkt_devp->wakelock_locked = 0;
 		smd_pkt_devp->poll_mode = 0;
 		D_READ("%s unlocked smd_pkt_dev id:%d wakelock\n",
 			__func__, smd_pkt_devp->i);
@@ -570,10 +575,11 @@
 	}
 
 	/* here we have a packet of size sz ready */
-	wake_up(&smd_pkt_devp->ch_read_wait_queue);
 	spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
 	wake_lock(&smd_pkt_devp->pa_wake_lock);
+	smd_pkt_devp->wakelock_locked = 1;
 	spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
+	wake_up(&smd_pkt_devp->ch_read_wait_queue);
 	schedule_work(&smd_pkt_devp->packet_arrival_work);
 	D_READ("%s: wake_up smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
 }
@@ -907,6 +913,7 @@
 
 	smd_pkt_devp->has_reset = 0;
 	smd_pkt_devp->do_reset_notification = 0;
+	smd_pkt_devp->wakelock_locked = 0;
 	wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
 	D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
 		 __func__, smd_pkt_devp->i);
@@ -962,6 +969,7 @@
 		init_waitqueue_head(&smd_pkt_devp[i]->ch_write_wait_queue);
 		smd_pkt_devp[i]->is_open = 0;
 		smd_pkt_devp[i]->poll_mode = 0;
+		smd_pkt_devp[i]->wakelock_locked = 0;
 		init_waitqueue_head(&smd_pkt_devp[i]->ch_opened_wait_queue);
 
 		spin_lock_init(&smd_pkt_devp[i]->pa_spinlock);
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index a77efe0..2980811 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -238,7 +238,7 @@
 }
 #endif
 
-static int __init msm_spm_dev_probe(struct platform_device *pdev)
+static int __devinit msm_spm_dev_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	int cpu = 0;
@@ -374,12 +374,12 @@
 	return -EFAULT;
 }
 
-static __initdata struct of_device_id msm_spm_match_table[] = {
+static struct of_device_id msm_spm_match_table[] = {
 	{.compatible = "qcom,spm-v2"},
 	{},
 };
 
-static __initdata struct platform_driver msm_spm_device_driver = {
+static struct platform_driver msm_spm_device_driver = {
 	.probe = msm_spm_dev_probe,
 	.driver = {
 		.name = "spm-v2",
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 90948ea..266c8b4 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -28,6 +28,7 @@
 #include "ramdump.h"
 
 #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);
@@ -52,12 +53,37 @@
 static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
 					uint32_t new_state)
 {
+	char *smem_reset_reason;
+	char buffer[MAX_BUF_SIZE];
+	unsigned smem_reset_size;
+	unsigned size;
+
 	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);
diff --git a/drivers/char/diag/Kconfig b/drivers/char/diag/Kconfig
index 53df29b..8f8707f 100644
--- a/drivers/char/diag/Kconfig
+++ b/drivers/char/diag/Kconfig
@@ -32,10 +32,10 @@
 
 menu "HSIC support for DIAG"
 
-config DIAG_HSIC_PIPE
+config DIAG_BRIDGE_CODE
 	depends on USB_QCOM_DIAG_BRIDGE
 	default y
-	bool "Enable 9K DIAG traffic over HSIC"
+	bool "Enable QSC/9K DIAG traffic over SMUX/HSIC"
 	help
-	 HSIC Transport Layer for DIAG Router
+	 SMUX/HSIC Transport Layer for DIAG Router
 endmenu
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index 3181d29..ea75ffd 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DIAG_CHAR) := diagchar.o
 obj-$(CONFIG_DIAG_SDIO_PIPE) += diagfwd_sdio.o
-obj-$(CONFIG_DIAG_HSIC_PIPE) += diagfwd_hsic.o
+obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_hsic.o
+obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_smux.o
 diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 49d687d..7e7b514 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -41,6 +41,7 @@
 #define SDIO_DATA		4
 #define WCNSS_DATA		5
 #define HSIC_DATA		6
+#define SMUX_DATA		7
 #define MODEM_PROC		0
 #define APPS_PROC		1
 #define QDSP_PROC		2
@@ -254,24 +255,30 @@
 	struct diag_request *usb_read_mdm_ptr;
 	struct diag_request *write_ptr_mdm;
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+	/* SGLTE variables */
+	int lcid;
+	unsigned char *buf_in_smux;
+	int in_busy_smux;
+	int diag_smux_enabled;
+	/* HSIC variables */
 	unsigned char *buf_in_hsic;
-	unsigned char *usb_buf_mdm_out;
-	int hsic_initialized;
 	int hsic_ch;
 	int hsic_device_enabled;
 	int hsic_device_opened;
 	int hsic_suspend;
-	int read_len_mdm;
 	int in_busy_hsic_read_on_device;
 	int in_busy_hsic_write_on_device;
 	int in_busy_hsic_write;
 	int in_busy_hsic_read;
-	int usb_mdm_connected;
-	struct usb_diag_ch *mdm_ch;
-	struct workqueue_struct *diag_hsic_wq;
-	struct work_struct diag_read_mdm_work;
 	struct work_struct diag_read_hsic_work;
+	/* USB MDM channel variables */
+	int usb_mdm_connected;
+	int read_len_mdm;
+	unsigned char *usb_buf_mdm_out;
+	struct usb_diag_ch *mdm_ch;
+	struct workqueue_struct *diag_bridge_wq;
+	struct work_struct diag_read_mdm_work;
 	struct work_struct diag_disconnect_work;
 	struct work_struct diag_usb_read_complete_work;
 	struct diag_request *usb_read_mdm_ptr;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 58a8676..d6a6e66 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -32,8 +32,9 @@
 #ifdef CONFIG_DIAG_SDIO_PIPE
 #include "diagfwd_sdio.h"
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
 #include "diagfwd_hsic.h"
+#include "diagfwd_smux.h"
 #endif
 #include <linux/timer.h>
 
@@ -234,9 +235,9 @@
 	if (driver->logging_process_id == current->tgid) {
 		driver->logging_mode = USB_MODE;
 		diagfwd_connect();
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
 		diagfwd_cancel_hsic();
-		diagfwd_connect_hsic(0);
+		diagfwd_connect_bridge(0);
 #endif
 	}
 #endif /* DIAG over USB */
@@ -481,8 +482,8 @@
 #ifdef CONFIG_DIAG_SDIO_PIPE
 			driver->in_busy_sdio = 1;
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
-			diagfwd_disconnect_hsic(0);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+			diagfwd_disconnect_bridge(0);
 #endif
 		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
 							== MEMORY_DEVICE_MODE) {
@@ -509,22 +510,22 @@
 				queue_work(driver->diag_sdio_wq,
 					&(driver->diag_read_sdio_work));
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
-			diagfwd_connect_hsic(0);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+			diagfwd_connect_bridge(0);
 #endif
 		}
 #ifdef CONFIG_DIAG_OVER_USB
 		else if (temp == USB_MODE && driver->logging_mode
 							 == NO_LOGGING_MODE) {
 			diagfwd_disconnect();
-#ifdef CONFIG_DIAG_HSIC_PIPE
-			diagfwd_disconnect_hsic(0);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+			diagfwd_disconnect_bridge(0);
 #endif
 		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
 								== USB_MODE) {
 			diagfwd_connect();
-#ifdef CONFIG_DIAG_HSIC_PIPE
-			diagfwd_connect_hsic(0);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+			diagfwd_connect_bridge(0);
 #endif
 		} else if (temp == USB_MODE && driver->logging_mode
 							== MEMORY_DEVICE_MODE) {
@@ -552,16 +553,16 @@
 				queue_work(driver->diag_sdio_wq,
 					&(driver->diag_read_sdio_work));
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
 			diagfwd_cancel_hsic();
-			diagfwd_connect_hsic(0);
+			diagfwd_connect_bridge(0);
 #endif
 		} else if (temp == MEMORY_DEVICE_MODE &&
 				 driver->logging_mode == USB_MODE) {
 			diagfwd_connect();
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
 			diagfwd_cancel_hsic();
-			diagfwd_connect_hsic(0);
+			diagfwd_connect_bridge(0);
 #endif
 		}
 #endif /* DIAG over USB */
@@ -720,7 +721,7 @@
 			driver->in_busy_sdio = 0;
 		}
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
 		pr_debug("diag: Copy data to user space %d\n",
 			 driver->in_busy_hsic_write_on_device);
 		if (driver->in_busy_hsic_write_on_device == 1) {
@@ -898,7 +899,7 @@
 			}
 		}
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
 		/* send masks to 9k too */
 		if (driver->hsic_ch && (payload_size > 0)) {
 			/* wait sending mask updates if HSIC ch not ready */
@@ -1199,6 +1200,18 @@
 inline void diag_sdio_fn(int type) {}
 #endif
 
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+void diag_bridge_fn(int type)
+{
+	if (type == INIT)
+		diagfwd_bridge_init();
+	else if (type == EXIT)
+		diagfwd_bridge_exit();
+}
+#else
+inline void diag_bridge_fn(int type) {}
+#endif
+
 static int __init diagchar_init(void)
 {
 	dev_t dev;
@@ -1243,9 +1256,7 @@
 		diagfwd_cntl_init();
 		driver->dci_state = diag_dci_init();
 		diag_sdio_fn(INIT);
-#ifdef CONFIG_DIAG_HSIC_PIPE
-		diagfwd_hsic_init();
-#endif
+		diag_bridge_fn(INIT);
 		pr_debug("diagchar initializing ..\n");
 		driver->num = 1;
 		driver->name = ((void *)driver) + sizeof(struct diagchar_dev);
@@ -1279,9 +1290,7 @@
 	diagfwd_exit();
 	diagfwd_cntl_exit();
 	diag_sdio_fn(EXIT);
-#ifdef CONFIG_DIAG_HSIC_PIPE
-	diagfwd_hsic_exit();
-#endif
+	diag_bridge_fn(EXIT);
 	return -1;
 }
 
@@ -1294,9 +1303,7 @@
 	diagfwd_exit();
 	diagfwd_cntl_exit();
 	diag_sdio_fn(EXIT);
-#ifdef CONFIG_DIAG_HSIC_PIPE
-	diagfwd_hsic_exit();
-#endif
+	diag_bridge_fn(EXIT);
 	diag_debugfs_cleanup();
 	diagchar_cleanup();
 	printk(KERN_INFO "done diagchar exit\n");
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 4ac2643..83d65b1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -49,7 +49,7 @@
 unsigned char diag_debug_buf[1024];
 static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
 struct diag_master_table entry;
-smd_channel_t *ch_temp, *chqdsp_temp, *ch_wcnss_temp;
+smd_channel_t *ch_temp = NULL, *chqdsp_temp = NULL, *ch_wcnss_temp = NULL;
 int diag_event_num_bytes;
 int diag_event_config;
 struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
@@ -300,12 +300,12 @@
 				&(driver->diag_read_sdio_work));
 		}
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
 		else if (proc_num == HSIC_DATA) {
 			driver->in_busy_hsic_read = 0;
 			driver->in_busy_hsic_write_on_device = 0;
 			if (driver->hsic_ch)
-				queue_work(driver->diag_hsic_wq,
+				queue_work(driver->diag_bridge_wq,
 					&(driver->diag_read_hsic_work));
 		}
 #endif
@@ -352,7 +352,7 @@
 						"while USB write\n");
 		}
 #endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
 		else if (proc_num == HSIC_DATA) {
 			if (driver->hsic_device_enabled) {
 				write_ptr->buf = buf;
@@ -360,6 +360,10 @@
 			} else
 				pr_err("diag: Incorrect hsic data "
 						"while USB write\n");
+		} else if (proc_num == SMUX_DATA) {
+				write_ptr->buf = buf;
+				pr_debug("diag: writing SMUX data\n");
+				err = usb_diag_write(driver->mdm_ch, write_ptr);
 		}
 #endif
 		APPEND_DEBUG('d');
@@ -922,8 +926,10 @@
 {
 	uint16_t subsys_cmd_code;
 	int subsys_id, ssid_first, ssid_last, ssid_range;
-	int packet_type = 1, i, cmd_code, rt_mask;
+	int packet_type = 1, i, cmd_code;
+	int rt_mask, rt_first_ssid, rt_last_ssid, rt_mask_size;
 	unsigned char *temp = buf;
+	uint8_t *rt_mask_ptr;
 	int data_type;
 #if defined(CONFIG_DIAG_OVER_USB)
 	int payload_length;
@@ -983,6 +989,38 @@
 			return 0;
 		}
 #endif
+	} /* Get runtime message mask  */
+	else if ((*buf == 0x7d) && (*(buf+1) == 0x3)) {
+		ssid_first = *(uint16_t *)(buf + 2);
+		ssid_last = *(uint16_t *)(buf + 4);
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (!(driver->ch) && chk_apps_only()) {
+			driver->apps_rsp_buf[0] = 0x7d;
+			driver->apps_rsp_buf[1] = 0x3;
+			*(uint16_t *)(driver->apps_rsp_buf+2) = ssid_first;
+			*(uint16_t *)(driver->apps_rsp_buf+4) = ssid_last;
+			driver->apps_rsp_buf[6] = 0x1; /* Success Status */
+			driver->apps_rsp_buf[7] = 0x0;
+			rt_mask_ptr = driver->msg_masks;
+			while (*(uint32_t *)(rt_mask_ptr + 4)) {
+				rt_first_ssid = *(uint32_t *)rt_mask_ptr;
+				rt_mask_ptr += 4;
+				rt_last_ssid = *(uint32_t *)rt_mask_ptr;
+				rt_mask_ptr += 4;
+				if (ssid_first == rt_first_ssid && ssid_last ==
+								 rt_last_ssid) {
+					rt_mask_size = 4 * (rt_last_ssid -
+							 rt_first_ssid + 1);
+					memcpy(driver->apps_rsp_buf+8,
+						 rt_mask_ptr, rt_mask_size);
+					ENCODE_RSP_AND_SEND(8+rt_mask_size-1);
+					return 0;
+				}
+				ptr += MAX_SSID_PER_RANGE*4;
+			}
+		} else
+			buf = temp;
+#endif
 	} /* Set runtime message mask  */
 	else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
 		ssid_first = *(uint16_t *)(buf + 2);
@@ -1695,7 +1733,8 @@
 		driver->ch = 0;
 		return;
 	} else if (event == SMD_EVENT_OPEN) {
-		driver->ch = ch_temp;
+		if (ch_temp)
+			driver->ch = ch_temp;
 	}
 	queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
 }
@@ -1709,7 +1748,8 @@
 		driver->chqdsp = 0;
 		return;
 	} else if (event == SMD_EVENT_OPEN) {
-		driver->chqdsp = chqdsp_temp;
+		if (chqdsp_temp)
+			driver->chqdsp = chqdsp_temp;
 	}
 	queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
 }
@@ -1723,7 +1763,8 @@
 		driver->ch_wcnss = 0;
 		return;
 	} else if (event == SMD_EVENT_OPEN) {
-		driver->ch_wcnss = ch_wcnss_temp;
+		if (ch_wcnss_temp)
+			driver->ch_wcnss = ch_wcnss_temp;
 	}
 	queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
 }
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index a3c6f26..d54d3dc 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -19,6 +19,7 @@
 #include <linux/workqueue.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
+#include <linux/smux.h>
 #include <asm/current.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <mach/usbdiag.h>
@@ -28,6 +29,7 @@
 #include "diagchar.h"
 #include "diagfwd.h"
 #include "diagfwd_hsic.h"
+#include "diagfwd_smux.h"
 
 static void diag_read_hsic_work_fn(struct work_struct *work)
 {
@@ -71,7 +73,8 @@
 	 * the next read
 	 */
 	if (!driver->in_busy_hsic_read)
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+		queue_work(driver->diag_bridge_wq,
+				 &driver->diag_read_hsic_work);
 }
 
 static void diag_hsic_read_complete_callback(void *ctxt, char *buf,
@@ -114,7 +117,8 @@
 	if (!driver->in_busy_hsic_write_on_device && ((driver->logging_mode
 			== MEMORY_DEVICE_MODE) || (driver->usb_mdm_connected &&
 						    !driver->hsic_suspend)))
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+		queue_work(driver->diag_bridge_wq,
+				 &driver->diag_read_hsic_work);
 }
 
 static void diag_hsic_write_complete_callback(void *ctxt, char *buf,
@@ -132,7 +136,7 @@
 		pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
 
 	if (driver->usb_mdm_connected)
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+		queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
 }
 
 static int diag_hsic_suspend(void *ctxt)
@@ -157,7 +161,8 @@
 
 	if (!driver->in_busy_hsic_write_on_device && (driver->logging_mode
 			== MEMORY_DEVICE_MODE || driver->usb_mdm_connected))
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+		queue_work(driver->diag_bridge_wq,
+			 &driver->diag_read_hsic_work);
 }
 
 static struct diag_bridge_ops hsic_diag_bridge_ops = {
@@ -209,42 +214,48 @@
 	return 0;
 }
 
-/* diagfwd_connect_hsic is called when the USB mdm channel is connected */
-int diagfwd_connect_hsic(int process_cable)
+/* diagfwd_connect_bridge is called when the USB mdm channel is connected */
+int diagfwd_connect_bridge(int process_cable)
 {
 	int err;
 
-	pr_debug("DIAG in %s\n", __func__);
+	pr_debug("diag: in %s\n", __func__);
 
 	/* If the usb cable is being connected */
 	if (process_cable) {
 		err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE,
 			N_MDM_READ);
 		if (err)
-			pr_err("DIAG: unable to alloc USB req on mdm"
+			pr_err("diag: unable to alloc USB req on mdm"
 				" ch err:%d\n", err);
 
 		driver->usb_mdm_connected = 1;
 	}
 
-	driver->in_busy_hsic_write_on_device = 0;
-	driver->in_busy_hsic_read_on_device = 0;
-	driver->in_busy_hsic_write = 0;
-	driver->in_busy_hsic_read = 0;
+	if (driver->hsic_device_enabled) {
+		driver->in_busy_hsic_write_on_device = 0;
+		driver->in_busy_hsic_read_on_device = 0;
+		driver->in_busy_hsic_write = 0;
+		driver->in_busy_hsic_read = 0;
+	} else if (driver->diag_smux_enabled) {
+		driver->in_busy_smux = 0;
+		diagfwd_connect_smux();
+		return 0;
+	}
 
 	/* If the hsic (diag_bridge) platform device is not open */
 	if (driver->hsic_device_enabled) {
 		if (!driver->hsic_device_opened) {
 			err = diag_bridge_open(&hsic_diag_bridge_ops);
 			if (err) {
-				pr_err("DIAG: HSIC channel open error: %d\n",
+				pr_err("diag: HSIC channel open error: %d\n",
 					err);
 			} else {
-				pr_debug("DIAG: opened HSIC channel\n");
+				pr_debug("diag: opened HSIC channel\n");
 				driver->hsic_device_opened = 1;
 			}
 		} else {
-			pr_debug("DIAG: HSIC channel already open\n");
+			pr_debug("diag: HSIC channel already open\n");
 		}
 
 		/*
@@ -256,24 +267,25 @@
 
 		/* Poll USB mdm channel to check for data */
 		if (driver->logging_mode == USB_MODE)
-			queue_work(driver->diag_hsic_wq,
+			queue_work(driver->diag_bridge_wq,
 					&driver->diag_read_mdm_work);
 
 		/* Poll HSIC channel to check for data */
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+		queue_work(driver->diag_bridge_wq,
+				 &driver->diag_read_hsic_work);
 	} else {
 		/* The hsic device driver has not yet been enabled */
-		pr_info("DIAG: HSIC channel not yet enabled\n");
+		pr_info("diag: HSIC channel not yet enabled\n");
 	}
 
 	return 0;
 }
 
 /*
- * diagfwd_disconnect_hsic is called when the USB mdm channel
+ * diagfwd_disconnect_bridge is called when the USB mdm channel
  * is disconnected
  */
-int diagfwd_disconnect_hsic(int process_cable)
+int diagfwd_disconnect_bridge(int process_cable)
 {
 	pr_debug("DIAG in %s\n", __func__);
 
@@ -284,12 +296,19 @@
 	}
 
 	if (driver->logging_mode != MEMORY_DEVICE_MODE) {
-		driver->in_busy_hsic_write_on_device = 1;
-		driver->in_busy_hsic_read_on_device = 1;
-		driver->in_busy_hsic_write = 1;
-		driver->in_busy_hsic_read = 1;
-		/* Turn off communication over usb mdm and hsic */
-		return diag_hsic_close();
+		if (driver->hsic_device_enabled) {
+			driver->in_busy_hsic_write_on_device = 1;
+			driver->in_busy_hsic_read_on_device = 1;
+			driver->in_busy_hsic_write = 1;
+			driver->in_busy_hsic_read = 1;
+			/* Turn off communication over usb mdm and hsic */
+			return diag_hsic_close();
+		} else if (driver->diag_smux_enabled) {
+			driver->in_busy_smux = 1;
+			driver->lcid = LCID_INVALID;
+			/* Turn off communication over usb mdm and smux */
+			msm_smux_close(LCID_VALID);
+		}
 	}
 	return 0;
 }
@@ -313,18 +332,23 @@
 	APPEND_DEBUG('q');
 
 	/* Read data from the hsic */
-	queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+	queue_work(driver->diag_bridge_wq, &driver->diag_read_hsic_work);
 
 	return 0;
 }
 
 /* Called after the asychronous usb_diag_read() on mdm channel is complete */
-static int diagfwd_read_complete_hsic(struct diag_request *diag_read_ptr)
+static int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
 {
 	/* The read of the usb driver on the mdm (not hsic) has completed */
 	driver->in_busy_hsic_read_on_device = 0;
 	driver->read_len_mdm = diag_read_ptr->actual;
 
+	if (driver->diag_smux_enabled) {
+		diagfwd_read_complete_smux();
+		return 0;
+	}
+	/* If SMUX not enabled, check for HSIC */
 	if (!driver->hsic_ch) {
 		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
 		return 0;
@@ -366,30 +390,34 @@
 	 * hsic channel
 	 */
 	if (!driver->in_busy_hsic_write)
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+		queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
 
 	return 0;
 }
 
-static void diagfwd_hsic_notifier(void *priv, unsigned event,
+static void diagfwd_bridge_notifier(void *priv, unsigned event,
 					struct diag_request *d_req)
 {
 	switch (event) {
 	case USB_DIAG_CONNECT:
-		diagfwd_connect_hsic(1);
+		diagfwd_connect_bridge(1);
 		break;
 	case USB_DIAG_DISCONNECT:
-		queue_work(driver->diag_hsic_wq, &driver->diag_disconnect_work);
+		queue_work(driver->diag_bridge_wq,
+			 &driver->diag_disconnect_work);
 		break;
 	case USB_DIAG_READ_DONE:
-		queue_work(driver->diag_hsic_wq,
+		queue_work(driver->diag_bridge_wq,
 				&driver->diag_usb_read_complete_work);
 		break;
 	case USB_DIAG_WRITE_DONE:
-		diagfwd_write_complete_hsic();
+		if (driver->hsic_device_enabled)
+			diagfwd_write_complete_hsic();
+		else if (driver->diag_smux_enabled)
+			diagfwd_write_complete_smux();
 		break;
 	default:
-		pr_err("DIAG in %s: Unknown event from USB diag:%u\n",
+		pr_err("diag: in %s: Unknown event from USB diag:%u\n",
 			__func__, event);
 		break;
 	}
@@ -397,16 +425,33 @@
 
 static void diag_usb_read_complete_fn(struct work_struct *w)
 {
-	diagfwd_read_complete_hsic(driver->usb_read_mdm_ptr);
+	diagfwd_read_complete_bridge(driver->usb_read_mdm_ptr);
 }
 
 static void diag_disconnect_work_fn(struct work_struct *w)
 {
-	diagfwd_disconnect_hsic(1);
+	diagfwd_disconnect_bridge(1);
 }
 
 static void diag_read_mdm_work_fn(struct work_struct *work)
 {
+	int ret;
+	if (driver->diag_smux_enabled) {
+		if (driver->lcid && driver->usb_buf_mdm_out &&
+					 (driver->read_len_mdm > 0)) {
+			ret = msm_smux_write(driver->lcid,  NULL,
+		 driver->usb_buf_mdm_out, driver->read_len_mdm);
+			if (ret)
+				pr_err("diag: writing to SMUX ch, r = %d,"
+					"lcid = %d\n", ret, driver->lcid);
+		}
+		driver->usb_read_mdm_ptr->buf = driver->usb_buf_mdm_out;
+		driver->usb_read_mdm_ptr->length = USB_MAX_OUT_BUF;
+		usb_diag_read(driver->mdm_ch, driver->usb_read_mdm_ptr);
+		return;
+	}
+
+	/* if SMUX not enabled, check for HSIC */
 	if (!driver->hsic_ch) {
 		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
 		return;
@@ -434,7 +479,8 @@
 	 * queue up the reading of data from the mdm channel
 	 */
 	if (!driver->in_busy_hsic_read_on_device)
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+		queue_work(driver->diag_bridge_wq,
+			 &driver->diag_read_mdm_work);
 }
 
 static int diag_hsic_probe(struct platform_device *pdev)
@@ -442,31 +488,10 @@
 	int err = 0;
 	pr_debug("diag: in %s\n", __func__);
 	if (!driver->hsic_device_enabled) {
-		driver->read_len_mdm = 0;
 		if (driver->buf_in_hsic == NULL)
 			driver->buf_in_hsic = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
-		if (driver->buf_in_hsic == NULL)
-			goto err;
-		if (driver->usb_buf_mdm_out  == NULL)
-			driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
-								 GFP_KERNEL);
-		if (driver->usb_buf_mdm_out == NULL)
-			goto err;
-		if (driver->write_ptr_mdm == NULL)
-			driver->write_ptr_mdm = kzalloc(
-			sizeof(struct diag_request), GFP_KERNEL);
-		if (driver->write_ptr_mdm == NULL)
-			goto err;
-		if (driver->usb_read_mdm_ptr == NULL)
-			driver->usb_read_mdm_ptr = kzalloc(
-			sizeof(struct diag_request), GFP_KERNEL);
-		if (driver->usb_read_mdm_ptr == NULL)
-			goto err;
-#ifdef CONFIG_DIAG_OVER_USB
-		INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
-#endif
 		INIT_WORK(&(driver->diag_read_hsic_work),
-						 diag_read_hsic_work_fn);
+					 diag_read_hsic_work_fn);
 		driver->hsic_device_enabled = 1;
 	}
 
@@ -495,25 +520,16 @@
 
 		if (driver->usb_mdm_connected) {
 			/* Poll USB mdm channel to check for data */
-			queue_work(driver->diag_hsic_wq,
+			queue_work(driver->diag_bridge_wq,
 					 &driver->diag_read_mdm_work);
 		}
 
 		/* Poll HSIC channel to check for data */
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+		queue_work(driver->diag_bridge_wq,
+				 &driver->diag_read_hsic_work);
 	}
 
 	return err;
-err:
-	pr_err("DIAG could not initialize buf for HSIC\n");
-	kfree(driver->buf_in_hsic);
-	kfree(driver->usb_buf_mdm_out);
-	kfree(driver->write_ptr_mdm);
-	kfree(driver->usb_read_mdm_ptr);
-	if (driver->diag_hsic_wq)
-		destroy_workqueue(driver->diag_hsic_wq);
-
-	return -ENOMEM;
 }
 
 static int diag_hsic_remove(struct platform_device *pdev)
@@ -550,55 +566,93 @@
 		   },
 };
 
-void diagfwd_hsic_init(void)
+void diagfwd_bridge_init(void)
 {
 	int ret;
 
-	pr_debug("DIAG in %s\n", __func__);
+	pr_debug("diag: in %s\n", __func__);
+	driver->diag_bridge_wq = create_singlethread_workqueue(
+							"diag_bridge_wq");
+	driver->read_len_mdm = 0;
+	if (driver->usb_buf_mdm_out  == NULL)
+		driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
+							 GFP_KERNEL);
+	if (driver->usb_buf_mdm_out == NULL)
+		goto err;
+	if (driver->write_ptr_mdm == NULL)
+		driver->write_ptr_mdm = kzalloc(
+		sizeof(struct diag_request), GFP_KERNEL);
+	if (driver->write_ptr_mdm == NULL)
+		goto err;
+	if (driver->usb_read_mdm_ptr == NULL)
+		driver->usb_read_mdm_ptr = kzalloc(
+		sizeof(struct diag_request), GFP_KERNEL);
+	if (driver->usb_read_mdm_ptr == NULL)
+		goto err;
 
-	driver->diag_hsic_wq = create_singlethread_workqueue("diag_hsic_wq");
+#ifdef CONFIG_DIAG_OVER_USB
+	INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
+#endif
 	INIT_WORK(&(driver->diag_disconnect_work), diag_disconnect_work_fn);
 	INIT_WORK(&(driver->diag_usb_read_complete_work),
 			diag_usb_read_complete_fn);
-
 #ifdef CONFIG_DIAG_OVER_USB
-	driver->mdm_ch = usb_diag_open(DIAG_MDM, driver, diagfwd_hsic_notifier);
+	driver->mdm_ch = usb_diag_open(DIAG_MDM, driver,
+						 diagfwd_bridge_notifier);
 	if (IS_ERR(driver->mdm_ch)) {
-		pr_err("DIAG Unable to open USB diag MDM channel\n");
+		pr_err("diag: Unable to open USB diag MDM channel\n");
 		goto err;
 	}
 #endif
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+	INIT_WORK(&(driver->diag_disconnect_work), diag_disconnect_work_fn);
+	INIT_WORK(&(driver->diag_usb_read_complete_work),
+			diag_usb_read_complete_fn);
+	/* register HSIC device */
 	ret = platform_driver_register(&msm_hsic_ch_driver);
 	if (ret)
-		pr_err("DIAG could not register HSIC device, ret: %d\n", ret);
-	else
-		driver->hsic_initialized = 1;
-
+		pr_err("diag: could not register HSIC device, ret: %d\n", ret);
+	/* register SMUX device */
+	ret = platform_driver_register(&msm_diagfwd_smux_driver);
+	if (ret)
+		pr_err("diag: could not register SMUX device, ret: %d\n", ret);
+#endif
 	return;
 err:
-	pr_err("DIAG could not initialize for HSIC execution\n");
-}
-
-void diagfwd_hsic_exit(void)
-{
-	pr_debug("DIAG in %s\n", __func__);
-
-	if (driver->hsic_initialized)
-		diag_hsic_close();
-
-#ifdef CONFIG_DIAG_OVER_USB
-	if (driver->usb_mdm_connected)
-		usb_diag_free_req(driver->mdm_ch);
-#endif
-	platform_driver_unregister(&msm_hsic_ch_driver);
-#ifdef CONFIG_DIAG_OVER_USB
-	usb_diag_close(driver->mdm_ch);
-#endif
-	kfree(driver->buf_in_hsic);
+	pr_err("diag: Could not initialize for bridge forwarding\n");
 	kfree(driver->usb_buf_mdm_out);
 	kfree(driver->write_ptr_mdm);
 	kfree(driver->usb_read_mdm_ptr);
-	destroy_workqueue(driver->diag_hsic_wq);
+	if (driver->diag_bridge_wq)
+		destroy_workqueue(driver->diag_bridge_wq);
 
-	driver->hsic_device_enabled = 0;
+	return;
+}
+
+void diagfwd_bridge_exit(void)
+{
+	pr_debug("diag: in %s\n", __func__);
+
+	if (driver->hsic_device_enabled) {
+		diag_hsic_close();
+		kfree(driver->buf_in_hsic);
+		driver->hsic_device_enabled = 0;
+	}
+	if (driver->diag_smux_enabled) {
+		driver->lcid = LCID_INVALID;
+		kfree(driver->buf_in_smux);
+		driver->diag_smux_enabled = 0;
+	}
+	platform_driver_unregister(&msm_hsic_ch_driver);
+	platform_driver_unregister(&msm_diagfwd_smux_driver);
+	/* destroy USB MDM specific variables */
+#ifdef CONFIG_DIAG_OVER_USB
+	if (driver->usb_mdm_connected)
+		usb_diag_free_req(driver->mdm_ch);
+	usb_diag_close(driver->mdm_ch);
+#endif
+	kfree(driver->usb_buf_mdm_out);
+	kfree(driver->write_ptr_mdm);
+	kfree(driver->usb_read_mdm_ptr);
+	destroy_workqueue(driver->diag_bridge_wq);
 }
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index a47ee26..b189c94 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -17,11 +17,11 @@
 #define N_MDM_WRITE	1 /* Upgrade to 2 with ping pong buffer */
 #define N_MDM_READ	1
 
-void __init diagfwd_hsic_init(void);
-int diagfwd_connect_hsic(int);
-int diagfwd_disconnect_hsic(int);
+int diagfwd_connect_bridge(int);
+int diagfwd_disconnect_bridge(int);
 int diagfwd_write_complete_hsic(void);
 int diagfwd_cancel_hsic(void);
-void diagfwd_hsic_exit(void);
+void diagfwd_bridge_init(void);
+void diagfwd_bridge_exit(void);
 
 #endif
diff --git a/drivers/char/diag/diagfwd_smux.c b/drivers/char/diag/diagfwd_smux.c
new file mode 100644
index 0000000..8bbc67e
--- /dev/null
+++ b/drivers/char/diag/diagfwd_smux.c
@@ -0,0 +1,156 @@
+/* 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/termios.h>
+#include <linux/slab.h>
+#include <linux/diagchar.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <mach/usbdiag.h>
+#include "diagchar.h"
+#include "diagfwd.h"
+#include "diagfwd_smux.h"
+
+void diag_smux_event(void *priv, int event_type, const void *metadata)
+{
+	unsigned char *rx_buf;
+	int len;
+
+	switch (event_type) {
+	case SMUX_CONNECTED:
+		pr_debug("diag: SMUX_CONNECTED received\n");
+		driver->in_busy_smux = 0;
+		/* read data from USB MDM channel & Initiate first write */
+		queue_work(driver->diag_bridge_wq,
+				 &(driver->diag_read_mdm_work));
+		break;
+	case SMUX_DISCONNECTED:
+		pr_info("diag: SMUX_DISCONNECTED received\n");
+		break;
+	case SMUX_WRITE_DONE:
+		pr_debug("diag: SMUX Write done\n");
+		break;
+	case SMUX_WRITE_FAIL:
+		pr_info("diag: SMUX Write Failed\n");
+		break;
+	case SMUX_READ_FAIL:
+		pr_info("diag: SMUX Read Failed\n");
+		break;
+	case SMUX_READ_DONE:
+		len = ((struct smux_meta_read *)metadata)->len;
+		rx_buf = ((struct smux_meta_read *)metadata)->buffer;
+		driver->write_ptr_mdm->length = len;
+		diag_device_write(driver->buf_in_smux, SMUX_DATA,
+						 driver->write_ptr_mdm);
+		break;
+	};
+}
+
+int diagfwd_write_complete_smux(void)
+{
+	pr_debug("diag: clear in_busy_smux\n");
+	driver->in_busy_smux = 0;
+	return 0;
+}
+
+int diagfwd_read_complete_smux(void)
+{
+	queue_work(driver->diag_bridge_wq, &(driver->diag_read_mdm_work));
+	return 0;
+}
+
+int diag_get_rx_buffer(void *priv, void **pkt_priv, void **buffer, int size)
+{
+	if (!driver->in_busy_smux) {
+		*pkt_priv = (void *)0x1234;
+		*buffer = driver->buf_in_smux;
+		pr_debug("diag: set in_busy_smux as 1\n");
+		driver->in_busy_smux = 1;
+	} else {
+		pr_debug("diag: read buffer for SMUX is BUSY\n");
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static int diagfwd_smux_runtime_suspend(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: suspending...\n");
+	return 0;
+}
+
+static int diagfwd_smux_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: resuming...\n");
+	return 0;
+}
+
+static const struct dev_pm_ops diagfwd_smux_dev_pm_ops = {
+	.runtime_suspend = diagfwd_smux_runtime_suspend,
+	.runtime_resume = diagfwd_smux_runtime_resume,
+};
+
+int diagfwd_connect_smux(void)
+{
+	void *priv = NULL;
+	int ret = 0;
+
+	if (driver->lcid == LCID_INVALID) {
+		ret = msm_smux_open(LCID_VALID, priv, diag_smux_event,
+						 diag_get_rx_buffer);
+		if (!ret) {
+			driver->lcid = LCID_VALID;
+			msm_smux_tiocm_set(driver->lcid, TIOCM_DTR, 0);
+			pr_info("diag: open SMUX ch, r = %d\n", ret);
+		} else {
+			pr_err("diag: failed to open SMUX ch, r = %d\n", ret);
+		}
+	}
+	/* Poll USB channel to check for data*/
+	queue_work(driver->diag_bridge_wq, &(driver->diag_read_mdm_work));
+	return ret;
+}
+
+static int diagfwd_smux_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	pr_info("diag: SMUX probe called\n");
+	driver->lcid = LCID_INVALID;
+	driver->diag_smux_enabled = 1;
+	if (driver->buf_in_smux == NULL) {
+		driver->buf_in_smux = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+		if (driver->buf_in_smux == NULL)
+			goto err;
+	}
+	/* Only required for Local loopback test
+	 * ret = msm_smux_set_ch_option(LCID_VALID,
+				 SMUX_CH_OPTION_LOCAL_LOOPBACK, 0);
+	 * if (ret)
+	 *	pr_err("diag: error setting SMUX ch option, r = %d\n", ret);
+	 */
+	ret = diagfwd_connect_smux();
+	return ret;
+
+err:
+	pr_err("diag: Could not initialize SMUX buffer\n");
+	kfree(driver->buf_in_smux);
+	return ret;
+}
+
+struct platform_driver msm_diagfwd_smux_driver = {
+	.probe = diagfwd_smux_probe,
+	.driver = {
+		   .name = "SMUX_DIAG",
+		   .owner = THIS_MODULE,
+		   .pm   = &diagfwd_smux_dev_pm_ops,
+		   },
+};
diff --git a/drivers/char/diag/diagfwd_smux.h b/drivers/char/diag/diagfwd_smux.h
new file mode 100644
index 0000000..e78b7ed
--- /dev/null
+++ b/drivers/char/diag/diagfwd_smux.h
@@ -0,0 +1,25 @@
+/* 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 DIAGFWD_SMUX_H
+#define DIAGFWD_SMUX_H
+
+#include <linux/smux.h>
+#define LCID_VALID	SMUX_USB_DIAG_0
+#define LCID_INVALID	0
+
+int diagfwd_read_complete_smux(void);
+int diagfwd_write_complete_smux(void);
+int diagfwd_connect_smux(void);
+extern struct platform_driver msm_diagfwd_smux_driver;
+
+#endif
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ef077a5..0dcf1a4 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -124,6 +124,15 @@
 	  Qualcomm MSM chips.  Most of the pins on the MSM can be
 	  selected for GPIO, and are controlled by this driver.
 
+config GPIO_MSM_V3
+	tristate "Qualcomm MSM GPIO v3"
+	depends on GPIOLIB && ARCH_MSM
+	help
+	  Say yes here to support the GPIO interface on ARM v7 based
+	  Qualcomm MSM chips for v3 version of the interface. Most of
+	  the pins on the MSM can be selected for GPIO, and are
+	  controlled by this driver.
+
 config GPIO_FSM9XXX
 	tristate "Qualcomm FSM GPIO"
 	depends on GPIOLIB && ARCH_MSM
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index babd44d..d15b628 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -33,7 +33,8 @@
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSM_V1)	+= gpio-msm-v1.o
-obj-$(CONFIG_GPIO_MSM_V2)	+= gpio-msm-v2.o
+obj-$(CONFIG_GPIO_MSM_V2)	+= gpio-msm-common.o gpio-msm-v2.o
+obj-$(CONFIG_GPIO_MSM_V3)	+= gpio-msm-common.o gpio-msm-v3.o
 obj-$(CONFIG_GPIO_FSM9XXX)	+= gpio-fsm9xxx.o
 obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)		+= gpio-mxs.o
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
new file mode 100644
index 0000000..9a9a783
--- /dev/null
+++ b/drivers/gpio/gpio-msm-common.c
@@ -0,0 +1,629 @@
+/* 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/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/err.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/gpiomux.h>
+#include <mach/mpm.h>
+#include "gpio-msm-common.h"
+
+enum msm_tlmm_register {
+	SDC4_HDRV_PULL_CTL = 0x20a0,
+	SDC3_HDRV_PULL_CTL = 0x20a4,
+	SDC1_HDRV_PULL_CTL = 0x20a0,
+};
+
+struct tlmm_field_cfg {
+	enum msm_tlmm_register reg;
+	u8                     off;
+};
+
+static const struct tlmm_field_cfg tlmm_hdrv_cfgs[] = {
+	{SDC4_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC4_CLK  */
+	{SDC4_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC4_CMD  */
+	{SDC4_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC4_DATA */
+	{SDC3_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC3_CLK  */
+	{SDC3_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC3_CMD  */
+	{SDC3_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC3_DATA */
+	{SDC1_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC1_CLK  */
+	{SDC1_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC1_CMD  */
+	{SDC1_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC1_DATA */
+};
+
+static const struct tlmm_field_cfg tlmm_pull_cfgs[] = {
+	{SDC4_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC4_CMD  */
+	{SDC4_HDRV_PULL_CTL, 9},  /* TLMM_PULL_SDC4_DATA */
+	{SDC3_HDRV_PULL_CTL, 14}, /* TLMM_PULL_SDC3_CLK  */
+	{SDC3_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC3_CMD  */
+	{SDC3_HDRV_PULL_CTL, 9},  /* TLMM_PULL_SDC3_DATA */
+	{SDC1_HDRV_PULL_CTL, 13}, /* TLMM_PULL_SDC1_CLK  */
+	{SDC1_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC1_CMD  */
+	{SDC1_HDRV_PULL_CTL, 9},  /* TLMM_PULL_SDC1_DATA */
+};
+
+/*
+ * Supported arch specific irq extension.
+ * Default make them NULL.
+ */
+struct irq_chip msm_gpio_irq_extn = {
+	.irq_eoi	= NULL,
+	.irq_mask	= NULL,
+	.irq_unmask	= NULL,
+	.irq_retrigger	= NULL,
+	.irq_set_type	= NULL,
+	.irq_set_wake	= NULL,
+	.irq_disable	= NULL,
+};
+
+/**
+ * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
+ *
+ * @enabled_irqs: a bitmap used to optimize the summary-irq handler.  By
+ * keeping track of which gpios are unmasked as irq sources, we avoid
+ * having to do __raw_readl calls on hundreds of iomapped registers each time
+ * the summary interrupt fires in order to locate the active interrupts.
+ *
+ * @wake_irqs: a bitmap for tracking which interrupt lines are enabled
+ * as wakeup sources.  When the device is suspended, interrupts which are
+ * not wakeup sources are disabled.
+ *
+ * @dual_edge_irqs: a bitmap used to track which irqs are configured
+ * as dual-edge, as this is not supported by the hardware and requires
+ * some special handling in the driver.
+ */
+struct msm_gpio_dev {
+	struct gpio_chip gpio_chip;
+	DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
+	DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);
+	DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
+	struct irq_domain domain;
+};
+
+static DEFINE_SPINLOCK(tlmm_lock);
+
+static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
+{
+	return container_of(chip, struct msm_gpio_dev, gpio_chip);
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	int rc;
+	rc = __msm_gpio_get_inout(offset);
+	mb();
+	return rc;
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	__msm_gpio_set_inout(offset, val);
+	mb();
+}
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	__msm_gpio_set_config_direction(offset, 1, 0);
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+	return 0;
+}
+
+static int msm_gpio_direction_output(struct gpio_chip *chip,
+				unsigned offset,
+				int val)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	__msm_gpio_set_config_direction(offset, 0, val);
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
+	struct irq_domain *domain = &g_dev->domain;
+	return domain->irq_base + (offset - chip->base);
+}
+
+static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
+{
+	struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
+	struct irq_domain *domain = &g_dev->domain;
+	return irq - domain->irq_base;
+}
+#else
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return MSM_GPIO_TO_INT(offset - chip->base);
+}
+
+static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
+{
+	return irq - MSM_GPIO_TO_INT(chip->base);
+}
+#endif
+
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return msm_gpiomux_get(chip->base + offset);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	msm_gpiomux_put(chip->base + offset);
+}
+
+static struct msm_gpio_dev msm_gpio = {
+	.gpio_chip = {
+		.label		  = "msmgpio",
+		.base             = 0,
+		.ngpio            = NR_MSM_GPIOS,
+		.direction_input  = msm_gpio_direction_input,
+		.direction_output = msm_gpio_direction_output,
+		.get              = msm_gpio_get,
+		.set              = msm_gpio_set,
+		.to_irq           = msm_gpio_to_irq,
+		.request          = msm_gpio_request,
+		.free             = msm_gpio_free,
+	},
+};
+
+static void switch_mpm_config(struct irq_data *d, unsigned val)
+{
+	/* switch the configuration in the mpm as well */
+	if (!msm_gpio_irq_extn.irq_set_type)
+		return;
+
+	if (val)
+		msm_gpio_irq_extn.irq_set_type(d, IRQF_TRIGGER_FALLING);
+	else
+		msm_gpio_irq_extn.irq_set_type(d, IRQF_TRIGGER_RISING);
+}
+
+/* For dual-edge interrupts in software, since the hardware has no
+ * such support:
+ *
+ * At appropriate moments, this function may be called to flip the polarity
+ * settings of both-edge irq lines to try and catch the next edge.
+ *
+ * The attempt is considered successful if:
+ * - the status bit goes high, indicating that an edge was caught, or
+ * - the input value of the gpio doesn't change during the attempt.
+ * If the value changes twice during the process, that would cause the first
+ * test to fail but would force the second, as two opposite
+ * transitions would cause a detection no matter the polarity setting.
+ *
+ * The do-loop tries to sledge-hammer closed the timing hole between
+ * the initial value-read and the polarity-write - if the line value changes
+ * during that window, an interrupt is lost, the new polarity setting is
+ * incorrect, and the first success test will fail, causing a retry.
+ *
+ * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c.
+ */
+static void msm_gpio_update_dual_edge_pos(struct irq_data *d, unsigned gpio)
+{
+	int loop_limit = 100;
+	unsigned val, val2, intstat;
+
+	do {
+		val = __msm_gpio_get_inout(gpio);
+		__msm_gpio_set_polarity(gpio, val);
+		val2 = __msm_gpio_get_inout(gpio);
+		intstat = __msm_gpio_get_intr_status(gpio);
+		if (intstat || val == val2) {
+			switch_mpm_config(d, val);
+			return;
+		}
+	} while (loop_limit-- > 0);
+	pr_err("%s: dual-edge irq failed to stabilize, %#08x != %#08x\n",
+	       __func__, val, val2);
+}
+
+static void msm_gpio_irq_ack(struct irq_data *d)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+
+	__msm_gpio_set_intr_status(gpio);
+	if (test_bit(gpio, msm_gpio.dual_edge_irqs))
+		msm_gpio_update_dual_edge_pos(d, gpio);
+	mb();
+}
+
+static void msm_gpio_irq_mask(struct irq_data *d)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	__msm_gpio_set_intr_cfg_enable(gpio, 0);
+	__clear_bit(gpio, msm_gpio.enabled_irqs);
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+	if (msm_gpio_irq_extn.irq_mask)
+		msm_gpio_irq_extn.irq_mask(d);
+
+}
+
+static void msm_gpio_irq_unmask(struct irq_data *d)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	__set_bit(gpio, msm_gpio.enabled_irqs);
+	__msm_gpio_set_intr_cfg_enable(gpio, 1);
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+	if (msm_gpio_irq_extn.irq_mask)
+		msm_gpio_irq_extn.irq_unmask(d);
+}
+
+static void msm_gpio_irq_disable(struct irq_data *d)
+{
+	if (msm_gpio_irq_extn.irq_disable)
+		msm_gpio_irq_extn.irq_disable(d);
+}
+
+static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+
+	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+		if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+			__set_bit(gpio, msm_gpio.dual_edge_irqs);
+		else
+			__clear_bit(gpio, msm_gpio.dual_edge_irqs);
+	} else {
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+		__clear_bit(gpio, msm_gpio.dual_edge_irqs);
+	}
+
+	__msm_gpio_set_intr_cfg_type(gpio, flow_type);
+
+	if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+		msm_gpio_update_dual_edge_pos(d, gpio);
+
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+	if (msm_gpio_irq_extn.irq_set_type)
+		msm_gpio_irq_extn.irq_set_type(d, flow_type);
+
+	return 0;
+}
+
+/*
+ * When the summary IRQ is raised, any number of GPIO lines may be high.
+ * It is the job of the summary handler to find all those GPIO lines
+ * which have been set as summary IRQ lines and which are triggered,
+ * and to call their interrupt handlers.
+ */
+static irqreturn_t msm_summary_irq_handler(int irq, void *data)
+{
+	unsigned long i;
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	for (i = find_first_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
+	     i < NR_MSM_GPIOS;
+	     i = find_next_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS, i + 1)) {
+		if (__msm_gpio_get_intr_status(i))
+			generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
+							   i));
+	}
+
+	chained_irq_exit(chip, desc);
+	return IRQ_HANDLED;
+}
+
+static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+
+	if (on) {
+		if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
+			irq_set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 1);
+		set_bit(gpio, msm_gpio.wake_irqs);
+	} else {
+		clear_bit(gpio, msm_gpio.wake_irqs);
+		if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
+			irq_set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 0);
+	}
+
+	if (msm_gpio_irq_extn.irq_set_wake)
+		msm_gpio_irq_extn.irq_set_wake(d, on);
+
+	return 0;
+}
+
+static struct irq_chip msm_gpio_irq_chip = {
+	.name		= "msmgpio",
+	.irq_mask	= msm_gpio_irq_mask,
+	.irq_unmask	= msm_gpio_irq_unmask,
+	.irq_ack	= msm_gpio_irq_ack,
+	.irq_set_type	= msm_gpio_irq_set_type,
+	.irq_set_wake	= msm_gpio_irq_set_wake,
+	.irq_disable	= msm_gpio_irq_disable,
+};
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parent, so it won't report false recursion.
+ */
+static struct lock_class_key msm_gpio_lock_class;
+
+static int __devinit msm_gpio_probe(void)
+{
+	int i, irq, ret;
+
+	spin_lock_init(&tlmm_lock);
+	bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
+	bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
+	bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
+	ret = gpiochip_add(&msm_gpio.gpio_chip);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
+		irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+		irq_set_lockdep_class(irq, &msm_gpio_lock_class);
+		irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
+					 handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
+			IRQF_TRIGGER_HIGH, "msmgpio", NULL);
+	if (ret) {
+		pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
+				ret);
+		return ret;
+	}
+	return 0;
+}
+
+static int __devexit msm_gpio_remove(void)
+{
+	int ret = gpiochip_remove(&msm_gpio.gpio_chip);
+
+	if (ret < 0)
+		return ret;
+
+	irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int msm_gpio_suspend(void)
+{
+	unsigned long irq_flags;
+	unsigned long i;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
+		__msm_gpio_set_intr_cfg_enable(i, 0);
+
+	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
+		__msm_gpio_set_intr_cfg_enable(i, 1);
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+	return 0;
+}
+
+void msm_gpio_show_resume_irq(void)
+{
+	unsigned long irq_flags;
+	int i, irq, intstat;
+
+	if (!msm_show_resume_irq_mask)
+		return;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS) {
+		intstat = __msm_gpio_get_intr_status(i);
+		if (intstat) {
+			irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+			pr_warning("%s: %d triggered\n",
+				__func__, irq);
+		}
+	}
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+}
+
+static void msm_gpio_resume(void)
+{
+	unsigned long irq_flags;
+	unsigned long i;
+
+	msm_gpio_show_resume_irq();
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
+		__msm_gpio_set_intr_cfg_enable(i, 0);
+
+	for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
+		__msm_gpio_set_intr_cfg_enable(i, 1);
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+}
+#else
+#define msm_gpio_suspend NULL
+#define msm_gpio_resume NULL
+#endif
+
+static struct syscore_ops msm_gpio_syscore_ops = {
+	.suspend = msm_gpio_suspend,
+	.resume = msm_gpio_resume,
+};
+
+static int __init msm_gpio_init(void)
+{
+	msm_gpio_probe();
+	register_syscore_ops(&msm_gpio_syscore_ops);
+	return 0;
+}
+
+static void __exit msm_gpio_exit(void)
+{
+	unregister_syscore_ops(&msm_gpio_syscore_ops);
+	msm_gpio_remove();
+}
+
+postcore_initcall(msm_gpio_init);
+module_exit(msm_gpio_exit);
+
+static void msm_tlmm_set_field(const struct tlmm_field_cfg *configs,
+			       unsigned id, unsigned width, unsigned val)
+{
+	unsigned long irqflags;
+	u32 mask = (1 << width) - 1;
+	u32 __iomem *reg = MSM_TLMM_BASE + configs[id].reg;
+	u32 reg_val;
+
+	spin_lock_irqsave(&tlmm_lock, irqflags);
+	reg_val = __raw_readl(reg);
+	reg_val &= ~(mask << configs[id].off);
+	reg_val |= (val & mask) << configs[id].off;
+	__raw_writel(reg_val, reg);
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irqflags);
+}
+
+void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt, int drv_str)
+{
+	msm_tlmm_set_field(tlmm_hdrv_cfgs, tgt, 3, drv_str);
+}
+EXPORT_SYMBOL(msm_tlmm_set_hdrive);
+
+void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull)
+{
+	msm_tlmm_set_field(tlmm_pull_cfgs, tgt, 2, pull);
+}
+EXPORT_SYMBOL(msm_tlmm_set_pull);
+
+int gpio_tlmm_config(unsigned config, unsigned disable)
+{
+	unsigned gpio = GPIO_PIN(config);
+
+	if (gpio > NR_MSM_GPIOS)
+		return -EINVAL;
+
+	__gpio_tlmm_config(config);
+	mb();
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_tlmm_config);
+
+int msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+					unsigned int input_polarity)
+{
+	unsigned long irq_flags;
+
+	if (gpio >= NR_MSM_GPIOS || irq >= NR_TLMM_MSM_DIR_CONN_IRQ)
+		return -EINVAL;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	__msm_gpio_install_direct_irq(gpio, irq, input_polarity);
+	mb();
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_gpio_install_direct_irq);
+
+#ifdef CONFIG_OF
+static int msm_gpio_domain_dt_translate(struct irq_domain *d,
+					struct device_node *controller,
+					const u32 *intspec,
+					unsigned int intsize,
+					unsigned long *out_hwirq,
+					unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize != 2)
+		return -EINVAL;
+
+	/* hwirq value */
+	*out_hwirq = intspec[0];
+
+	/* irq flags */
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+static struct irq_domain_ops msm_gpio_irq_domain_ops = {
+	.dt_translate = msm_gpio_domain_dt_translate,
+};
+
+int __init msm_gpio_of_init(struct device_node *node,
+			    struct device_node *parent)
+{
+	struct irq_domain *domain = &msm_gpio.domain;
+	int start;
+
+	start = irq_domain_find_free_range(0, NR_MSM_GPIOS);
+	domain->irq_base = irq_alloc_descs(start, 0, NR_MSM_GPIOS,
+							numa_node_id());
+	if (IS_ERR_VALUE(domain->irq_base)) {
+		WARN(1, "Cannot allocate irq_descs @ IRQ%d\n", start);
+		return domain->irq_base;
+	}
+
+	domain->nr_irq = NR_MSM_GPIOS;
+	domain->of_node = of_node_get(node);
+	domain->priv = &msm_gpio;
+	domain->ops = &msm_gpio_irq_domain_ops;
+	irq_domain_add(domain);
+	msm_gpio.gpio_chip.of_node = of_node_get(node);
+	pr_debug("%s: irq_base = %u\n", __func__, domain->irq_base);
+
+	return 0;
+}
+#endif
+
+MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
+MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("sysdev:msmgpio");
diff --git a/drivers/gpio/gpio-msm-common.h b/drivers/gpio/gpio-msm-common.h
new file mode 100644
index 0000000..c9ea3da
--- /dev/null
+++ b/drivers/gpio/gpio-msm-common.h
@@ -0,0 +1,29 @@
+/* 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_GPIO_COMMON_H
+#define __ARCH_ARM_MACH_MSM_GPIO_COMMON_H
+
+extern int msm_show_resume_irq_mask;
+
+unsigned __msm_gpio_get_inout(unsigned gpio);
+void __msm_gpio_set_inout(unsigned gpio, unsigned val);
+void __msm_gpio_set_config_direction(unsigned gpio, int input, int val);
+void __msm_gpio_set_polarity(unsigned gpio, unsigned val);
+unsigned __msm_gpio_get_intr_status(unsigned gpio);
+void __msm_gpio_set_intr_status(unsigned gpio);
+unsigned __msm_gpio_get_intr_config(unsigned gpio);
+void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val);
+void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type);
+void __gpio_tlmm_config(unsigned config);
+void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+					unsigned int input_polarity);
+#endif
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index ad436e0..fb43562 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -14,21 +14,12 @@
 #include <linux/bitops.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
-#include <linux/irqdomain.h>
-#include <linux/of.h>
-#include <linux/err.h>
-
-#include <asm/mach/irq.h>
+#include <linux/irq.h>
 
 #include <mach/msm_iomap.h>
 #include <mach/gpiomux.h>
-#include <mach/mpm.h>
+#include "gpio-msm-common.h"
 
 /* Bits of interest in the GPIO_IN_OUT register.
  */
@@ -75,54 +66,6 @@
 	DC_IRQ_ENABLE	= BIT(3),
 };
 
-enum msm_tlmm_register {
-	SDC4_HDRV_PULL_CTL = 0x20a0,
-	SDC3_HDRV_PULL_CTL = 0x20a4,
-	SDC1_HDRV_PULL_CTL = 0x20a0,
-};
-
-struct tlmm_field_cfg {
-	enum msm_tlmm_register reg;
-	u8                     off;
-};
-
-static const struct tlmm_field_cfg tlmm_hdrv_cfgs[] = {
-	{SDC4_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC4_CLK  */
-	{SDC4_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC4_CMD  */
-	{SDC4_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC4_DATA */
-	{SDC3_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC3_CLK  */
-	{SDC3_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC3_CMD  */
-	{SDC3_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC3_DATA */
-	{SDC1_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC1_CLK  */
-	{SDC1_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC1_CMD  */
-	{SDC1_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC1_DATA */
-};
-
-static const struct tlmm_field_cfg tlmm_pull_cfgs[] = {
-	{SDC4_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC4_CMD  */
-	{SDC4_HDRV_PULL_CTL, 9},  /* TLMM_PULL_SDC4_DATA */
-	{SDC3_HDRV_PULL_CTL, 14}, /* TLMM_PULL_SDC3_CLK  */
-	{SDC3_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC3_CMD  */
-	{SDC3_HDRV_PULL_CTL, 9},  /* TLMM_PULL_SDC3_DATA */
-	{SDC1_HDRV_PULL_CTL, 13}, /* TLMM_PULL_SDC1_CLK  */
-	{SDC1_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC1_CMD  */
-	{SDC1_HDRV_PULL_CTL, 9},  /* TLMM_PULL_SDC1_DATA */
-};
-
-/*
- * Supported arch specific irq extension.
- * Default make them NULL.
- */
-struct irq_chip msm_gpio_irq_extn = {
-	.irq_eoi	= NULL,
-	.irq_mask	= NULL,
-	.irq_unmask	= NULL,
-	.irq_retrigger	= NULL,
-	.irq_set_type	= NULL,
-	.irq_set_wake	= NULL,
-	.irq_disable	= NULL,
-};
-
 /*
  * When a GPIO triggers, two separate decisions are made, controlled
  * by two separate flags.
@@ -147,37 +90,6 @@
 #define GPIO_INTR_CFG(gpio)       (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
 #define GPIO_INTR_STATUS(gpio)    (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
 
-/**
- * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
- *
- * @enabled_irqs: a bitmap used to optimize the summary-irq handler.  By
- * keeping track of which gpios are unmasked as irq sources, we avoid
- * having to do __raw_readl calls on hundreds of iomapped registers each time
- * the summary interrupt fires in order to locate the active interrupts.
- *
- * @wake_irqs: a bitmap for tracking which interrupt lines are enabled
- * as wakeup sources.  When the device is suspended, interrupts which are
- * not wakeup sources are disabled.
- *
- * @dual_edge_irqs: a bitmap used to track which irqs are configured
- * as dual-edge, as this is not supported by the hardware and requires
- * some special handling in the driver.
- */
-struct msm_gpio_dev {
-	struct gpio_chip gpio_chip;
-	DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
-	DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);
-	DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
-	struct irq_domain domain;
-};
-
-static DEFINE_SPINLOCK(tlmm_lock);
-
-static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
-{
-	return container_of(chip, struct msm_gpio_dev, gpio_chip);
-}
-
 static inline void set_gpio_bits(unsigned n, void __iomem *reg)
 {
 	__raw_writel(__raw_readl(reg) | n, reg);
@@ -188,498 +100,99 @@
 	__raw_writel(__raw_readl(reg) & ~n, reg);
 }
 
-static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+unsigned __msm_gpio_get_inout(unsigned gpio)
 {
-	int rc;
-	rc = __raw_readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN_BIT);
-	mb();
-	return rc;
+	return __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
 }
 
-static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+void __msm_gpio_set_inout(unsigned gpio, unsigned val)
 {
-	__raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(offset));
-	mb();
+	__raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(gpio));
 }
 
-static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+void __msm_gpio_set_config_direction(unsigned gpio, int input, int val)
 {
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(offset));
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-	return 0;
+	if (input)
+		clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+	else {
+		__msm_gpio_set_inout(gpio, val);
+		set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+	}
 }
 
-static int msm_gpio_direction_output(struct gpio_chip *chip,
-				unsigned offset,
-				int val)
+void __msm_gpio_set_polarity(unsigned gpio, unsigned val)
 {
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	msm_gpio_set(chip, offset, val);
-	set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(offset));
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
-	struct irq_domain *domain = &g_dev->domain;
-	return domain->irq_base + (offset - chip->base);
-}
-
-static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
-{
-	struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
-	struct irq_domain *domain = &g_dev->domain;
-	return irq - domain->irq_base;
-}
-#else
-static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	return MSM_GPIO_TO_INT(offset - chip->base);
-}
-
-static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
-{
-	return irq - MSM_GPIO_TO_INT(chip->base);
-}
-#endif
-
-static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	return msm_gpiomux_get(chip->base + offset);
-}
-
-static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-	msm_gpiomux_put(chip->base + offset);
-}
-
-static struct msm_gpio_dev msm_gpio = {
-	.gpio_chip = {
-		.label		  = "msmgpio",
-		.base             = 0,
-		.ngpio            = NR_MSM_GPIOS,
-		.direction_input  = msm_gpio_direction_input,
-		.direction_output = msm_gpio_direction_output,
-		.get              = msm_gpio_get,
-		.set              = msm_gpio_set,
-		.to_irq           = msm_gpio_to_irq,
-		.request          = msm_gpio_request,
-		.free             = msm_gpio_free,
-	},
-};
-
-static void switch_mpm_config(struct irq_data *d, unsigned val)
-{
-	/* switch the configuration in the mpm as well */
-	if (!msm_gpio_irq_extn.irq_set_type)
-		return;
-
 	if (val)
-		msm_gpio_irq_extn.irq_set_type(d, IRQF_TRIGGER_FALLING);
+		clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
 	else
-		msm_gpio_irq_extn.irq_set_type(d, IRQF_TRIGGER_RISING);
+		set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
 }
 
-/* For dual-edge interrupts in software, since the hardware has no
- * such support:
- *
- * At appropriate moments, this function may be called to flip the polarity
- * settings of both-edge irq lines to try and catch the next edge.
- *
- * The attempt is considered successful if:
- * - the status bit goes high, indicating that an edge was caught, or
- * - the input value of the gpio doesn't change during the attempt.
- * If the value changes twice during the process, that would cause the first
- * test to fail but would force the second, as two opposite
- * transitions would cause a detection no matter the polarity setting.
- *
- * The do-loop tries to sledge-hammer closed the timing hole between
- * the initial value-read and the polarity-write - if the line value changes
- * during that window, an interrupt is lost, the new polarity setting is
- * incorrect, and the first success test will fail, causing a retry.
- *
- * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c.
- */
-static void msm_gpio_update_dual_edge_pos(struct irq_data *d, unsigned gpio)
+unsigned __msm_gpio_get_intr_status(unsigned gpio)
 {
-	int loop_limit = 100;
-	unsigned val, val2, intstat;
-
-	do {
-		val = __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
-		if (val)
-			clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
-		else
-			set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
-		val2 = __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
-		intstat = __raw_readl(GPIO_INTR_STATUS(gpio)) &
+	return __raw_readl(GPIO_INTR_STATUS(gpio)) &
 					BIT(INTR_STATUS_BIT);
-		if (intstat || val == val2) {
-			switch_mpm_config(d, val);
-			return;
-		}
-	} while (loop_limit-- > 0);
-	pr_err("%s: dual-edge irq failed to stabilize, "
-	       "interrupts dropped. %#08x != %#08x\n",
-	       __func__, val, val2);
 }
 
-static void msm_gpio_irq_ack(struct irq_data *d)
+void __msm_gpio_set_intr_status(unsigned gpio)
 {
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
-
 	__raw_writel(BIT(INTR_STATUS_BIT), GPIO_INTR_STATUS(gpio));
-	if (test_bit(gpio, msm_gpio.dual_edge_irqs))
-		msm_gpio_update_dual_edge_pos(d, gpio);
-	mb();
 }
 
-static void __msm_gpio_irq_mask(unsigned int gpio)
+unsigned __msm_gpio_get_intr_config(unsigned gpio)
 {
-	__raw_writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
-	clr_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+	return __raw_readl(GPIO_INTR_CFG(gpio));
 }
 
-static void msm_gpio_irq_mask(struct irq_data *d)
+void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val)
 {
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
-	unsigned long irq_flags;
+	if (val) {
+		set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE,
+				GPIO_INTR_CFG(gpio));
+		__raw_writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
 
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	__msm_gpio_irq_mask(gpio);
-	__clear_bit(gpio, msm_gpio.enabled_irqs);
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
-	if (msm_gpio_irq_extn.irq_mask)
-		msm_gpio_irq_extn.irq_mask(d);
-
-}
-
-static void __msm_gpio_irq_unmask(unsigned int gpio)
-{
-	set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
-	__raw_writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
-}
-
-static void msm_gpio_irq_unmask(struct irq_data *d)
-{
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	__set_bit(gpio, msm_gpio.enabled_irqs);
-	__msm_gpio_irq_unmask(gpio);
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
-	if (msm_gpio_irq_extn.irq_mask)
-		msm_gpio_irq_extn.irq_unmask(d);
-}
-
-static void msm_gpio_irq_disable(struct irq_data *d)
-{
-	if (msm_gpio_irq_extn.irq_disable)
-		msm_gpio_irq_extn.irq_disable(d);
-}
-
-static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
-	unsigned long irq_flags;
-	uint32_t bits;
-
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-
-	bits = __raw_readl(GPIO_INTR_CFG(gpio));
-
-	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
-		bits |= INTR_DECT_CTL_EDGE;
-		__irq_set_handler_locked(d->irq, handle_edge_irq);
-		if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
-			__set_bit(gpio, msm_gpio.dual_edge_irqs);
-		else
-			__clear_bit(gpio, msm_gpio.dual_edge_irqs);
 	} else {
-		bits &= ~INTR_DECT_CTL_EDGE;
-		__irq_set_handler_locked(d->irq, handle_level_irq);
-		__clear_bit(gpio, msm_gpio.dual_edge_irqs);
+		__raw_writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
+		clr_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE,
+				GPIO_INTR_CFG(gpio));
 	}
+}
 
-	if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
-		bits |= INTR_POL_CTL_HI;
+void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
+{
+	unsigned cfg;
+
+	cfg  = __msm_gpio_get_intr_config(gpio);
+	if (type & IRQ_TYPE_EDGE_BOTH)
+		cfg |= INTR_DECT_CTL_EDGE;
 	else
-		bits &= ~INTR_POL_CTL_HI;
+		cfg &= ~INTR_DECT_CTL_EDGE;
 
-	__raw_writel(bits, GPIO_INTR_CFG(gpio));
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+		cfg |= INTR_POL_CTL_HI;
+	else
+		cfg &= ~INTR_POL_CTL_HI;
 
-	if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
-		msm_gpio_update_dual_edge_pos(d, gpio);
-
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
-	if (msm_gpio_irq_extn.irq_set_type)
-		msm_gpio_irq_extn.irq_set_type(d, flow_type);
-
-	return 0;
+	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
 }
 
-/*
- * When the summary IRQ is raised, any number of GPIO lines may be high.
- * It is the job of the summary handler to find all those GPIO lines
- * which have been set as summary IRQ lines and which are triggered,
- * and to call their interrupt handlers.
- */
-static irqreturn_t msm_summary_irq_handler(int irq, void *data)
-{
-	unsigned long i;
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-
-	chained_irq_enter(chip, desc);
-
-	for (i = find_first_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
-	     i < NR_MSM_GPIOS;
-	     i = find_next_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS, i + 1)) {
-		if (__raw_readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS_BIT))
-			generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
-							   i));
-	}
-
-	chained_irq_exit(chip, desc);
-	return IRQ_HANDLED;
-}
-
-static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
-
-	if (on) {
-		if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
-			irq_set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 1);
-		set_bit(gpio, msm_gpio.wake_irqs);
-	} else {
-		clear_bit(gpio, msm_gpio.wake_irqs);
-		if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
-			irq_set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 0);
-	}
-
-	if (msm_gpio_irq_extn.irq_set_wake)
-		msm_gpio_irq_extn.irq_set_wake(d, on);
-
-	return 0;
-}
-
-static struct irq_chip msm_gpio_irq_chip = {
-	.name		= "msmgpio",
-	.irq_mask	= msm_gpio_irq_mask,
-	.irq_unmask	= msm_gpio_irq_unmask,
-	.irq_ack	= msm_gpio_irq_ack,
-	.irq_set_type	= msm_gpio_irq_set_type,
-	.irq_set_wake	= msm_gpio_irq_set_wake,
-	.irq_disable	= msm_gpio_irq_disable,
-};
-
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parent, so it won't report false recursion.
- */
-static struct lock_class_key msm_gpio_lock_class;
-
-static int __devinit msm_gpio_probe(void)
-{
-	int i, irq, ret;
-
-	spin_lock_init(&tlmm_lock);
-	bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
-	bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
-	bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
-	ret = gpiochip_add(&msm_gpio.gpio_chip);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
-		irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
-		irq_set_lockdep_class(irq, &msm_gpio_lock_class);
-		irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
-					 handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
-			IRQF_TRIGGER_HIGH, "msmgpio", NULL);
-	if (ret) {
-		pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
-				ret);
-		return ret;
-	}
-	return 0;
-}
-
-static int __devexit msm_gpio_remove(void)
-{
-	int ret = gpiochip_remove(&msm_gpio.gpio_chip);
-
-	if (ret < 0)
-		return ret;
-
-	irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int msm_gpio_suspend(void)
-{
-	unsigned long irq_flags;
-	unsigned long i;
-
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
-			__msm_gpio_irq_mask(i);
-
-	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
-		__msm_gpio_irq_unmask(i);
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-	return 0;
-}
-
-extern int msm_show_resume_irq_mask;
-
-void msm_gpio_show_resume_irq(void)
-{
-	unsigned long irq_flags;
-	int i, irq, intstat;
-
-	if (!msm_show_resume_irq_mask)
-		return;
-
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS) {
-		intstat = __raw_readl(GPIO_INTR_STATUS(i)) &
-					BIT(INTR_STATUS_BIT);
-		if (intstat) {
-			irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
-			pr_warning("%s: %d triggered\n",
-				__func__, irq);
-		}
-	}
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-}
-
-static void msm_gpio_resume(void)
-{
-	unsigned long irq_flags;
-	unsigned long i;
-
-	msm_gpio_show_resume_irq();
-
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
-		__msm_gpio_irq_mask(i);
-
-	for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
-		__msm_gpio_irq_unmask(i);
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-}
-#else
-#define msm_gpio_suspend NULL
-#define msm_gpio_resume NULL
-#endif
-
-static struct syscore_ops msm_gpio_syscore_ops = {
-	.suspend = msm_gpio_suspend,
-	.resume = msm_gpio_resume,
-};
-
-static int __init msm_gpio_init(void)
-{
-	msm_gpio_probe();
-	register_syscore_ops(&msm_gpio_syscore_ops);
-	return 0;
-}
-
-static void __exit msm_gpio_exit(void)
-{
-	unregister_syscore_ops(&msm_gpio_syscore_ops);
-	msm_gpio_remove();
-}
-
-postcore_initcall(msm_gpio_init);
-module_exit(msm_gpio_exit);
-
-static void msm_tlmm_set_field(const struct tlmm_field_cfg *configs,
-			       unsigned id, unsigned width, unsigned val)
-{
-	unsigned long irqflags;
-	u32 mask = (1 << width) - 1;
-	u32 __iomem *reg = MSM_TLMM_BASE + configs[id].reg;
-	u32 reg_val;
-
-	spin_lock_irqsave(&tlmm_lock, irqflags);
-	reg_val = __raw_readl(reg);
-	reg_val &= ~(mask << configs[id].off);
-	reg_val |= (val & mask) << configs[id].off;
-	__raw_writel(reg_val, reg);
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irqflags);
-}
-
-void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt, int drv_str)
-{
-	msm_tlmm_set_field(tlmm_hdrv_cfgs, tgt, 3, drv_str);
-}
-EXPORT_SYMBOL(msm_tlmm_set_hdrive);
-
-void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull)
-{
-	msm_tlmm_set_field(tlmm_pull_cfgs, tgt, 2, pull);
-}
-EXPORT_SYMBOL(msm_tlmm_set_pull);
-
-int gpio_tlmm_config(unsigned config, unsigned disable)
+void __gpio_tlmm_config(unsigned config)
 {
 	uint32_t flags;
 	unsigned gpio = GPIO_PIN(config);
 
-	if (gpio > NR_MSM_GPIOS)
-		return -EINVAL;
-
 	flags = ((GPIO_DIR(config) << 9) & (0x1 << 9)) |
 		((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
 		((GPIO_FUNC(config) << 2) & (0xf << 2)) |
 		((GPIO_PULL(config) & 0x3));
 	__raw_writel(flags, GPIO_CONFIG(gpio));
-	mb();
-
-	return 0;
 }
-EXPORT_SYMBOL(gpio_tlmm_config);
 
-int msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
 					unsigned int input_polarity)
 {
-	unsigned long irq_flags;
 	uint32_t bits;
 
-	if (gpio >= NR_MSM_GPIOS || irq >= NR_TLMM_MSM_DIR_CONN_IRQ)
-		return -EINVAL;
-
-	spin_lock_irqsave(&tlmm_lock, irq_flags);
-
 	__raw_writel(__raw_readl(GPIO_CONFIG(gpio)) | BIT(GPIO_OE_BIT),
 		GPIO_CONFIG(gpio));
 	__raw_writel(__raw_readl(GPIO_INTR_CFG(gpio)) &
@@ -692,66 +205,4 @@
 	if (input_polarity)
 		bits |= DC_POLARITY_HI;
 	__raw_writel(bits, DIR_CONN_INTR_CFG_SU(irq));
-
-	mb();
-	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
-	return 0;
 }
-EXPORT_SYMBOL(msm_gpio_install_direct_irq);
-
-#ifdef CONFIG_OF
-static int msm_gpio_domain_dt_translate(struct irq_domain *d,
-					struct device_node *controller,
-					const u32 *intspec,
-					unsigned int intsize,
-					unsigned long *out_hwirq,
-					unsigned int *out_type)
-{
-	if (d->of_node != controller)
-		return -EINVAL;
-	if (intsize != 2)
-		return -EINVAL;
-
-	/* hwirq value */
-	*out_hwirq = intspec[0];
-
-	/* irq flags */
-	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
-	return 0;
-}
-
-static struct irq_domain_ops msm_gpio_irq_domain_ops = {
-	.dt_translate = msm_gpio_domain_dt_translate,
-};
-
-int __init msm_gpio_of_init(struct device_node *node,
-			    struct device_node *parent)
-{
-	struct irq_domain *domain = &msm_gpio.domain;
-	int start;
-
-	start = irq_domain_find_free_range(0, NR_MSM_GPIOS);
-	domain->irq_base = irq_alloc_descs(start, 0, NR_MSM_GPIOS,
-							numa_node_id());
-	if (IS_ERR_VALUE(domain->irq_base)) {
-		WARN(1, "Cannot allocate irq_descs @ IRQ%d\n", start);
-		return domain->irq_base;
-	}
-
-	domain->irq_base = irq_domain_find_free_range(0, NR_MSM_GPIOS);
-	domain->nr_irq = NR_MSM_GPIOS;
-	domain->of_node = of_node_get(node);
-	domain->priv = &msm_gpio;
-	domain->ops = &msm_gpio_irq_domain_ops;
-	irq_domain_add(domain);
-	pr_debug("%s: irq_base = %u\n", __func__, domain->irq_base);
-
-	return 0;
-}
-#endif
-
-MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
-MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("sysdev:msmgpio");
diff --git a/drivers/gpio/gpio-msm-v3.c b/drivers/gpio/gpio-msm-v3.c
new file mode 100644
index 0000000..49ad517
--- /dev/null
+++ b/drivers/gpio/gpio-msm-v3.c
@@ -0,0 +1,217 @@
+/* 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/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/gpiomux.h>
+#include "gpio-msm-common.h"
+
+/* Bits of interest in the GPIO_IN_OUT register.
+ */
+enum {
+	GPIO_IN_BIT  = 0,
+	GPIO_OUT_BIT = 1
+};
+
+/* Bits of interest in the GPIO_INTR_STATUS register.
+ */
+enum {
+	INTR_STATUS_BIT = 0,
+};
+
+/* Bits of interest in the GPIO_CFG register.
+ */
+enum {
+	GPIO_OE_BIT = 9,
+};
+
+/* Bits of interest in the GPIO_INTR_CFG register.
+ */
+enum {
+	INTR_ENABLE_BIT        = 0,
+	INTR_POL_CTL_BIT       = 1,
+	INTR_DECT_CTL_BIT      = 2,
+	INTR_RAW_STATUS_EN_BIT = 4,
+	INTR_TARGET_PROC_BIT   = 5,
+	INTR_DIR_CONN_EN_BIT   = 8,
+};
+
+/*
+ * There is no 'DC_POLARITY_LO' because the GIC is incapable
+ * of asserting on falling edge or level-low conditions.  Even though
+ * the registers allow for low-polarity inputs, the case can never arise.
+ */
+enum {
+	DC_GPIO_SEL_BIT = 0,
+	DC_POLARITY_BIT	= 8,
+};
+
+/*
+ * When a GPIO triggers, two separate decisions are made, controlled
+ * by two separate flags.
+ *
+ * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
+ * register for that GPIO will be updated to reflect the triggering of that
+ * gpio.  If this bit is 0, this register will not be updated.
+ * - Second, INTR_ENABLE controls whether an interrupt is triggered.
+ *
+ * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
+ * can be triggered but the status register will not reflect it.
+ */
+#define INTR_RAW_STATUS_EN BIT(INTR_RAW_STATUS_EN_BIT)
+#define INTR_ENABLE        BIT(INTR_ENABLE_BIT)
+#define INTR_POL_CTL_HI    BIT(INTR_POL_CTL_BIT)
+#define INTR_DIR_CONN_EN   BIT(INTR_DIR_CONN_EN_BIT)
+#define DC_POLARITY_HI     BIT(DC_POLARITY_BIT)
+
+#define INTR_TARGET_PROC_APPS    (4 << INTR_TARGET_PROC_BIT)
+#define INTR_TARGET_PROC_NONE    (7 << INTR_TARGET_PROC_BIT)
+
+#define INTR_DECT_CTL_LEVEL      (0 << INTR_DECT_CTL_BIT)
+#define INTR_DECT_CTL_POS_EDGE   (1 << INTR_DECT_CTL_BIT)
+#define INTR_DECT_CTL_NEG_EDGE   (2 << INTR_DECT_CTL_BIT)
+#define INTR_DECT_CTL_DUAL_EDGE  (3 << INTR_DECT_CTL_BIT)
+#define INTR_DECT_CTL_MASK       (3 << INTR_DECT_CTL_BIT)
+
+#define GPIO_CONFIG(gpio)        (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio)))
+#define GPIO_IN_OUT(gpio)        (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio)))
+#define GPIO_INTR_CFG(gpio)      (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
+#define GPIO_INTR_STATUS(gpio)   (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
+#define GPIO_DIR_CONN_INTR(intr) (MSM_TLMM_BASE + 0x2800 + (0x04 * (intr)))
+
+static inline void set_gpio_bits(unsigned n, void __iomem *reg)
+{
+	__raw_writel(__raw_readl(reg) | n, reg);
+}
+
+static inline void clr_gpio_bits(unsigned n, void __iomem *reg)
+{
+	__raw_writel(__raw_readl(reg) & ~n, reg);
+}
+
+unsigned __msm_gpio_get_inout(unsigned gpio)
+{
+	return __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
+}
+
+void __msm_gpio_set_inout(unsigned gpio, unsigned val)
+{
+	__raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(gpio));
+}
+
+void __msm_gpio_set_config_direction(unsigned gpio, int input, int val)
+{
+	if (input) {
+		clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+	} else {
+		__msm_gpio_set_inout(gpio, val);
+		set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+	}
+}
+
+void __msm_gpio_set_polarity(unsigned gpio, unsigned val)
+{
+	if (val)
+		clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
+	else
+		set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
+}
+
+unsigned __msm_gpio_get_intr_status(unsigned gpio)
+{
+	return __raw_readl(GPIO_INTR_STATUS(gpio)) &
+					BIT(INTR_STATUS_BIT);
+}
+
+void __msm_gpio_set_intr_status(unsigned gpio)
+{
+	__raw_writel(BIT(INTR_STATUS_BIT), GPIO_INTR_STATUS(gpio));
+}
+
+unsigned __msm_gpio_get_intr_config(unsigned gpio)
+{
+	return __raw_readl(GPIO_INTR_CFG(gpio));
+}
+
+void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val)
+{
+	unsigned cfg;
+
+	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;
+	} else {
+		cfg &= ~(INTR_TARGET_PROC_APPS | INTR_RAW_STATUS_EN |
+			INTR_ENABLE);
+		cfg |= INTR_TARGET_PROC_NONE;
+	}
+	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
+}
+
+void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
+{
+	unsigned cfg;
+
+	cfg = __raw_readl(GPIO_INTR_CFG(gpio));
+	cfg &= ~INTR_DECT_CTL_MASK;
+	if (type == IRQ_TYPE_EDGE_RISING)
+		cfg |= INTR_DECT_CTL_POS_EDGE;
+	else if (type == IRQ_TYPE_EDGE_FALLING)
+		cfg |= INTR_DECT_CTL_NEG_EDGE;
+	else if (type == IRQ_TYPE_EDGE_BOTH)
+		cfg |= INTR_DECT_CTL_DUAL_EDGE;
+	else
+		cfg |= INTR_DECT_CTL_LEVEL;
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+		cfg |= INTR_POL_CTL_HI;
+	else
+		cfg &= ~INTR_POL_CTL_HI;
+
+	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
+}
+
+void __gpio_tlmm_config(unsigned config)
+{
+	unsigned flags;
+	unsigned gpio = GPIO_PIN(config);
+
+	flags = ((GPIO_DIR(config) << 9) & (0x1 << 9)) |
+		((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
+		((GPIO_FUNC(config) << 2) & (0xf << 2)) |
+		((GPIO_PULL(config) & 0x3));
+	__raw_writel(flags, GPIO_CONFIG(gpio));
+}
+
+void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+					unsigned int input_polarity)
+{
+	unsigned cfg;
+
+	set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+	cfg = __raw_readl(GPIO_INTR_CFG(gpio));
+	cfg &= ~(INTR_TARGET_PROC_NONE | INTR_RAW_STATUS_EN | INTR_ENABLE);
+	cfg |= INTR_TARGET_PROC_APPS | INTR_DIR_CONN_EN;
+	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
+
+	cfg = gpio;
+	if (input_polarity)
+		cfg |= DC_POLARITY_HI;
+	__raw_writel(cfg, GPIO_DIR_CONN_INTR(irq));
+}
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
index d9a23e1..97859e5 100644
--- a/drivers/gpio/qpnp-gpio.c
+++ b/drivers/gpio/qpnp-gpio.c
@@ -22,6 +22,8 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
+#include <linux/export.h>
+#include <linux/module.h>
 #include <linux/qpnp/gpio.h>
 #include <linux/export.h>
 
@@ -504,27 +506,26 @@
 }
 
 static int qpnp_gpio_of_gpio_xlate(struct gpio_chip *gpio_chip,
-				   struct device_node *np,
-				   const void *gpio_spec, u32 *flags)
+				   const struct of_phandle_args *gpio_spec,
+				   u32 *flags)
 {
 	struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
 	struct qpnp_gpio_spec *q_spec;
-	const __be32 *gpio = gpio_spec;
-	u32 n = be32_to_cpup(gpio);
 
 	if (WARN_ON(gpio_chip->of_gpio_n_cells < 2)) {
 		pr_err("of_gpio_n_cells < 2\n");
 		return -EINVAL;
 	}
 
-	q_spec = qpnp_pmic_gpio_get_spec(q_chip, n);
+	q_spec = qpnp_pmic_gpio_get_spec(q_chip, gpio_spec->args[0]);
 	if (!q_spec) {
-		pr_err("no such PMIC gpio %u in device topology\n", n);
+		pr_err("no such PMIC gpio %u in device topology\n",
+							gpio_spec->args[0]);
 		return -EINVAL;
 	}
 
 	if (flags)
-		*flags = be32_to_cpu(gpio[1]);
+		*flags = gpio_spec->args[1];
 
 	return q_spec->gpio_chip_idx;
 }
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 35af06e..0a71982 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -248,10 +248,6 @@
 #define A3XX_VBIF_ARB_CTL 0x303C
 #define A3XX_VBIF_OUT_AXI_AOOO_EN 0x305E
 #define A3XX_VBIF_OUT_AXI_AOOO 0x305F
-#define A3XX_VBIF_ERR_PENDING  0x3064
-#define A3XX_VBIF_ERR_MASK 0x3066
-#define A3XX_VBIF_ERR_CLEAR 0x3067
-#define A3XX_VBIF_ERR_INFO 0x3068
 
 /* Bit flags for RBBM_CTL */
 #define RBBM_RBBM_CTL_RESET_PWR_CTR1  (1 << 1)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 66baee1..3de3af9 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -156,7 +156,7 @@
 		"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
 		1536, 768, 3, SZ_512K },
 	/* A3XX doesn't use the pix_shader_start */
-	{ ADRENO_REV_A305, 3, 0, 5, 0,
+	{ ADRENO_REV_A305, 3, 0, 5, ANY_ID,
 		"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
 		512, 0, 2, SZ_256K },
 	/* A3XX doesn't use the pix_shader_start */
@@ -254,7 +254,7 @@
 	int sizedwords = 0;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct kgsl_memdesc **reg_map_desc;
-	void *reg_map_array;
+	void *reg_map_array = NULL;
 	int num_iommu_units, i;
 
 	if (!adreno_dev->drawctxt_active)
@@ -500,8 +500,9 @@
 	 * thing and set the chip_id based on the SoC
 	 */
 
+	unsigned int version = socinfo_get_version();
+
 	if (cpu_is_apq8064()) {
-		unsigned int version = socinfo_get_version();
 
 		/* A320 */
 		majorid = 2;
@@ -518,10 +519,21 @@
 		else
 			patchid = 0;
 	} else if (cpu_is_msm8930()) {
+
 		/* A305 */
 		majorid = 0;
 		minorid = 5;
-		patchid = 0;
+
+		/*
+		 * V1.2 has some GPU work arounds that we need to communicate
+		 * up to user space via the patchid
+		 */
+
+		if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
+			(SOCINFO_VERSION_MINOR(version) == 2))
+			patchid = 2;
+		else
+			patchid = 0;
 	}
 
 	return (0x03 << 24) | (majorid << 16) | (minorid << 8) | patchid;
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 4ce56a4..feaa36f 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -46,6 +46,8 @@
 
 #define ADRENO_ISTORE_START 0x5000 /* Istore offset */
 
+#define ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW	50
+
 enum adreno_gpurev {
 	ADRENO_REV_UNKNOWN = 0,
 	ADRENO_REV_A200 = 200,
@@ -90,11 +92,14 @@
 	unsigned int reg_rbbm_status;
 	unsigned int reg_cp_pfp_ucode_data;
 	unsigned int reg_cp_pfp_ucode_addr;
+	/* keeps track of when we need to execute the draw workaround code */
+	int ctx_switches_since_last_draw;
 
 	/* GPU specific function hooks */
 	int (*ctxt_create)(struct adreno_device *, struct adreno_context *);
 	void (*ctxt_save)(struct adreno_device *, struct adreno_context *);
 	void (*ctxt_restore)(struct adreno_device *, struct adreno_context *);
+	void (*ctxt_draw_workaround)(struct adreno_device *);
 	irqreturn_t (*irq_handler)(struct adreno_device *);
 	void (*irq_control)(struct adreno_device *, int);
 	void * (*snapshot)(struct adreno_device *, void *, int *, int);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 7ccfd3f..c3c266e 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1450,11 +1450,49 @@
 	return ret;
 }
 
+static void a2xx_drawctxt_draw_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;
+
+	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+				    &cmd[0], 11);
+}
+
 static void a2xx_drawctxt_save(struct adreno_device *adreno_dev,
 			struct adreno_context *context)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
-	unsigned int cmd[22];
 
 	if (context == NULL)
 		return;
@@ -1499,33 +1537,11 @@
 			adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
 				context->chicken_restore, 3);
 		}
+		adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
 
 		context->flags |= CTXT_FLAGS_GMEM_RESTORE;
-	} else if (adreno_is_a225(adreno_dev)) {
-		unsigned int *cmds = &cmd[0];
-		/*
-		 * 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;
-
-		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
-					    &cmd[0], 11);
-	}
+	} else if (adreno_is_a225(adreno_dev))
+		a2xx_drawctxt_draw_workaround(adreno_dev);
 }
 
 static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
@@ -1983,6 +1999,7 @@
 	.ctxt_create = a2xx_drawctxt_create,
 	.ctxt_save = a2xx_drawctxt_save,
 	.ctxt_restore = a2xx_drawctxt_restore,
+	.ctxt_draw_workaround = a2xx_drawctxt_draw_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 09eae17..600e04f 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2336,39 +2336,6 @@
 	adreno_ringbuffer_submit(rb);
 }
 
-#define VBIF_MAX_CLIENTS 6
-
-static void a3xx_vbif_callback(struct adreno_device *adreno_dev,
-	unsigned int status)
-{
-	struct kgsl_device *device = &adreno_dev->dev;
-	int i;
-	char str[80], *ptr = str;
-	int slen = sizeof(str) - 1;
-
-	KGSL_DRV_INFO(device, "VBIF error | status=%X\n",
-		status);
-
-	for (i = 0; i < VBIF_MAX_CLIENTS; i++) {
-		if (status & (1 << i)) {
-			unsigned int err;
-			int ret;
-
-			adreno_regwrite(device, A3XX_VBIF_ERR_INFO, i);
-			adreno_regread(device, A3XX_VBIF_ERR_INFO, &err);
-
-			ret = snprintf(ptr, slen, "%d:%8.8X ", i, err);
-			ptr += ret;
-			slen -= ret;
-		}
-	}
-
-	KGSL_DRV_INFO(device, "%s\n", str);
-
-	/* Clear the errors */
-	adreno_regwrite(device, A3XX_VBIF_ERR_CLEAR, status);
-}
-
 static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
@@ -2472,7 +2439,6 @@
 
 #define A3XX_INT_MASK \
 	((1 << A3XX_INT_RBBM_AHB_ERROR) |        \
-	 (1 << A3XX_INT_RBBM_REG_TIMEOUT) |      \
 	 (1 << A3XX_INT_RBBM_ATB_BUS_OVERFLOW) | \
 	 (1 << A3XX_INT_CP_T0_PACKET_IN_IB) |    \
 	 (1 << A3XX_INT_CP_OPCODE_ERROR) |       \
@@ -2545,15 +2511,6 @@
 	if (status)
 		adreno_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD,
 			status);
-
-	/* Check for VBIF errors */
-	adreno_regread(&adreno_dev->dev, A3XX_VBIF_ERR_PENDING, &status);
-
-	if (status) {
-		a3xx_vbif_callback(adreno_dev, status);
-		ret = IRQ_HANDLED;
-	}
-
 	return ret;
 }
 
@@ -2561,17 +2518,10 @@
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 
-	if (state) {
+	if (state)
 		adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK);
-
-		/* Enable VBIF interrupts - write 0 to enable them all */
-		adreno_regwrite(device, A3XX_VBIF_ERR_MASK, 0);
-		/* Clear outstanding VBIF errors */
-		adreno_regwrite(device, A3XX_VBIF_ERR_CLEAR, 0x3F);
-	} else {
+	else
 		adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, 0);
-		adreno_regwrite(device, A3XX_VBIF_ERR_MASK, 0xFFFFFFFF);
-	}
 }
 
 static unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev)
@@ -2671,6 +2621,7 @@
 	.ctxt_create = a3xx_drawctxt_create,
 	.ctxt_save = a3xx_drawctxt_save,
 	.ctxt_restore = a3xx_drawctxt_restore,
+	.ctxt_draw_workaround = NULL,
 	.rb_init = a3xx_rb_init,
 	.irq_control = a3xx_irq_control,
 	.irq_handler = a3xx_irq_handler,
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 0d15fb9..49d035f 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -270,8 +270,13 @@
 	}
 
 	/* already current? */
-	if (adreno_dev->drawctxt_active == drawctxt)
+	if (adreno_dev->drawctxt_active == drawctxt) {
+		if (adreno_dev->gpudev->ctxt_draw_workaround &&
+			adreno_is_a225(adreno_dev))
+				adreno_dev->gpudev->ctxt_draw_workaround(
+					adreno_dev);
 		return;
+	}
 
 	KGSL_CTXT_INFO(device, "from %p to %p flags %d\n",
 			adreno_dev->drawctxt_active, drawctxt, flags);
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index a0907d7..5572695 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -674,6 +674,12 @@
 				adreno_find_ctxtmem(device, ptbase, ibaddr,
 					ibsize);
 
+			/* IOMMU uses a NOP IB placed in setsate memory */
+			if (NULL == memdesc)
+				if (kgsl_gpuaddr_in_memdesc(
+						&device->mmu.setstate_memory,
+						ibaddr, ibsize))
+					memdesc = &device->mmu.setstate_memory;
 			/*
 			 * The IB from CP_IB1_BASE and the IBs for legacy
 			 * context switch go into the snapshot all
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index febb265..b3f2d1e 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -82,7 +82,8 @@
 		return -ENOSYS;
 	}
 
-	ptbase = iommu_get_pt_base_addr(domain);
+	ptbase = KGSL_IOMMU_GET_IOMMU_REG(iommu_unit->reg_map.hostptr,
+					iommu_dev->ctx_id, TTBR0);
 
 	fsr = KGSL_IOMMU_GET_IOMMU_REG(iommu_unit->reg_map.hostptr,
 		iommu_dev->ctx_id, FSR);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index ff9f0b8..5216b34 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -761,7 +761,7 @@
 		return 0;
 
 	spin_lock(&pt->lock);
-	if (pt->tlb_flags && (1<<id)) {
+	if (pt->tlb_flags & (1<<id)) {
 		result = KGSL_MMUFLAGS_TLBFLUSH;
 		pt->tlb_flags &= ~(1<<id);
 	}
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 60231f6..3eff40f 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -143,7 +143,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s context_id=%u curr_ts=%u timestamp=0x%x timeout=%u",
+		"d_name=%s context_id=%u curr_ts=0x%x timestamp=0x%x timeout=%u",
 		__get_str(device_name),
 		__entry->context_id,
 		__entry->curr_ts,
@@ -175,7 +175,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s curr_ts=%u result=%d",
+		"d_name=%s curr_ts=0x%x result=%d",
 		__get_str(device_name),
 		__entry->curr_ts,
 		__entry->result
@@ -386,7 +386,7 @@
 
 	TP_printk(
 		"d_name=%s gpuaddr=0x%08x size=%d type=%d ctx=%u"
-		" curr_ts=0x%08x free_ts=0x%08x",
+		" curr_ts=0x%x free_ts=0x%x",
 		__get_str(device_name),
 		__entry->gpuaddr,
 		__entry->size,
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index 5d3a948..964218f 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -248,6 +248,12 @@
 	---help---
 	  Enable support for Gemini Jpeg Engine
 
+config MSM_MERCURY
+        tristate "Qualcomm MSM Mercury Jpeg Decoder Engine support"
+        depends on MSM_CAMERA && ARCH_MSM8960
+        ---help---
+          Enable support for Mercury Jpeg Engine
+
 config MSM_VPE
 	tristate "Qualcomm MSM Video Pre-processing Engine support"
 	depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60)
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index e4d4081..67da5ea 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -18,7 +18,7 @@
 else
   obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
 endif
-obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/
+obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/ mercury/
 obj-$(CONFIG_MSM_CAMERA_FLASH) += flash.o
 obj-$(CONFIG_ARCH_MSM_ARM11) += msm_vfe7x.o
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.h b/drivers/media/video/msm/gemini/msm_gemini_platform.h
index 4542129..eb6b9f0 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_platform.h
+++ b/drivers/media/video/msm/gemini/msm_gemini_platform.h
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/ion.h>
+#include <linux/iommu.h>
 void msm_gemini_platform_p2v(struct file  *file,
 				struct ion_handle **ionhandle);
 uint32_t msm_gemini_platform_v2p(int fd, uint32_t len, struct file **file,
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.c b/drivers/media/video/msm/gemini/msm_gemini_sync.c
index fe7c99f..b55ec18 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_sync.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_sync.c
@@ -453,6 +453,7 @@
 {
 	struct msm_gemini_core_buf *buf_p;
 	struct msm_gemini_buf buf_cmd;
+	int rc = 0;
 
 	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_gemini_buf))) {
 		GMN_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
@@ -469,17 +470,25 @@
 		(int) buf_cmd.vaddr, buf_cmd.y_len);
 
 	if (pgmn_dev->op_mode == MSM_GEMINI_MODE_REALTIME_ENCODE) {
-		buf_p->y_buffer_addr    = buf_cmd.y_off;
+		rc = msm_iommu_map_contig_buffer(
+			(unsigned long)buf_cmd.y_off, CAMERA_DOMAIN, GEN_POOL,
+			((buf_cmd.y_len + buf_cmd.cbcr_len + 4095) & (~4095)),
+			SZ_4K, IOMMU_WRITE | IOMMU_READ,
+			(unsigned long *)&buf_p->y_buffer_addr);
+		if (rc < 0) {
+			pr_err("%s iommu mapping failed with error %d\n",
+				 __func__, rc);
+			kfree(buf_p);
+			return rc;
+		}
 	} else {
 	buf_p->y_buffer_addr    = msm_gemini_platform_v2p(buf_cmd.fd,
 		buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
 		&buf_p->handle)	+ buf_cmd.offset;
 	}
 	buf_p->y_len          = buf_cmd.y_len;
-
 	buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr + buf_cmd.y_len;
 	buf_p->cbcr_len       = buf_cmd.cbcr_len;
-
 	buf_p->num_of_mcu_rows = buf_cmd.num_of_mcu_rows;
 	GMN_DBG("%s: y_addr=%x,y_len=%x,cbcr_addr=%x,cbcr_len=%x\n", __func__,
 		buf_p->y_buffer_addr, buf_p->y_len, buf_p->cbcr_buffer_addr,
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.c b/drivers/media/video/msm/io/msm_camera_i2c.c
index 6f45637..cecf9b0 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.c
+++ b/drivers/media/video/msm/io/msm_camera_i2c.c
@@ -165,6 +165,31 @@
 
 	return rc;
 }
+int32_t msm_camera_i2c_set_write_mask_data(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t data, int16_t mask,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc;
+	uint16_t reg_data;
+	CDBG("%s\n", __func__);
+	if (mask == -1)
+		return 0;
+	if (mask == 0)
+		rc = msm_camera_i2c_write(client, addr, data, data_type);
+	else{
+		rc = msm_camera_i2c_read(client, addr, &reg_data, data_type);
+		if (rc < 0) {
+			CDBG("%s read fail\n", __func__);
+			return rc;
+		}
+		reg_data  = reg_data & mask;
+		reg_data  = (reg_data | (data & (~mask)));
+		rc = msm_camera_i2c_write(client, addr, reg_data, data_type);
+		if (rc < 0)
+			CDBG("%s write fail\n", __func__);
+	}
+	return rc;
+}
 
 int32_t msm_camera_i2c_compare(struct msm_camera_i2c_client *client,
 	uint16_t addr, uint16_t data,
@@ -291,6 +316,13 @@
 					reg_conf_tbl->reg_data,
 					MSM_CAMERA_I2C_WORD_DATA, 0);
 				break;
+			case MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA:
+				rc = msm_camera_i2c_set_write_mask_data(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					reg_conf_tbl->mask,
+					MSM_CAMERA_I2C_BYTE_DATA);
+				break;
 			default:
 				pr_err("%s: Unsupport data type: %d\n",
 					__func__, dt);
@@ -402,7 +434,6 @@
 
 	if (i >= conf->num_index)
 		return rc;
-
 	rc = msm_sensor_write_all_conf_array(client,
 		&conf->conf[i*conf->num_conf], conf->num_conf);
 
@@ -426,4 +457,3 @@
 	return rc;
 }
 
-
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/video/msm/io/msm_camera_i2c.h
index 2fbf5ca..01c8259 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.h
+++ b/drivers/media/video/msm/io/msm_camera_i2c.h
@@ -42,6 +42,7 @@
 	MSM_CAMERA_I2C_UNSET_BYTE_MASK,
 	MSM_CAMERA_I2C_SET_WORD_MASK,
 	MSM_CAMERA_I2C_UNSET_WORD_MASK,
+	MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA,
 };
 
 enum msm_camera_i2c_cmd_type {
@@ -52,6 +53,7 @@
 struct msm_camera_i2c_reg_conf {
 	uint16_t reg_addr;
 	uint16_t reg_data;
+	int16_t mask;
 	enum msm_camera_i2c_data_type dt;
 	enum msm_camera_i2c_cmd_type cmd_type;
 };
diff --git a/drivers/media/video/msm/mercury/Makefile b/drivers/media/video/msm/mercury/Makefile
new file mode 100644
index 0000000..ce4c86d
--- /dev/null
+++ b/drivers/media/video/msm/mercury/Makefile
@@ -0,0 +1,3 @@
+GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+EXTRA_CFLAGS += -Idrivers/media/video/msm
+obj-$(CONFIG_MSM_MERCURY) += msm_mercury_dev.o msm_mercury_core.o msm_mercury_hw.o msm_mercury_platform.o msm_mercury_sync.o
diff --git a/drivers/media/video/msm/mercury/msm_mercury_common.h b/drivers/media/video/msm/mercury/msm_mercury_common.h
new file mode 100644
index 0000000..f5939c1
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_common.h
@@ -0,0 +1,24 @@
+/* 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_MERCURY_COMMON_H
+#define MSM_MERCURY_COMMON_H
+
+#define MSM_MERCURY_DEBUG
+#ifdef MSM_MERCURY_DEBUG
+#define MCR_DBG(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define MCR_DBG(fmt, args...) do { } while (0)
+#endif
+
+#define MCR_PR_ERR   pr_err
+#endif /* MSM_MERCURY_COMMON_H */
diff --git a/drivers/media/video/msm/mercury/msm_mercury_core.c b/drivers/media/video/msm/mercury/msm_mercury_core.c
new file mode 100644
index 0000000..a91c257
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_core.c
@@ -0,0 +1,136 @@
+/* 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/sched.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include "msm_mercury_hw.h"
+#include "msm_mercury_core.h"
+#include "msm_mercury_platform.h"
+#include "msm_mercury_common.h"
+
+static int reset_done_ack;
+static spinlock_t reset_lock;
+static wait_queue_head_t reset_wait;
+
+int mercury_core_reset(void)
+{
+	struct clk *clk = NULL;
+
+	/*Resettting MMSS Fabric*/
+
+	clk = clk_get(NULL, "jpegd_clk");
+
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+
+	msm_bus_axi_porthalt(MSM_BUS_MASTER_JPEG_DEC);
+	clk_reset(clk, CLK_RESET_ASSERT);
+
+	/*need to have some delay here, there is no
+	 other way to know if hardware reset is complete*/
+	usleep_range(1000, 1200);
+
+	msm_bus_axi_portunhalt(MSM_BUS_MASTER_JPEG_DEC);
+	clk_reset(clk, CLK_RESET_DEASSERT);
+
+	return 0;
+}
+
+int msm_mercury_core_reset(void)
+{
+	unsigned long flags;
+	int rc = 0;
+	int tm = 500;/*500ms*/
+	MCR_DBG("\n%s\n(%d)%s()\n", __FILE__, __LINE__, __func__);
+
+	spin_lock_irqsave(&reset_lock, flags);
+	reset_done_ack = 0;
+	spin_unlock_irqrestore(&reset_lock, flags);
+
+	msm_mercury_hw_reset();
+	rc = wait_event_interruptible_timeout(reset_wait,
+		reset_done_ack,
+		msecs_to_jiffies(tm));
+
+	if (!reset_done_ack) {
+		MCR_DBG("%s: reset ACK failed %d", __func__, rc);
+		return -EBUSY;
+	}
+
+	MCR_DBG("(%d)%s() reset_done_ack rc %d\n\n", __LINE__, __func__, rc);
+	spin_lock_irqsave(&reset_lock, flags);
+	reset_done_ack = 0;
+	spin_unlock_irqrestore(&reset_lock, flags);
+
+	return 0;
+}
+
+void msm_mercury_core_init(void)
+{
+	init_waitqueue_head(&reset_wait);
+	spin_lock_init(&reset_lock);
+}
+
+static int (*msm_mercury_irq_handler) (int, void *, void *);
+
+irqreturn_t msm_mercury_core_irq(int irq_num, void *context)
+{
+	void *data = NULL;
+	unsigned long flags;
+	uint16_t mcr_rd_irq;
+	uint16_t mcr_wr_irq;
+	uint32_t jpeg_status;
+
+	MCR_DBG("\n(%d)%s() irq_number = %d", __LINE__, __func__, irq_num);
+
+	spin_lock_irqsave(&reset_lock, flags);
+	reset_done_ack = 1;
+	spin_unlock_irqrestore(&reset_lock, flags);
+
+	msm_mercury_hw_irq_get_status(&mcr_rd_irq, &mcr_wr_irq);
+	msm_mercury_hw_get_jpeg_status(&jpeg_status);
+	MCR_DBG("mercury_rd_irq = 0x%08X\n", mcr_rd_irq);
+	MCR_DBG("mercury_wr_irq = 0x%08X\n", mcr_wr_irq);
+	MCR_DBG("jpeg_status = 0x%08X\n", jpeg_status);
+	if (mcr_wr_irq & MSM_MERCURY_HW_IRQ_SW_RESET_ACK) {
+		MCR_DBG("*** SW Reset IRQ received ***\n");
+		wake_up(&reset_wait);
+		msm_mercury_hw_wr_irq_clear(MSM_MERCURY_HW_IRQ_SW_RESET_ACK);
+	}
+	if (mcr_wr_irq & MSM_MERCURY_HW_IRQ_WR_ERR_ACK) {
+		MCR_DBG("   *** Error IRQ received ***\n");
+		msm_mercury_irq_handler(MSM_MERCURY_HW_IRQ_WR_ERR_ACK,
+								context, data);
+	}
+	if (mcr_wr_irq & MSM_MERCURY_HW_IRQ_WR_EOI_ACK) {
+		MCR_DBG("   *** WE_EOI IRQ received ***\n");
+		msm_mercury_irq_handler(MSM_MERCURY_HW_IRQ_WR_EOI_ACK,
+								context, data);
+	}
+	return IRQ_HANDLED;
+}
+
+void msm_mercury_core_irq_install(int (*irq_handler) (int, void *, void *))
+{
+	msm_mercury_irq_handler = irq_handler;
+}
+
+void msm_mercury_core_irq_remove(void)
+{
+	msm_mercury_irq_handler = NULL;
+}
diff --git a/drivers/media/video/msm/mercury/msm_mercury_core.h b/drivers/media/video/msm/mercury/msm_mercury_core.h
new file mode 100644
index 0000000..e374cee
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_core.h
@@ -0,0 +1,29 @@
+/* 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_MERCURY_CORE_H
+#define MSM_MERCURY_CORE_H
+
+#include <linux/interrupt.h>
+#include "msm_mercury_hw.h"
+
+#define msm_mercury_core_buf msm_mercury_hw_buf
+
+irqreturn_t msm_mercury_core_irq(int irq_num, void *context);
+
+void msm_mercury_core_irq_install(int (*irq_handler) (int, void *, void *));
+void msm_mercury_core_irq_remove(void);
+
+int msm_mercury_core_reset(void);
+void msm_mercury_core_init(void);
+
+#endif /* MSM_MERCURY_CORE_H */
diff --git a/drivers/media/video/msm/mercury/msm_mercury_dev.c b/drivers/media/video/msm/mercury/msm_mercury_dev.c
new file mode 100644
index 0000000..df32b26
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_dev.c
@@ -0,0 +1,256 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_mercury.h>
+#include <mach/board.h>
+#include "msm_mercury_sync.h"
+#include "msm_mercury_common.h"
+#include "msm.h"
+
+#define MSM_MERCURY_NAME "mercury"
+
+static int msm_mercury_open(struct inode *inode, struct file *filp)
+{
+	int rc;
+
+	struct msm_mercury_device *pmercury_dev = container_of(inode->i_cdev,
+		struct msm_mercury_device, cdev);
+	filp->private_data = pmercury_dev;
+
+	MCR_DBG("\n---(%d)%s()\n", __LINE__, __func__);
+
+	rc = __msm_mercury_open(pmercury_dev);
+
+	MCR_DBG("%s:%d] %s open_count = %d\n", __func__, __LINE__,
+		filp->f_path.dentry->d_name.name, pmercury_dev->open_count);
+
+	return rc;
+}
+
+static int msm_mercury_release(struct inode *inode, struct file *filp)
+{
+	int rc;
+
+	struct msm_mercury_device *pmercury_dev = filp->private_data;
+
+	MCR_DBG("\n---(%d)%s()\n", __LINE__, __func__);
+
+	rc = __msm_mercury_release(pmercury_dev);
+
+	MCR_DBG("%s:%d] %s open_count = %d\n", __func__, __LINE__,
+		filp->f_path.dentry->d_name.name, pmercury_dev->open_count);
+	return rc;
+}
+
+static long msm_mercury_ioctl(struct file *filp, unsigned int cmd,
+	unsigned long arg) {
+	int rc;
+	struct msm_mercury_device *pmercury_dev = filp->private_data;
+	rc = __msm_mercury_ioctl(pmercury_dev, cmd, arg);
+	return rc;
+}
+
+static const struct file_operations msm_mercury_fops = {
+	.owner     = THIS_MODULE,
+	.open    = msm_mercury_open,
+	.release = msm_mercury_release,
+	.unlocked_ioctl = msm_mercury_ioctl,
+};
+
+static struct class *msm_mercury_class;
+static dev_t msm_mercury_devno;
+static struct msm_mercury_device *msm_mercury_device_p;
+
+int msm_mercury_subdev_init(struct v4l2_subdev *mercury_sd)
+{
+	int rc;
+	struct msm_mercury_device *pgmn_dev =
+		(struct msm_mercury_device *)mercury_sd->host_priv;
+
+	MCR_DBG("%s:%d: mercury_sd=0x%x pgmn_dev=0x%x\n",
+		__func__, __LINE__, (uint32_t)mercury_sd, (uint32_t)pgmn_dev);
+	rc = __msm_mercury_open(pgmn_dev);
+	MCR_DBG("%s:%d: rc=%d\n",
+		__func__, __LINE__, rc);
+	return rc;
+}
+
+static long msm_mercury_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	long rc;
+	struct msm_mercury_device *pgmn_dev =
+		(struct msm_mercury_device *)sd->host_priv;
+
+	MCR_DBG("%s: cmd=%d\n", __func__, cmd);
+
+	MCR_DBG("%s: pgmn_dev 0x%x", __func__, (uint32_t)pgmn_dev);
+
+	MCR_DBG("%s: Calling __msm_mercury_ioctl\n", __func__);
+
+	rc = __msm_mercury_ioctl(pgmn_dev, cmd, (unsigned long)arg);
+	pr_debug("%s: X\n", __func__);
+	return rc;
+}
+
+void msm_mercury_subdev_release(struct v4l2_subdev *mercury_sd)
+{
+	int rc;
+	struct msm_mercury_device *pgmn_dev =
+		(struct msm_mercury_device *)mercury_sd->host_priv;
+	MCR_DBG("%s:pgmn_dev=0x%x", __func__, (uint32_t)pgmn_dev);
+	rc = __msm_mercury_release(pgmn_dev);
+	MCR_DBG("%s:rc=%d", __func__, rc);
+}
+
+static const struct v4l2_subdev_core_ops msm_mercury_subdev_core_ops = {
+	.ioctl = msm_mercury_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_mercury_subdev_ops = {
+	.core = &msm_mercury_subdev_core_ops,
+};
+
+static int msm_mercury_init(struct platform_device *pdev)
+{
+	int rc = -1;
+	struct device *dev;
+
+	MCR_DBG("%s:\n", __func__);
+	msm_mercury_device_p = __msm_mercury_init(pdev);
+	if (msm_mercury_device_p == NULL) {
+		MCR_PR_ERR("%s: initialization failed\n", __func__);
+		goto fail;
+	}
+
+	v4l2_subdev_init(&msm_mercury_device_p->subdev,
+		&msm_mercury_subdev_ops);
+	v4l2_set_subdev_hostdata(&msm_mercury_device_p->subdev,
+		msm_mercury_device_p);
+	pr_debug("%s: msm_mercury_device_p 0x%x", __func__,
+		(uint32_t)msm_mercury_device_p);
+	MCR_DBG("%s:mercury: platform_set_drvdata\n", __func__);
+	platform_set_drvdata(pdev, &msm_mercury_device_p->subdev);
+
+	rc = alloc_chrdev_region(&msm_mercury_devno, 0, 1, MSM_MERCURY_NAME);
+	if (rc < 0) {
+		MCR_PR_ERR("%s: failed to allocate chrdev\n", __func__);
+		goto fail_1;
+	}
+
+	if (!msm_mercury_class) {
+		msm_mercury_class = class_create(THIS_MODULE, MSM_MERCURY_NAME);
+		if (IS_ERR(msm_mercury_class)) {
+			rc = PTR_ERR(msm_mercury_class);
+			MCR_PR_ERR("%s: create device class failed\n",
+				__func__);
+			goto fail_2;
+		}
+	}
+
+	dev = device_create(msm_mercury_class, NULL,
+		MKDEV(MAJOR(msm_mercury_devno), MINOR(msm_mercury_devno)), NULL,
+		"%s%d", MSM_MERCURY_NAME, 0);
+
+	if (IS_ERR(dev)) {
+		MCR_PR_ERR("%s: error creating device\n", __func__);
+		rc = -ENODEV;
+		goto fail_3;
+	}
+
+	cdev_init(&msm_mercury_device_p->cdev, &msm_mercury_fops);
+	msm_mercury_device_p->cdev.owner = THIS_MODULE;
+	msm_mercury_device_p->cdev.ops   =
+		(const struct file_operations *) &msm_mercury_fops;
+	rc = cdev_add(&msm_mercury_device_p->cdev, msm_mercury_devno, 1);
+	if (rc < 0) {
+		MCR_PR_ERR("%s: error adding cdev\n", __func__);
+		rc = -ENODEV;
+		goto fail_4;
+	}
+
+	MCR_DBG("%s %s: success\n", __func__, MSM_MERCURY_NAME);
+
+	return rc;
+
+fail_4:
+	device_destroy(msm_mercury_class, msm_mercury_devno);
+
+fail_3:
+	class_destroy(msm_mercury_class);
+
+fail_2:
+	unregister_chrdev_region(msm_mercury_devno, 1);
+
+fail_1:
+	__msm_mercury_exit(msm_mercury_device_p);
+
+fail:
+	return rc;
+}
+
+static void msm_mercury_exit(void)
+{
+	cdev_del(&msm_mercury_device_p->cdev);
+	device_destroy(msm_mercury_class, msm_mercury_devno);
+	class_destroy(msm_mercury_class);
+	unregister_chrdev_region(msm_mercury_devno, 1);
+
+	__msm_mercury_exit(msm_mercury_device_p);
+}
+
+static int __msm_mercury_probe(struct platform_device *pdev)
+{
+	return msm_mercury_init(pdev);
+}
+
+static int __msm_mercury_remove(struct platform_device *pdev)
+{
+	msm_mercury_exit();
+	return 0;
+}
+
+static struct platform_driver msm_mercury_driver = {
+	.probe  = __msm_mercury_probe,
+	.remove = __msm_mercury_remove,
+	.driver = {
+		.name = MSM_MERCURY_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_mercury_driver_init(void)
+{
+	int rc;
+	rc = platform_driver_register(&msm_mercury_driver);
+	return rc;
+}
+
+static void __exit msm_mercury_driver_exit(void)
+{
+	platform_driver_unregister(&msm_mercury_driver);
+}
+
+MODULE_DESCRIPTION("msm mercury jpeg driver");
+
+module_init(msm_mercury_driver_init);
+module_exit(msm_mercury_driver_exit);
diff --git a/drivers/media/video/msm/mercury/msm_mercury_hw.c b/drivers/media/video/msm/mercury/msm_mercury_hw.c
new file mode 100644
index 0000000..7bc4abe
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_hw.c
@@ -0,0 +1,361 @@
+/* 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/delay.h>
+#include <linux/io.h>
+#include "msm_mercury_hw.h"
+#include "msm_mercury_common.h"
+#include "msm_mercury_hw_reg.h"
+#include "msm_mercury_macros.h"
+
+static void *mercury_region_base;
+static uint32_t mercury_region_size;
+
+
+void msm_mercury_hw_write(struct msm_mercury_hw_cmd *hw_cmd_p)
+{
+	uint32_t *paddr;
+	uint32_t old_data, new_data;
+
+	paddr = mercury_region_base + hw_cmd_p->offset;
+
+	if (hw_cmd_p->mask == 0xffffffff) {
+		old_data = 0;
+	} else {
+		old_data = readl_relaxed(paddr);
+		old_data &= ~hw_cmd_p->mask;
+	}
+
+	new_data = hw_cmd_p->data & hw_cmd_p->mask;
+	new_data |= old_data;
+	writel_relaxed(new_data, paddr);
+}
+
+uint32_t msm_mercury_hw_read(struct msm_mercury_hw_cmd *hw_cmd_p)
+{
+	uint32_t *paddr;
+	uint32_t data;
+
+	paddr = mercury_region_base + hw_cmd_p->offset;
+
+	data = readl_relaxed(paddr);
+	data &= hw_cmd_p->mask;
+
+	MCR_DBG("MERCURY_READ: offset=0x%04X data=0x%08X\n",
+		hw_cmd_p->offset, data);
+
+	return data;
+}
+
+void msm_mercury_hw_start_decode(void)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kread(JPEG_STATUS);
+	mercury_kread(RTDMA_JPEG_RD_STA_ACK);
+	mercury_kread(RTDMA_JPEG_WR_STA_ACK);
+	mercury_kread(RTDMA_JPEG_RD_BUF_Y_PNTR);
+	mercury_kread(RTDMA_JPEG_WR_BUF_Y_PNTR);
+	mercury_kread(RTDMA_JPEG_WR_BUF_U_PNTR);
+	mercury_kwrite(RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO, (7<<2));
+	return;
+}
+
+void msm_mercury_hw_bitstream_buf_cfg(uint32_t bitstream_buf_addr)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kwrite(RTDMA_JPEG_RD_BUF_Y_PNTR, bitstream_buf_addr);
+	return;
+}
+
+
+void msm_mercury_hw_output_y_buf_cfg(uint32_t y_buf_addr)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kwrite(RTDMA_JPEG_WR_BUF_Y_PNTR, y_buf_addr);
+	return;
+}
+
+void msm_mercury_hw_output_u_buf_cfg(uint32_t u_buf_addr)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kwrite(RTDMA_JPEG_WR_BUF_U_PNTR, u_buf_addr);
+	return;
+}
+
+void msm_mercury_hw_output_v_buf_cfg(uint32_t v_buf_addr)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kwrite(RTDMA_JPEG_WR_BUF_V_PNTR, v_buf_addr);
+	return;
+}
+
+int msm_mercury_hw_wait(struct msm_mercury_hw_cmd *hw_cmd_p, int m_us)
+{
+	int tm = hw_cmd_p->n;
+	uint32_t data;
+	uint32_t wait_data = hw_cmd_p->data & hw_cmd_p->mask;
+
+	data = msm_mercury_hw_read(hw_cmd_p);
+	if (data != wait_data) {
+		while (tm) {
+			udelay(m_us);
+			data = msm_mercury_hw_read(hw_cmd_p);
+			if (data == wait_data)
+				break;
+			tm--;
+		}
+	}
+	hw_cmd_p->data = data;
+	return tm;
+}
+
+void msm_mercury_hw_irq_get_status(uint16_t *rd_irq, uint16_t *wr_irq)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+	rmb();
+	mercury_kread(RTDMA_JPEG_RD_STA_ACK);
+	*rd_irq = hw_cmd.data;
+
+	mercury_kread(RTDMA_JPEG_WR_STA_ACK);
+	*wr_irq = hw_cmd.data;
+	rmb();
+}
+
+void msm_mercury_hw_get_jpeg_status(uint32_t *jpeg_status)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	rmb();
+	mercury_kread(JPEG_STATUS);
+	*jpeg_status = hw_cmd.data;
+	rmb();
+}
+
+uint32_t msm_mercury_get_restartInterval(void)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	rmb();
+	mercury_kread(JPEG_DRI);
+	rmb();
+	return hw_cmd.data;
+
+}
+
+void msm_mercury_hw_rd_irq_clear(uint32_t val)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+	mercury_kwrite(RTDMA_JPEG_RD_STA_ACK, val);
+}
+
+void msm_mercury_hw_wr_irq_clear(uint32_t val)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kwrite(RTDMA_JPEG_WR_STA_ACK, val);
+}
+
+void msm_mercury_hw_set_rd_irq_mask(uint32_t val)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kwrite(RTDMA_JPEG_RD_INT_EN, val);
+}
+
+void msm_mercury_hw_set_wr_irq_mask(uint32_t val)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kwrite(RTDMA_JPEG_WR_INT_EN, val);
+}
+
+void msm_mercury_set_jpeg_ctl_common(uint32_t val)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	mercury_kwrite(JPEG_CTRL_COMMON, val);
+}
+
+void msm_mercury_hw_reset(void)
+{
+	uint32_t val;
+	struct msm_mercury_hw_cmd hw_cmd;
+
+	wmb();
+	/* disable all interrupts*/
+	mercury_kwrite(RTDMA_JPEG_RD_INT_EN, 0);
+
+	mercury_kwrite(RTDMA_JPEG_WR_INT_EN, 0);
+
+	/* clear pending interrupts*/
+	val = 0;
+	MEM_OUTF2(&val, RTDMA_JPEG_WR_STA_ACK,
+		SW_RESET_ABORT_RDY_ACK,
+		ERR_ACK, 1, 1);
+	MEM_OUTF2(&val, RTDMA_JPEG_WR_STA_ACK, EOF_ACK, SOF_ACK, 1, 1);
+	mercury_kwrite(RTDMA_JPEG_WR_STA_ACK, val);
+
+	val = 0;
+	MEM_OUTF2(&val, RTDMA_JPEG_RD_STA_ACK, EOF_ACK, SOF_ACK, 1, 1);
+	mercury_kwrite(RTDMA_JPEG_RD_STA_ACK, val);
+
+	/* enable SWResetAbortRdyInt for core reset*/
+	val = 0;
+	MEM_OUTF(&val, RTDMA_JPEG_WR_INT_EN, SW_RESET_ABORT_RDY_EN, 1);
+	mercury_kwrite(RTDMA_JPEG_WR_INT_EN, val);
+
+	/* Reset Core from MMSS Fabric*/
+	mercury_core_reset();
+
+	/* disable all interrupts*/
+	mercury_kwrite(RTDMA_JPEG_WR_INT_EN, 0);
+
+	/* clear pending interrupts*/
+	val = 0;
+	MEM_OUTF2(&val, RTDMA_JPEG_WR_STA_ACK,
+		SW_RESET_ABORT_RDY_ACK,
+		ERR_ACK, 1, 1);
+	MEM_OUTF2(&val, RTDMA_JPEG_WR_STA_ACK, EOF_ACK, SOF_ACK, 1, 1);
+	mercury_kwrite(RTDMA_JPEG_WR_STA_ACK, val);
+
+	val = 0;
+	MEM_OUTF2(&val, RTDMA_JPEG_RD_STA_ACK, EOF_ACK, SOF_ACK, 1, 1);
+	mercury_kwrite(RTDMA_JPEG_RD_STA_ACK, val);
+
+	/* enable neccessary interrupt source*/
+	val = 0;
+	MEM_OUTF2(&val, RTDMA_JPEG_WR_INT_EN, EOF_EN, ERR_EN, 1, 1);
+	MEM_OUTF(&val, RTDMA_JPEG_WR_INT_EN, SW_RESET_ABORT_RDY_EN, 1);
+	mercury_kwrite(RTDMA_JPEG_WR_INT_EN, val);
+
+	wmb();
+
+}
+
+void msm_mercury_hw_init(void *base, int size)
+{
+	mercury_region_base = base;
+	mercury_region_size = size;
+}
+
+
+void msm_mercury_hw_delay(struct msm_mercury_hw_cmd *hw_cmd_p, int m_us)
+{
+	int tm = hw_cmd_p->n;
+	while (tm) {
+		udelay(m_us);
+		tm--;
+	}
+}
+
+int msm_mercury_hw_exec_cmds(struct msm_mercury_hw_cmd *hw_cmd_p, int m_cmds)
+{
+	int is_copy_to_user = -1;
+	uint32_t data;
+	if (m_cmds > 1)
+		MCR_DBG("m_cmds = %d\n", m_cmds);
+
+	while (m_cmds--) {
+		if (hw_cmd_p->offset > mercury_region_size) {
+			MCR_PR_ERR("%s:%d] %d exceed hw region %d\n",
+					__func__, __LINE__, hw_cmd_p->offset,
+					mercury_region_size);
+			return -EFAULT;
+		}
+
+		switch (hw_cmd_p->type) {
+		case MSM_MERCURY_HW_CMD_TYPE_READ:
+			hw_cmd_p->data = msm_mercury_hw_read(hw_cmd_p);
+			is_copy_to_user = 1;
+			break;
+
+		case MSM_MERCURY_HW_CMD_TYPE_WRITE:
+			msm_mercury_hw_write(hw_cmd_p);
+			break;
+
+		case MSM_MERCURY_HW_CMD_TYPE_WRITE_OR:
+			data = msm_mercury_hw_read(hw_cmd_p);
+			hw_cmd_p->data = (hw_cmd_p->data & hw_cmd_p->mask) |
+				data;
+			msm_mercury_hw_write(hw_cmd_p);
+			break;
+
+		case MSM_MERCURY_HW_CMD_TYPE_UWAIT:
+			msm_mercury_hw_wait(hw_cmd_p, 1);
+			break;
+
+		case MSM_MERCURY_HW_CMD_TYPE_MWAIT:
+			msm_mercury_hw_wait(hw_cmd_p, 1000);
+			break;
+
+		case MSM_MERCURY_HW_CMD_TYPE_UDELAY:
+			msm_mercury_hw_delay(hw_cmd_p, 1);
+			break;
+
+		case MSM_MERCURY_HW_CMD_TYPE_MDELAY:
+			msm_mercury_hw_delay(hw_cmd_p, 1000);
+			break;
+
+		default:
+			MCR_DBG("wrong hw command type\n");
+			break;
+		}
+
+		hw_cmd_p++;
+	}
+	return is_copy_to_user;
+}
+
+void msm_mercury_hw_region_dump(int size)
+{
+	uint32_t *p;
+	uint8_t *p8;
+
+	MCR_DBG("(%d)%s()\n", __LINE__, __func__);
+	if (size > mercury_region_size)
+		MCR_DBG("%s:%d] wrong region dump size\n",
+			__func__, __LINE__);
+
+	p = (uint32_t *) mercury_region_base;
+	while (size >= 16) {
+		MCR_DBG("0x%08X] %08X %08X %08X %08X\n",
+			mercury_region_size - size,
+			readl_relaxed(p), readl_relaxed(p+1),
+			readl_relaxed(p+2), readl_relaxed(p+3));
+		p += 4;
+		size -= 16;
+	}
+
+	if (size > 0) {
+		uint32_t d;
+		MCR_DBG("0x%08X] ", mercury_region_size - size);
+		while (size >= 4) {
+			MCR_DBG("%08X ", readl_relaxed(p++));
+			size -= 4;
+		}
+
+		d = readl_relaxed(p);
+		p8 = (uint8_t *) &d;
+		while (size) {
+			MCR_DBG("%02X", *p8++);
+			size--;
+		}
+
+		MCR_DBG("\n");
+	}
+}
diff --git a/drivers/media/video/msm/mercury/msm_mercury_hw.h b/drivers/media/video/msm/mercury/msm_mercury_hw.h
new file mode 100644
index 0000000..f6e3e49
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_hw.h
@@ -0,0 +1,70 @@
+/* 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_MERCURY_HW_H
+#define MSM_MERCURY_HW_H
+
+#include <media/msm_mercury.h>
+
+/*number of pel per block (horiz/vert)*/
+#define JPEGDEC_BLOCK_SIZE                 (8)
+/* Hardware alignment*/
+#define JPEGDEC_HW_ALIGN                   (8)
+#define JPEGDEC_HW_SAMPLING_RATIO_MAX      (4)
+
+#define MSM_MERCURY_HW_IRQ_SW_RESET_ACK    (1<<3)
+#define MSM_MERCURY_HW_IRQ_WR_ERR_ACK      (1<<2)
+#define MSM_MERCURY_HW_IRQ_WR_EOI_ACK      (1<<1)
+#define MSM_MERCURY_HW_IRQ_WR_SOF_ACK      (1<<0)
+
+#define MSM_MERCURY_HW_IRQ_RD_EOF_ACK      (1<<1)
+#define MSM_MERCURY_HW_IRQ_RD_SOF_ACK      (1<<0)
+
+extern int mercury_core_reset(void);
+
+struct msm_mercury_hw_buf {
+		struct msm_mercury_buf vbuf;
+		struct file  *file;
+		uint32_t framedone_len;
+		uint32_t y_buffer_addr;
+		uint32_t y_len;
+		uint32_t cbcr_buffer_addr;
+		uint32_t cbcr_len;
+		uint32_t num_of_mcu_rows;
+		struct msm_mapped_buffer *msm_buffer;
+		int *subsystem_id;
+		struct ion_handle *handle;
+};
+
+
+void msm_mercury_hw_reset(void);
+void msm_mercury_hw_init(void *base, int size);
+void msm_mercury_hw_rd_irq_clear(uint32_t val);
+void msm_mercury_hw_wr_irq_clear(uint32_t val);
+
+uint32_t msm_mercury_hw_read(struct msm_mercury_hw_cmd *hw_cmd_p);
+void msm_mercury_hw_write(struct msm_mercury_hw_cmd *hw_cmd_p);
+int msm_mercury_hw_wait(struct msm_mercury_hw_cmd *hw_cmd_p, int m_us);
+void msm_mercury_hw_delay(struct msm_mercury_hw_cmd *hw_cmd_p, int m_us);
+int msm_mercury_hw_exec_cmds(struct msm_mercury_hw_cmd *hw_cmd_p, int m_cmds);
+void msm_mercury_hw_region_dump(int size);
+
+
+void msm_mercury_hw_irq_get_status(uint16_t *rd_irq, uint16_t *wr_irq);
+void msm_mercury_hw_start_decode(void);
+void msm_mercury_hw_get_jpeg_status(uint32_t *jpeg_status);
+void msm_mercury_hw_output_y_buf_cfg(uint32_t y_buf_addr);
+void msm_mercury_hw_output_u_buf_cfg(uint32_t u_buf_addr);
+void msm_mercury_hw_output_v_buf_cfg(uint32_t v_buf_addr);
+void msm_mercury_hw_bitstream_buf_cfg(uint32_t bitstream_buf_addr);
+
+#endif /* MSM_MERCURY_HW_H */
diff --git a/drivers/media/video/msm/mercury/msm_mercury_hw_reg.h b/drivers/media/video/msm/mercury/msm_mercury_hw_reg.h
new file mode 100644
index 0000000..671bc66
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_hw_reg.h
@@ -0,0 +1,715 @@
+/* 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_MERCURY_HW_REG_H
+#define MSM_MERCURY_HW_REG_H
+
+
+#define JPEGD_BASE  0x00000000
+
+/* Register ADDR, RMSK, and SHFT*/
+/* RW */
+#define JPEG_CTRL_COMMON                        JPEG_CTRL_COMMON
+#define HWIO_JPEG_CTRL_COMMON_ADDR            (JPEGD_BASE+0x00000000)
+#define HWIO_JPEG_CTRL_COMMON__POR                    0x00000000
+#define HWIO_JPEG_CTRL_COMMON__RMSK                   0x0000001F
+#define HWIO_JPEG_CTRL_COMMON__SHFT                            0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_CTRL_COMMON__JPEG_CTRL_COMMON_ZZ_OVERRIDE_EN__BMSK 0x00000010
+#define HWIO_JPEG_CTRL_COMMON__JPEG_CTRL_COMMON_ZZ_OVERRIDE_EN__SHFT          4
+#define HWIO_JPEG_CTRL_COMMON__JPEG_CTRL_COMMON_MODE__BMSK           0x0000000F
+#define HWIO_JPEG_CTRL_COMMON__JPEG_CTRL_COMMON_MODE__SHFT                    0
+
+/* Register Field FMSK and SHFT*/
+/* RW */
+#define JPEG_CTRL_ENCODE                     JPEG_CTRL_ENCODE
+#define HWIO_JPEG_CTRL_ENCODE_ADDR        (JPEGD_BASE+0x00000008)
+#define HWIO_JPEG_CTRL_ENCODE__POR                 0x00000000
+#define HWIO_JPEG_CTRL_ENCODE__RMSK                0x00000010
+#define HWIO_JPEG_CTRL_ENCODE__SHFT                         4
+/* Register Element MIN and MAX*/
+#define HWIO_JPEG_CTRL_ENCODE___S                           4
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_CTRL_ENCODE__JPEG_CTRL_ENCODE_EOI_MARKER_EN__BMSK  0x00000010
+#define HWIO_JPEG_CTRL_ENCODE__JPEG_CTRL_ENCODE_EOI_MARKER_EN__SHFT           4
+
+/* Register Field FMSK and SHFT*/
+#define JPEG_STATUS                        JPEG_STATUS
+#define HWIO_JPEG_STATUS_ADDR        (JPEGD_BASE+0x00000010)
+#define HWIO_JPEG_STATUS__POR               0x00000000
+#define HWIO_JPEG_STATUS__RMSK              0x00003FF0
+#define HWIO_JPEG_STATUS__SHFT                       4
+/* Register Element MIN and MAX*/
+#define HWIO_JPEG_STATUS___S                         4
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_STATUS__JPEG_STATUS_REGISTER_TIMEOUT__BMSK       0x00002000
+#define HWIO_JPEG_STATUS__JPEG_STATUS_REGISTER_TIMEOUT__SHFT               13
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_EOI__BMSK               0x00001000
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_EOI__SHFT                       12
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_UNESCAPED_FF__BMSK  0x00000800
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_UNESCAPED_FF__SHFT          11
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_INV_HUFFCODE__BMSK  0x00000400
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_INV_HUFFCODE__SHFT          10
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_INV_MARKER__BMSK    0x00000200
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_INV_MARKER__SHFT             9
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_RSTRT_SEQ__BMSK     0x00000100
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_RSTRT_SEQ__SHFT              8
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_RSTRT_OVRFLW__BMSK  0x00000080
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_RSTRT_OVRFLW__SHFT           7
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_RSTRT_UNDFLW__BMSK  0x00000040
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_RSTRT_UNDFLW__SHFT           6
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_SCAN_OVRFLW__BMSK   0x00000020
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_SCAN_OVRFLW__SHFT            5
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_SCAN_UNDFLW__BMSK   0x00000010
+#define HWIO_JPEG_STATUS__JPEG_STATUS_DHDQ_ERR_SCAN_UNDFLW__SHFT            4
+
+/* Register ADDR, RMSK, and SHFT*/
+/* R */
+#define JPEG_SOF_REG_0                               JPEG_SOF_REG_0
+#define HWIO_JPEG_SOF_REG_0_ADDR  /* RW */               (JPEGD_BASE+0x00000014)
+#define HWIO_JPEG_SOF_REG_0__POR                         0x00000000
+#define HWIO_JPEG_SOF_REG_0__RMSK                        0x000000FF
+#define HWIO_JPEG_SOF_REG_0__SHFT                                 0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_SOF_REG_0__JPEG_SOF_REG_0_NF__BMSK     0x000000FF
+#define HWIO_JPEG_SOF_REG_0__JPEG_SOF_REG_0_NF__SHFT              0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_SOF_REG_1                               JPEG_SOF_REG_1
+#define HWIO_JPEG_SOF_REG_1_ADDR  /* RW */               (JPEGD_BASE+0x00000018)
+#define HWIO_JPEG_SOF_REG_1__POR                         0x00000000
+#define HWIO_JPEG_SOF_REG_1__RMSK                        0x00FFFFFF
+#define HWIO_JPEG_SOF_REG_1__SHFT                                 0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_SOF_REG_1__JPEG_SOF_REG_1_C__BMSK      0x00FF0000
+#define HWIO_JPEG_SOF_REG_1__JPEG_SOF_REG_1_C__SHFT              16
+#define HWIO_JPEG_SOF_REG_1__JPEG_SOF_REG_1_H__BMSK      0x0000F000
+#define HWIO_JPEG_SOF_REG_1__JPEG_SOF_REG_1_H__SHFT              12
+#define HWIO_JPEG_SOF_REG_1__JPEG_SOF_REG_1_V__BMSK      0x00000F00
+#define HWIO_JPEG_SOF_REG_1__JPEG_SOF_REG_1_V__SHFT               8
+#define HWIO_JPEG_SOF_REG_1__JPEG_SOF_REG_1_TQ__BMSK     0x000000FF
+#define HWIO_JPEG_SOF_REG_1__JPEG_SOF_REG_1_TQ__SHFT              0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_SOF_REG_2                               JPEG_SOF_REG_2
+#define HWIO_JPEG_SOF_REG_2_ADDR  /* RW */               (JPEGD_BASE+0x0000001C)
+#define HWIO_JPEG_SOF_REG_2__POR                         0x00000000
+#define HWIO_JPEG_SOF_REG_2__RMSK                        0xFFFFFFFF
+#define HWIO_JPEG_SOF_REG_2__SHFT                                 0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_SOF_REG_2__JPEG_SOF_REG_2_Y__BMSK      0xFFFF0000
+#define HWIO_JPEG_SOF_REG_2__JPEG_SOF_REG_2_Y__SHFT              16
+#define HWIO_JPEG_SOF_REG_2__JPEG_SOF_REG_2_X__BMSK      0x0000FFFF
+#define HWIO_JPEG_SOF_REG_2__JPEG_SOF_REG_2_X__SHFT               0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_SOS_REG_0                               JPEG_SOS_REG_0
+#define HWIO_JPEG_SOS_REG_0_ADDR  /* RW */               (JPEGD_BASE+0x00000020)
+#define HWIO_JPEG_SOS_REG_0__POR                         0x00000000
+#define HWIO_JPEG_SOS_REG_0__RMSK                        0xFF000000
+#define HWIO_JPEG_SOS_REG_0__SHFT                                24
+/*Register Element MIN and MAX*/
+#define HWIO_JPEG_SOS_REG_0___S                                  24
+#define HWIO_JPEG_SOS_REG_0___S                                  24
+#define HWIO_JPEG_SOS_REG_0___S                                  24
+#define HWIO_JPEG_SOS_REG_0___S                                  24
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_SOS_REG_0__JPEG_SOS_REG_0_NS__BMSK       0xFF000000
+#define HWIO_JPEG_SOS_REG_0__JPEG_SOS_REG_0_NS__SHFT               24
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_SOS_REG_1                                   JPEG_SOS_REG_1
+#define HWIO_JPEG_SOS_REG_1_ADDR  /* RW */              (JPEGD_BASE+0x00000024)
+#define HWIO_JPEG_SOS_REG_1__POR                        0x00000000
+#define HWIO_JPEG_SOS_REG_1__RMSK                       0x0000FFFF
+#define HWIO_JPEG_SOS_REG_1__SHFT                                0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_SOS_REG_1__JPEG_SOS_REG_1_CS__BMSK    0x0000FF00
+#define HWIO_JPEG_SOS_REG_1__JPEG_SOS_REG_1_CS__SHFT             8
+#define HWIO_JPEG_SOS_REG_1__JPEG_SOS_REG_1_TD__BMSK    0x000000F0
+#define HWIO_JPEG_SOS_REG_1__JPEG_SOS_REG_1_TD__SHFT             4
+#define HWIO_JPEG_SOS_REG_1__JPEG_SOS_REG_1_TA__BMSK    0x0000000F
+#define HWIO_JPEG_SOS_REG_1__JPEG_SOS_REG_1_TA__SHFT             0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_QT_IDX                                       JPEG_QT_IDX
+#define HWIO_JPEG_QT_IDX_ADDR       (JPEGD_BASE+0x00000030)
+#define HWIO_JPEG_QT_IDX__POR                              0x00000000
+#define HWIO_JPEG_QT_IDX__RMSK                             0x0000FFFF
+#define HWIO_JPEG_QT_IDX__SHFT                                      0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_QT_IDX__JPEG_QT_IDX_TABLE_1__BMSK        0x0000FF00
+#define HWIO_JPEG_QT_IDX__JPEG_QT_IDX_TABLE_1__SHFT                  8
+#define HWIO_JPEG_QT_IDX__JPEG_QT_IDX_TABLE_0__BMSK         0x000000FF
+#define HWIO_JPEG_QT_IDX__JPEG_QT_IDX_TABLE_0__SHFT                  0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_DQT                                        JPEG_DQT
+#define HWIO_JPEG_DQT_ADDR  /* RW */                    (JPEGD_BASE+0x00000034)
+#define HWIO_JPEG_DQT__POR                              0x00000000
+#define HWIO_JPEG_DQT__RMSK                             0x0F00FFFF
+#define HWIO_JPEG_DQT__SHFT                             0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DQT__JPEG_DQT_TQ__BMSK                0x0F000000
+#define HWIO_JPEG_DQT__JPEG_DQT_TQ__SHFT                24
+#define HWIO_JPEG_DQT__JPEG_DQT_QK__BMSK                0x0000FFFF
+#define HWIO_JPEG_DQT__JPEG_DQT_QK__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_DRI                                JPEG_DRI
+#define HWIO_JPEG_DRI_ADDR  /* RW */            (JPEGD_BASE+0x00000040)
+#define HWIO_JPEG_DRI__POR                      0x00000000
+#define HWIO_JPEG_DRI__RMSK                     0x0000FFFF
+#define HWIO_JPEG_DRI__SHFT                              0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DRI__JPEG_DRI_RI__BMSK        0x0000FFFF
+#define HWIO_JPEG_DRI__JPEG_DRI_RI__SHFT                 0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_DHT_REG_0                               JPEG_DHT_REG_0
+#define HWIO_JPEG_DHT_REG_0_ADDR  /* RW */               (JPEGD_BASE+0x00000050)
+#define HWIO_JPEG_DHT_REG_0__POR                         0x00000000
+#define HWIO_JPEG_DHT_REG_0__RMSK                        0x000000FF
+#define HWIO_JPEG_DHT_REG_0__SHFT                                 0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DHT_REG_0__JPEG_DHT_REG_0_TH__BMSK     0x000000F0
+#define HWIO_JPEG_DHT_REG_0__JPEG_DHT_REG_0_TH__SHFT              4
+#define HWIO_JPEG_DHT_REG_0__JPEG_DHT_REG_0_TC__BMSK     0x0000000F
+#define HWIO_JPEG_DHT_REG_0__JPEG_DHT_REG_0_TC__SHFT              0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_DHT_IDX                                        JPEG_DHT_IDX
+#define HWIO_JPEG_DHT_IDX_ADDR  /* RW */      (JPEGD_BASE+0x00000054)
+#define HWIO_JPEG_DHT_IDX__POR                                0x00000000
+#define HWIO_JPEG_DHT_IDX__RMSK                               0x00000FFF
+#define HWIO_JPEG_DHT_IDX__SHFT                                        0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DHT_IDX__JPEG_DHT_IDX_CCC_MAX__BMSK         0x00000F00
+#define HWIO_JPEG_DHT_IDX__JPEG_DHT_IDX_CCC_MAX__SHFT                  8
+#define HWIO_JPEG_DHT_IDX__JPEG_DHT_IDX_VIJ__BMSK             0x000000FF
+#define HWIO_JPEG_DHT_IDX__JPEG_DHT_IDX_VIJ__SHFT                      0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_DHT_REG_1                          JPEG_DHT_REG_1
+#define HWIO_JPEG_DHT_REG_1_ADDR  /* RW */          (JPEGD_BASE+0x00000058)
+#define HWIO_JPEG_DHT_REG_1__POR                    0x00000000
+#define HWIO_JPEG_DHT_REG_1__RMSK                   0xFFFFFFFF
+#define HWIO_JPEG_DHT_REG_1__SHFT                            0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DHT_REG_1__JPEG_DHT_REG_1_VIJ_0__BMSK       0xFF000000
+#define HWIO_JPEG_DHT_REG_1__JPEG_DHT_REG_1_VIJ_0__SHFT               24
+#define HWIO_JPEG_DHT_REG_1__JPEG_DHT_REG_1_VIJ_1__BMSK       0x00FF0000
+#define HWIO_JPEG_DHT_REG_1__JPEG_DHT_REG_1_VIJ_1__SHFT               16
+#define HWIO_JPEG_DHT_REG_1__JPEG_DHT_REG_1_VIJ_2__BMSK       0x0000FF00
+#define HWIO_JPEG_DHT_REG_1__JPEG_DHT_REG_1_VIJ_2__SHFT                8
+#define HWIO_JPEG_DHT_REG_1__JPEG_DHT_REG_1_VIJ_3__BMSK       0x000000FF
+#define HWIO_JPEG_DHT_REG_1__JPEG_DHT_REG_1_VIJ_3__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_DHT_CCC_MAX                          JPEG_DHT_CCC_MAX
+#define HWIO_JPEG_DHT_CCC_MAX_ADDR  /* RW */            (JPEGD_BASE+0x0000005C)
+#define HWIO_JPEG_DHT_CCC_MAX__POR                      0x00000000
+#define HWIO_JPEG_DHT_CCC_MAX__RMSK                     0xFFFFFFFF
+#define HWIO_JPEG_DHT_CCC_MAX__SHFT                              0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_CCC_MAX_MAX__BMSK    0xFFFF0000
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_CCC_MAX_MAX__SHFT            16
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_CCC_MAX_CCC__BMSK    0x0000FFFF
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_CCC_MAX_CCC__SHFT             0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_CCC_MAX_MAX__BMSK    0xFFFF0000
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_CCC_MAX_MAX__SHFT            16
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_CCC_MAX_CCC__BMSK    0x0000FFFF
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_CCC_MAX_CCC__SHFT             0
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_LI__BMSK       0x000000FF
+#define HWIO_JPEG_DHT_CCC_MAX__JPEG_DHT_LI__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_DEC_SCALE                       JPEG_DEC_SCALE
+#define HWIO_JPEG_DEC_SCALE_ADDR  /* RW */       (JPEGD_BASE+0x00000060)
+#define HWIO_JPEG_DEC_SCALE__POR                 0x00000000
+#define HWIO_JPEG_DEC_SCALE__RMSK                0x00000003
+#define HWIO_JPEG_DEC_SCALE__SHFT                         0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DEC_SCALE__JPEG_DEC_SCALE_RATIO__BMSK       0x00000003
+#define HWIO_JPEG_DEC_SCALE__JPEG_DEC_SCALE_RATIO__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_CONVERT                         JPEG_CONVERT
+#define HWIO_JPEG_CONVERT_ADDR  /* RW */       (JPEGD_BASE+0x00000064)
+#define HWIO_JPEG_CONVERT__POR                 0x00000000
+#define HWIO_JPEG_CONVERT__RMSK                0xFFFF13FF
+#define HWIO_JPEG_CONVERT__SHFT                         0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_MONO_CB_VALUE__BMSK      0xFF000000
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_MONO_CB_VALUE__SHFT              24
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_MONO_CR_VALUE__BMSK      0x00FF0000
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_MONO_CR_VALUE__SHFT              16
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_CLAMP_EN__BMSK           0x00001000
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_CLAMP_EN__SHFT                   12
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_CBCR_SWITCH__BMSK        0x00000200
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_CBCR_SWITCH__SHFT                 9
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_MONOCHROME_EN__BMSK      0x00000100
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_MONOCHROME_EN__SHFT               8
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_MEM_ORG__BMSK            0x000000C0
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_MEM_ORG__SHFT                     6
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_422_MCU_TYPE__BMSK       0x00000030
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_422_MCU_TYPE__SHFT                4
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_OUTPUT_FORMAT__BMSK      0x0000000C
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_OUTPUT_FORMAT__SHFT               2
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_INPUT_FORMAT__BMSK       0x00000003
+#define HWIO_JPEG_CONVERT__JPEG_CONVERT_INPUT_FORMAT__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_ENC_BYTE_CNT                       JPEG_ENC_BYTE_CNT
+#define HWIO_JPEG_ENC_BYTE_CNT_ADDR  /* RW */          (JPEGD_BASE+0x00000070)
+#define HWIO_JPEG_ENC_BYTE_CNT__POR                    0x00000000
+#define HWIO_JPEG_ENC_BYTE_CNT__RMSK                   0xFFFFFFFF
+#define HWIO_JPEG_ENC_BYTE_CNT__SHFT                            0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_ENC_BYTE_CNT__JPEG_ENC_BYTE_CNT_TOT__BMSK     0xFFFFFFFF
+#define HWIO_JPEG_ENC_BYTE_CNT__JPEG_ENC_BYTE_CNT_TOT__SHFT              0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_DEBUG                                  JPEG_DEBUG
+#define HWIO_JPEG_DEBUG_ADDR  /* RW */              (JPEGD_BASE+0x00000080)
+#define HWIO_JPEG_DEBUG__POR                        0x4A504547
+#define HWIO_JPEG_DEBUG__RMSK                       0xFFFFFFFF
+#define HWIO_JPEG_DEBUG__SHFT                                0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_DEBUG__JPEG_DEBUG__BMSK            0xFFFFFFFF
+#define HWIO_JPEG_DEBUG__JPEG_DEBUG__SHFT                     0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_SPARE                                JPEG_SPARE
+#define HWIO_JPEG_SPARE_ADDR  /* RW */            (JPEGD_BASE+0x00000084)
+#define HWIO_JPEG_SPARE__POR                      0x00000000
+#define HWIO_JPEG_SPARE__RMSK                     0xFFFFFFFF
+#define HWIO_JPEG_SPARE__SHFT                              0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_SPARE__JPEG_SPARE_00__BMSK            0xFFFFFFFF
+#define HWIO_JPEG_SPARE__JPEG_SPARE_00__SHFT                     0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEG_REGISTER_TIMEOUT                       JPEG_REGISTER_TIMEOUT
+#define HWIO_JPEG_REGISTER_TIMEOUT_ADDR    (JPEGD_BASE+0x00000088)
+#define HWIO_JPEG_REGISTER_TIMEOUT__POR                        0x0000FFFF
+#define HWIO_JPEG_REGISTER_TIMEOUT__RMSK                       0x0000FFFF
+#define HWIO_JPEG_REGISTER_TIMEOUT__SHFT                                0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEG_REGISTER_TIMEOUT__JPEG_TIMEOUT_VALUE__BMSK        0x0000FFFF
+#define HWIO_JPEG_REGISTER_TIMEOUT__JPEG_TIMEOUT_VALUE__SHFT                 0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEGD_STATUS_BUS_DATA                     JPEGD_STATUS_BUS_DATA
+#define HWIO_JPEGD_STATUS_BUS_DATA_ADDR  /* RW */       (JPEGD_BASE+0x00000258)
+#define HWIO_JPEGD_STATUS_BUS_DATA__POR                      0x00000000
+#define HWIO_JPEGD_STATUS_BUS_DATA__RMSK                     0xFFFFFFFF
+#define HWIO_JPEGD_STATUS_BUS_DATA__SHFT                              0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEGD_STATUS_BUS_DATA__STATUS_BUS_DATA__BMSK      0xFFFFFFFF
+#define HWIO_JPEGD_STATUS_BUS_DATA__STATUS_BUS_DATA__SHFT               0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEGD_STATUS_BUS_CONFIG                     JPEGD_STATUS_BUS_CONFIG
+#define HWIO_JPEGD_STATUS_BUS_CONFIG_ADDR  /* RW */     (JPEGD_BASE+0x0000025C)
+#define HWIO_JPEGD_STATUS_BUS_CONFIG__POR                        0x00000000
+#define HWIO_JPEGD_STATUS_BUS_CONFIG__RMSK                       0x0000001F
+#define HWIO_JPEGD_STATUS_BUS_CONFIG__SHFT                                0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEGD_STATUS_BUS_CONFIG__STATUS_BUS_SEL__BMSK         0x0000001F
+#define HWIO_JPEGD_STATUS_BUS_CONFIG__STATUS_BUS_SEL__SHFT                  0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_AXI_CONFIG                       RTDMA_JPEG_AXI_CONFIG
+#define HWIO_RTDMA_JPEG_AXI_CONFIG_ADDR  /* RW */        (JPEGD_BASE+0x00000260)
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__POR                        0x00000024
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__RMSK                       0x00000FFF
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__SHFT                                0
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__OUT_OF_ORDER_WR__BMSK          0x00000800
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__OUT_OF_ORDER_WR__SHFT                  11
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__OUT_OF_ORDER_RD__BMSK          0x00000400
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__OUT_OF_ORDER_RD__SHFT                  10
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__BOUND_LIMIT__BMSK              0x00000300
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__BOUND_LIMIT__SHFT                       8
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__PACK_TIMEOUT__BMSK             0x000000F0
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__PACK_TIMEOUT__SHFT                      4
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__PACK_MAX_BLEN__BMSK            0x0000000F
+#define HWIO_RTDMA_JPEG_AXI_CONFIG__PACK_MAX_BLEN__SHFT                     0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define JPEGD_CLK_CONTROL                             JPEGD_CLK_CONTROL
+#define HWIO_JPEGD_CLK_CONTROL_ADDR  /* RW */   (JPEGD_BASE+0x00000264)
+#define HWIO_JPEGD_CLK_CONTROL__POR             0x00000005
+#define HWIO_JPEGD_CLK_CONTROL__RMSK                         0x0000000F
+#define HWIO_JPEGD_CLK_CONTROL__SHFT                                  0
+/* Register Field FMSK and SHFT*/
+#define HWIO_JPEGD_CLK_CONTROL__JPEG_CLKIDLE__BMSK           0x00000008
+#define HWIO_JPEGD_CLK_CONTROL__JPEG_CLKIDLE__SHFT                    3
+#define HWIO_JPEGD_CLK_CONTROL__JPEG_CLKON__BMSK             0x00000004
+#define HWIO_JPEGD_CLK_CONTROL__JPEG_CLKON__SHFT                      2
+#define HWIO_JPEGD_CLK_CONTROL__AXI_CLKIDLE__BMSK            0x00000002
+#define HWIO_JPEGD_CLK_CONTROL__AXI_CLKIDLE__SHFT                     1
+#define HWIO_JPEGD_CLK_CONTROL__AXI_CLKON__BMSK              0x00000001
+#define HWIO_JPEGD_CLK_CONTROL__AXI_CLKON__SHFT                       0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_BUF_CONFIG                     RTDMA_JPEG_WR_BUF_CONFIG
+#define HWIO_RTDMA_JPEG_WR_BUF_CONFIG_ADDR  /* RW */   (JPEGD_BASE+0x00000200)
+#define HWIO_RTDMA_JPEG_WR_BUF_CONFIG__POR             0x00000000
+#define HWIO_RTDMA_JPEG_WR_BUF_CONFIG__RMSK            0x0000001F
+#define HWIO_RTDMA_JPEG_WR_BUF_CONFIG__SHFT                     0
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_BUF_CONFIG__BUF_FORMAT__BMSK         0x0000001C
+#define HWIO_RTDMA_JPEG_WR_BUF_CONFIG__BUF_FORMAT__SHFT                  2
+#define HWIO_RTDMA_JPEG_WR_BUF_CONFIG__NUM_OF_PLANES__BMSK      0x00000003
+#define HWIO_RTDMA_JPEG_WR_BUF_CONFIG__NUM_OF_PLANES__SHFT               0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_OP                               RTDMA_JPEG_WR_OP
+#define HWIO_RTDMA_JPEG_WR_OP_ADDR  /* RW */        (JPEGD_BASE+0x00000204)
+#define HWIO_RTDMA_JPEG_WR_OP__POR                  0x00000000
+#define HWIO_RTDMA_JPEG_WR_OP__RMSK                 0x00000013
+#define HWIO_RTDMA_JPEG_WR_OP__SHFT                          0
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_OP__ALIGN__BMSK          0x00000010
+#define HWIO_RTDMA_JPEG_WR_OP__ALIGN__SHFT                   4
+#define HWIO_RTDMA_JPEG_WR_OP__FLIP__BMSK           0x00000002
+#define HWIO_RTDMA_JPEG_WR_OP__FLIP__SHFT                    1
+#define HWIO_RTDMA_JPEG_WR_OP__MIRROR__BMSK         0x00000001
+#define HWIO_RTDMA_JPEG_WR_OP__MIRROR__SHFT                  0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_BUF_Y_PNTR                      RTDMA_JPEG_WR_BUF_Y_PNTR
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR_ADDR    (JPEGD_BASE+0x00000208)
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR__POR                0x00000000
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR__RMSK               0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR__SHFT                        3
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR___S                          3
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR___S                          3
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR___S                          3
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR___S                          3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR__PNTR__BMSK         0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_WR_BUF_Y_PNTR__PNTR__SHFT                  3
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_BUF_U_PNTR                      RTDMA_JPEG_WR_BUF_U_PNTR
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR_ADDR  /* RW */     (JPEGD_BASE+0x0000020C)
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR__POR               0x00000000
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR__RMSK              0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR__SHFT                       3
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR___S                         3
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR___S                         3
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR___S                         3
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR___S                         3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR__PNTR__BMSK        0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_WR_BUF_U_PNTR__PNTR__SHFT                 3
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_BUF_V_PNTR                       RTDMA_JPEG_WR_BUF_V_PNTR
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR_ADDR   (JPEGD_BASE+0x00000210)
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR__POR                0x00000000
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR__RMSK               0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR__SHFT                        3
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR___S                          3
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR___S                          3
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR___S                          3
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR___S                          3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR__PNTR__BMSK         0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_WR_BUF_V_PNTR__PNTR__SHFT                  3
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_BUF_PITCH                         RTDMA_JPEG_WR_BUF_PITCH
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH_ADDR  /* RW */    (JPEGD_BASE+0x00000214)
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH__POR              0x00000000
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH__RMSK             0x00003FF8
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH__SHFT                      3
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH___S                        3
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH___S                        3
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH___S                        3
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH___S                        3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH__PITCH__BMSK          0x00003FF8
+#define HWIO_RTDMA_JPEG_WR_BUF_PITCH__PITCH__SHFT                   3
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_PLANE_SIZE                      RTDMA_JPEG_WR_PLANE_SIZE
+#define HWIO_RTDMA_JPEG_WR_PLANE_SIZE_ADDR  /* RW */  (JPEGD_BASE+0x00000218)
+#define HWIO_RTDMA_JPEG_WR_PLANE_SIZE__POR            0x00000000
+#define HWIO_RTDMA_JPEG_WR_PLANE_SIZE__RMSK           0x1FFF1FFF
+#define HWIO_RTDMA_JPEG_WR_PLANE_SIZE__SHFT                    0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_PLANE_SIZE__PLANE_VSIZE__BMSK       0x1FFF0000
+#define HWIO_RTDMA_JPEG_WR_PLANE_SIZE__PLANE_VSIZE__SHFT               16
+#define HWIO_RTDMA_JPEG_WR_PLANE_SIZE__PLANE_HSIZE__BMSK       0x00001FFF
+#define HWIO_RTDMA_JPEG_WR_PLANE_SIZE__PLANE_HSIZE__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_BLOCK_SIZE                      RTDMA_JPEG_WR_BLOCK_SIZE
+#define HWIO_RTDMA_JPEG_WR_BLOCK_SIZE_ADDR  /* RW */    (JPEGD_BASE+0x0000021C)
+#define HWIO_RTDMA_JPEG_WR_BLOCK_SIZE__POR              0x00000000
+#define HWIO_RTDMA_JPEG_WR_BLOCK_SIZE__RMSK             0x00000FFF
+#define HWIO_RTDMA_JPEG_WR_BLOCK_SIZE__SHFT                      0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_BLOCK_SIZE__BLOCK_VSIZE__BMSK           0x00000FC0
+#define HWIO_RTDMA_JPEG_WR_BLOCK_SIZE__BLOCK_VSIZE__SHFT                    6
+#define HWIO_RTDMA_JPEG_WR_BLOCK_SIZE__BLOCK_HSIZE__BMSK           0x0000003F
+#define HWIO_RTDMA_JPEG_WR_BLOCK_SIZE__BLOCK_HSIZE__SHFT                    0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_BUFFER_SIZE                      RTDMA_JPEG_WR_BUFFER_SIZE
+#define HWIO_RTDMA_JPEG_WR_BUFFER_SIZE_ADDR  /* RW */   (JPEGD_BASE+0x00000220)
+#define HWIO_RTDMA_JPEG_WR_BUFFER_SIZE__POR             0x00000000
+#define HWIO_RTDMA_JPEG_WR_BUFFER_SIZE__RMSK            0x00001FFF
+#define HWIO_RTDMA_JPEG_WR_BUFFER_SIZE__SHFT                     0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_BUFFER_SIZE__BUFFER_VSIZE__BMSK         0x00001FFF
+#define HWIO_RTDMA_JPEG_WR_BUFFER_SIZE__BUFFER_VSIZE__SHFT                  0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_STA_ACK                      RTDMA_JPEG_WR_STA_ACK
+#define HWIO_RTDMA_JPEG_WR_STA_ACK_ADDR  /* RW */   (JPEGD_BASE+0x00000224)
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__POR             0x00000000
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__RMSK            0x0000000F
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SHFT                     3
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_WR_STA_ACK___S                       3
+#define HWIO_RTDMA_JPEG_WR_STA_ACK___S                       3
+#define HWIO_RTDMA_JPEG_WR_STA_ACK___S                       3
+#define HWIO_RTDMA_JPEG_WR_STA_ACK___S                       3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SW_RESET_ABORT_RDY_STA__BMSK   0x00000008
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SW_RESET_ABORT_RDY_STA__SHFT            3
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SW_RESET_ABORT_RDY_ACK__BMSK   0x00000008
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SW_RESET_ABORT_RDY_ACK__SHFT            3
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__ERR_STA__BMSK                  0x00000004
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__ERR_STA__SHFT                           2
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__ERR_ACK__BMSK                  0x00000004
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__ERR_ACK__SHFT                           2
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__EOF_STA__BMSK                  0x00000002
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__EOF_STA__SHFT                           1
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__EOF_ACK__BMSK                  0x00000002
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__EOF_ACK__SHFT                           1
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SOF_STA__BMSK                  0x00000001
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SOF_STA__SHFT                           0
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SOF_ACK__BMSK           0x00000001
+#define HWIO_RTDMA_JPEG_WR_STA_ACK__SOF_ACK__SHFT                    0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_WR_INT_EN                      RTDMA_JPEG_WR_INT_EN
+#define HWIO_RTDMA_JPEG_WR_INT_EN_ADDR  /* W */        (JPEGD_BASE+0x00000228)
+#define HWIO_RTDMA_JPEG_WR_INT_EN__POR                 0x00000000
+#define HWIO_RTDMA_JPEG_WR_INT_EN__RMSK                0x0000000F
+#define HWIO_RTDMA_JPEG_WR_INT_EN__SHFT                         0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_WR_INT_EN__SW_RESET_ABORT_RDY_EN__BMSK 0x00000008
+#define HWIO_RTDMA_JPEG_WR_INT_EN__SW_RESET_ABORT_RDY_EN__SHFT          3
+#define HWIO_RTDMA_JPEG_WR_INT_EN__ERR_EN__BMSK                0x00000004
+#define HWIO_RTDMA_JPEG_WR_INT_EN__ERR_EN__SHFT                         2
+#define HWIO_RTDMA_JPEG_WR_INT_EN__EOF_EN__BMSK                0x00000002
+#define HWIO_RTDMA_JPEG_WR_INT_EN__EOF_EN__SHFT                         1
+#define HWIO_RTDMA_JPEG_WR_INT_EN__SOF_EN__BMSK                0x00000001
+#define HWIO_RTDMA_JPEG_WR_INT_EN__SOF_EN__SHFT                         0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_BUF_CONFIG                     RTDMA_JPEG_RD_BUF_CONFIG
+#define HWIO_RTDMA_JPEG_RD_BUF_CONFIG_ADDR  /* RW */     (JPEGD_BASE+0x00000100)
+#define HWIO_RTDMA_JPEG_RD_BUF_CONFIG__POR               0x00000000
+#define HWIO_RTDMA_JPEG_RD_BUF_CONFIG__RMSK              0x0000001F
+#define HWIO_RTDMA_JPEG_RD_BUF_CONFIG__SHFT                       0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_BUF_CONFIG__BUF_FORMAT__BMSK          0x0000001C
+#define HWIO_RTDMA_JPEG_RD_BUF_CONFIG__BUF_FORMAT__SHFT                   2
+#define HWIO_RTDMA_JPEG_RD_BUF_CONFIG__NUM_OF_PLANES__BMSK       0x00000003
+#define HWIO_RTDMA_JPEG_RD_BUF_CONFIG__NUM_OF_PLANES__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT, W */
+#define RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO   RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO_ADDR  (JPEGD_BASE+0x00000104)
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__POR            0x00000000
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__RMSK           0x0000001C
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__SHFT                    2
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO___S                      2
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO___S                      2
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO___S                      2
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO___S                      2
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__BUF_APPLY__BMSK   0x00000010
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__BUF_APPLY__SHFT            4
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__BUF_EOF__BMSK     0x00000008
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__BUF_EOF__SHFT              3
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__BUF_SOF__BMSK     0x00000004
+#define HWIO_RTDMA_JPEG_RD_BUF_MNGR_BUF_ID_FIFO__BUF_SOF__SHFT              2
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_BUF_Y_PNTR                        RTDMA_JPEG_RD_BUF_Y_PNTR
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR_ADDR  /* RW */   (JPEGD_BASE+0x0000010C)
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR__POR             0x00000000
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR__RMSK            0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR__SHFT                     3
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR___S                       3
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR___S                       3
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR___S                       3
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR___S                       3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR__PNTR__BMSK      0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_RD_BUF_Y_PNTR__PNTR__SHFT               3
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_BUF_U_PNTR                     RTDMA_JPEG_RD_BUF_U_PNTR
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR_ADDR  /* RW */ (JPEGD_BASE+0x00000110)
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR__POR           0x00000000
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR__RMSK          0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR__SHFT                   3
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR___S                     3
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR___S                     3
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR___S                     3
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR___S                     3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR__PNTR__BMSK        0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_RD_BUF_U_PNTR__PNTR__SHFT               3
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_BUF_V_PNTR                     RTDMA_JPEG_RD_BUF_V_PNTR
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR_ADDR  /* RW */    (JPEGD_BASE+0x00000114)
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR__POR              0x00000000
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR__RMSK             0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR__SHFT                      3
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR___S                        3
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR___S                        3
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR___S                        3
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR___S                        3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR__PNTR__BMSK       0xFFFFFFF8
+#define HWIO_RTDMA_JPEG_RD_BUF_V_PNTR__PNTR__SHFT                3
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_BUF_PITCH                       RTDMA_JPEG_RD_BUF_PITCH
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH_ADDR  /* RW */    (JPEGD_BASE+0x00000118)
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH__POR              0x00000000
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH__RMSK             0x00003FF8
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH__SHFT                      3
+
+/* Register Element MIN and MAX*/
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH___S                        3
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH___S                        3
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH___S                        3
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH___S                        3
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH__PITCH__BMSK            0x00003FF8
+#define HWIO_RTDMA_JPEG_RD_BUF_PITCH__PITCH__SHFT                     3
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_PLANE_SIZE                     RTDMA_JPEG_RD_PLANE_SIZE
+#define HWIO_RTDMA_JPEG_RD_PLANE_SIZE_ADDR  /* RW */  (JPEGD_BASE+0x0000011C)
+#define HWIO_RTDMA_JPEG_RD_PLANE_SIZE__POR            0x00000000
+#define HWIO_RTDMA_JPEG_RD_PLANE_SIZE__RMSK            0x1FFF1FFF
+#define HWIO_RTDMA_JPEG_RD_PLANE_SIZE__SHFT                     0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_PLANE_SIZE__PLANE_VSIZE__BMSK         0x1FFF0000
+#define HWIO_RTDMA_JPEG_RD_PLANE_SIZE__PLANE_VSIZE__SHFT                 16
+#define HWIO_RTDMA_JPEG_RD_PLANE_SIZE__PLANE_HSIZE__BMSK         0x00001FFF
+#define HWIO_RTDMA_JPEG_RD_PLANE_SIZE__PLANE_HSIZE__SHFT                  0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_BLOCK_SIZE                       RTDMA_JPEG_RD_BLOCK_SIZE
+#define HWIO_RTDMA_JPEG_RD_BLOCK_SIZE_ADDR  /* RW */    (JPEGD_BASE+0x00000120)
+#define HWIO_RTDMA_JPEG_RD_BLOCK_SIZE__POR              0x000003CF
+#define HWIO_RTDMA_JPEG_RD_BLOCK_SIZE__RMSK             0x00000FFF
+#define HWIO_RTDMA_JPEG_RD_BLOCK_SIZE__SHFT                      0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_BLOCK_SIZE__BLOCK_VSIZE__BMSK       0x00000FC0
+#define HWIO_RTDMA_JPEG_RD_BLOCK_SIZE__BLOCK_VSIZE__SHFT                6
+#define HWIO_RTDMA_JPEG_RD_BLOCK_SIZE__BLOCK_HSIZE__BMSK       0x0000003F
+#define HWIO_RTDMA_JPEG_RD_BLOCK_SIZE__BLOCK_HSIZE__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_BUFFER_SIZE               RTDMA_JPEG_RD_BUFFER_SIZE
+#define HWIO_RTDMA_JPEG_RD_BUFFER_SIZE_ADDR  (JPEGD_BASE+0x00000124)
+#define HWIO_RTDMA_JPEG_RD_BUFFER_SIZE__POR               0x00000000
+#define HWIO_RTDMA_JPEG_RD_BUFFER_SIZE__RMSK              0x00001FFF
+#define HWIO_RTDMA_JPEG_RD_BUFFER_SIZE__SHFT                       0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_BUFFER_SIZE__BUFFER_VSIZE__BMSK      0x00001FFF
+#define HWIO_RTDMA_JPEG_RD_BUFFER_SIZE__BUFFER_VSIZE__SHFT                0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_STA_ACK                     RTDMA_JPEG_RD_STA_ACK
+#define HWIO_RTDMA_JPEG_RD_STA_ACK_ADDR         (JPEGD_BASE+0x00000128)
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__POR                     0x00000000
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__RMSK                    0x00000003
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__SHFT                             0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__EOF_STA__BMSK           0x00000002
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__EOF_STA__SHFT                    1
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__SOF_STA__BMSK           0x00000001
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__SOF_STA__SHFT                    0
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__EOF_ACK__BMSK           0x00000002
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__EOF_ACK__SHFT                    1
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__SOF_ACK__BMSK           0x00000001
+#define HWIO_RTDMA_JPEG_RD_STA_ACK__SOF_ACK__SHFT                    0
+
+/* Register ADDR, RMSK, and SHFT*/
+#define RTDMA_JPEG_RD_INT_EN                      RTDMA_JPEG_RD_INT_EN
+#define HWIO_RTDMA_JPEG_RD_INT_EN_ADDR  /* W */        (JPEGD_BASE+0x0000012C)
+#define HWIO_RTDMA_JPEG_RD_INT_EN__POR                      0x00000000
+#define HWIO_RTDMA_JPEG_RD_INT_EN__RMSK                     0x00000003
+#define HWIO_RTDMA_JPEG_RD_INT_EN__SHFT                              0
+
+/* Register Field FMSK and SHFT*/
+#define HWIO_RTDMA_JPEG_RD_INT_EN__EOF_EN__BMSK             0x00000002
+#define HWIO_RTDMA_JPEG_RD_INT_EN__EOF_EN__SHFT                      1
+#define HWIO_RTDMA_JPEG_RD_INT_EN__SOF_EN__BMSK             0x00000001
+#define HWIO_RTDMA_JPEG_RD_INT_EN__SOF_EN__SHFT                      0
+
+#endif /* MSM_MERCURY_HW_REG_H */
diff --git a/drivers/media/video/msm/mercury/msm_mercury_macros.h b/drivers/media/video/msm/mercury/msm_mercury_macros.h
new file mode 100644
index 0000000..33c4f9a
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_macros.h
@@ -0,0 +1,118 @@
+/* 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_MERCURY_MACROS_H
+#define MSM_MERCURY_MACROS_H
+
+#include <media/msm_mercury.h>
+
+#define mercury_kread(reg) \
+	hw_cmd.type = MSM_MERCURY_HW_CMD_TYPE_READ; \
+	hw_cmd.n = 1; \
+	hw_cmd.offset = HWIO_##reg##_ADDR; \
+	hw_cmd.mask = HWIO_##reg##__RMSK; \
+	hw_cmd.data = 0x0; \
+	msm_mercury_hw_exec_cmds(&hw_cmd, 1);
+
+#define mercury_kwrite(reg, val) \
+	hw_cmd.offset = HWIO_##reg##_ADDR; \
+	hw_cmd.mask = HWIO_##reg##__RMSK; \
+	hw_cmd.type = MSM_MERCURY_HW_CMD_TYPE_WRITE; \
+	hw_cmd.n = 1; \
+	hw_cmd.data = val; \
+	msm_mercury_hw_exec_cmds(&hw_cmd, 1);
+
+#define GET_FVAL(val, reg, field) ((val & HWIO_FMSK(reg, field)) >> \
+	HWIO_SHFT(reg, field))
+
+#define byte unsigned char
+#define word unsigned short
+#define dword unsigned long
+
+#define inp(port)    (*((dword *) (port)))
+#define inpb(port)     (*((byte *) (port)))
+#define inpw(port)   (*((word *) (port)))
+#define inpdw(port)   (*((dword *)(port)))
+
+#define outp(port, val)   (*((dword *) (port)) = ((dword) (val)))
+#define outpb(port, val)   (*((byte *) (port)) = ((byte) (val)))
+#define outpw(port, val)  (*((word *) (port)) = ((word) (val)))
+#define outpdw(port, val) (*((dword *) (port)) = ((dword) (val)))
+
+
+#define in_byte(addr)				(inp(addr))
+#define in_byte_masked(addr, mask)	(inp(addr) & (byte)mask)
+#define out_byte(addr, val)			 outp(addr, val)
+#define in_word(addr)				(inpw(addr))
+#define in_word_masked(addr, mask)	(inpw(addr) & (word)mask)
+#define out_word(addr, val)			 outpw(addr, val)
+#define in_dword(addr)				(inpdw(addr))
+#define in_dword_masked(addr, mask)	(inpdw(addr) & mask)
+#define out_dword(addr, val)			 outpdw(addr, val)
+
+/* shadowed, masked output for write-only registers */
+#define out_byte_masked(io, mask, val, shadow)  \
+	do { \
+		shadow = (shadow & (word)(~(mask))) | \
+		((word)((val) & (mask))); \
+		(void) out_byte(io, shadow);\
+	} while (0);
+
+#define out_word_masked(io, mask, val, shadow)  \
+	do { \
+		shadow = (shadow & (word)(~(mask))) | \
+		((word)((val) & (mask))); \
+		(void) out_word(io, shadow); \
+	} while (0);
+
+#define out_dword_masked(io, mask, val, shadow)  \
+	do { \
+		shadow = (shadow & (dword)(~(mask))) | \
+		((dword)((val) & (mask))); \
+		(void) out_dword(io, shadow);\
+	} while (0);
+
+#define out_byte_masked_ns(io, mask, val, current_reg_content)  \
+	(void) out_byte(io, ((current_reg_content & \
+	(word)(~(mask))) | ((word)((val) & (mask)))))
+
+#define out_word_masked_ns(io, mask, val, current_reg_content)  \
+	(void) out_word(io, ((current_reg_content & \
+	(word)(~(mask))) | ((word)((val) & (mask)))))
+
+#define out_dword_masked_ns(io, mask, val, current_reg_content) \
+	(void) out_dword(io, ((current_reg_content & \
+	(dword)(~(mask))) | ((dword)((val) & (mask)))))
+
+#define MEM_INF(val, reg, field)	((val & HWIO_FMSK(reg, field)) >> \
+	HWIO_SHFT(reg, field))
+
+#define MEM_OUTF(mem, reg, field, val)\
+	out_dword_masked_ns(mem, HWIO_FMSK(reg, field), \
+	(unsigned  int)val<<HWIO_SHFT(reg, field), in_dword(mem))
+
+#define MEM_OUTF2(mem, reg, field2, field1, val2, val1)  \
+	out_dword_masked_ns(mem, (HWIO_FMSK(reg, field2)| \
+	HWIO_FMSK(reg, field1)), \
+	(((unsigned int)val2<<HWIO_SHFT(reg, field2))| \
+	((unsigned int)val1<<HWIO_SHFT(reg, field1))), in_dword(mem))
+
+#define MEM_OUTF3(mem, reg, fld3, fld2, fld1, val3, val2, val1)  \
+	out_dword_masked_ns(mem, (HWIO_FMSK(reg, fld3)| \
+	HWIO_FMSK(reg, fld2)|HWIO_FMSK(reg, fld1)), \
+	(((unsigned int)val3<<HWIO_SHFT(reg, fld3))| \
+	((unsigned int)val2<<HWIO_SHFT(reg, fld2))| \
+	((unsigned int)val1<<HWIO_SHFT(reg, fld1))), in_dword(mem))
+
+#define HWIO_FMSK(reg, field)   HWIO_##reg##__##field##__BMSK
+#define HWIO_SHFT(reg, field)   HWIO_##reg##__##field##__SHFT
+#endif
diff --git a/drivers/media/video/msm/mercury/msm_mercury_platform.c b/drivers/media/video/msm/mercury/msm_mercury_platform.c
new file mode 100644
index 0000000..9366ef3
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_platform.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/module.h>
+#include <linux/pm_qos_params.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/android_pmem.h>
+#include <mach/clk.h>
+#include <mach/camera.h>
+#include <mach/msm_subsystem_map.h>
+
+#include "msm_mercury_platform.h"
+#include "msm_mercury_sync.h"
+#include "msm_mercury_common.h"
+#include "msm_mercury_hw.h"
+
+
+struct ion_client *mercury_client;
+
+static struct msm_cam_clk_info mercury_jpegd_clk_info[] = {
+	{"core_clk", 200000000},
+	{"iface_clk", -1}
+};
+
+void msm_mercury_platform_p2v(struct file  *file,
+	struct ion_handle **ionhandle)
+{
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_unmap_iommu(mercury_client, *ionhandle, CAMERA_DOMAIN,
+		GEN_POOL);
+	ion_free(mercury_client, *ionhandle);
+	*ionhandle = NULL;
+#elif CONFIG_ANDROID_PMEM
+	put_pmem_file(file);
+#endif
+}
+
+uint32_t msm_mercury_platform_v2p(int fd, uint32_t len,
+	struct file **file_p,
+	struct ion_handle **ionhandle)
+{
+	unsigned long paddr;
+	unsigned long size;
+	int rc;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	*ionhandle = ion_import_fd(mercury_client, fd);
+	if (IS_ERR_OR_NULL(*ionhandle))
+		return 0;
+
+	rc = ion_map_iommu(mercury_client, *ionhandle, CAMERA_DOMAIN,
+		GEN_POOL, SZ_4K, 0, &paddr,
+		(unsigned long *)&size, UNCACHED, 0);
+#elif CONFIG_ANDROID_PMEM
+	unsigned long kvstart;
+	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
+#else
+	rc = 0;
+	paddr = 0;
+	size = 0;
+#endif
+	if (rc < 0) {
+		MCR_PR_ERR("%s: get_pmem_file fd %d error %d\n", __func__, fd,
+			rc);
+		goto error1;
+	}
+
+	/* validate user input */
+	if (len > size) {
+		MCR_PR_ERR("%s: invalid offset + len\n", __func__);
+		goto error1;
+	}
+
+	return paddr;
+error1:
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_free(mercury_client, *ionhandle);
+#endif
+	return 0;
+}
+
+int msm_mercury_platform_init(struct platform_device *pdev,
+	struct resource **mem,
+	void **base,
+	int *irq,
+	irqreturn_t (*handler) (int, void *),
+	void *context)
+{
+	int rc = 0;
+	int mercury_irq;
+	struct resource *mercury_mem, *mercury_io, *mercury_irq_res;
+	void *mercury_base;
+	struct msm_mercury_device *pmercury_dev =
+		(struct msm_mercury_device *) context;
+
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+
+	mercury_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mercury_mem) {
+		MCR_PR_ERR("%s: no mem resource?\n", __func__);
+		return -ENODEV;
+	}
+
+	mercury_irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mercury_irq_res) {
+		MCR_PR_ERR("no irq resource?\n");
+		return -ENODEV;
+	}
+	mercury_irq = mercury_irq_res->start;
+
+	mercury_io = request_mem_region(mercury_mem->start,
+		resource_size(mercury_mem), pdev->name);
+	if (!mercury_io) {
+		MCR_PR_ERR("%s: region already claimed\n", __func__);
+		return -EBUSY;
+	}
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+	mercury_base = ioremap(mercury_mem->start,
+		resource_size(mercury_mem));
+	if (!mercury_base) {
+		rc = -ENOMEM;
+		MCR_PR_ERR("%s: ioremap failed\n", __func__);
+		goto fail1;
+	}
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+
+	rc = msm_cam_clk_enable(&pmercury_dev->pdev->dev,
+		mercury_jpegd_clk_info, pmercury_dev->mercury_clk,
+		ARRAY_SIZE(mercury_jpegd_clk_info), 1);
+	if (rc < 0)
+		MCR_PR_ERR("%s:%d] rc = %d\n", __func__, __LINE__, rc);
+
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+	msm_mercury_hw_init(mercury_base, resource_size(mercury_mem));
+	rc = request_irq(mercury_irq, handler, IRQF_TRIGGER_RISING,
+		"mercury", context);
+	if (rc) {
+		MCR_PR_ERR("%s: request_irq failed, %d\n", __func__,
+			mercury_irq);
+		goto fail3;
+	}
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+	*mem  = mercury_mem;
+	*base = mercury_base;
+	*irq  = mercury_irq;
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	mercury_client = msm_ion_client_create(-1, "camera/mercury");
+#endif
+	MCR_PR_ERR("%s:%d] success\n", __func__, __LINE__);
+	return rc;
+fail3:
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+	msm_cam_clk_enable(&pmercury_dev->pdev->dev, mercury_jpegd_clk_info,
+		pmercury_dev->mercury_clk,
+		ARRAY_SIZE(mercury_jpegd_clk_info), 0);
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+	iounmap(mercury_base);
+fail1:
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+	release_mem_region(mercury_mem->start, resource_size(mercury_mem));
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+	return rc;
+}
+
+int msm_mercury_platform_release(struct resource *mem, void *base,
+	int irq, void *context)
+{
+	int result = 0;
+	struct msm_mercury_device *pmercury_dev =
+		(struct msm_mercury_device *) context;
+
+	free_irq(irq, context);
+	msm_cam_clk_enable(&pmercury_dev->pdev->dev, mercury_jpegd_clk_info,
+		pmercury_dev->mercury_clk, ARRAY_SIZE(mercury_jpegd_clk_info),
+		0);
+	iounmap(base);
+	release_mem_region(mem->start, resource_size(mem));
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_client_destroy(mercury_client);
+#endif
+	MCR_DBG("%s:%d] success\n", __func__, __LINE__);
+	return result;
+}
+
diff --git a/drivers/media/video/msm/mercury/msm_mercury_platform.h b/drivers/media/video/msm/mercury/msm_mercury_platform.h
new file mode 100644
index 0000000..8f4a7e3
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_platform.h
@@ -0,0 +1,39 @@
+/* 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_MERCURY_PLATFORM_H
+#define MSM_MERCURY_PLATFORM_H
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/ion.h>
+
+int msm_mercury_platform_clk_enable(void);
+int msm_mercury_platform_clk_disable(void);
+
+void msm_mercury_platform_p2v(struct file  *file,
+	struct ion_handle **ionhandle);
+
+uint32_t msm_mercury_platform_v2p(int fd, uint32_t len, struct file **file,
+	struct ion_handle **ionhandle);
+
+int msm_mercury_platform_init(struct platform_device *pdev,
+	struct resource **mem,
+	void **base,
+	int *irq,
+	irqreturn_t (*handler) (int, void *),
+	void *context);
+
+int msm_mercury_platform_release(struct resource *mem, void *base, int irq,
+	void *context);
+
+#endif /* MSM_MERCURY_PLATFORM_H */
diff --git a/drivers/media/video/msm/mercury/msm_mercury_sync.c b/drivers/media/video/msm/mercury/msm_mercury_sync.c
new file mode 100644
index 0000000..31fb8b4
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_sync.c
@@ -0,0 +1,614 @@
+/* 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/sched.h>
+#include <linux/list.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <media/msm_mercury.h>
+
+#include "msm_mercury_sync.h"
+#include "msm_mercury_core.h"
+#include "msm_mercury_platform.h"
+#include "msm_mercury_common.h"
+#include "msm_mercury_macros.h"
+#include "msm_mercury_hw_reg.h"
+
+static struct msm_mercury_core_buf out_buf_local;
+static struct msm_mercury_core_buf in_buf_local;
+
+/*************** queue helper ****************/
+inline void msm_mercury_q_init(char const *name, struct msm_mercury_q *q_p)
+{
+	MCR_DBG("%s:%d] %s\n", __func__, __LINE__, name);
+	q_p->name = name;
+	spin_lock_init(&q_p->lck);
+	INIT_LIST_HEAD(&q_p->q);
+	init_waitqueue_head(&q_p->wait);
+	q_p->unblck = 0;
+}
+
+inline void *msm_mercury_q_out(struct msm_mercury_q *q_p)
+{
+	unsigned long flags;
+	struct msm_mercury_q_entry *q_entry_p = NULL;
+	void *data = NULL;
+
+	MCR_DBG("(%d)%s()  %s\n", __LINE__, __func__, q_p->name);
+	spin_lock_irqsave(&q_p->lck, flags);
+	if (!list_empty(&q_p->q)) {
+		q_entry_p = list_first_entry(&q_p->q,
+			struct msm_mercury_q_entry,
+			list);
+		list_del_init(&q_entry_p->list);
+	}
+	spin_unlock_irqrestore(&q_p->lck, flags);
+
+	if (q_entry_p) {
+		data = q_entry_p->data;
+		kfree(q_entry_p);
+	} else {
+		MCR_DBG("%s:%d] %s no entry\n", __func__, __LINE__, q_p->name);
+	}
+
+	return data;
+}
+
+inline int msm_mercury_q_in(struct msm_mercury_q *q_p, void *data)
+{
+	unsigned long flags;
+
+	struct msm_mercury_q_entry *q_entry_p;
+
+	MCR_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+
+	q_entry_p = kmalloc(sizeof(struct msm_mercury_q_entry), GFP_ATOMIC);
+	if (!q_entry_p) {
+		MCR_PR_ERR("%s: no mem\n", __func__);
+		return -EFAULT;
+	}
+	q_entry_p->data = data;
+
+	spin_lock_irqsave(&q_p->lck, flags);
+	list_add_tail(&q_entry_p->list, &q_p->q);
+	spin_unlock_irqrestore(&q_p->lck, flags);
+
+	return 0;
+}
+
+inline int msm_mercury_q_in_buf(struct msm_mercury_q *q_p,
+	struct msm_mercury_core_buf *buf)
+{
+	struct msm_mercury_core_buf *buf_p;
+
+	MCR_DBG("%s:%d]\n", __func__, __LINE__);
+	buf_p = kmalloc(sizeof(struct msm_mercury_core_buf), GFP_ATOMIC);
+	if (!buf_p) {
+		MCR_PR_ERR("%s: no mem\n", __func__);
+		return -EFAULT;
+	}
+
+	memcpy(buf_p, buf, sizeof(struct msm_mercury_core_buf));
+
+	msm_mercury_q_in(q_p, buf_p);
+	return 0;
+}
+
+inline int msm_mercury_q_wait(struct msm_mercury_q *q_p)
+{
+	int tm = MAX_SCHEDULE_TIMEOUT; /* 500ms */
+	int rc;
+
+	MCR_DBG("%s:%d %s wait\n", __func__, __LINE__, q_p->name);
+	rc = wait_event_interruptible_timeout(q_p->wait,
+		(!list_empty_careful(&q_p->q) || q_p->unblck),
+		msecs_to_jiffies(tm));
+
+	MCR_DBG("%s:%d %s wait done (rc=%d)\n", __func__,
+		__LINE__, q_p->name, rc);
+	if (list_empty_careful(&q_p->q)) {
+		if (rc == 0) {
+			rc = -ETIMEDOUT;
+			MCR_PR_ERR("%s:%d] %s timeout\n", __func__,
+				__LINE__, q_p->name);
+		} else if (q_p->unblck) {
+			MCR_DBG("%s:%d %s unblock is true", __func__,
+				__LINE__, q_p->name);
+			rc = q_p->unblck;
+			q_p->unblck = 0;
+		} else if (rc < 0) {
+			MCR_PR_ERR("%s:%d %s rc %d\n", __func__, __LINE__,
+				q_p->name, rc);
+		}
+	}
+	return rc;
+}
+
+inline int msm_mercury_q_wakeup(struct msm_mercury_q *q_p)
+{
+	MCR_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	wake_up(&q_p->wait);
+	return 0;
+}
+
+inline int msm_mercury_q_wr_eoi(struct msm_mercury_q *q_p)
+{
+	MCR_DBG("%s:%d] Wake up %s\n", __func__, __LINE__, q_p->name);
+	q_p->unblck = MSM_MERCURY_EVT_FRAMEDONE;
+	wake_up(&q_p->wait);
+	return 0;
+}
+
+inline int msm_mercury_q_wr_err(struct msm_mercury_q *q_p)
+{
+	MCR_DBG("%s:%d] Wake up %s\n", __func__, __LINE__, q_p->name);
+	q_p->unblck = MSM_MERCURY_EVT_ERR;
+	wake_up(&q_p->wait);
+	return 0;
+}
+
+inline int msm_mercury_q_unblock(struct msm_mercury_q *q_p)
+{
+	MCR_DBG("%s:%d] Wake up %s\n", __func__, __LINE__, q_p->name);
+	q_p->unblck = MSM_MERCURY_EVT_UNBLOCK;
+	wake_up(&q_p->wait);
+	return 0;
+}
+
+inline void msm_mercury_q_cleanup(struct msm_mercury_q *q_p)
+{
+	void *data;
+	MCR_DBG("\n%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	do {
+		data = msm_mercury_q_out(q_p);
+		if (data) {
+			MCR_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+			kfree(data);
+		}
+	} while (data);
+	q_p->unblck = 0;
+}
+
+/*************** event queue ****************/
+int msm_mercury_framedone_irq(struct msm_mercury_device *pmercury_dev)
+{
+	MCR_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_mercury_q_unblock(&pmercury_dev->evt_q);
+
+	MCR_DBG("%s:%d] Exit\n", __func__, __LINE__);
+	return 0;
+}
+
+int msm_mercury_evt_get(struct msm_mercury_device *pmercury_dev,
+	void __user *arg)
+{
+	struct msm_mercury_ctrl_cmd ctrl_cmd;
+	int rc = 0;
+
+	MCR_DBG("(%d)%s() Enter\n", __LINE__, __func__);
+	ctrl_cmd.type = (uint32_t)msm_mercury_q_wait(&pmercury_dev->evt_q);
+
+	rc = copy_to_user(arg, &ctrl_cmd, sizeof(ctrl_cmd));
+
+	if (rc) {
+		MCR_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int msm_mercury_evt_get_unblock(struct msm_mercury_device *pmercury_dev)
+{
+	MCR_DBG("--(%d)%s() Enter\n", __LINE__, __func__);
+	msm_mercury_q_unblock(&pmercury_dev->evt_q);
+	return 0;
+}
+
+int msm_mercury_output_buf_cfg(struct msm_mercury_device *pmercury_dev,
+	void __user *arg)
+{
+	struct msm_mercury_buf buf_cmd;
+
+
+	MCR_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_mercury_buf))) {
+		MCR_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	out_buf_local.y_buffer_addr = msm_mercury_platform_v2p(buf_cmd.fd,
+		buf_cmd.y_len, &out_buf_local.file, &out_buf_local.handle);
+	out_buf_local.cbcr_buffer_addr = out_buf_local.y_buffer_addr +
+		buf_cmd.y_len;
+
+	if (!out_buf_local.y_buffer_addr) {
+		MCR_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	msm_mercury_hw_output_y_buf_cfg(out_buf_local.y_buffer_addr);
+	msm_mercury_hw_output_u_buf_cfg(out_buf_local.cbcr_buffer_addr);
+
+	MCR_DBG("(%d)%s()\n  y_buf=0x%08X, y_len=0x%08X, vaddr=0x%08X\n"
+		"  u_buf=0x%08X, u_len=0x%08X\n\n", __LINE__, __func__,
+		out_buf_local.y_buffer_addr, buf_cmd.y_len, (int) buf_cmd.vaddr,
+		out_buf_local.cbcr_buffer_addr, buf_cmd.cbcr_len);
+
+	return 0;
+}
+
+int msm_mercury_input_buf_cfg(struct msm_mercury_device *pmercury_dev,
+	void __user *arg)
+{
+	struct msm_mercury_buf buf_cmd;
+
+
+	MCR_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_mercury_buf))) {
+		MCR_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	in_buf_local.y_buffer_addr = msm_mercury_platform_v2p(buf_cmd.fd,
+		buf_cmd.y_len, &in_buf_local.file, &in_buf_local.handle);
+
+	if (!in_buf_local.y_buffer_addr) {
+		MCR_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	msm_mercury_hw_bitstream_buf_cfg(in_buf_local.y_buffer_addr);
+
+	MCR_DBG("(%d)%s()\n  bitstream_buf=0x%08X, len=0x%08X, vaddr=0x%08X\n",
+		__LINE__, __func__, in_buf_local.y_buffer_addr, buf_cmd.y_len,
+		(int) buf_cmd.vaddr);
+
+	return 0;
+}
+
+int msm_mercury_output_get(struct msm_mercury_device *pmercury_dev,
+	void __user *to)
+{
+	MCR_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_mercury_platform_p2v(out_buf_local.file, &out_buf_local.handle);
+	return 0;
+}
+
+int msm_mercury_input_get(struct msm_mercury_device *pmercury_dev,
+	void __user *to)
+{
+
+
+	MCR_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_mercury_platform_p2v(in_buf_local.file, &in_buf_local.handle);
+	return 0;
+}
+
+int msm_mercury_ioctl_dump_regs(void)
+{
+	uint32_t mercury_regs[] = {
+		0x0000, 0x0008, 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024,
+		0x0030, 0x0034, 0x0040, 0x0050, 0x0054, 0x0058, 0x005C, 0x0060,
+		0x0064, 0x0070, 0x0080, 0x0084, 0x0088, 0x0258, 0x025C, 0x0260,
+		0x0264, 0x0200, 0x0204, 0x0208, 0x020C, 0x0210, 0x0214, 0x0218,
+		0x021C, 0x0220, 0x0224, 0x0228, 0x0100, 0x0104, 0x010C, 0x0110,
+		0x0114, 0x0118, 0x011C, 0x0120, 0x0124, 0x0128, 0x012C};
+
+	struct msm_mercury_hw_cmd hw_cmd;
+	int len = sizeof(mercury_regs)/4;
+	int i;
+
+	MCR_DBG("\n%s\n  (%d)%s()\n", __FILE__, __LINE__, __func__);
+
+	hw_cmd.mask = 0xFFFFFFFF;
+	hw_cmd.type = MSM_MERCURY_HW_CMD_TYPE_READ;
+	hw_cmd.n = 1;
+
+	for (i = 0; i < len; i++) {
+		hw_cmd.offset = mercury_regs[i];
+		msm_mercury_hw_exec_cmds(&hw_cmd, 1);
+	}
+
+	return 0;
+}
+
+int msm_mercury_ioctl_magic_code(struct msm_mercury_device *pmercury_dev,
+	void * __user arg)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+	int rc = 0;
+
+	rc = copy_from_user(&hw_cmd, arg, sizeof(struct msm_mercury_hw_cmd));
+	if (rc) {
+		printk(KERN_ERR "%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	hw_cmd.data = 0x600D600D;
+	rc = copy_to_user(arg, &hw_cmd, sizeof(hw_cmd));
+
+	if (rc) {
+		printk(KERN_ERR "%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int msm_mercury_irq(int event, void *context, void *data)
+{
+	struct msm_mercury_device *pmercury_dev =
+		(struct msm_mercury_device *) context;
+
+	switch (event) {
+	case MSM_MERCURY_HW_IRQ_SW_RESET_ACK:
+		/* wake up evt_q*/
+		MCR_DBG("(%d)%s Wake up event q from Reset IRQ\n", __LINE__,
+			__func__);
+		msm_mercury_q_wakeup(&pmercury_dev->evt_q);
+		break;
+	case MSM_MERCURY_HW_IRQ_WR_EOI_ACK:
+		/*wake up evt_q*/
+		MCR_DBG("%d%s Wake up eventq from WR_EOI IRQ\n", __LINE__,
+			__func__);
+		msm_mercury_q_wr_eoi(&pmercury_dev->evt_q);
+		break;
+	case MSM_MERCURY_HW_IRQ_WR_ERR_ACK:
+		MCR_DBG("(%d)%s Wake up eventq from WR_ERR IRQ\n",
+			__LINE__, __func__);
+		msm_mercury_q_wr_err(&pmercury_dev->evt_q);
+		break;
+	default:
+		MCR_DBG("(%d)%s (default) Wake up event q from WR_ERR IRQ\n",
+			__LINE__, __func__);
+		msm_mercury_q_wr_err(&pmercury_dev->evt_q);
+	}
+	return 0;
+}
+
+int __msm_mercury_open(struct msm_mercury_device *pmercury_dev)
+{
+	int rc = 0;
+
+	mutex_lock(&pmercury_dev->lock);
+	if (pmercury_dev->open_count) {
+		/* only open once */
+		MCR_PR_ERR("%s:%d] busy\n", __func__, __LINE__);
+		mutex_unlock(&pmercury_dev->lock);
+		return -EBUSY;
+	}
+	pmercury_dev->open_count++;
+	mutex_unlock(&pmercury_dev->lock);
+
+	msm_mercury_core_irq_install(msm_mercury_irq);
+
+	rc = msm_mercury_platform_init(pmercury_dev->pdev,
+		&pmercury_dev->mem, &pmercury_dev->base,
+		&pmercury_dev->irq, msm_mercury_core_irq, pmercury_dev);
+	if (rc) {
+		MCR_PR_ERR("%s:%d] platform_init fail %d\n", __func__,
+			__LINE__, rc);
+		return rc;
+	}
+
+	MCR_DBG("\n%s:%d] platform resources - mem 0x%p, base 0x%p, irq %d\n",
+		__func__, __LINE__, pmercury_dev->mem, pmercury_dev->base,
+		pmercury_dev->irq);
+
+	msm_mercury_q_cleanup(&pmercury_dev->evt_q);
+	msm_mercury_core_init();
+
+	MCR_DBG("\n%s:%d] success\n", __func__, __LINE__);
+	return rc;
+}
+
+int __msm_mercury_release(struct msm_mercury_device *pmercury_dev)
+{
+	MCR_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	mutex_lock(&pmercury_dev->lock);
+	if (!pmercury_dev->open_count) {
+		MCR_PR_ERR(KERN_ERR "%s: not opened\n", __func__);
+		mutex_unlock(&pmercury_dev->lock);
+		return -EINVAL;
+	}
+	pmercury_dev->open_count--;
+	mutex_unlock(&pmercury_dev->lock);
+
+	msm_mercury_q_cleanup(&pmercury_dev->evt_q);
+
+	if (pmercury_dev->open_count)
+		MCR_PR_ERR(KERN_ERR "%s: multiple opens\n", __func__);
+
+	if (pmercury_dev->open_count)
+		MCR_PR_ERR(KERN_ERR "%s: multiple opens\n", __func__);
+
+
+	msm_mercury_platform_release(pmercury_dev->mem, pmercury_dev->base,
+		pmercury_dev->irq, pmercury_dev);
+
+	return 0;
+}
+
+int msm_mercury_ioctl_hw_cmd(struct msm_mercury_device *pmercury_dev,
+	void * __user arg)
+{
+	struct msm_mercury_hw_cmd hw_cmd;
+	int is_copy_to_user;
+	int rc = 0;
+
+	rc = copy_from_user(&hw_cmd, arg, sizeof(struct msm_mercury_hw_cmd));
+	if (rc) {
+		MCR_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	is_copy_to_user = msm_mercury_hw_exec_cmds(&hw_cmd, 1);
+	if (is_copy_to_user >= 0) {
+		rc = copy_to_user(arg, &hw_cmd, sizeof(hw_cmd));
+
+		if (rc) {
+			MCR_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+int msm_mercury_ioctl_hw_cmds(struct msm_mercury_device *pmercury_dev,
+	void * __user arg)
+{
+	int is_copy_to_user;
+	int len;
+	uint32_t m;
+	struct msm_mercury_hw_cmds *hw_cmds_p;
+	struct msm_mercury_hw_cmd *hw_cmd_p;
+
+	if (copy_from_user(&m, arg, sizeof(m))) {
+		MCR_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	len = sizeof(struct msm_mercury_hw_cmds) +
+		sizeof(struct msm_mercury_hw_cmd) * (m - 1);
+	hw_cmds_p = kmalloc(len, GFP_KERNEL);
+	if (!hw_cmds_p) {
+		MCR_PR_ERR("[%d]%s() no mem %d\n", __LINE__, __func__, len);
+		return -EFAULT;
+	}
+
+	if (copy_from_user(hw_cmds_p, arg, len)) {
+		MCR_PR_ERR("[%d]%s Fail to copy hw_cmds of len %d from user\n",
+			__LINE__, __func__, len);
+		kfree(hw_cmds_p);
+		return -EFAULT;
+	}
+
+	hw_cmd_p = (struct msm_mercury_hw_cmd *) &(hw_cmds_p->hw_cmd);
+
+	is_copy_to_user = msm_mercury_hw_exec_cmds(hw_cmd_p, m);
+
+	if (is_copy_to_user >= 0) {
+		if (copy_to_user(arg, hw_cmds_p, len)) {
+			MCR_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+			kfree(hw_cmds_p);
+			return -EFAULT;
+		}
+	}
+	kfree(hw_cmds_p);
+	return 0;
+}
+
+int msm_mercury_ioctl_reset(struct msm_mercury_device *pmercury_dev,
+	void * __user arg)
+{
+	int rc = 0;
+
+	MCR_DBG("(%d)%s() Enter\n", __LINE__, __func__);
+	rc = msm_mercury_core_reset();
+
+	return rc;
+}
+
+long __msm_mercury_ioctl(struct msm_mercury_device *pmercury_dev,
+	unsigned int cmd, unsigned long arg)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case MSM_MCR_IOCTL_GET_HW_VERSION:
+		rc = msm_mercury_ioctl_magic_code(pmercury_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_RESET:
+		rc = msm_mercury_ioctl_reset(pmercury_dev, (void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_EVT_GET:
+		rc = msm_mercury_evt_get(pmercury_dev, (void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_EVT_GET_UNBLOCK:
+		rc = msm_mercury_evt_get_unblock(pmercury_dev);
+		break;
+
+	case MSM_MCR_IOCTL_HW_CMD:
+		rc = msm_mercury_ioctl_hw_cmd(pmercury_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_HW_CMDS:
+		rc = msm_mercury_ioctl_hw_cmds(pmercury_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_INPUT_BUF_CFG:
+		rc = msm_mercury_input_buf_cfg(pmercury_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_OUTPUT_BUF_CFG:
+		rc = msm_mercury_output_buf_cfg(pmercury_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_OUTPUT_GET:
+		rc = msm_mercury_output_get(pmercury_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_INPUT_GET:
+		rc = msm_mercury_input_get(pmercury_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_MCR_IOCTL_TEST_DUMP_REGION:
+		rc = msm_mercury_ioctl_dump_regs();
+		break;
+
+	default:
+		printk(KERN_ERR "(%d)%s()  cmd = %d not supported\n",
+			__LINE__, __func__, _IOC_NR(cmd));
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+struct msm_mercury_device *__msm_mercury_init(struct platform_device *pdev)
+{
+	struct msm_mercury_device *pmercury_dev;
+	pmercury_dev = kzalloc(sizeof(struct msm_mercury_device), GFP_ATOMIC);
+	if (!pmercury_dev) {
+		printk(KERN_ERR "%s:%d]no mem\n", __func__, __LINE__);
+		return NULL;
+	}
+
+	mutex_init(&pmercury_dev->lock);
+
+	pmercury_dev->pdev = pdev;
+
+	msm_mercury_q_init("evt_q", &pmercury_dev->evt_q);
+
+	return pmercury_dev;
+}
+
+int __msm_mercury_exit(struct msm_mercury_device *pmercury_dev)
+{
+	mutex_destroy(&pmercury_dev->lock);
+	kfree(pmercury_dev);
+	return 0;
+}
+
diff --git a/drivers/media/video/msm/mercury/msm_mercury_sync.h b/drivers/media/video/msm/mercury/msm_mercury_sync.h
new file mode 100644
index 0000000..f392907
--- /dev/null
+++ b/drivers/media/video/msm/mercury/msm_mercury_sync.h
@@ -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.
+ */
+
+#ifndef MSM_MERCURY_SYNC_H
+#define MSM_MERCURY_SYNC_H
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include "msm_mercury_core.h"
+
+struct msm_mercury_q {
+		char const  *name;
+		struct list_head  q;
+		spinlock_t  lck;
+		wait_queue_head_t wait;
+		int        unblck;
+};
+
+struct msm_mercury_q_entry {
+		struct list_head list;
+		void   *data;
+};
+
+struct msm_mercury_device {
+		struct platform_device *pdev;
+		struct resource        *mem;
+		int                     irq;
+		void                   *base;
+		struct clk *mercury_clk[2];
+		struct device *device;
+		struct cdev   cdev;
+		struct mutex  lock;
+		char      open_count;
+		uint8_t       op_mode;
+
+		/* event queue including frame done & err indications*/
+		struct msm_mercury_q evt_q;
+		struct v4l2_subdev subdev;
+
+};
+
+int __msm_mercury_open(struct msm_mercury_device *pmcry_dev);
+int __msm_mercury_release(struct msm_mercury_device *pmcry_dev);
+
+long __msm_mercury_ioctl(struct msm_mercury_device *pmcry_dev,
+	unsigned int cmd, unsigned long arg);
+
+struct msm_mercury_device *__msm_mercury_init(struct platform_device *pdev);
+int __msm_mercury_exit(struct msm_mercury_device *pmcry_dev);
+int msm_mercury_ioctl_hw_cmds(struct msm_mercury_device *pmcry_dev,
+	void * __user arg);
+int msm_mercury_ioctl_hw_cmds_wo(struct msm_mercury_device *pmcry_dev,
+	void * __user arg);
+#endif /* MSM_MERCURY_SYNC_H */
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 09511b1..c3c09d4 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -108,6 +108,25 @@
 	return rc;
 }
 
+static int msm_camera_v4l2_private_s_ctrl(struct file *f, void *pctx,
+			struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+	int rc = -EINVAL;
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+	WARN_ON(pctx != f->private_data);
+	mutex_lock(&pcam->vid_lock);
+	switch (ioctl_ptr->id) {
+	case MSM_V4L2_PID_CTRL_CMD:
+		rc = msm_server_proc_ctrl_cmd(pcam, ioctl_ptr, 1);
+		break;
+	}
+	mutex_unlock(&pcam->vid_lock);
+	return rc;
+}
+
 static int msm_camera_v4l2_s_ctrl(struct file *f, void *pctx,
 					struct v4l2_control *ctrl)
 {
@@ -127,17 +146,6 @@
 			 __func__, pcam_inst, pcam_inst->my_index);
 		pcam_inst->is_mem_map_inst = 1;
 		break;
-	case MSM_V4L2_PID_MMAP_ENTRY:
-		if (copy_from_user(&pcam_inst->mem_map,
-			(void *)ctrl->value,
-			sizeof(struct msm_mem_map_info))) {
-			rc = -EFAULT;
-		} else
-			D("%s:mmap entry:cookie=0x%x,mem_type=%d,len=%d\n",
-				__func__, pcam_inst->mem_map.cookie,
-				pcam_inst->mem_map.mem_type,
-				pcam_inst->mem_map.length);
-		break;
 	default:
 		if (ctrl->id == MSM_V4L2_PID_CAM_MODE)
 			pcam->op_mode = ctrl->value;
@@ -685,6 +693,22 @@
 	return rc;
 }
 
+static long msm_camera_v4l2_private_ioctl(struct file *file, void *fh,
+					  bool valid_prio, int cmd,
+					  void *arg)
+{
+	int rc = -EINVAL;
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
+
+	switch (cmd) {
+	case MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL:
+		rc = msm_camera_v4l2_private_s_ctrl(file, fh, ioctl_ptr);
+		break;
+	}
+	return rc;
+}
+
 /* v4l2_ioctl_ops */
 static const struct v4l2_ioctl_ops g_msm_ioctl_ops = {
 	.vidioc_querycap = msm_camera_v4l2_querycap,
@@ -724,6 +748,7 @@
 	/* event subscribe/unsubscribe */
 	.vidioc_subscribe_event = msm_camera_v4l2_subscribe_event,
 	.vidioc_unsubscribe_event = msm_camera_v4l2_unsubscribe_event,
+	.vidioc_default = msm_camera_v4l2_private_ioctl,
 };
 
 /* v4l2_file_operations */
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 8500d47..42330b4 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <linux/pm_qos.h>
+#include <linux/wakelock.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
@@ -32,16 +33,22 @@
 #include <mach/camera.h>
 #include <media/msm_isp.h>
 #include <linux/ion.h>
+#include <linux/iommu.h>
 #include <media/msm_gestures.h>
 
 #define MSM_V4L2_DIMENSION_SIZE 96
 #define MAX_DEV_NAME_LEN 50
 
-#define ERR_USER_COPY(to) pr_debug("%s(%d): copy %s user\n", \
+#define ERR_USER_COPY(to) pr_err("%s(%d): copy %s user\n", \
 				__func__, __LINE__, ((to) ? "to" : "from"))
 #define ERR_COPY_FROM_USER() ERR_USER_COPY(0)
 #define ERR_COPY_TO_USER() ERR_USER_COPY(1)
 
+#define COPY_FROM_USER(error, dest, src, size) \
+	(error = (copy_from_user(dest, src, size) ? -EFAULT : 0))
+#define COPY_TO_USER(error, dest, src, size) \
+	(error = (copy_to_user(dest, src, size) ? -EFAULT : 0))
+
 #define MSM_CSIPHY_DRV_NAME "msm_csiphy"
 #define MSM_CSID_DRV_NAME "msm_csid"
 #define MSM_CSIC_DRV_NAME "msm_csic"
@@ -49,6 +56,7 @@
 #define MSM_VFE_DRV_NAME "msm_vfe"
 #define MSM_VPE_DRV_NAME "msm_vpe"
 #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 MAX_NUM_CSIPHY_DEV 3
@@ -99,6 +107,7 @@
 		qcmd = list_first_entry(&__q->list,   \
 			struct msm_queue_cmd, member);	\
 			list_del_init(&qcmd->member);	 \
+			kfree(qcmd->command);		\
 			free_qcmd(qcmd);		\
 	 };			  \
 	spin_unlock_irqrestore(&__q->lock, flags);	\
@@ -144,7 +153,6 @@
 	NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */
 	NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */
 	NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
-	NOTIFY_VPE_MSG_EVT,
 	NOTIFY_PCLK_CHANGE, /* arg = pclk */
 	NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
 	NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
@@ -203,6 +211,7 @@
 	struct msm_pp_frame src_frame;
 	struct msm_pp_frame dest_frame;
 	struct msm_mctl_pp_frame_cmd pp_frame_cmd;
+	struct msm_cam_media_controller *p_mctl;
 };
 
 struct msm_mctl_pp_ctrl {
@@ -258,7 +267,7 @@
 	uint8_t opencnt; /*mctl ref count*/
 	const char *apps_id; /*ID for app that open this session*/
 	struct mutex lock;
-	struct pm_qos_request idle_pm_qos; /*avoid low power mode when active*/
+	struct wake_lock wake_lock; /*avoid low power mode when active*/
 	struct pm_qos_request pm_qos_req_list;
 	struct msm_mctl_pp_info pp_info;
 	struct msm_mctl_stats_t stats_info; /*stats pmem info*/
@@ -271,6 +280,12 @@
 
 	/*sensor info*/
 	struct msm_camera_sensor_info *sdata;
+
+	/*IOMMU mapped IMEM addresses*/
+	uint32_t ping_imem_y;
+	uint32_t ping_imem_cbcr;
+	uint32_t pong_imem_y;
+	uint32_t pong_imem_cbcr;
 };
 
 /* abstract camera device represents a VFE and connected sensor */
@@ -284,7 +299,8 @@
 		 unsigned int cmd, unsigned long arg);
 	int (*isp_notify)(struct v4l2_subdev *sd,
 		unsigned int notification, void *arg);
-	void (*isp_release)(struct v4l2_subdev *sd);
+	void (*isp_release)(struct msm_cam_media_controller *mctl,
+		struct v4l2_subdev *sd);
 	int (*isp_pp_cmd)(struct msm_cam_media_controller *pmctl,
 		 struct msm_mctl_pp_cmd, void *data);
 
@@ -577,6 +593,10 @@
 int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam);
 long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
 		unsigned int cmd, unsigned long evt);
+int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom);
+void msm_queue_init(struct msm_device_queue *queue, const char *name);
+void msm_enqueue(struct msm_device_queue *queue, struct list_head *entry);
+void msm_drain_eventq(struct msm_device_queue *queue);
 #endif /* __KERNEL__ */
 
 #endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/video/msm/msm_camera.c
index ec1e253..624fe9b 100644
--- a/drivers/media/video/msm/msm_camera.c
+++ b/drivers/media/video/msm/msm_camera.c
@@ -36,7 +36,6 @@
 #include <linux/hrtimer.h>
 #include <linux/ion.h>
 
-#include <mach/cpuidle.h>
 DEFINE_MUTEX(ctrl_cmd_lock);
 
 #define CAMERA_STOP_VIDEO 58
@@ -3086,7 +3085,7 @@
 		msm_queue_drain(&sync->pict_q, list_pict);
 		msm_queue_drain(&sync->event_q, list_config);
 
-		pm_qos_update_request(&sync->idle_pm_qos, PM_QOS_DEFAULT_VALUE);
+		wake_unlock(&sync->wake_lock);
 		sync->apps_id = NULL;
 		sync->core_powered_on = 0;
 	}
@@ -3746,8 +3745,7 @@
 	sync->apps_id = apps_id;
 
 	if (!sync->core_powered_on && !is_controlnode) {
-		pm_qos_update_request(&sync->idle_pm_qos,
-				      msm_cpuidle_get_deep_idle_latency());
+		wake_lock(&sync->wake_lock);
 
 		msm_camvfe_fn_init(&sync->vfefn, sync);
 		if (sync->vfefn.vfe_init) {
@@ -3961,12 +3959,11 @@
 	msm_queue_init(&sync->pict_q, "pict");
 	msm_queue_init(&sync->vpe_q, "vpe");
 
-	pm_qos_add_request(&sync->idle_pm_qos, PM_QOS_CPU_DMA_LATENCY,
-				PM_QOS_DEFAULT_VALUE);
+	wake_lock_init(&sync->wake_lock, WAKE_LOCK_SUSPEND, "msm_camera");
 
 	rc = msm_camio_probe_on(pdev);
 	if (rc < 0) {
-		pm_qos_remove_request(&sync->idle_pm_qos);
+		wake_lock_destroy(&sync->wake_lock);
 		return rc;
 	}
 	rc = sensor_probe(sync->sdata, &sctrl);
@@ -3979,7 +3976,7 @@
 		pr_err("%s: failed to initialize %s\n",
 			__func__,
 			sync->sdata->sensor_name);
-		pm_qos_remove_request(&sync->idle_pm_qos);
+		wake_lock_destroy(&sync->wake_lock);
 		return rc;
 	}
 
@@ -3998,7 +3995,7 @@
 
 static int msm_sync_destroy(struct msm_sync *sync)
 {
-	pm_qos_remove_request(&sync->idle_pm_qos);
+	wake_lock_destroy(&sync->wake_lock);
 	return 0;
 }
 
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 148f8b5..fab0095 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -211,9 +211,9 @@
 	case VFE_MSG_V32_JPEG_CAPTURE:
 		D("%s:VFE_MSG_V32_JPEG_CAPTURE vdata->type %d\n", __func__,
 			vdata->type);
-		free_buf.num_planes = 1;
-		free_buf.ch_paddr[0] = IMEM_Y_PING_OFFSET;
-		free_buf.ch_paddr[1] = IMEM_CBCR_PING_OFFSET;
+		free_buf.num_planes = 2;
+		free_buf.ch_paddr[0] = pmctl->ping_imem_y;
+		free_buf.ch_paddr[1] = pmctl->ping_imem_cbcr;
 		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -222,8 +222,8 @@
 			__func__, free_buf.ch_paddr[0], free_buf.ch_paddr[1]);
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		/* Write the same buffer into PONG */
-		free_buf.ch_paddr[0] = IMEM_Y_PONG_OFFSET;
-		free_buf.ch_paddr[1] = IMEM_CBCR_PONG_OFFSET;
+		free_buf.ch_paddr[0] = pmctl->pong_imem_y;
+		free_buf.ch_paddr[1] = pmctl->pong_imem_cbcr;
 		cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -467,19 +467,54 @@
 		return -EINVAL;
 	}
 
+	rc = msm_iommu_map_contig_buffer(
+		(unsigned long)IMEM_Y_PING_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
+		SZ_4K, IOMMU_WRITE | IOMMU_READ,
+		(unsigned long *)&mctl->ping_imem_y);
+	mctl->ping_imem_cbcr = mctl->ping_imem_y + IMEM_Y_SIZE;
+	if (rc < 0) {
+		pr_err("%s: ping iommu mapping returned error %d\n",
+			__func__, rc);
+		mctl->ping_imem_y = 0;
+		mctl->ping_imem_cbcr = 0;
+	}
+	msm_iommu_map_contig_buffer(
+		(unsigned long)IMEM_Y_PONG_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
+		SZ_4K, IOMMU_WRITE | IOMMU_READ,
+		(unsigned long *)&mctl->pong_imem_y);
+	mctl->pong_imem_cbcr = mctl->pong_imem_y + IMEM_Y_SIZE;
+	if (rc < 0) {
+		pr_err("%s: pong iommu mapping returned error %d\n",
+			 __func__, rc);
+		mctl->pong_imem_y = 0;
+		mctl->pong_imem_cbcr = 0;
+	}
+
 	rc = msm_vfe_subdev_init(sd, mctl);
 	if (rc < 0) {
 		pr_err("%s: vfe_init failed at %d\n",
-					__func__, rc);
+			__func__, rc);
 	}
 	return rc;
 }
 
-static void msm_isp_release(
+static void msm_isp_release(struct msm_cam_media_controller *mctl,
 	struct v4l2_subdev *sd)
 {
 	D("%s\n", __func__);
 	msm_vfe_subdev_release(sd);
+	msm_iommu_unmap_contig_buffer(mctl->ping_imem_y,
+		CAMERA_DOMAIN, GEN_POOL,
+		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
+	msm_iommu_unmap_contig_buffer(mctl->pong_imem_y,
+		CAMERA_DOMAIN, GEN_POOL,
+		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
+	mctl->ping_imem_y = 0;
+	mctl->ping_imem_cbcr = 0;
+	mctl->pong_imem_y = 0;
+	mctl->pong_imem_cbcr = 0;
 }
 
 static int msm_config_vfe(struct v4l2_subdev *sd,
@@ -626,6 +661,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.
@@ -707,13 +744,6 @@
 
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
 	switch (cmd) {
-	case MSM_CAM_IOCTL_PICT_PP_DONE:
-		/* Release the preview of snapshot frame
-		 * that was grabbed.
-		 */
-		/*rc = msm_pp_release(pmsm->sync, arg);*/
-		break;
-
 	case MSM_CAM_IOCTL_CONFIG_VFE:
 		/* Coming from config thread for update */
 		rc = msm_config_vfe(sd, pmctl, argp);
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 716575a..ed6c493 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -20,6 +20,7 @@
 #include <linux/videodev2.h>
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
+#include <linux/wakelock.h>
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
@@ -27,8 +28,6 @@
 
 #include <linux/android_pmem.h>
 
-#include <mach/cpuidle.h>
-
 #include "msm.h"
 #include "msm_cam_server.h"
 #include "msm_csid.h"
@@ -570,8 +569,7 @@
 	/* open sub devices - once only*/
 	if (!p_mctl->opencnt) {
 		uint32_t csid_version;
-		pm_qos_update_request(&p_mctl->idle_pm_qos,
-				      msm_cpuidle_get_deep_idle_latency());
+		wake_lock(&p_mctl->wake_lock);
 
 		csid_core = camdev->csid_core;
 		rc = msm_mctl_register_subdevs(p_mctl, csid_core);
@@ -667,12 +665,11 @@
 			}
 		}
 
-		if (camdev->is_ispif) {
-			pm_qos_add_request(&p_mctl->pm_qos_req_list,
-				PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
-			pm_qos_update_request(&p_mctl->pm_qos_req_list,
-				MSM_V4L2_SWFI_LATENCY);
-		}
+		pm_qos_add_request(&p_mctl->pm_qos_req_list,
+			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
+		pm_qos_update_request(&p_mctl->pm_qos_req_list,
+			MSM_V4L2_SWFI_LATENCY);
+
 		p_mctl->apps_id = apps_id;
 		p_mctl->opencnt++;
 	} else {
@@ -694,7 +691,7 @@
 			pr_err("%s: axi release failed %d\n", __func__, rc);
 axi_init_failed:
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
-		p_mctl->isp_sdev->isp_release(p_mctl->isp_sdev->sd);
+		p_mctl->isp_sdev->isp_release(p_mctl, p_mctl->isp_sdev->sd);
 isp_open_failed:
 	if (camdev->is_csic)
 		if (v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
@@ -720,7 +717,7 @@
 		pr_err("%s: sensor powerdown failed: %d\n", __func__, rc);
 sensor_sdev_failed:
 register_sdev_failed:
-	pm_qos_update_request(&p_mctl->idle_pm_qos, PM_QOS_DEFAULT_VALUE);
+	wake_unlock(&p_mctl->wake_lock);
 	mutex_unlock(&p_mctl->lock);
 	return rc;
 }
@@ -757,7 +754,7 @@
 	}
 
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
-		p_mctl->isp_sdev->isp_release(
+		p_mctl->isp_sdev->isp_release(p_mctl,
 			p_mctl->isp_sdev->sd);
 
 	if (camdev->is_csid) {
@@ -770,18 +767,18 @@
 			VIDIOC_MSM_CSIPHY_RELEASE, NULL);
 	}
 
-	if (camdev->is_ispif) {
-		pm_qos_update_request(&p_mctl->pm_qos_req_list,
-				PM_QOS_DEFAULT_VALUE);
-		pm_qos_remove_request(&p_mctl->pm_qos_req_list);
-	}
-
-	if (p_mctl->act_sdev)
+	if (p_mctl->act_sdev) {
 		v4l2_subdev_call(p_mctl->act_sdev, core, s_power, 0);
+		p_mctl->act_sdev = NULL;
+	}
 
 	v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
 
-	pm_qos_update_request(&p_mctl->idle_pm_qos, PM_QOS_DEFAULT_VALUE);
+	pm_qos_update_request(&p_mctl->pm_qos_req_list,
+				PM_QOS_DEFAULT_VALUE);
+	pm_qos_remove_request(&p_mctl->pm_qos_req_list);
+
+	wake_unlock(&p_mctl->wake_lock);
 	return rc;
 }
 
@@ -865,8 +862,7 @@
 		return -EINVAL;
 	}
 
-	pm_qos_add_request(&pmctl->idle_pm_qos, PM_QOS_CPU_DMA_LATENCY,
-				PM_QOS_DEFAULT_VALUE);
+	wake_lock_init(&pmctl->wake_lock, WAKE_LOCK_SUSPEND, "msm_camera");
 	mutex_init(&pmctl->lock);
 	pmctl->opencnt = 0;
 
@@ -906,7 +902,7 @@
 	}
 
 	mutex_destroy(&pmctl->lock);
-	pm_qos_remove_request(&pmctl->idle_pm_qos);
+	wake_lock_destroy(&pmctl->wake_lock);
 	msm_cam_server_free_mctl(pcam->mctl_handle);
 	return rc;
 }
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 1088a54..eade6f1 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -454,7 +454,7 @@
 					image_mode, fbuf,
 					&frame_id, 1);
 				D("%s mctl node buf done %d\n", __func__, 0);
-				return -EINVAL;
+				return rc;
 			} else {
 			  pr_err("%s Invalid instance, dropping buffer\n",
 				  __func__);
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index f4c04bb..844a3ff 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -36,18 +36,6 @@
 #define D(fmt, args...) do {} while (0)
 #endif
 
-
-static int msm_mctl_pp_vpe_ioctl(struct v4l2_subdev *vpe_sd,
-	struct msm_mctl_pp_cmd *cmd, void *data)
-{
-	int rc = 0;
-	struct msm_mctl_pp_params parm;
-	parm.cmd = cmd;
-	parm.data = data;
-	rc = v4l2_subdev_call(vpe_sd, core, ioctl, VIDIOC_MSM_VPE_CFG, &parm);
-	return rc;
-}
-
 static int msm_mctl_pp_buf_divert(
 			struct msm_cam_media_controller *pmctl,
 			struct msm_cam_v4l2_dev_inst *pcam_inst,
@@ -384,244 +372,6 @@
 		return -EINVAL;
 }
 
-int msm_mctl_pp_proc_vpe_cmd(
-	struct msm_cam_media_controller *p_mctl,
-	struct msm_mctl_pp_cmd *pp_cmd)
-{
-	int rc = 0, idx;
-	void __user *argp = (void __user *)pp_cmd->value;
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
-
-	switch (pp_cmd->id) {
-	case VPE_CMD_INIT:
-	case VPE_CMD_DEINIT:
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		break;
-	case VPE_CMD_DISABLE:
-	case VPE_CMD_RESET:
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		break;
-	case VPE_CMD_ENABLE: {
-		struct msm_vpe_clock_rate clk_rate;
-		if (sizeof(struct msm_vpe_clock_rate) !=
-			pp_cmd->length) {
-			pr_err("%s: vpe cmd size mismatch "
-				"(id=%d, length = %d, expect size = %d",
-				__func__, pp_cmd->id, pp_cmd->length,
-				sizeof(struct msm_vpe_clock_rate));
-				rc = -EINVAL;
-				break;
-		}
-		if (copy_from_user(&clk_rate, pp_cmd->value,
-			sizeof(struct msm_vpe_clock_rate))) {
-			pr_err("%s:clk_rate copy failed", __func__);
-			return -EFAULT;
-		}
-		pp_cmd->value = (void *)&clk_rate;
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		pp_cmd->value = argp;
-		break;
-	}
-	case VPE_CMD_FLUSH: {
-		struct msm_vpe_flush_frame_buffer flush_buf;
-		if (sizeof(struct msm_vpe_flush_frame_buffer) !=
-			pp_cmd->length) {
-			D("%s: size mismatch(id=%d, len = %d, expected = %d",
-				__func__, pp_cmd->id, pp_cmd->length,
-				sizeof(struct msm_vpe_flush_frame_buffer));
-				rc = -EINVAL;
-				break;
-		}
-		if (copy_from_user(
-			&flush_buf, pp_cmd->value, sizeof(flush_buf)))
-			return -EFAULT;
-		pp_cmd->value = (void *)&flush_buf;
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		if (rc == 0) {
-			if (copy_to_user((void *)argp,
-						&flush_buf,
-						sizeof(flush_buf))) {
-				ERR_COPY_TO_USER();
-				rc = -EFAULT;
-			}
-			pp_cmd->value = argp;
-		}
-	}
-	break;
-	case VPE_CMD_OPERATION_MODE_CFG: {
-		struct msm_vpe_op_mode_cfg op_mode_cfg;
-		if (sizeof(struct msm_vpe_op_mode_cfg) !=
-		pp_cmd->length) {
-			D("%s: size mismatch(id=%d, len = %d, expected = %d",
-				__func__, pp_cmd->id, pp_cmd->length,
-				sizeof(struct msm_vpe_op_mode_cfg));
-				rc = -EINVAL;
-				break;
-		}
-		if (copy_from_user(&op_mode_cfg,
-			pp_cmd->value,
-			sizeof(op_mode_cfg)))
-			return -EFAULT;
-		pp_cmd->value = (void *)&op_mode_cfg;
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		break;
-	}
-	case VPE_CMD_INPUT_PLANE_CFG: {
-		struct msm_vpe_input_plane_cfg input_cfg;
-		if (sizeof(struct msm_vpe_input_plane_cfg) !=
-			pp_cmd->length) {
-			D("%s: mismatch(id=%d, len = %d, expected = %d",
-				__func__, pp_cmd->id, pp_cmd->length,
-				sizeof(struct msm_vpe_input_plane_cfg));
-				rc = -EINVAL;
-				break;
-		}
-		if (copy_from_user(
-			&input_cfg, pp_cmd->value, sizeof(input_cfg)))
-			return -EFAULT;
-		pp_cmd->value = (void *)&input_cfg;
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		break;
-	}
-	case VPE_CMD_OUTPUT_PLANE_CFG: {
-		struct msm_vpe_output_plane_cfg output_cfg;
-		if (sizeof(struct msm_vpe_output_plane_cfg) !=
-			pp_cmd->length) {
-			D("%s: size mismatch(id=%d, len = %d, expected = %d",
-				__func__, pp_cmd->id, pp_cmd->length,
-				sizeof(struct msm_vpe_output_plane_cfg));
-				rc = -EINVAL;
-				break;
-		}
-		if (copy_from_user(&output_cfg, pp_cmd->value,
-			sizeof(output_cfg))) {
-			D("%s: cannot copy pp_cmd->value, size=%d",
-				__func__, pp_cmd->length);
-			return -EFAULT;
-		}
-		pp_cmd->value = (void *)&output_cfg;
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		break;
-	}
-	case VPE_CMD_INPUT_PLANE_UPDATE: {
-		struct msm_vpe_input_plane_update_cfg input_update_cfg;
-		if (sizeof(struct msm_vpe_input_plane_update_cfg) !=
-			pp_cmd->length) {
-			D("%s: size mismatch(id=%d, len = %d, expected = %d",
-				__func__, pp_cmd->id, pp_cmd->length,
-				sizeof(struct msm_vpe_input_plane_update_cfg));
-				rc = -EINVAL;
-				break;
-		}
-		if (copy_from_user(&input_update_cfg, pp_cmd->value,
-			sizeof(input_update_cfg)))
-			return -EFAULT;
-		pp_cmd->value = (void *)&input_update_cfg;
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		break;
-	}
-	case VPE_CMD_SCALE_CFG_TYPE: {
-		struct msm_vpe_scaler_cfg scaler_cfg;
-		if (sizeof(struct msm_vpe_scaler_cfg) !=
-			pp_cmd->length) {
-			D("%s: size mismatch(id=%d, len = %d, expected = %d",
-				__func__, pp_cmd->id, pp_cmd->length,
-				sizeof(struct msm_vpe_scaler_cfg));
-				rc = -EINVAL;
-				break;
-		}
-		if (copy_from_user(&scaler_cfg, pp_cmd->value,
-			sizeof(scaler_cfg)))
-			return -EFAULT;
-		pp_cmd->value = (void *)&scaler_cfg;
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, NULL);
-		break;
-	}
-	case VPE_CMD_ZOOM: {
-		struct msm_mctl_pp_frame_info *zoom;
-		zoom = kmalloc(sizeof(struct msm_mctl_pp_frame_info),
-					GFP_ATOMIC);
-		if (!zoom) {
-			rc = -ENOMEM;
-			break;
-		}
-		if (sizeof(zoom->pp_frame_cmd) != pp_cmd->length) {
-			D("%s: size mismatch(id=%d, len = %d, expected = %d",
-				__func__, pp_cmd->id, pp_cmd->length,
-				sizeof(zoom->pp_frame_cmd));
-				rc = -EINVAL;
-				kfree(zoom);
-				break;
-		}
-		if (copy_from_user(&zoom->pp_frame_cmd, pp_cmd->value,
-			sizeof(zoom->pp_frame_cmd))) {
-			kfree(zoom);
-			return -EFAULT;
-		}
-		D("%s: src=0x%x, dest=0x%x,cookie=0x%x,action=0x%x,path=0x%x",
-				__func__, zoom->pp_frame_cmd.src_buf_handle,
-				zoom->pp_frame_cmd.dest_buf_handle,
-				zoom->pp_frame_cmd.cookie,
-				zoom->pp_frame_cmd.vpe_output_action,
-				zoom->pp_frame_cmd.path);
-		idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr,
-			zoom->pp_frame_cmd.path);
-		if (idx < 0) {
-			pr_err("%s Invalid path, returning\n", __func__);
-			kfree(zoom);
-			return idx;
-		}
-		pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
-		if (!pcam_inst) {
-			pr_err("%s Invalid instance, returning\n", __func__);
-			kfree(zoom);
-			return -EINVAL;
-		}
-		zoom->user_cmd = pp_cmd->id;
-		rc = msm_mctl_pp_get_phy_addr(pcam_inst,
-			zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame);
-		if (rc) {
-			kfree(zoom);
-			break;
-		}
-		rc = msm_mctl_pp_get_phy_addr(pcam_inst,
-			zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame);
-		if (rc) {
-			kfree(zoom);
-			break;
-		}
-		rc = msm_mctl_pp_copy_timestamp_and_frame_id(
-			zoom->pp_frame_cmd.src_buf_handle,
-
-			zoom->pp_frame_cmd.dest_buf_handle);
-		if (rc) {
-			kfree(zoom);
-			break;
-		}
-		rc = msm_mctl_pp_vpe_ioctl(
-			p_mctl->vpe_sdev, pp_cmd, (void *)zoom);
-		if (rc) {
-			kfree(zoom);
-			break;
-		}
-		break;
-	}
-	default:
-		rc = -1;
-		break;
-	}
-	return rc;
-}
-
 static int msm_mctl_pp_path_to_img_mode(int path)
 {
 	switch (path) {
@@ -717,9 +467,6 @@
 		return -EFAULT;
 
 	switch (pp_cmd.type) {
-	case MSM_PP_CMD_TYPE_VPE:
-		rc = msm_mctl_pp_proc_vpe_cmd(p_mctl, &pp_cmd.cmd);
-		break;
 	case MSM_PP_CMD_TYPE_MCTL:
 		rc = msm_mctl_pp_proc_cmd(p_mctl, &pp_cmd.cmd);
 		break;
@@ -739,71 +486,6 @@
 	return rc;
 }
 
-int msm_mctl_pp_notify(struct msm_cam_media_controller *p_mctl,
-			struct msm_mctl_pp_frame_info *pp_frame_info)
-{
-		struct msm_mctl_pp_frame_cmd *pp_frame_cmd;
-		pp_frame_cmd = &pp_frame_info->pp_frame_cmd;
-
-		D("%s: msm_cam_evt_divert_frame=%d",
-			__func__, sizeof(struct msm_mctl_pp_event_info));
-		if ((MSM_MCTL_PP_VPE_FRAME_TO_APP &
-			pp_frame_cmd->vpe_output_action)) {
-			struct msm_free_buf done_frame;
-			int img_mode =
-				msm_mctl_pp_path_to_img_mode(
-					pp_frame_cmd->path);
-			if (img_mode < 0) {
-				pr_err("%s Invalid image mode\n", __func__);
-				return img_mode;
-			}
-			done_frame.ch_paddr[0] =
-				pp_frame_info->dest_frame.sp.phy_addr;
-			done_frame.vb =
-				pp_frame_info->dest_frame.handle;
-			msm_mctl_buf_done_pp(
-				p_mctl, img_mode, &done_frame, 0, 0);
-			D("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
-				__func__, done_frame.vb,
-				pp_frame_cmd->path, done_frame.ch_paddr[0]);
-		}
-		if ((MSM_MCTL_PP_VPE_FRAME_ACK &
-			pp_frame_cmd->vpe_output_action)) {
-			struct v4l2_event v4l2_evt;
-			struct msm_mctl_pp_event_info *pp_event_info;
-			struct msm_isp_event_ctrl *isp_event;
-			isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl),
-								GFP_ATOMIC);
-			if (!isp_event) {
-				pr_err("%s Insufficient memory.", __func__);
-				return -ENOMEM;
-			}
-			memset(&v4l2_evt, 0, sizeof(v4l2_evt));
-			*((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;
-
-			/* Get hold of pp event info struct inside event ctrl.*/
-			pp_event_info = &(isp_event->isp_data.pp_event_info);
-
-			pp_event_info->event = MCTL_PP_EVENT_CMD_ACK;
-			pp_event_info->ack.cmd = pp_frame_info->user_cmd;
-			pp_event_info->ack.status = 0;
-			pp_event_info->ack.cookie = pp_frame_cmd->cookie;
-			v4l2_evt.id = 0;
-			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-						MSM_CAM_RESP_MCTL_PP_EVENT;
-
-			v4l2_event_queue(
-				p_mctl->config_device->
-					config_stat_event_queue.pvdev,
-				&v4l2_evt);
-			D("%s: ack to daemon, cookie=0x%x, event = 0x%x",
-				__func__, pp_frame_info->pp_frame_cmd.cookie,
-				v4l2_evt.type);
-		}
-		kfree(pp_frame_info); /* free mem */
-		return 0;
-}
-
 int msm_mctl_pp_reserve_free_frame(
 	struct msm_cam_media_controller *p_mctl,
 	void __user *arg)
@@ -1027,3 +709,54 @@
 
 	return rc;
 }
+
+int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom)
+{
+	struct msm_cam_media_controller *p_mctl;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	int rc = 0, idx;
+
+	if (!zoom || !zoom->p_mctl) {
+		pr_err("%s Invalid input, not sending buffer to VPE ",
+			__func__);
+		return -EINVAL;
+	}
+	p_mctl = zoom->p_mctl;
+	idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr,
+		zoom->pp_frame_cmd.path);
+	if (idx < 0) {
+		pr_err("%s Invalid path, returning\n", __func__);
+		return idx;
+	}
+	pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
+	if (!pcam_inst) {
+		pr_err("%s Invalid instance, returning\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = msm_mctl_pp_get_phy_addr(pcam_inst,
+		zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame);
+	if (rc) {
+		pr_err("%s Error getting buffer address for src frame\n",
+			__func__);
+		return rc;
+	}
+
+	rc = msm_mctl_pp_get_phy_addr(pcam_inst,
+		zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame);
+	if (rc) {
+		pr_err("%s Error getting buffer address for dest frame\n",
+			__func__);
+		return rc;
+	}
+
+	rc = msm_mctl_pp_copy_timestamp_and_frame_id(
+		zoom->pp_frame_cmd.src_buf_handle,
+		zoom->pp_frame_cmd.dest_buf_handle);
+	if (rc < 0) {
+		pr_err("%s Error copying timestamp info\n",
+			__func__);
+		return rc;
+	}
+	return rc;
+}
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index a010817..7a2670c 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);
@@ -999,6 +953,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();
@@ -3582,11 +3573,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:
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 98c1ca0..3611656 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -30,25 +30,24 @@
 atomic_t irq_cnt;
 
 #define VFE32_AXI_OFFSET 0x0050
-#define vfe32_get_ch_ping_addr(chn) \
-	(msm_camera_io_r(vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
-#define vfe32_get_ch_pong_addr(chn) \
-	(msm_camera_io_r(vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
-#define vfe32_get_ch_addr(ping_pong, chn) \
-	(((ping_pong) & (1 << (chn))) == 0 ? \
-	vfe32_get_ch_pong_addr(chn) : vfe32_get_ch_ping_addr(chn))
+#define vfe32_get_ch_ping_addr(base, chn) \
+	(msm_camera_io_r((base) + 0x0050 + 0x18 * (chn)))
+#define vfe32_get_ch_pong_addr(base, chn) \
+	(msm_camera_io_r((base) + 0x0050 + 0x18 * (chn) + 4))
+#define vfe32_get_ch_addr(ping_pong, base, chn) \
+	((((ping_pong) & (1 << (chn))) == 0) ? \
+	(vfe32_get_ch_pong_addr((base), chn)) : \
+	(vfe32_get_ch_ping_addr((base), chn)))
 
-#define vfe32_put_ch_ping_addr(chn, addr) \
-	(msm_camera_io_w((addr), vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
-#define vfe32_put_ch_pong_addr(chn, addr) \
-	(msm_camera_io_w((addr), \
-	vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
-#define vfe32_put_ch_addr(ping_pong, chn, addr) \
+#define vfe32_put_ch_ping_addr(base, chn, addr) \
+	(msm_camera_io_w((addr), (base) + 0x0050 + 0x18 * (chn)))
+#define vfe32_put_ch_pong_addr(base, chn, addr) \
+	(msm_camera_io_w((addr), (base) + 0x0050 + 0x18 * (chn) + 4))
+#define vfe32_put_ch_addr(ping_pong, base, chn, addr) \
 	(((ping_pong) & (1 << (chn))) == 0 ?   \
-	vfe32_put_ch_pong_addr((chn), (addr)) : \
-	vfe32_put_ch_ping_addr((chn), (addr)))
+	vfe32_put_ch_pong_addr((base), (chn), (addr)) : \
+	vfe32_put_ch_ping_addr((base), (chn), (addr)))
 
-static struct vfe32_ctrl_type *vfe32_ctrl;
 static uint32_t vfe_clk_rate;
 
 struct vfe32_isr_queue_cmd {
@@ -357,112 +356,117 @@
 	"DEMOSAICV3_UPDATE",
 };
 
-static void vfe32_stop(void)
+static void vfe32_stop(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
 
-	atomic_set(&vfe32_ctrl->vstate, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
 
 	/* for reset hw modules, and send msg when reset_irq comes.*/
-	spin_lock_irqsave(&vfe32_ctrl->stop_flag_lock, flags);
-	vfe32_ctrl->stop_ack_pending = TRUE;
-	spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
+	spin_lock_irqsave(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
+	vfe32_ctrl->share_ctrl->stop_ack_pending = TRUE;
+	spin_unlock_irqrestore(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
 
 	/* disable all interrupts.  */
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-		vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-			vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
 
 	/* clear all pending interrupts*/
 	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-		vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
 	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-		vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
 	/* Ensure the write order while writing
 	to the command register using the barrier */
 	msm_camera_io_w_mb(1,
-		vfe32_ctrl->vfebase + VFE_IRQ_CMD);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
 
 	/* in either continuous or snapshot mode, stop command can be issued
 	 * at any time. stop camif immediately. */
 	msm_camera_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
-		vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
+		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,
+	struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl)
 {
 	struct msm_vfe_resp rp;
 	unsigned long flags = 0;
-	spin_lock_irqsave(&vfe32_ctrl->sd_notify_lock, flags);
+	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;
 	rp.type	   = id;
-	v4l2_subdev_notify(&vfe32_ctrl->subdev, NOTIFY_VFE_BUF_EVT, &rp);
-	spin_unlock_irqrestore(&vfe32_ctrl->sd_notify_lock, flags);
+	v4l2_subdev_notify(sd, NOTIFY_VFE_BUF_EVT, &rp);
+	spin_unlock_irqrestore(&share_ctrl->sd_notify_lock, flags);
 }
 
-static int vfe32_config_axi(int mode, uint32_t *ao)
+static int vfe32_config_axi(
+	struct axi_ctrl_t *axi_ctrl, int mode, uint32_t *ao)
 {
 	uint32_t *ch_info;
 	uint32_t *axi_cfg = ao+V32_AXI_BUS_FMT_OFF;
 
 	/* Update the corresponding write masters for each output*/
 	ch_info = axi_cfg + V32_AXI_CFG_LEN;
-	vfe32_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
-	vfe32_ctrl->outpath.out0.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
-	vfe32_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
-	vfe32_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
-	vfe32_ctrl->outpath.out1.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
-	vfe32_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
-	vfe32_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
-	vfe32_ctrl->outpath.out2.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
-	vfe32_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+	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.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.out2.ch0 = 0x0000FFFF & *ch_info;
+	axi_ctrl->share_ctrl->outpath.out2.ch1 =
+		0x0000FFFF & (*ch_info++ >> 16);
+	axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
 
 	switch (mode) {
 	case OUTPUT_PRIM:
-		vfe32_ctrl->outpath.output_mode =
+		axi_ctrl->share_ctrl->outpath.output_mode =
 			VFE32_OUTPUT_MODE_PRIMARY;
 		break;
 	case OUTPUT_PRIM_ALL_CHNLS:
-		vfe32_ctrl->outpath.output_mode =
+		axi_ctrl->share_ctrl->outpath.output_mode =
 			VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
 		break;
 	case OUTPUT_PRIM|OUTPUT_SEC:
-		vfe32_ctrl->outpath.output_mode =
+		axi_ctrl->share_ctrl->outpath.output_mode =
 			VFE32_OUTPUT_MODE_PRIMARY;
-		vfe32_ctrl->outpath.output_mode |=
+		axi_ctrl->share_ctrl->outpath.output_mode |=
 			VFE32_OUTPUT_MODE_SECONDARY;
 		break;
 	case OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS:
-		vfe32_ctrl->outpath.output_mode =
+		axi_ctrl->share_ctrl->outpath.output_mode =
 			VFE32_OUTPUT_MODE_PRIMARY;
-		vfe32_ctrl->outpath.output_mode |=
+		axi_ctrl->share_ctrl->outpath.output_mode |=
 			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
 		break;
 	case OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC:
-		vfe32_ctrl->outpath.output_mode =
+		axi_ctrl->share_ctrl->outpath.output_mode =
 			VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
-		vfe32_ctrl->outpath.output_mode |=
+		axi_ctrl->share_ctrl->outpath.output_mode |=
 			VFE32_OUTPUT_MODE_SECONDARY;
 		break;
 	default:
 		pr_err("%s Invalid AXI mode %d ", __func__, mode);
 		return -EINVAL;
 	}
-	msm_camera_io_w(*ao, vfe32_ctrl->vfebase +
+	msm_camera_io_w(*ao, axi_ctrl->share_ctrl->vfebase +
 		VFE_BUS_IO_FORMAT_CFG);
-	msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+	msm_camera_io_memcpy(axi_ctrl->share_ctrl->vfebase +
 		vfe32_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
 		vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length - V32_AXI_CH_INF_LEN
 		- V32_AXI_BUS_FMT_LEN);
 	return 0;
 }
 
-static void vfe32_reset_internal_variables(void)
+static void vfe32_reset_internal_variables(
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
 	vfe32_ctrl->vfeImaskCompositePacked = 0;
@@ -470,9 +474,9 @@
 	vfe32_ctrl->start_ack_pending = FALSE;
 	atomic_set(&irq_cnt, 0);
 
-	spin_lock_irqsave(&vfe32_ctrl->stop_flag_lock, flags);
-	vfe32_ctrl->stop_ack_pending  = FALSE;
-	spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
+	spin_lock_irqsave(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
+	vfe32_ctrl->share_ctrl->stop_ack_pending  = FALSE;
+	spin_unlock_irqrestore(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
 
 	vfe32_ctrl->reset_ack_pending  = FALSE;
 
@@ -481,17 +485,17 @@
 	spin_unlock_irqrestore(&vfe32_ctrl->update_ack_lock, flags);
 
 	vfe32_ctrl->recording_state = VFE_STATE_IDLE;
-	vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
+	vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
 
-	atomic_set(&vfe32_ctrl->vstate, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
 
 	/* 0 for continuous mode, 1 for snapshot mode */
-	vfe32_ctrl->operation_mode = 0;
-	vfe32_ctrl->outpath.output_mode = 0;
-	vfe32_ctrl->vfe_capture_count = 0;
+	vfe32_ctrl->share_ctrl->operation_mode = 0;
+	vfe32_ctrl->share_ctrl->outpath.output_mode = 0;
+	vfe32_ctrl->share_ctrl->vfe_capture_count = 0;
 
 	/* this is unsigned 32 bit integer. */
-	vfe32_ctrl->vfeFrameId = 0;
+	vfe32_ctrl->share_ctrl->vfeFrameId = 0;
 	/* Stats control variables. */
 	memset(&(vfe32_ctrl->afStatsControl), 0,
 		sizeof(struct vfe_stats_control));
@@ -516,30 +520,30 @@
 	vfe32_ctrl->snapshot_frame_cnt = 0;
 }
 
-static void vfe32_reset(void)
+static void vfe32_reset(struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	vfe32_reset_internal_variables();
+	vfe32_reset_internal_variables(vfe32_ctrl);
 	/* disable all interrupts.  vfeImaskLocal is also reset to 0
 	* to begin with. */
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-		vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
 
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-		vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
 
 	/* clear all pending interrupts*/
 	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-		vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
 	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-		vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
 
 	/* Ensure the write order while writing
 	to the command register using the barrier */
-	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_IRQ_CMD);
+	msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
 
 	/* enable reset_ack interrupt.  */
 	msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
-	vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+	vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
 
 	/* Write to VFE_GLOBAL_RESET_CMD to reset the vfe hardware. Once reset
 	 * is done, hardware interrupt will be generated.  VFE ist processes
@@ -549,409 +553,516 @@
 	/* Ensure the write order while writing
 	to the command register using the barrier */
 	msm_camera_io_w_mb(VFE_RESET_UPON_RESET_CMD,
-		vfe32_ctrl->vfebase + VFE_GLOBAL_RESET);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
 }
 
-static int vfe32_operation_config(uint32_t *cmd)
+static int vfe32_operation_config(uint32_t *cmd,
+			struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	uint32_t *p = cmd;
 
-	vfe32_ctrl->operation_mode = *p;
-	vfe32_ctrl->stats_comp = *(++p);
+	vfe32_ctrl->share_ctrl->operation_mode = *p;
+	vfe32_ctrl->share_ctrl->stats_comp = *(++p);
 	vfe32_ctrl->hfr_mode = *(++p);
 
-	msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CFG);
-	msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_MODULE_CFG);
-	msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_PIXEL_IF_CFG);
-	if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
+	msm_camera_io_w(*(++p),
+		vfe32_ctrl->share_ctrl->vfebase + VFE_CFG);
+	msm_camera_io_w(*(++p),
+		vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
+	msm_camera_io_w(*(++p),
+		vfe32_ctrl->share_ctrl->vfebase + VFE_PIXEL_IF_CFG);
+	if (msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
+		V32_GET_HW_VERSION_OFF) ==
 		VFE33_HW_NUMBER) {
-		msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI0_CFG);
-		msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI1_CFG);
+		msm_camera_io_w(*(++p),
+			vfe32_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
+		msm_camera_io_w(*(++p),
+			vfe32_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
 	}  else {
 		++p;
 		++p;
 	}
-	msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_REALIGN_BUF);
-	msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CHROMA_UP);
-	msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_STATS_CFG);
+	msm_camera_io_w(*(++p),
+		vfe32_ctrl->share_ctrl->vfebase + VFE_REALIGN_BUF);
+	msm_camera_io_w(*(++p),
+		vfe32_ctrl->share_ctrl->vfebase + VFE_CHROMA_UP);
+	msm_camera_io_w(*(++p),
+		vfe32_ctrl->share_ctrl->vfebase + VFE_STATS_CFG);
 	return 0;
 }
 
-static uint32_t vfe_stats_awb_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_awb_buf_init(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
 {
 	uint32_t *ptr = in->statsBuf;
 	uint32_t addr;
 
 	addr = ptr[0];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_AWB_WR_PING_ADDR);
 	addr = ptr[1];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_AWB_WR_PONG_ADDR);
 	vfe32_ctrl->awbStatsControl.nextFrameAddrBuf = in->statsBuf[2];
 	return 0;
 }
 
-static uint32_t vfe_stats_aec_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_aec_buf_init(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
 {
 	uint32_t *ptr = in->statsBuf;
 	uint32_t addr;
 
 	addr = ptr[0];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AEC_WR_PING_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_AEC_WR_PING_ADDR);
 	addr = ptr[1];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AEC_WR_PONG_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_AEC_WR_PONG_ADDR);
 
 	vfe32_ctrl->aecStatsControl.nextFrameAddrBuf = in->statsBuf[2];
 	return 0;
 }
 
-static uint32_t vfe_stats_af_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_af_buf_init(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
 {
 	uint32_t *ptr = in->statsBuf;
 	uint32_t addr;
 
 	addr = ptr[0];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_AF_WR_PING_ADDR);
 	addr = ptr[1];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_AF_WR_PONG_ADDR);
 
 	vfe32_ctrl->afStatsControl.nextFrameAddrBuf = in->statsBuf[2];
 	return 0;
 }
 
-static uint32_t vfe_stats_ihist_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_ihist_buf_init(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
 {
 	uint32_t *ptr = in->statsBuf;
 	uint32_t addr;
 
 	addr = ptr[0];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PING_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_HIST_WR_PING_ADDR);
 	addr = ptr[1];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PONG_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_HIST_WR_PONG_ADDR);
 
 	vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf = in->statsBuf[2];
 	return 0;
 }
 
-static uint32_t vfe_stats_rs_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_rs_buf_init(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
 {
 	uint32_t *ptr = in->statsBuf;
 	uint32_t addr;
 
 	addr = ptr[0];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_RS_WR_PING_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_RS_WR_PING_ADDR);
 	addr = ptr[1];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_RS_WR_PONG_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_RS_WR_PONG_ADDR);
 
 	vfe32_ctrl->rsStatsControl.nextFrameAddrBuf = in->statsBuf[2];
 	return 0;
 }
 
-static uint32_t vfe_stats_cs_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_cs_buf_init(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
 {
 	uint32_t *ptr = in->statsBuf;
 	uint32_t addr;
 
 	addr = ptr[0];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_CS_WR_PING_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_CS_WR_PING_ADDR);
 	addr = ptr[1];
 	msm_camera_io_w(addr,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_CS_WR_PONG_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_BUS_STATS_CS_WR_PONG_ADDR);
 
 	vfe32_ctrl->csStatsControl.nextFrameAddrBuf = in->statsBuf[2];
 	return 0;
 }
 
-static void vfe32_start_common(void)
+static void vfe32_start_common(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	uint32_t irq_mask = 0x00E00021;
 	vfe32_ctrl->start_ack_pending = TRUE;
 	CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
-		vfe32_ctrl->operation_mode, vfe32_ctrl->outpath.output_mode);
-	if (vfe32_ctrl->stats_comp)
+		vfe32_ctrl->share_ctrl->operation_mode,
+		vfe32_ctrl->share_ctrl->outpath.output_mode);
+	if (vfe32_ctrl->share_ctrl->stats_comp)
 		irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
 	else
 		irq_mask |= 0x000FE000;
 
-	msm_camera_io_w(irq_mask, vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+	msm_camera_io_w(irq_mask,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
 	msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
-		vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
 
 	/* Ensure the write order while writing
 	to the command register using the barrier */
-	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
+	msm_camera_io_w_mb(1,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	msm_camera_io_w_mb(1,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
 
-
-	atomic_set(&vfe32_ctrl->vstate, 1);
+	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 1);
 }
 
-static int vfe32_start_recording(struct msm_cam_media_controller *pmctl)
+static int vfe32_start_recording(
+	struct msm_cam_media_controller *pmctl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	msm_camio_bus_scale_cfg(
 		pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
 	vfe32_ctrl->recording_state = VFE_STATE_START_REQUESTED;
-	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	msm_camera_io_w_mb(1,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	return 0;
 }
 
-static int vfe32_stop_recording(struct msm_cam_media_controller *pmctl)
+static int vfe32_stop_recording(
+	struct msm_cam_media_controller *pmctl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	vfe32_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
-	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	msm_camera_io_w_mb(1,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	msm_camio_bus_scale_cfg(
 		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	return 0;
 }
 
-static void vfe32_start_liveshot(struct msm_cam_media_controller *pmctl)
+static void vfe32_start_liveshot(
+	struct msm_cam_media_controller *pmctl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	/* Hardcode 1 live snapshot for now. */
-	vfe32_ctrl->outpath.out0.capture_cnt = 1;
-	vfe32_ctrl->vfe_capture_count = vfe32_ctrl->outpath.out0.capture_cnt;
+	vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt = 1;
+	vfe32_ctrl->share_ctrl->vfe_capture_count =
+		vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt;
 
-	vfe32_ctrl->liveshot_state = VFE_STATE_START_REQUESTED;
-	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_START_REQUESTED;
+	msm_camera_io_w_mb(1, vfe32_ctrl->
+		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 }
 
-static int vfe32_zsl(struct msm_cam_media_controller *pmctl)
+static int vfe32_zsl(
+	struct msm_cam_media_controller *pmctl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	uint32_t irq_comp_mask = 0;
 	/* capture command is valid for both idle and active state. */
 	irq_comp_mask	=
-		msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+		msm_camera_io_r(vfe32_ctrl->
+		share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
 	CDBG("%s:op mode %d O/P Mode %d\n", __func__,
-		vfe32_ctrl->operation_mode, vfe32_ctrl->outpath.output_mode);
+		vfe32_ctrl->share_ctrl->operation_mode,
+		vfe32_ctrl->share_ctrl->outpath.output_mode);
 
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
-		irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out0.ch0)) |
-				(0x1 << (vfe32_ctrl->outpath.out0.ch1)));
-	} else if (vfe32_ctrl->outpath.output_mode &
+	if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_PRIMARY) {
+		irq_comp_mask |= (
+			(0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch0)) |
+			(0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch1)));
+	} else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-		irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out0.ch0)) |
-				(0x1 << (vfe32_ctrl->outpath.out0.ch1)) |
-				(0x1 << (vfe32_ctrl->outpath.out0.ch2)));
+		irq_comp_mask |= (
+			(0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch0)) |
+			(0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch1)) |
+			(0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch2)));
 	}
 
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
-		irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8)) |
-				(0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8)));
-	} else if (vfe32_ctrl->outpath.output_mode &
+	if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask |= ((0x1 << (vfe32_ctrl->
+				share_ctrl->outpath.out1.ch0 + 8)) |
+			(0x1 << (vfe32_ctrl->
+				share_ctrl->outpath.out1.ch1 + 8)));
+	} else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			   VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-		irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8)) |
-				(0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8)) |
-				(0x1 << (vfe32_ctrl->outpath.out1.ch2 + 8)));
+		irq_comp_mask |= (
+			(0x1 << (vfe32_ctrl->
+				share_ctrl->outpath.out1.ch0 + 8)) |
+			(0x1 << (vfe32_ctrl->
+				share_ctrl->outpath.out1.ch1 + 8)) |
+			(0x1 << (vfe32_ctrl->
+				share_ctrl->outpath.out1.ch2 + 8)));
 	}
 
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-	} else if (vfe32_ctrl->outpath.output_mode &
+	if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out0.ch0]);
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out0.ch1]);
+	} else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out0.ch0]);
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out0.ch1]);
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out0.ch2]);
 	}
 
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
-	} else if (vfe32_ctrl->outpath.output_mode &
+	if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out1.ch0]);
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out1.ch1]);
+	} else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch2]);
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out1.ch0]);
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out1.ch1]);
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out1.ch2]);
 	}
 
-	msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-	vfe32_start_common();
+	msm_camera_io_w(irq_comp_mask,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	vfe32_start_common(vfe32_ctrl);
 	msm_camio_bus_scale_cfg(
 		pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
 
-	msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x18C);
-	msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x188);
+	msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x18C);
+	msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x188);
 	return 0;
 }
 static int vfe32_capture_raw(
 	struct msm_cam_media_controller *pmctl,
+	struct vfe32_ctrl_type *vfe32_ctrl,
 	uint32_t num_frames_capture)
 {
 	uint32_t irq_comp_mask = 0;
 
-	vfe32_ctrl->outpath.out0.capture_cnt = num_frames_capture;
-	vfe32_ctrl->vfe_capture_count = num_frames_capture;
+	vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt = num_frames_capture;
+	vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
 
 	irq_comp_mask	=
-		msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+		msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
-		irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out0.ch0));
-		msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
+	if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_PRIMARY) {
+		irq_comp_mask |=
+			(0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch0));
+		msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+			share_ctrl->outpath.out0.ch0]);
 	}
 
-	msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	msm_camera_io_w(irq_comp_mask,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camio_bus_scale_cfg(
 		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
-	vfe32_start_common();
+	vfe32_start_common(vfe32_ctrl);
 	return 0;
 }
 
 static int vfe32_capture(
 	struct msm_cam_media_controller *pmctl,
-	uint32_t num_frames_capture)
+	uint32_t num_frames_capture,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	uint32_t irq_comp_mask = 0;
 
 	/* capture command is valid for both idle and active state. */
-	vfe32_ctrl->outpath.out1.capture_cnt = num_frames_capture;
-	if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
-		vfe32_ctrl->outpath.out0.capture_cnt =
+	vfe32_ctrl->share_ctrl->outpath.out1.capture_cnt = num_frames_capture;
+	if (vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_MAIN_AND_THUMB ||
+		vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_MAIN ||
+		vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_JPEG_AND_THUMB ||
+		vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_JPEG) {
+		vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt =
 			num_frames_capture;
 	}
 
-	vfe32_ctrl->vfe_capture_count = num_frames_capture;
+	vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
 	irq_comp_mask = msm_camera_io_r(
-				vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
-	if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
-		if (vfe32_ctrl->outpath.output_mode &
+	if (vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_MAIN_AND_THUMB ||
+		vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_JPEG_AND_THUMB ||
+		vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_MAIN) {
+		if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_PRIMARY) {
-			irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
-					0x1 << vfe32_ctrl->outpath.out0.ch1);
+			irq_comp_mask |= (0x1 << vfe32_ctrl->
+				share_ctrl->outpath.out0.ch0 |
+				0x1 << vfe32_ctrl->
+				share_ctrl->outpath.out0.ch1);
 		}
-		if (vfe32_ctrl->outpath.output_mode &
+		if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY) {
 			irq_comp_mask |=
-				(0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
-				0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8));
+				(0x1 << (vfe32_ctrl->
+					share_ctrl->outpath.out1.ch0 + 8) |
+				0x1 << (vfe32_ctrl->
+					share_ctrl->outpath.out1.ch1 + 8));
 		}
-		if (vfe32_ctrl->outpath.output_mode &
+		if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch1]);
 		}
-		if (vfe32_ctrl->outpath.output_mode &
+		if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out1.ch1]);
 		}
 	}
 
-	vfe32_ctrl->vfe_capture_count = num_frames_capture;
+	vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
 
-	msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-	msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	msm_camera_io_w(irq_comp_mask,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camio_bus_scale_cfg(
 		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 
-	vfe32_start_common();
+	vfe32_start_common(vfe32_ctrl);
 	/* for debug */
-	msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x18C);
-	msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x188);
+	msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x18C);
+	msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x188);
 	return 0;
 }
 
-static int vfe32_start(struct msm_cam_media_controller *pmctl)
+static int vfe32_start(
+	struct msm_cam_media_controller *pmctl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	uint32_t irq_comp_mask = 0;
 	irq_comp_mask	=
-		msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+		msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
+			VFE_IRQ_COMP_MASK);
 
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
-		irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
-			0x1 << vfe32_ctrl->outpath.out0.ch1);
-	} else if (vfe32_ctrl->outpath.output_mode &
+	if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
+		irq_comp_mask |= (
+			0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch0 |
+			0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch1);
+	} else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			   VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-		irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
-			0x1 << vfe32_ctrl->outpath.out0.ch1 |
-			0x1 << vfe32_ctrl->outpath.out0.ch2);
+		irq_comp_mask |= (
+			0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch0 |
+			0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch1 |
+			0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch2);
 	}
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
-		irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8));
-	} else if (vfe32_ctrl->outpath.output_mode &
+	if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask |= (
+			0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch1 + 8));
+	} else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-		irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8) |
-			0x1 << (vfe32_ctrl->outpath.out1.ch2 + 8));
+		irq_comp_mask |= (
+			0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
+			0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch2 + 8));
 	}
-	msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	msm_camera_io_w(irq_comp_mask,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
 	msm_camio_bus_scale_cfg(
 		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
-	vfe32_start_common();
+	vfe32_start_common(vfe32_ctrl);
 	return 0;
 }
 
-static void vfe32_update(void)
+static void vfe32_update(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
 	uint32_t value = 0;
 	if (vfe32_ctrl->update_linear) {
 		if (!msm_camera_io_r(
-			vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1))
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_LINEARIZATION_OFF1))
 			msm_camera_io_w(1,
-				vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1);
+				vfe32_ctrl->share_ctrl->vfebase +
+				V32_LINEARIZATION_OFF1);
 		else
 			msm_camera_io_w(0,
-				vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1);
+				vfe32_ctrl->share_ctrl->vfebase +
+				V32_LINEARIZATION_OFF1);
 		vfe32_ctrl->update_linear = false;
 	}
 
 	if (vfe32_ctrl->update_rolloff) {
-		value = msm_camera_io_r(vfe32_ctrl->vfebase +
+		value = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
 			V33_PCA_ROLL_OFF_CFG_OFF1);
 		value ^= V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK;
-		msm_camera_io_w(value, vfe32_ctrl->vfebase +
+		msm_camera_io_w(value, vfe32_ctrl->share_ctrl->vfebase +
 			V33_PCA_ROLL_OFF_CFG_OFF1);
 		vfe32_ctrl->update_rolloff = false;
 	}
 
 	if (vfe32_ctrl->update_la) {
-		if (!msm_camera_io_r(vfe32_ctrl->vfebase + V32_LA_OFF))
+		if (!msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF))
 			msm_camera_io_w(1,
-				vfe32_ctrl->vfebase + V32_LA_OFF);
+				vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF);
 		else
 			msm_camera_io_w(0,
-				vfe32_ctrl->vfebase + V32_LA_OFF);
+				vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF);
 		vfe32_ctrl->update_la = false;
 	}
 
 	if (vfe32_ctrl->update_gamma) {
-		value = msm_camera_io_r(vfe32_ctrl->vfebase + V32_RGB_G_OFF);
+		value = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF);
 		value ^= V32_GAMMA_LUT_BANK_SEL_MASK;
-		msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_RGB_G_OFF);
+		msm_camera_io_w(value,
+			vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF);
 		vfe32_ctrl->update_gamma = false;
 	}
 
@@ -960,11 +1071,12 @@
 	spin_unlock_irqrestore(&vfe32_ctrl->update_ack_lock, flags);
 	/* Ensure the write order while writing
 	to the command register using the barrier */
-	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	msm_camera_io_w_mb(1,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	return;
 }
 
-static void vfe32_sync_timer_stop(void)
+static void vfe32_sync_timer_stop(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	uint32_t value = 0;
 	vfe32_ctrl->sync_timer_state = 0;
@@ -976,10 +1088,13 @@
 		value = 0x40000;
 
 	/* Timer Stop */
-	msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF);
+	msm_camera_io_w(value,
+		vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF);
 }
 
-static void vfe32_sync_timer_start(const uint32_t *tbl)
+static void vfe32_sync_timer_start(
+	const uint32_t *tbl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	/* set bit 8 for auto increment. */
 	uint32_t value = 1;
@@ -1001,14 +1116,17 @@
 	}
 
 	/* Timer Start */
-	msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF);
+	msm_camera_io_w(value,
+		vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF);
 	/* Sync Timer Line Start */
 	value = *tbl++;
-	msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF +
+	msm_camera_io_w(value,
+		vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF +
 		4 + ((vfe32_ctrl->sync_timer_number) * 12));
 	/* Sync Timer Pixel Start */
 	value = *tbl++;
-	msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF +
+	msm_camera_io_w(value,
+			vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF +
 			 8 + ((vfe32_ctrl->sync_timer_number) * 12));
 	/* Sync Timer Pixel Duration */
 	value = *tbl++;
@@ -1016,87 +1134,99 @@
 	val = 10000000 / val;
 	val = value * 10000 / val;
 	CDBG("%s: Pixel Clk Cycles!!! %d\n", __func__, val);
-	msm_camera_io_w(val, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF +
+	msm_camera_io_w(val,
+		vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF +
 		12 + ((vfe32_ctrl->sync_timer_number) * 12));
 	/* Timer0 Active High/LOW */
 	value = *tbl++;
 	msm_camera_io_w(value,
-		vfe32_ctrl->vfebase + V32_SYNC_TIMER_POLARITY_OFF);
+		vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_POLARITY_OFF);
 	/* Selects sync timer 0 output to drive onto timer1 port */
 	value = 0;
-	msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_TIMER_SELECT_OFF);
+	msm_camera_io_w(value,
+		vfe32_ctrl->share_ctrl->vfebase + V32_TIMER_SELECT_OFF);
 }
 
-static void vfe32_program_dmi_cfg(enum VFE32_DMI_RAM_SEL bankSel)
+static void vfe32_program_dmi_cfg(
+	enum VFE32_DMI_RAM_SEL bankSel,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	/* set bit 8 for auto increment. */
 	uint32_t value = VFE_DMI_CFG_DEFAULT;
 	value += (uint32_t)bankSel;
 	CDBG("%s: banksel = %d\n", __func__, bankSel);
 
-	msm_camera_io_w(value, vfe32_ctrl->vfebase + VFE_DMI_CFG);
+	msm_camera_io_w(value, vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_CFG);
 	/* by default, always starts with offset 0.*/
-	msm_camera_io_w(0, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+	msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
 }
-static void vfe32_write_gamma_cfg(enum VFE32_DMI_RAM_SEL channel_sel,
-						const uint32_t *tbl)
+static void vfe32_write_gamma_cfg(
+	enum VFE32_DMI_RAM_SEL channel_sel,
+	const uint32_t *tbl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	int i;
 	uint32_t value, value1, value2;
-	vfe32_program_dmi_cfg(channel_sel);
+	vfe32_program_dmi_cfg(channel_sel, vfe32_ctrl);
 	for (i = 0 ; i < (VFE32_GAMMA_NUM_ENTRIES/2) ; i++) {
 		value = *tbl++;
 		value1 = value & 0x0000FFFF;
 		value2 = (value & 0xFFFF0000)>>16;
 		msm_camera_io_w((value1),
-			vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
 		msm_camera_io_w((value2),
-			vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
 	}
-	vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+	vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 }
 
-static void vfe32_read_gamma_cfg(enum VFE32_DMI_RAM_SEL channel_sel,
-	uint32_t *tbl)
+static void vfe32_read_gamma_cfg(
+	enum VFE32_DMI_RAM_SEL channel_sel,
+	uint32_t *tbl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	int i;
-	vfe32_program_dmi_cfg(channel_sel);
+	vfe32_program_dmi_cfg(channel_sel, vfe32_ctrl);
 	CDBG("%s: Gamma table channel: %d\n", __func__, channel_sel);
 	for (i = 0 ; i < VFE32_GAMMA_NUM_ENTRIES ; i++) {
-		*tbl = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+		*tbl = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
 		CDBG("%s: %08x\n", __func__, *tbl);
 		tbl++;
 	}
-	vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+	vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 }
 
-static void vfe32_write_la_cfg(enum VFE32_DMI_RAM_SEL channel_sel,
-						const uint32_t *tbl)
+static void vfe32_write_la_cfg(
+	enum VFE32_DMI_RAM_SEL channel_sel,
+	const uint32_t *tbl,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	uint32_t i;
 	uint32_t value, value1, value2;
 
-	vfe32_program_dmi_cfg(channel_sel);
+	vfe32_program_dmi_cfg(channel_sel, vfe32_ctrl);
 	for (i = 0 ; i < (VFE32_LA_TABLE_LENGTH/2) ; i++) {
 		value = *tbl++;
 		value1 = value & 0x0000FFFF;
 		value2 = (value & 0xFFFF0000)>>16;
 		msm_camera_io_w((value1),
-			vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
 		msm_camera_io_w((value2),
-			vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
 	}
-	vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+	vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 }
 
-static struct vfe32_output_ch *vfe32_get_ch(int path)
+static struct vfe32_output_ch *vfe32_get_ch(
+	int path, struct vfe_share_ctrl_t *share_ctrl)
 {
 	struct vfe32_output_ch *ch = NULL;
 
 	if (path == VFE_MSG_OUTPUT_PRIMARY)
-		ch = &vfe32_ctrl->outpath.out0;
+		ch = &share_ctrl->outpath.out0;
 	else if (path == VFE_MSG_OUTPUT_SECONDARY)
-		ch = &vfe32_ctrl->outpath.out1;
+		ch = &share_ctrl->outpath.out1;
 	else
 		pr_err("%s: Invalid path %d\n", __func__,
 			path);
@@ -1104,44 +1234,54 @@
 	BUG_ON(ch == NULL);
 	return ch;
 }
-static struct msm_free_buf *vfe32_check_free_buffer(int id, int path)
+static struct msm_free_buf *vfe32_check_free_buffer(
+	int id, int path, struct axi_ctrl_t *axi_ctrl)
 {
 	struct vfe32_output_ch *outch = NULL;
 	struct msm_free_buf *b = NULL;
-	vfe32_subdev_notify(id, path);
-	outch = vfe32_get_ch(path);
+	vfe32_subdev_notify(id, path,
+		&axi_ctrl->subdev, axi_ctrl->share_ctrl);
+	outch = vfe32_get_ch(path, axi_ctrl->share_ctrl);
 	if (outch->free_buf.ch_paddr[0])
 		b = &outch->free_buf;
 	return b;
 }
-static int vfe32_configure_pingpong_buffers(int id, int path)
+static int vfe32_configure_pingpong_buffers(
+	int id, int path, struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	struct vfe32_output_ch *outch = NULL;
 	int rc = 0;
-	vfe32_subdev_notify(id, path);
-	outch = vfe32_get_ch(path);
+	vfe32_subdev_notify(id, path,
+		&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]) {
 		/* Configure Preview Ping Pong */
 		pr_info("%s Configure ping/pong address for %d",
 						__func__, path);
-		vfe32_put_ch_ping_addr(outch->ch0,
+		vfe32_put_ch_ping_addr(
+			vfe32_ctrl->share_ctrl->vfebase, outch->ch0,
 			outch->ping.ch_paddr[0]);
-		vfe32_put_ch_pong_addr(outch->ch0,
+		vfe32_put_ch_pong_addr(
+			vfe32_ctrl->share_ctrl->vfebase, outch->ch0,
 			outch->pong.ch_paddr[0]);
 
-		if (vfe32_ctrl->operation_mode !=
+		if (vfe32_ctrl->share_ctrl->operation_mode !=
 			VFE_OUTPUTS_RAW) {
-			vfe32_put_ch_ping_addr(outch->ch1,
+			vfe32_put_ch_ping_addr(
+				vfe32_ctrl->share_ctrl->vfebase, outch->ch1,
 				outch->ping.ch_paddr[1]);
-			vfe32_put_ch_pong_addr(outch->ch1,
+			vfe32_put_ch_pong_addr(
+				vfe32_ctrl->share_ctrl->vfebase, outch->ch1,
 				outch->pong.ch_paddr[1]);
 		}
 
 		if (outch->ping.num_planes > 2)
-			vfe32_put_ch_ping_addr(outch->ch2,
+			vfe32_put_ch_ping_addr(
+				vfe32_ctrl->share_ctrl->vfebase, outch->ch2,
 				outch->ping.ch_paddr[2]);
 		if (outch->pong.num_planes > 2)
-			vfe32_put_ch_pong_addr(outch->ch2,
+			vfe32_put_ch_pong_addr(
+				vfe32_ctrl->share_ctrl->vfebase, outch->ch2,
 				outch->pong.ch_paddr[2]);
 
 		/* avoid stale info */
@@ -1154,37 +1294,41 @@
 	return rc;
 }
 
-static void vfe32_write_linear_cfg(enum VFE32_DMI_RAM_SEL channel_sel,
-	const uint32_t *tbl)
+static void vfe32_write_linear_cfg(
+	enum VFE32_DMI_RAM_SEL channel_sel,
+	const uint32_t *tbl, struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	uint32_t i;
 
-	vfe32_program_dmi_cfg(channel_sel);
+	vfe32_program_dmi_cfg(channel_sel, vfe32_ctrl);
 	/* for loop for configuring LUT. */
 	for (i = 0 ; i < VFE32_LINEARIZATON_TABLE_LENGTH ; i++) {
-		msm_camera_io_w(*tbl, vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+		msm_camera_io_w(*tbl,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
 		tbl++;
 	}
 	CDBG("done writing to linearization table\n");
-	vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+	vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 }
 
 static void vfe32_send_isp_msg(
-	struct vfe32_ctrl_type *vctrl,
+	struct v4l2_subdev *sd,
+	uint32_t vfeFrameId,
 	uint32_t isp_msg_id)
 {
 	struct isp_msg_event isp_msg_evt;
 
 	isp_msg_evt.msg_id = isp_msg_id;
-	isp_msg_evt.sof_count = vfe32_ctrl->vfeFrameId;
-	v4l2_subdev_notify(&vctrl->subdev,
+	isp_msg_evt.sof_count = vfeFrameId;
+	v4l2_subdev_notify(sd,
 			NOTIFY_ISP_MSG_EVT,
 			(void *)&isp_msg_evt);
 }
 
 static int vfe32_proc_general(
 	struct msm_cam_media_controller *pmctl,
-	struct msm_isp_cmd *cmd)
+	struct msm_isp_cmd *cmd,
+	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	int i , rc = 0;
 	uint32_t old_val = 0 , new_val = 0;
@@ -1199,32 +1343,34 @@
 	case VFE_CMD_RESET:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		vfe32_reset();
+		vfe32_reset(vfe32_ctrl);
 		break;
 	case VFE_CMD_START:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		if ((vfe32_ctrl->operation_mode ==
+		if ((vfe32_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
-				(vfe32_ctrl->operation_mode ==
+				(vfe32_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_PREVIEW))
 			/* Configure primary channel */
 			rc = vfe32_configure_pingpong_buffers(
-				VFE_MSG_V32_START, VFE_MSG_OUTPUT_PRIMARY);
+				VFE_MSG_V32_START, VFE_MSG_OUTPUT_PRIMARY,
+				vfe32_ctrl);
 		else
 			/* Configure secondary channel */
 			rc = vfe32_configure_pingpong_buffers(
-				VFE_MSG_V32_START, VFE_MSG_OUTPUT_SECONDARY);
+				VFE_MSG_V32_START, VFE_MSG_OUTPUT_SECONDARY,
+				vfe32_ctrl);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				   " for preview", __func__);
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe32_start(pmctl);
+		rc = vfe32_start(pmctl, vfe32_ctrl);
 		break;
 	case VFE_CMD_UPDATE:
-		vfe32_update();
+		vfe32_update(vfe32_ctrl);
 		break;
 	case VFE_CMD_CAPTURE_RAW:
 		pr_info("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
@@ -1233,15 +1379,16 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
-							VFE_MSG_OUTPUT_PRIMARY);
+		rc = vfe32_configure_pingpong_buffers(
+			VFE_MSG_V32_CAPTURE, VFE_MSG_OUTPUT_PRIMARY,
+			vfe32_ctrl);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				   " for snapshot", __func__);
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe32_capture_raw(pmctl, snapshot_cnt);
+		rc = vfe32_capture_raw(pmctl, vfe32_ctrl, snapshot_cnt);
 		break;
 	case VFE_CMD_CAPTURE:
 		if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
@@ -1250,8 +1397,10 @@
 			goto proc_general_done;
 		}
 
-		if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
+		if (vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_JPEG_AND_THUMB ||
+		vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_JPEG) {
 			if (snapshot_cnt != 1) {
 				pr_err("only support 1 inline snapshot\n");
 				rc = -EINVAL;
@@ -1260,12 +1409,14 @@
 			/* Configure primary channel for JPEG */
 			rc = vfe32_configure_pingpong_buffers(
 				VFE_MSG_V32_JPEG_CAPTURE,
-				VFE_MSG_OUTPUT_PRIMARY);
+				VFE_MSG_OUTPUT_PRIMARY,
+				vfe32_ctrl);
 		} else {
 			/* Configure primary channel */
 			rc = vfe32_configure_pingpong_buffers(
 				VFE_MSG_V32_CAPTURE,
-				VFE_MSG_OUTPUT_PRIMARY);
+				VFE_MSG_OUTPUT_PRIMARY,
+				vfe32_ctrl);
 		}
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
@@ -1274,41 +1425,44 @@
 			goto proc_general_done;
 		}
 		/* Configure secondary channel */
-		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
-						  VFE_MSG_OUTPUT_SECONDARY);
+		rc = vfe32_configure_pingpong_buffers(
+				VFE_MSG_V32_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
+				vfe32_ctrl);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				   " for secondary output", __func__);
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe32_capture(pmctl, snapshot_cnt);
+		rc = vfe32_capture(pmctl, snapshot_cnt, vfe32_ctrl);
 		break;
 	case VFE_CMD_START_RECORDING:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		if (vfe32_ctrl->operation_mode ==
+		if (vfe32_ctrl->share_ctrl->operation_mode ==
 			VFE_OUTPUTS_PREVIEW_AND_VIDEO)
 			rc = vfe32_configure_pingpong_buffers(
 				VFE_MSG_V32_START_RECORDING,
-				VFE_MSG_OUTPUT_SECONDARY);
-		else if (vfe32_ctrl->operation_mode ==
+				VFE_MSG_OUTPUT_SECONDARY,
+				vfe32_ctrl);
+		else if (vfe32_ctrl->share_ctrl->operation_mode ==
 			VFE_OUTPUTS_VIDEO_AND_PREVIEW)
 			rc = vfe32_configure_pingpong_buffers(
 				VFE_MSG_V32_START_RECORDING,
-				VFE_MSG_OUTPUT_PRIMARY);
+				VFE_MSG_OUTPUT_PRIMARY,
+				vfe32_ctrl);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				" for video", __func__);
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe32_start_recording(pmctl);
+		rc = vfe32_start_recording(pmctl, vfe32_ctrl);
 		break;
 	case VFE_CMD_STOP_RECORDING:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		rc = vfe32_stop_recording(pmctl);
+		rc = vfe32_stop_recording(pmctl, vfe32_ctrl);
 		break;
 	case VFE_CMD_OPERATION_CFG: {
 		if (cmd->length != V32_OPERATION_CFG_LEN) {
@@ -1322,7 +1476,7 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		rc = vfe32_operation_config(cmdp);
+		rc = vfe32_operation_config(cmdp, vfe32_ctrl);
 		}
 		break;
 
@@ -1338,12 +1492,14 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val |= AE_BG_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		}
 		break;
@@ -1359,12 +1515,14 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
+			VFE_MODULE_CFG);
 		old_val |= AF_BF_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		}
 		break;
@@ -1380,12 +1538,14 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val |= AWB_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		}
 		break;
@@ -1402,12 +1562,14 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val |= IHIST_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		}
 		break;
@@ -1426,7 +1588,8 @@
 			goto proc_general_done;
 		}
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		}
 		break;
@@ -1444,7 +1607,8 @@
 			goto proc_general_done;
 		}
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		}
 		break;
@@ -1454,7 +1618,7 @@
 		cmdp = kmalloc(cmd->length, GFP_ATOMIC);
 		/* Incrementing with 4 so as to point to the 2nd Register as
 		the 2nd register has the mce_enable bit */
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+		old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
 			V32_CHROMA_SUP_OFF + 4);
 		if (!cmdp) {
 			rc = -ENOMEM;
@@ -1471,21 +1635,22 @@
 		old_val &= MCE_EN_MASK;
 		new_val = new_val | old_val;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 4,
-			&new_val, 4);
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_CHROMA_SUP_OFF + 4, &new_val, 4);
 		cmdp_local += 1;
 
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+		old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
 			V32_CHROMA_SUP_OFF + 8);
 		new_val = *cmdp_local;
 		old_val &= MCE_Q_K_MASK;
 		new_val = new_val | old_val;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 8,
-			&new_val, 4);
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_CHROMA_SUP_OFF + 8, &new_val, 4);
 		cmdp_local += 1;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp_local, (vfe32_cmd[cmd->id].length));
 		}
 		break;
@@ -1503,31 +1668,31 @@
 			goto proc_general_done;
 		}
 		cmdp_local = cmdp;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF,
-			cmdp_local, 4);
+		msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
+			V32_CHROMA_SUP_OFF, cmdp_local, 4);
 
 		cmdp_local += 1;
 		new_val = *cmdp_local;
 		/* Incrementing with 4 so as to point to the 2nd Register as
 		 * the 2nd register has the mce_enable bit
 		 */
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+		old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
 			V32_CHROMA_SUP_OFF + 4);
 		old_val &= ~MCE_EN_MASK;
 		new_val = new_val | old_val;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 4,
-			&new_val, 4);
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_CHROMA_SUP_OFF + 4, &new_val, 4);
 		cmdp_local += 1;
 
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+		old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
 			V32_CHROMA_SUP_OFF + 8);
 		new_val = *cmdp_local;
 		old_val &= ~MCE_Q_K_MASK;
 		new_val = new_val | old_val;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 8,
-			&new_val, 4);
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_CHROMA_SUP_OFF + 8, &new_val, 4);
 		}
 		break;
 	case VFE_CMD_BLACK_LEVEL_CFG:
@@ -1547,27 +1712,28 @@
 		}
 		cmdp_local = cmdp;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp_local, 16);
 		cmdp_local += 4;
-		vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+		vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
 		/* for loop for extrcting init table. */
 		for (i = 0; i < (V32_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2); i++) {
 			msm_camera_io_w(*cmdp_local ,
-			vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
 			cmdp_local++;
 		}
 		CDBG("done writing init table\n");
 		/* by default, always starts with offset 0. */
 		msm_camera_io_w(V32_MESH_ROLL_OFF_DELTA_TABLE_OFFSET,
-		vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
 		/* for loop for extracting delta table. */
 		for (i = 0; i < (V32_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2); i++) {
 			msm_camera_io_w(*cmdp_local,
-			vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
 			cmdp_local++;
 		}
-		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 		}
 		break;
 
@@ -1584,27 +1750,29 @@
 			goto proc_general_done;
 		}
 		cmdp_local = cmdp;
-		vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+		vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
 		CDBG("%s: Mesh Rolloff init Table\n", __func__);
 		for (i = 0; i < (V32_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2); i++) {
 			*cmdp_local =
 				msm_camera_io_r(
-					vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+					vfe32_ctrl->share_ctrl->vfebase +
+					VFE_DMI_DATA_LO);
 			CDBG("%s: %08x\n", __func__, *cmdp_local);
 			cmdp_local++;
 		}
 		msm_camera_io_w(V32_MESH_ROLL_OFF_DELTA_TABLE_OFFSET,
-			vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
 		CDBG("%s: Mesh Rolloff Delta Table\n", __func__);
 		for (i = 0; i < (V32_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2); i++) {
 			*cmdp_local =
 				msm_camera_io_r(
-					vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+					vfe32_ctrl->share_ctrl->vfebase +
+					VFE_DMI_DATA_LO);
 			CDBG("%s: %08x\n", __func__, *cmdp_local);
 			cmdp_local++;
 		}
 		CDBG("done reading delta table\n");
-		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 		if (copy_to_user((void __user *)(cmd->value), cmdp,
 			temp1)) {
 			rc = -EFAULT;
@@ -1626,11 +1794,13 @@
 		}
 		cmdp_local = cmdp;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp_local, (vfe32_cmd[cmd->id].length));
 
 		cmdp_local += 1;
-		vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0, cmdp_local);
+		vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0,
+						   cmdp_local, vfe32_ctrl);
 		break;
 
 	case VFE_CMD_LA_UPDATE: {
@@ -1648,13 +1818,14 @@
 		}
 
 		cmdp_local = cmdp + 1;
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + V32_LA_OFF);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF);
 		if (old_val != 0x0)
 			vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0,
-				cmdp_local);
+				cmdp_local, vfe32_ctrl);
 		else
 			vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK1,
-				cmdp_local);
+				cmdp_local, vfe32_ctrl);
 		}
 		vfe32_ctrl->update_la = true;
 		break;
@@ -1671,19 +1842,24 @@
 			goto proc_general_done;
 		}
 		cmdp_local = cmdp;
-		if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_LA_OFF))
-			vfe32_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK1);
+		if (msm_camera_io_r(vfe32_ctrl->
+				share_ctrl->vfebase + V32_LA_OFF))
+			vfe32_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK1,
+						vfe32_ctrl);
 		else
-			vfe32_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK0);
+			vfe32_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK0,
+						vfe32_ctrl);
 		for (i = 0 ; i < (VFE32_LA_TABLE_LENGTH / 2) ; i++) {
 			*cmdp_local =
 				msm_camera_io_r(
-					vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
-			*cmdp_local |= (msm_camera_io_r(vfe32_ctrl->vfebase +
+					vfe32_ctrl->share_ctrl->vfebase +
+					VFE_DMI_DATA_LO);
+			*cmdp_local |= (msm_camera_io_r(
+				vfe32_ctrl->share_ctrl->vfebase +
 				VFE_DMI_DATA_LO)) << 16;
 			cmdp_local++;
 		}
-		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 		if (copy_to_user((void __user *)(cmd->value), cmdp,
 			temp1)) {
 			rc = -EFAULT;
@@ -1703,22 +1879,23 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_SCE_OFF,
-				cmdp, V32_SCE_LEN);
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_SCE_OFF,
+			cmdp, V32_SCE_LEN);
 		}
 		break;
 
 	case VFE_CMD_LIVESHOT:
 		/* Configure primary channel */
 		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
-						VFE_MSG_OUTPUT_PRIMARY);
+					VFE_MSG_OUTPUT_PRIMARY, vfe32_ctrl);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				   " for primary output", __func__);
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		vfe32_start_liveshot(pmctl);
+		vfe32_start_liveshot(pmctl, vfe32_ctrl);
 		break;
 
 	case VFE_CMD_LINEARIZATION_CFG:
@@ -1734,15 +1911,18 @@
 		}
 		cmdp_local = cmdp;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1,
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_LINEARIZATION_OFF1,
 			cmdp_local, V32_LINEARIZATION_LEN1);
 		cmdp_local += 4;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF2,
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_LINEARIZATION_OFF2,
 			cmdp_local, V32_LINEARIZATION_LEN2);
 
 		cmdp_local = cmdp + 17;
-		vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0, cmdp_local);
+		vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0,
+					cmdp_local, vfe32_ctrl);
 		break;
 
 	case VFE_CMD_LINEARIZATION_UPDATE:
@@ -1759,21 +1939,26 @@
 		cmdp_local = cmdp;
 		cmdp_local++;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1 + 4,
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_LINEARIZATION_OFF1 + 4,
 			cmdp_local, (V32_LINEARIZATION_LEN1 - 4));
 		cmdp_local += 3;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF2,
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_LINEARIZATION_OFF2,
 			cmdp_local, V32_LINEARIZATION_LEN2);
 		cmdp_local = cmdp + 17;
 		/*extracting the bank select*/
 		old_val = msm_camera_io_r(
-				vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1);
+				vfe32_ctrl->share_ctrl->vfebase +
+				V32_LINEARIZATION_OFF1);
 
 		if (old_val != 0x0)
-			vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0, cmdp_local);
+			vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0,
+						cmdp_local, vfe32_ctrl);
 		else
-			vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK1, cmdp_local);
+			vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK1,
+						cmdp_local, vfe32_ctrl);
 		vfe32_ctrl->update_linear = true;
 		break;
 
@@ -1790,18 +1975,20 @@
 		}
 		cmdp_local = cmdp;
 		if (msm_camera_io_r(
-			vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1))
-			vfe32_program_dmi_cfg(BLACK_LUT_RAM_BANK1);
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_LINEARIZATION_OFF1))
+			vfe32_program_dmi_cfg(BLACK_LUT_RAM_BANK1, vfe32_ctrl);
 		else
-			vfe32_program_dmi_cfg(BLACK_LUT_RAM_BANK0);
+			vfe32_program_dmi_cfg(BLACK_LUT_RAM_BANK0, vfe32_ctrl);
 		CDBG("%s: Linearization Table\n", __func__);
 		for (i = 0 ; i < VFE32_LINEARIZATON_TABLE_LENGTH ; i++) {
 			*cmdp_local = msm_camera_io_r(
-					vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+				vfe32_ctrl->share_ctrl->vfebase +
+				VFE_DMI_DATA_LO);
 			CDBG("%s: %08x\n", __func__, *cmdp_local);
 			cmdp_local++;
 		}
-		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 		if (copy_to_user((void __user *)(cmd->value), cmdp,
 			temp1)) {
 			rc = -EFAULT;
@@ -1829,15 +2016,17 @@
 		new_val = *cmdp_local;
 
 		old_val = msm_camera_io_r(
-				vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
 		old_val &= DEMOSAIC_MASK;
 		new_val = new_val | old_val;
 		*cmdp_local = new_val;
 
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
 			cmdp_local, V32_DEMOSAICV3_0_LEN);
 		cmdp_local += 1;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_1_OFF,
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_1_OFF,
 			cmdp_local, V32_DEMOSAICV3_1_LEN);
 		break;
 
@@ -1862,22 +2051,25 @@
 		new_val = *cmdp_local;
 
 		old_val = msm_camera_io_r(
-				vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
 		old_val &= DEMOSAIC_MASK;
 		new_val = new_val | old_val;
 		*cmdp_local = new_val;
 
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
 			cmdp_local, V32_DEMOSAICV3_0_LEN);
 		/* As the address space is not contiguous increment by 2
 		 * before copying to next address space */
 		cmdp_local += 1;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_1_OFF,
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_1_OFF,
 			cmdp_local, 2 * V32_DEMOSAICV3_0_LEN);
 		/* As the address space is not contiguous increment by 2
 		 * before copying to next address space */
 		cmdp_local += 2;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_2_OFF,
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_2_OFF,
 			cmdp_local, 2 * V32_DEMOSAICV3_0_LEN);
 		break;
 
@@ -1902,17 +2094,19 @@
 		new_val = *cmdp_local;
 
 		old_val = msm_camera_io_r(
-				vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
 		old_val &= ABF_MASK;
 		new_val = new_val | old_val;
 		*cmdp_local = new_val;
 
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
-		    cmdp_local, 4);
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
+			cmdp_local, 4);
 
 		cmdp_local += 1;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp_local, (vfe32_cmd[cmd->id].length));
 		}
 		break;
@@ -1934,16 +2128,18 @@
 		new_val = *cmdp_local;
 
 		old_val = msm_camera_io_r(
-				vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
 		old_val &= DBCC_MASK;
 
 		new_val = new_val | old_val;
 		*cmdp_local = new_val;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
-					cmdp_local, 4);
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
+			cmdp_local, 4);
 		cmdp_local += 1;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp_local, (vfe32_cmd[cmd->id].length));
 		break;
 
@@ -1964,28 +2160,28 @@
 		new_val = *cmdp_local;
 
 		old_val = msm_camera_io_r(
-				vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+			vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
 		old_val &= DBPC_MASK;
 
 		new_val = new_val | old_val;
 		*cmdp_local = new_val;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+		msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
 			V32_DEMOSAICV3_0_OFF,
 			cmdp_local, V32_DEMOSAICV3_LEN);
 		cmdp_local += 1;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+		msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
 			V32_DEMOSAICV3_DBPC_CFG_OFF,
 			cmdp_local, V32_DEMOSAICV3_DBPC_LEN);
 		cmdp_local += 1;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+		msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
 			V32_DEMOSAICV3_DBPC_CFG_OFF0,
 			cmdp_local, V32_DEMOSAICV3_DBPC_LEN);
 		cmdp_local += 1;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+		msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
 			V32_DEMOSAICV3_DBPC_CFG_OFF1,
 			cmdp_local, V32_DEMOSAICV3_DBPC_LEN);
 		cmdp_local += 1;
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+		msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
 			V32_DEMOSAICV3_DBPC_CFG_OFF2,
 			cmdp_local, V32_DEMOSAICV3_DBPC_LEN);
 		break;
@@ -2002,13 +2198,14 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_RGB_G_OFF,
+		msm_camera_io_memcpy(
+			vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF,
 			cmdp, 4);
 		cmdp += 1;
 
-		vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp);
-		vfe32_write_gamma_cfg(RGBLUT_RAM_CH1_BANK0, cmdp);
-		vfe32_write_gamma_cfg(RGBLUT_RAM_CH2_BANK0, cmdp);
+		vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp, vfe32_ctrl);
+		vfe32_write_gamma_cfg(RGBLUT_RAM_CH1_BANK0, cmdp, vfe32_ctrl);
+		vfe32_write_gamma_cfg(RGBLUT_RAM_CH2_BANK0, cmdp, vfe32_ctrl);
 		}
 	    cmdp -= 1;
 		break;
@@ -2025,16 +2222,23 @@
 			goto proc_general_done;
 		}
 
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + V32_RGB_G_OFF);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF);
 		cmdp += 1;
 		if (old_val != 0x0) {
-			vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp);
-			vfe32_write_gamma_cfg(RGBLUT_RAM_CH1_BANK0, cmdp);
-			vfe32_write_gamma_cfg(RGBLUT_RAM_CH2_BANK0, cmdp);
+			vfe32_write_gamma_cfg(
+				RGBLUT_RAM_CH0_BANK0, cmdp, vfe32_ctrl);
+			vfe32_write_gamma_cfg(
+				RGBLUT_RAM_CH1_BANK0, cmdp, vfe32_ctrl);
+			vfe32_write_gamma_cfg(
+				RGBLUT_RAM_CH2_BANK0, cmdp, vfe32_ctrl);
 		} else {
-			vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK1, cmdp);
-			vfe32_write_gamma_cfg(RGBLUT_RAM_CH1_BANK1, cmdp);
-			vfe32_write_gamma_cfg(RGBLUT_RAM_CH2_BANK1, cmdp);
+			vfe32_write_gamma_cfg(
+				RGBLUT_RAM_CH0_BANK1, cmdp, vfe32_ctrl);
+			vfe32_write_gamma_cfg(
+				RGBLUT_RAM_CH1_BANK1, cmdp, vfe32_ctrl);
+			vfe32_write_gamma_cfg(
+				RGBLUT_RAM_CH2_BANK1, cmdp, vfe32_ctrl);
 		}
 		}
 		vfe32_ctrl->update_gamma = TRUE;
@@ -2054,12 +2258,14 @@
 		}
 		cmdp_local = cmdp;
 
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + V32_RGB_G_OFF);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF);
 		temp2 = old_val ? RGBLUT_RAM_CH0_BANK1 :
 			RGBLUT_RAM_CH0_BANK0;
 		for (i = 0; i < 3; i++) {
 			vfe32_read_gamma_cfg(temp2,
-				cmdp_local + (VFE32_GAMMA_NUM_ENTRIES * i));
+				cmdp_local + (VFE32_GAMMA_NUM_ENTRIES * i),
+				vfe32_ctrl);
 			temp2 += 2;
 		}
 		if (copy_to_user((void __user *)(cmd->value), cmdp,
@@ -2070,54 +2276,60 @@
 		break;
 
 	case VFE_CMD_STATS_AWB_STOP: {
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= ~AWB_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
 	case VFE_CMD_STATS_AE_STOP: {
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= ~AE_BG_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
 	case VFE_CMD_STATS_AF_STOP: {
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= ~AF_BF_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
 
 	case VFE_CMD_STATS_IHIST_STOP: {
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= ~IHIST_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
 
 	case VFE_CMD_STATS_RS_STOP: {
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= ~RS_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
 
 	case VFE_CMD_STATS_CS_STOP: {
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= ~CS_ENABLE_MASK;
 		msm_camera_io_w(old_val,
-			vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		}
 		break;
 	case VFE_CMD_STOP:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		vfe32_stop();
+		vfe32_stop(vfe32_ctrl);
 		break;
 
 	case VFE_CMD_SYNC_TIMER_SETTING:
@@ -2131,7 +2343,7 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		vfe32_sync_timer_start(cmdp);
+		vfe32_sync_timer_start(cmdp, vfe32_ctrl);
 		break;
 
 	case VFE_CMD_MODULE_CFG: {
@@ -2147,27 +2359,29 @@
 			goto proc_general_done;
 		}
 		*cmdp &= ~STATS_ENABLE_MASK;
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+		old_val = msm_camera_io_r(
+			vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
 		old_val &= STATS_ENABLE_MASK;
 		*cmdp |= old_val;
 
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		}
 		break;
 
 	case VFE_CMD_ZSL:
 		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
-			VFE_MSG_OUTPUT_PRIMARY);
+			VFE_MSG_OUTPUT_PRIMARY, vfe32_ctrl);
 		if (rc < 0)
 			goto proc_general_done;
 		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
-			VFE_MSG_OUTPUT_SECONDARY);
+			VFE_MSG_OUTPUT_SECONDARY, vfe32_ctrl);
 		if (rc < 0)
 			goto proc_general_done;
 
-		rc = vfe32_zsl(pmctl);
+		rc = vfe32_zsl(pmctl, vfe32_ctrl);
 		break;
 
 	case VFE_CMD_ASF_CFG:
@@ -2183,11 +2397,13 @@
 			goto proc_general_done;
 		}
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		cmdp_local = cmdp + V32_ASF_LEN/4;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V32_ASF_SPECIAL_EFX_CFG_OFF,
+			vfe32_ctrl->share_ctrl->vfebase +
+			V32_ASF_SPECIAL_EFX_CFG_OFF,
 			cmdp_local, V32_ASF_SPECIAL_EFX_CFG_LEN);
 		break;
 
@@ -2209,37 +2425,44 @@
 		cmdp_local++;
 
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V33_PCA_ROLL_OFF_CFG_OFF1,
+			vfe32_ctrl->share_ctrl->vfebase +
+			V33_PCA_ROLL_OFF_CFG_OFF1,
 			cmdp_local, V33_PCA_ROLL_OFF_CFG_LEN1);
 		cmdp_local += 4;
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + V33_PCA_ROLL_OFF_CFG_OFF2,
+			vfe32_ctrl->share_ctrl->vfebase +
+			V33_PCA_ROLL_OFF_CFG_OFF2,
 			cmdp_local, V33_PCA_ROLL_OFF_CFG_LEN2);
 
 		cmdp_local += 3;
 		CDBG("%s: start writing RollOff Ram0 table\n", __func__);
-		vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
-		msm_camera_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
+		msm_camera_io_w(temp1,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
 		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
 			msm_camera_io_w(*(cmdp_local + 1),
-				vfe32_ctrl->vfebase + VFE33_DMI_DATA_HI);
+				vfe32_ctrl->share_ctrl->vfebase +
+				VFE33_DMI_DATA_HI);
 			msm_camera_io_w(*cmdp_local,
-				vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+				vfe32_ctrl->share_ctrl->vfebase +
+				VFE33_DMI_DATA_LO);
 			cmdp_local += 2;
 		}
 		CDBG("%s: end writing RollOff Ram0 table\n", __func__);
 
 		CDBG("%s: start writing RollOff Ram1 table\n", __func__);
-		vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
-		msm_camera_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0, vfe32_ctrl);
+		msm_camera_io_w(temp1,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
 		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
 			msm_camera_io_w(*cmdp_local,
-				vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+				vfe32_ctrl->share_ctrl->vfebase +
+				VFE33_DMI_DATA_LO);
 			cmdp_local += 2;
 		}
 		CDBG("%s: end writing RollOff Ram1 table\n", __func__);
 
-		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 		break;
 
 	case VFE_CMD_PCA_ROLL_OFF_UPDATE:
@@ -2259,41 +2482,46 @@
 		temp1 = *cmdp_local;
 		cmdp_local += 8;
 
-		temp2 = msm_camera_io_r(vfe32_ctrl->vfebase +
+		temp2 = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
 			V33_PCA_ROLL_OFF_CFG_OFF1)
 			& V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK;
 
 		CDBG("%s: start writing RollOff Ram0 table\n", __func__);
 		if (temp2)
-			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
 		else
-			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1);
+			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1, vfe32_ctrl);
 
-		msm_camera_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		msm_camera_io_w(temp1,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
 		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
 			msm_camera_io_w(*(cmdp_local + 1),
-				vfe32_ctrl->vfebase + VFE33_DMI_DATA_HI);
+				vfe32_ctrl->share_ctrl->vfebase +
+				VFE33_DMI_DATA_HI);
 			msm_camera_io_w(*cmdp_local,
-				vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+				vfe32_ctrl->share_ctrl->vfebase +
+				VFE33_DMI_DATA_LO);
 			cmdp_local += 2;
 		}
 		CDBG("%s: end writing RollOff Ram0 table\n", __func__);
 
 		CDBG("%s: start writing RollOff Ram1 table\n", __func__);
 		if (temp2)
-			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
+			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0, vfe32_ctrl);
 		else
-			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1);
+			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1, vfe32_ctrl);
 
-		msm_camera_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		msm_camera_io_w(temp1,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
 		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
 			msm_camera_io_w(*cmdp_local,
-				vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+				vfe32_ctrl->share_ctrl->vfebase +
+				VFE33_DMI_DATA_LO);
 			cmdp_local += 2;
 		}
 		CDBG("%s: end writing RollOff Ram1 table\n", __func__);
 
-		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 		vfe32_ctrl->update_rolloff = true;
 		break;
 	case VFE_CMD_GET_PCA_ROLLOFF_TABLE:
@@ -2308,33 +2536,37 @@
 			goto proc_general_done;
 		}
 		cmdp_local = cmdp;
-		old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+		old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
 			V33_PCA_ROLL_OFF_CFG_OFF1) &
 			V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK;
 
 		if (old_val)
-			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1);
+			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1, vfe32_ctrl);
 		else
-			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
 
 		CDBG("%s: PCA Rolloff Ram0\n", __func__);
 		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE * 2; i++) {
 			temp2 = (i == (V33_PCA_ROLL_OFF_TABLE_SIZE));
 			if (old_val && temp2)
-				vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1);
+				vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1,
+				vfe32_ctrl);
 			else if (!old_val && temp2)
-				vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
+				vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0,
+				vfe32_ctrl);
 
-			*cmdp_local = msm_camera_io_r(vfe32_ctrl->vfebase +
+			*cmdp_local = msm_camera_io_r(
+				vfe32_ctrl->share_ctrl->vfebase +
 				VFE33_DMI_DATA_LO);
 			*(cmdp_local + 1) =
-				msm_camera_io_r(vfe32_ctrl->vfebase +
+				msm_camera_io_r(
+				vfe32_ctrl->share_ctrl->vfebase +
 				VFE33_DMI_DATA_HI);
 			CDBG("%s: %08x%08x\n", __func__,
 				*(cmdp_local + 1), *cmdp_local);
 			cmdp_local += 2;
 		}
-		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
 		if (copy_to_user((void __user *)(cmd->value), cmdp,
 			temp1)) {
 			rc = -EFAULT;
@@ -2352,7 +2584,7 @@
 			goto proc_general_done;
 		}
 		*cmdp = msm_camera_io_r(
-				vfe32_ctrl->vfebase+V32_GET_HW_VERSION_OFF);
+			vfe32_ctrl->share_ctrl->vfebase+V32_GET_HW_VERSION_OFF);
 		if (copy_to_user((void __user *)(cmd->value), cmdp,
 			V32_GET_HW_VERSION_LEN)) {
 			rc = -EFAULT;
@@ -2360,7 +2592,8 @@
 		}
 		break;
 	case VFE_CMD_GET_REG_DUMP:
-		temp1 = sizeof(uint32_t) * vfe32_ctrl->register_total;
+		temp1 = sizeof(uint32_t) *
+			vfe32_ctrl->share_ctrl->register_total;
 		if (cmd->length != temp1) {
 			rc = -EINVAL;
 			goto proc_general_done;
@@ -2370,11 +2603,12 @@
 			rc = -ENOMEM;
 			goto proc_general_done;
 		}
-		msm_camera_io_dump(
-			vfe32_ctrl->vfebase, vfe32_ctrl->register_total*4);
+		msm_camera_io_dump(vfe32_ctrl->share_ctrl->vfebase,
+			vfe32_ctrl->share_ctrl->register_total*4);
 		CDBG("%s: %p %p %d\n", __func__, (void *)cmdp,
-			vfe32_ctrl->vfebase, temp1);
-		memcpy_fromio((void *)cmdp, vfe32_ctrl->vfebase, temp1);
+			vfe32_ctrl->share_ctrl->vfebase, temp1);
+		memcpy_fromio((void *)cmdp,
+			vfe32_ctrl->share_ctrl->vfebase, temp1);
 		if (copy_to_user((void __user *)(cmd->value), cmdp, temp1)) {
 			rc = -EFAULT;
 			goto proc_general_done;
@@ -2399,7 +2633,8 @@
 		}
 
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		vfe32_ctrl->frame_skip_cnt = ((uint32_t)
 			*cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
@@ -2423,7 +2658,8 @@
 			goto proc_general_done;
 		}
 		msm_camera_io_memcpy(
-			vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
 		break;
 
@@ -2435,10 +2671,11 @@
 	return rc;
 }
 
-static void vfe32_stats_af_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_af_ack(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+	spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
 		&vfe32_ctrl->comp_stats_ack_lock :
 		&vfe32_ctrl->af_ack_lock);
 	spin_lock_irqsave(lock, flags);
@@ -2447,10 +2684,11 @@
 	spin_unlock_irqrestore(lock, flags);
 }
 
-static void vfe32_stats_awb_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_awb_ack(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+	spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
 		&vfe32_ctrl->comp_stats_ack_lock :
 		&vfe32_ctrl->awb_ack_lock);
 	spin_lock_irqsave(lock, flags);
@@ -2459,10 +2697,11 @@
 	spin_unlock_irqrestore(lock, flags);
 }
 
-static void vfe32_stats_aec_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_aec_ack(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+	spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
 		&vfe32_ctrl->comp_stats_ack_lock :
 		&vfe32_ctrl->aec_ack_lock);
 	spin_lock_irqsave(lock, flags);
@@ -2471,10 +2710,11 @@
 	spin_unlock_irqrestore(lock, flags);
 }
 
-static void vfe32_stats_ihist_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_ihist_ack(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+	spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
 		&vfe32_ctrl->comp_stats_ack_lock :
 		&vfe32_ctrl->ihist_ack_lock);
 	spin_lock_irqsave(lock, flags);
@@ -2482,10 +2722,11 @@
 	vfe32_ctrl->ihistStatsControl.ackPending = FALSE;
 	spin_unlock_irqrestore(lock, flags);
 }
-static void vfe32_stats_rs_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_rs_ack(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+	spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
 		&vfe32_ctrl->comp_stats_ack_lock :
 		&vfe32_ctrl->rs_ack_lock);
 	spin_lock_irqsave(lock, flags);
@@ -2493,10 +2734,11 @@
 	vfe32_ctrl->rsStatsControl.ackPending = FALSE;
 	spin_unlock_irqrestore(lock, flags);
 }
-static void vfe32_stats_cs_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_cs_ack(
+	struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+	spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
 		&vfe32_ctrl->comp_stats_ack_lock :
 		&vfe32_ctrl->cs_ack_lock);
 	spin_lock_irqsave(lock, flags);
@@ -2505,73 +2747,85 @@
 	spin_unlock_irqrestore(lock, flags);
 }
 
-static inline void vfe32_read_irq_status(struct vfe32_irq_status *out)
+static inline void vfe32_read_irq_status(
+	struct axi_ctrl_t *axi_ctrl, struct vfe32_irq_status *out)
 {
 	uint32_t *temp;
 	memset(out, 0, sizeof(struct vfe32_irq_status));
-	temp = (uint32_t *)(vfe32_ctrl->vfebase + VFE_IRQ_STATUS_0);
+	temp = (uint32_t *)(axi_ctrl->share_ctrl->vfebase + VFE_IRQ_STATUS_0);
 	out->vfeIrqStatus0 = msm_camera_io_r(temp);
 
-	temp = (uint32_t *)(vfe32_ctrl->vfebase + VFE_IRQ_STATUS_1);
+	temp = (uint32_t *)(axi_ctrl->share_ctrl->vfebase + VFE_IRQ_STATUS_1);
 	out->vfeIrqStatus1 = msm_camera_io_r(temp);
 
-	temp = (uint32_t *)(vfe32_ctrl->vfebase + VFE_CAMIF_STATUS);
+	temp = (uint32_t *)(axi_ctrl->share_ctrl->vfebase + VFE_CAMIF_STATUS);
 	out->camifStatus = msm_camera_io_r(temp);
 	CDBG("camifStatus  = 0x%x\n", out->camifStatus);
 
 	/* clear the pending interrupt of the same kind.*/
 	msm_camera_io_w(out->vfeIrqStatus0,
-		vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
 	msm_camera_io_w(out->vfeIrqStatus1,
-		vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
 
 	/* Ensure the write order while writing
 	to the command register using the barrier */
-	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_IRQ_CMD);
+	msm_camera_io_w_mb(1, axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
 
 }
 
-static void vfe32_process_reg_update_irq(void)
+static void vfe32_process_reg_update_irq(
+		struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
 
 	if (vfe32_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
-		if (vfe32_ctrl->operation_mode ==
+		if (vfe32_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-		} else if (vfe32_ctrl->operation_mode ==
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch1]);
+		} else if (vfe32_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out1.ch1]);
 		}
 		vfe32_ctrl->recording_state = VFE_STATE_STARTED;
-		msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+		msm_camera_io_w_mb(1,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 		CDBG("start video triggered .\n");
 	} else if (vfe32_ctrl->recording_state ==
 			VFE_STATE_STOP_REQUESTED) {
-		if (vfe32_ctrl->operation_mode ==
+		if (vfe32_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
-			msm_camera_io_w(0, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-		} else if (vfe32_ctrl->operation_mode ==
+			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch1]);
+		} else if (vfe32_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
-			msm_camera_io_w(0, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(0, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out1.ch1]);
 		}
 		CDBG("stop video triggered .\n");
 	}
 
 	if (vfe32_ctrl->start_ack_pending == TRUE) {
-		vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_START_ACK);
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_START_ACK);
 		vfe32_ctrl->start_ack_pending = FALSE;
 	} else {
 		if (vfe32_ctrl->recording_state ==
@@ -2581,10 +2835,12 @@
 			 * when we process the next reg update irq.
 			 */
 			msm_camera_io_w_mb(1,
-			vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 		} else if (vfe32_ctrl->recording_state ==
 					VFE_STATE_STOPPED) {
-			vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_STOP_REC_ACK);
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				vfe32_ctrl->share_ctrl->vfeFrameId,
+				MSG_ID_STOP_REC_ACK);
 			vfe32_ctrl->recording_state = VFE_STATE_IDLE;
 		}
 		spin_lock_irqsave(&vfe32_ctrl->update_ack_lock, flags);
@@ -2592,80 +2848,102 @@
 			vfe32_ctrl->update_ack_pending = FALSE;
 			spin_unlock_irqrestore(
 				&vfe32_ctrl->update_ack_lock, flags);
-			vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_UPDATE_ACK);
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				vfe32_ctrl->share_ctrl->vfeFrameId,
+				MSG_ID_UPDATE_ACK);
 		} else {
 			spin_unlock_irqrestore(
 				&vfe32_ctrl->update_ack_lock, flags);
 		}
 	}
 
-	if (vfe32_ctrl->liveshot_state == VFE_STATE_START_REQUESTED) {
+	if (vfe32_ctrl->share_ctrl->liveshot_state ==
+		VFE_STATE_START_REQUESTED) {
 		pr_info("%s enabling liveshot output\n", __func__);
-		if (vfe32_ctrl->outpath.output_mode &
+		if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-			vfe32_ctrl->liveshot_state = VFE_STATE_STARTED;
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch1]);
+			vfe32_ctrl->share_ctrl->liveshot_state =
+				VFE_STATE_STARTED;
 		}
 	}
 
-	if (vfe32_ctrl->liveshot_state == VFE_STATE_STARTED) {
-		vfe32_ctrl->vfe_capture_count--;
-		if (!vfe32_ctrl->vfe_capture_count)
-			vfe32_ctrl->liveshot_state = VFE_STATE_STOP_REQUESTED;
-		msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	} else if (vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED) {
+	if (vfe32_ctrl->share_ctrl->liveshot_state == VFE_STATE_STARTED) {
+		vfe32_ctrl->share_ctrl->vfe_capture_count--;
+		if (!vfe32_ctrl->share_ctrl->vfe_capture_count)
+			vfe32_ctrl->share_ctrl->liveshot_state =
+				VFE_STATE_STOP_REQUESTED;
+		msm_camera_io_w_mb(1, vfe32_ctrl->
+			share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	} else if (vfe32_ctrl->share_ctrl->liveshot_state ==
+			VFE_STATE_STOP_REQUESTED) {
 		CDBG("%s: disabling liveshot output\n", __func__);
-		if (vfe32_ctrl->outpath.output_mode &
+		if (vfe32_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(0, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(0, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-			vfe32_ctrl->liveshot_state = VFE_STATE_STOPPED;
-			msm_camera_io_w_mb(1, vfe32_ctrl->vfebase +
+			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[vfe32_ctrl->
+				share_ctrl->outpath.out0.ch1]);
+			vfe32_ctrl->share_ctrl->liveshot_state =
+				VFE_STATE_STOPPED;
+			msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
 				VFE_REG_UPDATE_CMD);
 		}
-	} else if (vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED) {
-		vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
+	} else if (vfe32_ctrl->share_ctrl->liveshot_state ==
+			VFE_STATE_STOPPED) {
+		vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
 	}
 
-	if ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
-		(vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) ||
-		(vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) ||
-		(vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) {
+	if ((vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_MAIN) ||
+		(vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_MAIN_AND_THUMB) ||
+		(vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_JPEG) ||
+		(vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_JPEG_AND_THUMB)) {
 		/* in snapshot mode */
 		/* later we need to add check for live snapshot mode. */
 		if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
 			(vfe32_ctrl->snapshot_frame_cnt %
 				vfe32_ctrl->frame_skip_cnt))) {
-			vfe32_ctrl->vfe_capture_count--;
+			vfe32_ctrl->share_ctrl->vfe_capture_count--;
 			/* if last frame to be captured: */
-			if (vfe32_ctrl->vfe_capture_count == 0) {
+			if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
 				/* stop the bus output:write master enable = 0*/
-				if (vfe32_ctrl->outpath.output_mode &
-						VFE32_OUTPUT_MODE_PRIMARY) {
-					msm_camera_io_w(0, vfe32_ctrl->vfebase +
+				if (vfe32_ctrl->share_ctrl->outpath.output_mode
+					& VFE32_OUTPUT_MODE_PRIMARY) {
+					msm_camera_io_w(0,
+						vfe32_ctrl->share_ctrl->vfebase+
 						vfe32_AXI_WM_CFG[vfe32_ctrl->
-							outpath.out0.ch0]);
-					msm_camera_io_w(0, vfe32_ctrl->vfebase +
+						share_ctrl->outpath.out0.ch0]);
+					msm_camera_io_w(0,
+						vfe32_ctrl->share_ctrl->vfebase+
 						vfe32_AXI_WM_CFG[vfe32_ctrl->
-							outpath.out0.ch1]);
+						share_ctrl->outpath.out0.ch1]);
 				}
-				if (vfe32_ctrl->outpath.output_mode &
+				if (vfe32_ctrl->share_ctrl->outpath.output_mode&
 						VFE32_OUTPUT_MODE_SECONDARY) {
-					msm_camera_io_w(0, vfe32_ctrl->vfebase +
+					msm_camera_io_w(0,
+						vfe32_ctrl->share_ctrl->vfebase+
 						vfe32_AXI_WM_CFG[vfe32_ctrl->
-							outpath.out1.ch0]);
-					msm_camera_io_w(0, vfe32_ctrl->vfebase +
+						share_ctrl->outpath.out1.ch0]);
+					msm_camera_io_w(0,
+						vfe32_ctrl->share_ctrl->vfebase+
 						vfe32_AXI_WM_CFG[vfe32_ctrl->
-							outpath.out1.ch1]);
+						share_ctrl->outpath.out1.ch1]);
 				}
 				msm_camera_io_w_mb
 				(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
-				vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
+				vfe32_ctrl->share_ctrl->vfebase +
+				VFE_CAMIF_COMMAND);
 				vfe32_ctrl->snapshot_frame_cnt = -1;
 				vfe32_ctrl->frame_skip_cnt = 31;
 				vfe32_ctrl->frame_skip_pattern = 0xffffffff;
@@ -2673,116 +2951,143 @@
 		} /*if frame is not being dropped*/
 		vfe32_ctrl->snapshot_frame_cnt++;
 		/* then do reg_update. */
-		msm_camera_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+		msm_camera_io_w(1,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	} /* if snapshot mode. */
 }
 
-static void vfe32_set_default_reg_values(void)
+static void vfe32_set_default_reg_values(
+			struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	msm_camera_io_w(0x800080, vfe32_ctrl->vfebase + VFE_DEMUX_GAIN_0);
-	msm_camera_io_w(0x800080, vfe32_ctrl->vfebase + VFE_DEMUX_GAIN_1);
+	msm_camera_io_w(0x800080,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
+	msm_camera_io_w(0x800080,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
 	/* What value should we program CGC_OVERRIDE to? */
-	msm_camera_io_w(0xFFFFF, vfe32_ctrl->vfebase + VFE_CGC_OVERRIDE);
+	msm_camera_io_w(0xFFFFF,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
 
 	/* default frame drop period and pattern */
-	msm_camera_io_w(0x1f, vfe32_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
-	msm_camera_io_w(0x1f, vfe32_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
+	msm_camera_io_w(0x1f,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
+	msm_camera_io_w(0x1f,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
 	msm_camera_io_w(0xFFFFFFFF,
-		vfe32_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
 	msm_camera_io_w(0xFFFFFFFF,
-		vfe32_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_PATTERN);
-	msm_camera_io_w(0x1f, vfe32_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y);
-	msm_camera_io_w(0x1f, vfe32_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_FRAMEDROP_ENC_CBCR_PATTERN);
+	msm_camera_io_w(0x1f,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y);
+	msm_camera_io_w(0x1f,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR);
 	msm_camera_io_w(0xFFFFFFFF,
-		vfe32_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
 	msm_camera_io_w(0xFFFFFFFF,
-		vfe32_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
-	msm_camera_io_w(0, vfe32_ctrl->vfebase + VFE_CLAMP_MIN);
-	msm_camera_io_w(0xFFFFFF, vfe32_ctrl->vfebase + VFE_CLAMP_MAX);
+		vfe32_ctrl->share_ctrl->vfebase +
+		VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
+	msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MIN);
+	msm_camera_io_w(0xFFFFFF,
+		vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MAX);
 
 	/* stats UB config */
 	msm_camera_io_w(0x3980007,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AEC_UB_CFG);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AEC_UB_CFG);
 	msm_camera_io_w(0x3A00007,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AF_UB_CFG);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AF_UB_CFG);
 	msm_camera_io_w(0x3A8000F,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_AWB_UB_CFG);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AWB_UB_CFG);
 	msm_camera_io_w(0x3B80007,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_RS_UB_CFG);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_RS_UB_CFG);
 	msm_camera_io_w(0x3C0001F,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_CS_UB_CFG);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_CS_UB_CFG);
 	msm_camera_io_w(0x3E0001F,
-		vfe32_ctrl->vfebase + VFE_BUS_STATS_HIST_UB_CFG);
+		vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_HIST_UB_CFG);
 }
 
-static void vfe32_process_reset_irq(void)
+static void vfe32_process_reset_irq(
+		struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
 
-	atomic_set(&vfe32_ctrl->vstate, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
 
-	spin_lock_irqsave(&vfe32_ctrl->stop_flag_lock, flags);
-	if (vfe32_ctrl->stop_ack_pending) {
-		vfe32_ctrl->stop_ack_pending = FALSE;
-		spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
-		vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_STOP_ACK);
+	spin_lock_irqsave(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
+	if (vfe32_ctrl->share_ctrl->stop_ack_pending) {
+		vfe32_ctrl->share_ctrl->stop_ack_pending = FALSE;
+		spin_unlock_irqrestore(
+			&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_STOP_ACK);
 	} else {
-		spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
+		spin_unlock_irqrestore(
+			&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
 		/* this is from reset command. */
-		vfe32_set_default_reg_values();
+		vfe32_set_default_reg_values(vfe32_ctrl);
 
 		/* reload all write masters. (frame & line)*/
-		msm_camera_io_w(0x7FFF, vfe32_ctrl->vfebase + VFE_BUS_CMD);
-		vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_RESET_ACK);
+		msm_camera_io_w(0x7FFF,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_RESET_ACK);
 	}
 }
 
-static void vfe32_process_camif_sof_irq(void)
+static void vfe32_process_camif_sof_irq(
+		struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	if (vfe32_ctrl->operation_mode ==
+	if (vfe32_ctrl->share_ctrl->operation_mode ==
 		VFE_OUTPUTS_RAW) {
 		if (vfe32_ctrl->start_ack_pending) {
-			vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_START_ACK);
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				vfe32_ctrl->share_ctrl->vfeFrameId,
+				MSG_ID_START_ACK);
 			vfe32_ctrl->start_ack_pending = FALSE;
 		}
-		vfe32_ctrl->vfe_capture_count--;
+		vfe32_ctrl->share_ctrl->vfe_capture_count--;
 		/* if last frame to be captured: */
-		if (vfe32_ctrl->vfe_capture_count == 0) {
+		if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
 			/* Ensure the write order while writing
 			 to the command register using the barrier */
 			msm_camera_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
-				vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
+			vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
 		}
 	} /* if raw snapshot mode. */
 	if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
-		(vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_VIDEO) &&
-		(vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
-		vfe32_ctrl->vfeFrameId++;
+		(vfe32_ctrl->share_ctrl->operation_mode ==
+			VFE_MODE_OF_OPERATION_VIDEO) &&
+		(vfe32_ctrl->share_ctrl->vfeFrameId %
+			vfe32_ctrl->hfr_mode != 0)) {
+		vfe32_ctrl->share_ctrl->vfeFrameId++;
 		CDBG("Skip the SOF notification when HFR enabled\n");
 		return;
 	}
-	vfe32_ctrl->vfeFrameId++;
-	vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_SOF_ACK);
-	CDBG("camif_sof_irq, frameId = %d\n", vfe32_ctrl->vfeFrameId);
+	vfe32_ctrl->share_ctrl->vfeFrameId++;
+	vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+		vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_SOF_ACK);
+	CDBG("camif_sof_irq, frameId = %d\n",
+		vfe32_ctrl->share_ctrl->vfeFrameId);
 
 	if (vfe32_ctrl->sync_timer_state) {
 		if (vfe32_ctrl->sync_timer_repeat_count == 0)
-			vfe32_sync_timer_stop();
+			vfe32_sync_timer_stop(vfe32_ctrl);
 		else
 			vfe32_ctrl->sync_timer_repeat_count--;
 	}
 }
 
-static void vfe32_process_error_irq(uint32_t errStatus)
+static void vfe32_process_error_irq(
+	struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
 {
 	uint32_t reg_value;
 
 	if (errStatus & VFE32_IMASK_CAMIF_ERROR) {
 		pr_err("vfe32_irq: camif errors\n");
 		reg_value = msm_camera_io_r(
-				vfe32_ctrl->vfebase + VFE_CAMIF_STATUS);
+			axi_ctrl->share_ctrl->vfebase + VFE_CAMIF_STATUS);
 		pr_err("camifStatus  = 0x%x\n", reg_value);
-		vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_CAMIF_ERROR);
+		vfe32_send_isp_msg(&axi_ctrl->subdev,
+			axi_ctrl->share_ctrl->vfeFrameId, MSG_ID_CAMIF_ERROR);
 	}
 
 	if (errStatus & VFE32_IMASK_BHIST_OVWR)
@@ -2806,7 +3111,7 @@
 	if (errStatus & VFE32_IMASK_VIOLATION) {
 		pr_err("vfe32_irq: violation interrupt\n");
 		reg_value = msm_camera_io_r(
-				vfe32_ctrl->vfebase + VFE_VIOLATION_STATUS);
+			axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
 		pr_err("%s: violationStatus  = 0x%x\n", __func__, reg_value);
 	}
 
@@ -2856,7 +3161,8 @@
 		pr_err("vfe32_irq: axi error\n");
 }
 
-static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
+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)
 {
 	struct isp_msg_output msg;
@@ -2865,15 +3171,16 @@
 	msg.buf.ch_paddr[0]	= ch0_paddr;
 	msg.buf.ch_paddr[1]	= ch1_paddr;
 	msg.buf.ch_paddr[2]	= ch2_paddr;
-	msg.frameCounter = vfe32_ctrl->vfeFrameId;
+	msg.frameCounter = axi_ctrl->share_ctrl->vfeFrameId;
 
-	v4l2_subdev_notify(&vfe32_ctrl->subdev,
+	v4l2_subdev_notify(&axi_ctrl->subdev,
 			NOTIFY_VFE_MSG_OUT,
 			&msg);
 	return;
 }
 
-static void vfe32_process_output_path_irq_0(void)
+static void vfe32_process_output_path_irq_0(
+	struct axi_ctrl_t *axi_ctrl)
 {
 	uint32_t ping_pong;
 	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
@@ -2881,7 +3188,7 @@
 	struct msm_free_buf *free_buf = NULL;
 
 	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
-		VFE_MSG_OUTPUT_PRIMARY);
+		VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
 
 	/* we render frames in the following conditions:
 	1. Continuous mode and the free buffer is avaialable.
@@ -2889,73 +3196,91 @@
 	when pending snapshot count is <=1,  then no need to use
 	free buffer.
 	*/
-	out_bool = ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_RAW ||
-		vfe32_ctrl->liveshot_state == VFE_STATE_STARTED ||
-		vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED ||
-		vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED) &&
-		(vfe32_ctrl->vfe_capture_count <= 1)) || free_buf;
+	out_bool = (
+		(axi_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_MAIN ||
+		axi_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_MAIN_AND_THUMB ||
+		axi_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_JPEG ||
+		axi_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_JPEG_AND_THUMB ||
+		axi_ctrl->share_ctrl->operation_mode ==
+			VFE_OUTPUTS_RAW ||
+		axi_ctrl->share_ctrl->liveshot_state ==
+			VFE_STATE_STARTED ||
+		axi_ctrl->share_ctrl->liveshot_state ==
+			VFE_STATE_STOP_REQUESTED ||
+		axi_ctrl->share_ctrl->liveshot_state ==
+			VFE_STATE_STOPPED) &&
+		(axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
+			free_buf;
 
 	if (out_bool) {
-		ping_pong = msm_camera_io_r(vfe32_ctrl->vfebase +
+		ping_pong = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
 			VFE_BUS_PING_PONG_STATUS);
 
 		/* Channel 0*/
-		ch0_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out0.ch0);
+		ch0_paddr = vfe32_get_ch_addr(
+			ping_pong, axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch0);
 		/* Channel 1*/
-		ch1_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out0.ch1);
+		ch1_paddr = vfe32_get_ch_addr(
+			ping_pong, axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch1);
 		/* Channel 2*/
-		ch2_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out0.ch2);
+		ch2_paddr = vfe32_get_ch_addr(
+			ping_pong, axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch2);
 
 		CDBG("output path 0, ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
 			ch0_paddr, ch1_paddr, ch2_paddr);
 		if (free_buf) {
 			/* Y channel */
 			vfe32_put_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out0.ch0,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch0,
 			free_buf->ch_paddr[0]);
 			/* Chroma channel */
 			vfe32_put_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out0.ch1,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out0.ch1,
 			free_buf->ch_paddr[1]);
 			if (free_buf->num_planes > 2)
 				vfe32_put_ch_addr(ping_pong,
-					vfe32_ctrl->outpath.out0.ch2,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out0.ch2,
 					free_buf->ch_paddr[2]);
 		}
-		if (vfe32_ctrl->operation_mode ==
+		if (axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_THUMB_AND_MAIN ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_THUMB_AND_JPEG ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_JPEG_AND_THUMB ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_RAW ||
-			vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED)
-			vfe32_ctrl->outpath.out0.capture_cnt--;
+			axi_ctrl->share_ctrl->liveshot_state ==
+				VFE_STATE_STOPPED)
+			axi_ctrl->share_ctrl->outpath.out0.capture_cnt--;
 
-		vfe_send_outmsg(&vfe32_ctrl->subdev,
+		vfe_send_outmsg(axi_ctrl,
 			MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
 			ch1_paddr, ch2_paddr);
 
-		if (vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED)
-			vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
+		if (axi_ctrl->share_ctrl->liveshot_state == VFE_STATE_STOPPED)
+			axi_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
 
 	} else {
-		vfe32_ctrl->outpath.out0.frame_drop_cnt++;
+		axi_ctrl->share_ctrl->outpath.out0.frame_drop_cnt++;
 		CDBG("path_irq_0 - no free buffer!\n");
 	}
 }
 
-static void vfe32_process_output_path_irq_1(void)
+static void vfe32_process_output_path_irq_1(
+	struct axi_ctrl_t *axi_ctrl)
 {
 	uint32_t ping_pong;
 	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
@@ -2964,81 +3289,89 @@
 	struct msm_free_buf *free_buf = NULL;
 
 	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
-		VFE_MSG_OUTPUT_SECONDARY);
-	out_bool = ((vfe32_ctrl->operation_mode ==
+		VFE_MSG_OUTPUT_SECONDARY, axi_ctrl);
+	out_bool = ((axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_THUMB_AND_MAIN ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_RAW ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_JPEG_AND_THUMB) &&
-			(vfe32_ctrl->vfe_capture_count <= 1)) || free_buf;
+			(axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
+				free_buf;
 
 	if (out_bool) {
-		ping_pong = msm_camera_io_r(vfe32_ctrl->vfebase +
+		ping_pong = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
 			VFE_BUS_PING_PONG_STATUS);
 
 		/* Y channel */
 		ch0_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch0);
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch0);
 		/* Chroma channel */
 		ch1_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch1);
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch1);
 		ch2_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch2);
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch2);
 
 		CDBG("%s ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
 			__func__, ch0_paddr, ch1_paddr, ch2_paddr);
 		if (free_buf) {
 			/* Y channel */
 			vfe32_put_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch0,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch0,
 			free_buf->ch_paddr[0]);
 			/* Chroma channel */
 			vfe32_put_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch1,
+			axi_ctrl->share_ctrl->vfebase,
+			axi_ctrl->share_ctrl->outpath.out1.ch1,
 			free_buf->ch_paddr[1]);
 			if (free_buf->num_planes > 2)
 				vfe32_put_ch_addr(ping_pong,
-					vfe32_ctrl->outpath.out1.ch2,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out1.ch2,
 					free_buf->ch_paddr[2]);
 		}
-		if (vfe32_ctrl->operation_mode ==
+		if (axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_THUMB_AND_MAIN ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_RAW ||
-			vfe32_ctrl->operation_mode ==
+			axi_ctrl->share_ctrl->operation_mode ==
 				VFE_OUTPUTS_JPEG_AND_THUMB)
-			vfe32_ctrl->outpath.out1.capture_cnt--;
+			axi_ctrl->share_ctrl->outpath.out1.capture_cnt--;
 
-		vfe_send_outmsg(&vfe32_ctrl->subdev,
+		vfe_send_outmsg(axi_ctrl,
 			MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
 			ch1_paddr, ch2_paddr);
 	} else {
-		vfe32_ctrl->outpath.out1.frame_drop_cnt++;
+		axi_ctrl->share_ctrl->outpath.out1.frame_drop_cnt++;
 		CDBG("path_irq_1 - no free buffer!\n");
 	}
 }
 
-static uint32_t  vfe32_process_stats_irq_common(uint32_t statsNum,
-						uint32_t newAddr) {
-
+static uint32_t  vfe32_process_stats_irq_common(
+	struct vfe32_ctrl_type *vfe32_ctrl,
+	uint32_t statsNum, uint32_t newAddr)
+{
 	uint32_t pingpongStatus;
 	uint32_t returnAddr;
 	uint32_t pingpongAddr;
 
 	/* must be 0=ping, 1=pong */
 	pingpongStatus =
-		((msm_camera_io_r(vfe32_ctrl->vfebase +
+		((msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
 		VFE_BUS_PING_PONG_STATUS))
 	& ((uint32_t)(1<<(statsNum + 7)))) >> (statsNum + 7);
 	/* stats bits starts at 7 */
 	CDBG("statsNum %d, pingpongStatus %d\n", statsNum, pingpongStatus);
 	pingpongAddr =
-		((uint32_t)(vfe32_ctrl->vfebase +
+		((uint32_t)(vfe32_ctrl->share_ctrl->vfebase +
 				VFE_BUS_STATS_PING_PONG_BASE)) +
 				(3*statsNum)*4 + (1-pingpongStatus)*4;
 	returnAddr = msm_camera_io_r((uint32_t *)pingpongAddr);
@@ -3047,14 +3380,15 @@
 }
 
 static void
-vfe_send_stats_msg(uint32_t bufAddress, uint32_t statsNum)
+vfe_send_stats_msg(struct vfe32_ctrl_type *vfe32_ctrl,
+	uint32_t bufAddress, uint32_t statsNum)
 {
 	unsigned long flags;
 	/* fill message with right content. */
 	/* @todo This is causing issues, need further investigate */
 	/* spin_lock_irqsave(&ctrl->state_lock, flags); */
 	struct isp_msg_stats msgStats;
-	msgStats.frameCounter = vfe32_ctrl->vfeFrameId;
+	msgStats.frameCounter = vfe32_ctrl->share_ctrl->vfeFrameId;
 	msgStats.buffer = bufAddress;
 
 	switch (statsNum) {
@@ -3114,12 +3448,13 @@
 	return;
 }
 
-static void vfe_send_comp_stats_msg(uint32_t status_bits)
+static void vfe_send_comp_stats_msg(
+	struct vfe32_ctrl_type *vfe32_ctrl, uint32_t status_bits)
 {
 	struct msm_stats_buf msgStats;
 	uint32_t temp;
 
-	msgStats.frame_id = vfe32_ctrl->vfeFrameId;
+	msgStats.frame_id = vfe32_ctrl->share_ctrl->vfeFrameId;
 	msgStats.status_bits = status_bits;
 
 	msgStats.aec.buff = vfe32_ctrl->aecStatsControl.bufToRender;
@@ -3130,7 +3465,8 @@
 	msgStats.rs.buff = vfe32_ctrl->rsStatsControl.bufToRender;
 	msgStats.cs.buff = vfe32_ctrl->csStatsControl.bufToRender;
 
-	temp = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_STATS_AWB_SGW_CFG);
+	temp = msm_camera_io_r(
+		vfe32_ctrl->share_ctrl->vfebase + VFE_STATS_AWB_SGW_CFG);
 	msgStats.awb_ymin = (0xFF00 & temp) >> 8;
 
 	v4l2_subdev_notify(&vfe32_ctrl->subdev,
@@ -3138,18 +3474,18 @@
 				&msgStats);
 }
 
-static void vfe32_process_stats_ae_irq(void)
+static void vfe32_process_stats_ae_irq(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&vfe32_ctrl->aec_ack_lock, flags);
 	if (!(vfe32_ctrl->aecStatsControl.ackPending)) {
 		spin_unlock_irqrestore(&vfe32_ctrl->aec_ack_lock, flags);
 		vfe32_ctrl->aecStatsControl.bufToRender =
-			vfe32_process_stats_irq_common(statsAeNum,
+			vfe32_process_stats_irq_common(vfe32_ctrl, statsAeNum,
 			vfe32_ctrl->aecStatsControl.nextFrameAddrBuf);
 
-		vfe_send_stats_msg(vfe32_ctrl->aecStatsControl.bufToRender,
-						statsAeNum);
+		vfe_send_stats_msg(vfe32_ctrl,
+			vfe32_ctrl->aecStatsControl.bufToRender, statsAeNum);
 	} else{
 		spin_unlock_irqrestore(&vfe32_ctrl->aec_ack_lock, flags);
 		vfe32_ctrl->aecStatsControl.droppedStatsFrameCount++;
@@ -3158,18 +3494,18 @@
 	}
 }
 
-static void vfe32_process_stats_awb_irq(void)
+static void vfe32_process_stats_awb_irq(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&vfe32_ctrl->awb_ack_lock, flags);
 	if (!(vfe32_ctrl->awbStatsControl.ackPending)) {
 		spin_unlock_irqrestore(&vfe32_ctrl->awb_ack_lock, flags);
 		vfe32_ctrl->awbStatsControl.bufToRender =
-			vfe32_process_stats_irq_common(statsAwbNum,
+			vfe32_process_stats_irq_common(vfe32_ctrl, statsAwbNum,
 			vfe32_ctrl->awbStatsControl.nextFrameAddrBuf);
 
-		vfe_send_stats_msg(vfe32_ctrl->awbStatsControl.bufToRender,
-						statsAwbNum);
+		vfe_send_stats_msg(vfe32_ctrl,
+			vfe32_ctrl->awbStatsControl.bufToRender, statsAwbNum);
 	} else{
 		spin_unlock_irqrestore(&vfe32_ctrl->awb_ack_lock, flags);
 		vfe32_ctrl->awbStatsControl.droppedStatsFrameCount++;
@@ -3178,18 +3514,18 @@
 	}
 }
 
-static void vfe32_process_stats_af_irq(void)
+static void vfe32_process_stats_af_irq(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&vfe32_ctrl->af_ack_lock, flags);
 	if (!(vfe32_ctrl->afStatsControl.ackPending)) {
 		spin_unlock_irqrestore(&vfe32_ctrl->af_ack_lock, flags);
 		vfe32_ctrl->afStatsControl.bufToRender =
-			vfe32_process_stats_irq_common(statsAfNum,
+			vfe32_process_stats_irq_common(vfe32_ctrl, statsAfNum,
 			vfe32_ctrl->afStatsControl.nextFrameAddrBuf);
 
-		vfe_send_stats_msg(vfe32_ctrl->afStatsControl.bufToRender,
-						statsAfNum);
+		vfe_send_stats_msg(vfe32_ctrl,
+			vfe32_ctrl->afStatsControl.bufToRender, statsAfNum);
 	} else{
 		spin_unlock_irqrestore(&vfe32_ctrl->af_ack_lock, flags);
 		vfe32_ctrl->afStatsControl.droppedStatsFrameCount++;
@@ -3198,15 +3534,17 @@
 	}
 }
 
-static void vfe32_process_stats_ihist_irq(void)
+static void vfe32_process_stats_ihist_irq(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	if (!(vfe32_ctrl->ihistStatsControl.ackPending)) {
 		vfe32_ctrl->ihistStatsControl.bufToRender =
-			vfe32_process_stats_irq_common(statsIhistNum,
+			vfe32_process_stats_irq_common(
+			vfe32_ctrl, statsIhistNum,
 			vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf);
 
-		vfe_send_stats_msg(vfe32_ctrl->ihistStatsControl.bufToRender,
-						statsIhistNum);
+		vfe_send_stats_msg(vfe32_ctrl,
+			vfe32_ctrl->ihistStatsControl.bufToRender,
+			statsIhistNum);
 	} else {
 		vfe32_ctrl->ihistStatsControl.droppedStatsFrameCount++;
 		CDBG("%s: droppedStatsFrameCount = %d", __func__,
@@ -3214,15 +3552,15 @@
 	}
 }
 
-static void vfe32_process_stats_rs_irq(void)
+static void vfe32_process_stats_rs_irq(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	if (!(vfe32_ctrl->rsStatsControl.ackPending)) {
 		vfe32_ctrl->rsStatsControl.bufToRender =
-			vfe32_process_stats_irq_common(statsRsNum,
+			vfe32_process_stats_irq_common(vfe32_ctrl, statsRsNum,
 			vfe32_ctrl->rsStatsControl.nextFrameAddrBuf);
 
-		vfe_send_stats_msg(vfe32_ctrl->rsStatsControl.bufToRender,
-						statsRsNum);
+		vfe_send_stats_msg(vfe32_ctrl,
+			vfe32_ctrl->rsStatsControl.bufToRender, statsRsNum);
 	} else {
 		vfe32_ctrl->rsStatsControl.droppedStatsFrameCount++;
 		CDBG("%s: droppedStatsFrameCount = %d", __func__,
@@ -3230,15 +3568,15 @@
 	}
 }
 
-static void vfe32_process_stats_cs_irq(void)
+static void vfe32_process_stats_cs_irq(struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	if (!(vfe32_ctrl->csStatsControl.ackPending)) {
 		vfe32_ctrl->csStatsControl.bufToRender =
-			vfe32_process_stats_irq_common(statsCsNum,
+			vfe32_process_stats_irq_common(vfe32_ctrl, statsCsNum,
 			vfe32_ctrl->csStatsControl.nextFrameAddrBuf);
 
-		vfe_send_stats_msg(vfe32_ctrl->csStatsControl.bufToRender,
-						statsCsNum);
+		vfe_send_stats_msg(vfe32_ctrl,
+			vfe32_ctrl->csStatsControl.bufToRender, statsCsNum);
 	} else {
 		vfe32_ctrl->csStatsControl.droppedStatsFrameCount++;
 		CDBG("%s: droppedStatsFrameCount = %d", __func__,
@@ -3246,7 +3584,8 @@
 	}
 }
 
-static void vfe32_process_stats(uint32_t status_bits)
+static void vfe32_process_stats(struct vfe32_ctrl_type *vfe32_ctrl,
+	uint32_t status_bits)
 {
 	unsigned long flags;
 	int32_t process_stats = false;
@@ -3257,7 +3596,8 @@
 		if (!vfe32_ctrl->aecStatsControl.ackPending) {
 			vfe32_ctrl->aecStatsControl.ackPending = TRUE;
 			vfe32_ctrl->aecStatsControl.bufToRender =
-				vfe32_process_stats_irq_common(statsAeNum,
+				vfe32_process_stats_irq_common(
+				vfe32_ctrl, statsAeNum,
 				vfe32_ctrl->aecStatsControl.nextFrameAddrBuf);
 			process_stats = true;
 		} else{
@@ -3272,7 +3612,8 @@
 		if (!vfe32_ctrl->awbStatsControl.ackPending) {
 			vfe32_ctrl->awbStatsControl.ackPending = TRUE;
 			vfe32_ctrl->awbStatsControl.bufToRender =
-				vfe32_process_stats_irq_common(statsAwbNum,
+				vfe32_process_stats_irq_common(
+				vfe32_ctrl, statsAwbNum,
 				vfe32_ctrl->awbStatsControl.nextFrameAddrBuf);
 			process_stats = true;
 		} else{
@@ -3288,7 +3629,8 @@
 		if (!vfe32_ctrl->afStatsControl.ackPending) {
 			vfe32_ctrl->afStatsControl.ackPending = TRUE;
 			vfe32_ctrl->afStatsControl.bufToRender =
-				vfe32_process_stats_irq_common(statsAfNum,
+				vfe32_process_stats_irq_common(
+				vfe32_ctrl, statsAfNum,
 				vfe32_ctrl->afStatsControl.nextFrameAddrBuf);
 			process_stats = true;
 		} else {
@@ -3303,7 +3645,8 @@
 		if (!vfe32_ctrl->ihistStatsControl.ackPending) {
 			vfe32_ctrl->ihistStatsControl.ackPending = TRUE;
 			vfe32_ctrl->ihistStatsControl.bufToRender =
-				vfe32_process_stats_irq_common(statsIhistNum,
+				vfe32_process_stats_irq_common(
+				vfe32_ctrl, statsIhistNum,
 				vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf);
 			process_stats = true;
 		} else {
@@ -3318,7 +3661,8 @@
 		if (!vfe32_ctrl->rsStatsControl.ackPending) {
 			vfe32_ctrl->rsStatsControl.ackPending = TRUE;
 			vfe32_ctrl->rsStatsControl.bufToRender =
-				vfe32_process_stats_irq_common(statsRsNum,
+				vfe32_process_stats_irq_common(
+				vfe32_ctrl, statsRsNum,
 				vfe32_ctrl->rsStatsControl.nextFrameAddrBuf);
 			process_stats = true;
 		} else {
@@ -3329,12 +3673,12 @@
 		vfe32_ctrl->rsStatsControl.bufToRender = 0;
 	}
 
-
 	if (status_bits & VFE_IRQ_STATUS0_STATS_CS) {
 		if (!vfe32_ctrl->csStatsControl.ackPending) {
 			vfe32_ctrl->csStatsControl.ackPending = TRUE;
 			vfe32_ctrl->csStatsControl.bufToRender =
-				vfe32_process_stats_irq_common(statsCsNum,
+				vfe32_process_stats_irq_common(
+				vfe32_ctrl, statsCsNum,
 				vfe32_ctrl->csStatsControl.nextFrameAddrBuf);
 			process_stats = true;
 		} else {
@@ -3347,83 +3691,89 @@
 
 	spin_unlock_irqrestore(&vfe32_ctrl->comp_stats_ack_lock, flags);
 	if (process_stats)
-		vfe_send_comp_stats_msg(status_bits);
+		vfe_send_comp_stats_msg(vfe32_ctrl, status_bits);
 
 	return;
 }
 
-static void vfe32_process_stats_irq(uint32_t irqstatus)
+static void vfe32_process_stats_irq(
+	struct vfe32_ctrl_type *vfe32_ctrl, uint32_t irqstatus)
 {
 	uint32_t status_bits = VFE_COM_STATUS & irqstatus;
 
 	if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
-		(vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
+		(vfe32_ctrl->share_ctrl->vfeFrameId %
+		 vfe32_ctrl->hfr_mode != 0)) {
 		CDBG("Skip the stats when HFR enabled\n");
 		return;
 	}
 
-	vfe32_process_stats(status_bits);
+	vfe32_process_stats(vfe32_ctrl, status_bits);
 	return;
 }
 
-static void vfe32_process_irq(uint32_t irqstatus)
+static void vfe32_process_irq(
+	struct vfe32_ctrl_type *vfe32_ctrl, uint32_t irqstatus)
 {
 	if (irqstatus &
 		VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
-		vfe32_process_stats_irq(irqstatus);
+		vfe32_process_stats_irq(vfe32_ctrl, irqstatus);
 		return;
 	}
 
 	switch (irqstatus) {
 	case VFE_IRQ_STATUS0_CAMIF_SOF_MASK:
 		CDBG("irq	camifSofIrq\n");
-		vfe32_process_camif_sof_irq();
+		vfe32_process_camif_sof_irq(vfe32_ctrl);
 		break;
 	case VFE_IRQ_STATUS0_REG_UPDATE_MASK:
 		CDBG("irq	regUpdateIrq\n");
-		vfe32_process_reg_update_irq();
+		vfe32_process_reg_update_irq(vfe32_ctrl);
 		break;
 	case VFE_IMASK_WHILE_STOPPING_1:
 		CDBG("irq	resetAckIrq\n");
-		vfe32_process_reset_irq();
+		vfe32_process_reset_irq(vfe32_ctrl);
 		break;
 	case VFE_IRQ_STATUS0_STATS_AEC:
 		CDBG("Stats AEC irq occured.\n");
-		vfe32_process_stats_ae_irq();
+		vfe32_process_stats_ae_irq(vfe32_ctrl);
 		break;
 	case VFE_IRQ_STATUS0_STATS_AWB:
 		CDBG("Stats AWB irq occured.\n");
-		vfe32_process_stats_awb_irq();
+		vfe32_process_stats_awb_irq(vfe32_ctrl);
 		break;
 	case VFE_IRQ_STATUS0_STATS_AF:
 		CDBG("Stats AF irq occured.\n");
-		vfe32_process_stats_af_irq();
+		vfe32_process_stats_af_irq(vfe32_ctrl);
 		break;
 	case VFE_IRQ_STATUS0_STATS_IHIST:
 		CDBG("Stats IHIST irq occured.\n");
-		vfe32_process_stats_ihist_irq();
+		vfe32_process_stats_ihist_irq(vfe32_ctrl);
 		break;
 	case VFE_IRQ_STATUS0_STATS_RS:
 		CDBG("Stats RS irq occured.\n");
-		vfe32_process_stats_rs_irq();
+		vfe32_process_stats_rs_irq(vfe32_ctrl);
 		break;
 	case VFE_IRQ_STATUS0_STATS_CS:
 		CDBG("Stats CS irq occured.\n");
-		vfe32_process_stats_cs_irq();
+		vfe32_process_stats_cs_irq(vfe32_ctrl);
 		break;
 	case VFE_IRQ_STATUS0_SYNC_TIMER0:
 		CDBG("SYNC_TIMER 0 irq occured.\n");
-		vfe32_send_isp_msg(vfe32_ctrl,
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->vfeFrameId,
 			MSG_ID_SYNC_TIMER0_DONE);
 		break;
 	case VFE_IRQ_STATUS0_SYNC_TIMER1:
 		CDBG("SYNC_TIMER 1 irq occured.\n");
-		vfe32_send_isp_msg(vfe32_ctrl,
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->vfeFrameId,
 			MSG_ID_SYNC_TIMER1_DONE);
 		break;
 	case VFE_IRQ_STATUS0_SYNC_TIMER2:
 		CDBG("SYNC_TIMER 2 irq occured.\n");
-		vfe32_send_isp_msg(vfe32_ctrl,
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->vfeFrameId,
 			MSG_ID_SYNC_TIMER2_DONE);
 		break;
 	default:
@@ -3474,11 +3824,12 @@
 				NOTIFY_VFE_IRQ,
 				(void *)VFE_IMASK_WHILE_STOPPING_1);
 
-		if (atomic_read(&vfe32_ctrl->vstate)) {
+		if (atomic_read(&axi_ctrl->share_ctrl->vstate)) {
 			if (qcmd->vfeInterruptStatus1 &
 					VFE32_IMASK_ERROR_ONLY_1) {
 				pr_err("irq	errorIrq\n");
 				vfe32_process_error_irq(
+					axi_ctrl,
 					qcmd->vfeInterruptStatus1 &
 					VFE32_IMASK_ERROR_ONLY_1);
 			}
@@ -3487,7 +3838,7 @@
 				(void *)qcmd->vfeInterruptStatus0);
 
 			/* then process stats irq. */
-			if (vfe32_ctrl->stats_comp) {
+			if (axi_ctrl->share_ctrl->stats_comp) {
 				/* process stats comb interrupt. */
 				if (qcmd->vfeInterruptStatus0 &
 					VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
@@ -3567,7 +3918,7 @@
 
 	CDBG("vfe_parse_irq\n");
 
-	vfe32_read_irq_status(&irq);
+	vfe32_read_irq_status(axi_ctrl, &irq);
 
 	if ((irq.vfeIrqStatus0 == 0) && (irq.vfeIrqStatus1 == 0)) {
 		CDBG("vfe_parse_irq: vfeIrqStatus0 & 1 are both 0!\n");
@@ -3581,12 +3932,12 @@
 		return IRQ_HANDLED;
 	}
 
-	spin_lock_irqsave(&vfe32_ctrl->stop_flag_lock, flags);
-	if (vfe32_ctrl->stop_ack_pending) {
+	spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+	if (axi_ctrl->share_ctrl->stop_ack_pending) {
 		irq.vfeIrqStatus0 &= VFE_IMASK_WHILE_STOPPING_0;
 		irq.vfeIrqStatus1 &= VFE_IMASK_WHILE_STOPPING_1;
 	}
-	spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
+	spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
 
 	CDBG("vfe_parse_irq: Irq_status0 = 0x%x, Irq_status1 = 0x%x.\n",
 		irq.vfeIrqStatus0, irq.vfeIrqStatus1);
@@ -3608,6 +3959,8 @@
 {
 	struct msm_cam_media_controller *pmctl =
 		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+	struct vfe32_ctrl_type *vfe32_ctrl =
+		(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
 	struct msm_isp_cmd vfecmd;
 	struct msm_camvfe_params *vfe_params =
 		(struct msm_camvfe_params *)arg;
@@ -3619,8 +3972,14 @@
 	struct vfe_cmd_stats_buf *scfg = NULL;
 	struct msm_pmem_region   *regptr = NULL;
 	struct vfe_cmd_stats_ack *sack = NULL;
+
+	if (!vfe32_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return -EFAULT;
+	}
+
 	if (cmd->cmd_type == CMD_VFE_PROCESS_IRQ) {
-		vfe32_process_irq((uint32_t) data);
+		vfe32_process_irq(vfe32_ctrl, (uint32_t) data);
 		return rc;
 	} else if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
 		cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
@@ -3688,22 +4047,22 @@
 		/* individual */
 		switch (cmd->cmd_type) {
 		case CMD_STATS_AEC_ENABLE:
-			rc = vfe_stats_aec_buf_init(scfg);
+			rc = vfe_stats_aec_buf_init(vfe32_ctrl, scfg);
 			break;
 		case CMD_STATS_AF_ENABLE:
-			rc = vfe_stats_af_buf_init(scfg);
+			rc = vfe_stats_af_buf_init(vfe32_ctrl, scfg);
 			break;
 		case CMD_STATS_AWB_ENABLE:
-			rc = vfe_stats_awb_buf_init(scfg);
+			rc = vfe_stats_awb_buf_init(vfe32_ctrl, scfg);
 			break;
 		case CMD_STATS_IHIST_ENABLE:
-			rc = vfe_stats_ihist_buf_init(scfg);
+			rc = vfe_stats_ihist_buf_init(vfe32_ctrl, scfg);
 			break;
 		case CMD_STATS_RS_ENABLE:
-			rc = vfe_stats_rs_buf_init(scfg);
+			rc = vfe_stats_rs_buf_init(vfe32_ctrl, scfg);
 			break;
 		case CMD_STATS_CS_ENABLE:
-			rc = vfe_stats_cs_buf_init(scfg);
+			rc = vfe_stats_cs_buf_init(vfe32_ctrl, scfg);
 			break;
 		default:
 			pr_err("%s Unsupported cmd type %d",
@@ -3714,50 +4073,51 @@
 	}
 	switch (cmd->cmd_type) {
 	case CMD_GENERAL:
-		rc = vfe32_proc_general(pmctl, &vfecmd);
+		rc = vfe32_proc_general(pmctl, &vfecmd, vfe32_ctrl);
 		break;
-
 	case CMD_CONFIG_PING_ADDR: {
 		int path = *((int *)cmd->value);
-		struct vfe32_output_ch *outch = vfe32_get_ch(path);
+		struct vfe32_output_ch *outch =
+			vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
 		outch->ping = *((struct msm_free_buf *)data);
 	}
 		break;
 
 	case CMD_CONFIG_PONG_ADDR: {
 		int path = *((int *)cmd->value);
-		struct vfe32_output_ch *outch = vfe32_get_ch(path);
+		struct vfe32_output_ch *outch =
+			vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
 		outch->pong = *((struct msm_free_buf *)data);
 	}
 		break;
 
 	case CMD_CONFIG_FREE_BUF_ADDR: {
 		int path = *((int *)cmd->value);
-		struct vfe32_output_ch *outch = vfe32_get_ch(path);
+		struct vfe32_output_ch *outch =
+			vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
 		outch->free_buf = *((struct msm_free_buf *)data);
 	}
 		break;
-
 	case CMD_SNAP_BUF_RELEASE:
 		break;
 	case CMD_STATS_AEC_BUF_RELEASE:
-		vfe32_stats_aec_ack(sack);
+		vfe32_stats_aec_ack(vfe32_ctrl, sack);
 		break;
 	case CMD_STATS_AF_BUF_RELEASE:
-		vfe32_stats_af_ack(sack);
+		vfe32_stats_af_ack(vfe32_ctrl, sack);
 		break;
 	case CMD_STATS_AWB_BUF_RELEASE:
-		vfe32_stats_awb_ack(sack);
+		vfe32_stats_awb_ack(vfe32_ctrl, sack);
 		break;
 
 	case CMD_STATS_IHIST_BUF_RELEASE:
-		vfe32_stats_ihist_ack(sack);
+		vfe32_stats_ihist_ack(vfe32_ctrl, sack);
 		break;
 	case CMD_STATS_RS_BUF_RELEASE:
-		vfe32_stats_rs_ack(sack);
+		vfe32_stats_rs_ack(vfe32_ctrl, sack);
 		break;
 	case CMD_STATS_CS_BUF_RELEASE:
-		vfe32_stats_cs_ack(sack);
+		vfe32_stats_cs_ack(vfe32_ctrl, sack);
 		break;
 	default:
 		pr_err("%s Unsupported AXI configuration %x ", __func__,
@@ -3816,17 +4176,16 @@
 	v4l2_set_subdev_hostdata(sd, mctl);
 	spin_lock_init(&axi_ctrl->tasklet_lock);
 	INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
+	spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
 
-	axi_ctrl->vfebase = ioremap(axi_ctrl->vfemem->start,
+	axi_ctrl->share_ctrl->vfebase = ioremap(axi_ctrl->vfemem->start,
 		resource_size(axi_ctrl->vfemem));
-	if (!axi_ctrl->vfebase) {
+	if (!axi_ctrl->share_ctrl->vfebase) {
 		rc = -ENOMEM;
 		pr_err("%s: vfe ioremap failed\n", __func__);
 		goto remap_failed;
 	}
 
-	vfe32_ctrl->vfebase = axi_ctrl->vfebase;
-
 	if (axi_ctrl->fs_vfe == NULL) {
 		axi_ctrl->fs_vfe =
 			regulator_get(&axi_ctrl->pdev->dev, "fs_vfe");
@@ -3854,11 +4213,12 @@
 	msm_camio_bus_scale_cfg(
 		mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 
-	if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
+	if (msm_camera_io_r(
+		axi_ctrl->share_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
 		VFE32_HW_NUMBER)
-		vfe32_ctrl->register_total = VFE32_REGISTER_TOTAL;
+		axi_ctrl->share_ctrl->register_total = VFE32_REGISTER_TOTAL;
 	else
-		vfe32_ctrl->register_total = VFE33_REGISTER_TOTAL;
+		axi_ctrl->share_ctrl->register_total = VFE33_REGISTER_TOTAL;
 
 	enable_irq(axi_ctrl->vfeirq->start);
 
@@ -3868,8 +4228,8 @@
 	regulator_put(axi_ctrl->fs_vfe);
 	axi_ctrl->fs_vfe = NULL;
 fs_failed:
-	iounmap(axi_ctrl->vfebase);
-	axi_ctrl->vfebase = NULL;
+	iounmap(axi_ctrl->share_ctrl->vfebase);
+	axi_ctrl->share_ctrl->vfebase = NULL;
 remap_failed:
 	disable_irq(axi_ctrl->vfeirq->start);
 	return rc;
@@ -3879,9 +4239,11 @@
 			struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
+	struct vfe32_ctrl_type *vfe32_ctrl =
+		(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
 	v4l2_set_subdev_hostdata(sd, mctl);
 
-	spin_lock_init(&vfe32_ctrl->stop_flag_lock);
+	spin_lock_init(&vfe32_ctrl->share_ctrl->stop_flag_lock);
 	spin_lock_init(&vfe32_ctrl->state_lock);
 	spin_lock_init(&vfe32_ctrl->io_lock);
 	spin_lock_init(&vfe32_ctrl->update_ack_lock);
@@ -3893,7 +4255,6 @@
 	spin_lock_init(&vfe32_ctrl->rs_ack_lock);
 	spin_lock_init(&vfe32_ctrl->cs_ack_lock);
 	spin_lock_init(&vfe32_ctrl->comp_stats_ack_lock);
-	spin_lock_init(&vfe32_ctrl->sd_notify_lock);
 
 	vfe32_ctrl->update_linear = false;
 	vfe32_ctrl->update_rolloff = false;
@@ -3909,6 +4270,11 @@
 	struct msm_cam_media_controller *pmctl =
 		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return;
+	}
+
 	CDBG("%s, free_irq\n", __func__);
 	disable_irq(axi_ctrl->vfeirq->start);
 	tasklet_kill(&axi_ctrl->vfe32_tasklet);
@@ -3919,8 +4285,8 @@
 		regulator_put(axi_ctrl->fs_vfe);
 		axi_ctrl->fs_vfe = NULL;
 	}
-	iounmap(axi_ctrl->vfebase);
-	axi_ctrl->vfebase = NULL;
+	iounmap(axi_ctrl->share_ctrl->vfebase);
+	axi_ctrl->share_ctrl->vfebase = NULL;
 
 	if (atomic_read(&irq_cnt))
 		pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
@@ -3931,78 +4297,92 @@
 
 void msm_vfe_subdev_release(struct v4l2_subdev *sd)
 {
-	vfe32_ctrl->vfebase = 0;
+	struct vfe32_ctrl_type *vfe32_ctrl =
+		(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
+	if (!vfe32_ctrl->share_ctrl->vfebase)
+		vfe32_ctrl->share_ctrl->vfebase = NULL;
 }
 
-void axi_start(void)
+void axi_start(struct axi_ctrl_t *axi_ctrl)
 {
-	switch (vfe32_ctrl->operation_mode) {
+	switch (axi_ctrl->share_ctrl->operation_mode) {
 	case VFE_OUTPUTS_PREVIEW:
 	case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
-		if (vfe32_ctrl->outpath.output_mode &
+		if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-		} else if (vfe32_ctrl->outpath.output_mode &
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out0.ch1]);
+		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out0.ch0]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out0.ch1]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out0.ch2]);
 		}
 		break;
 	default:
-		if (vfe32_ctrl->outpath.output_mode &
+		if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
-		} else if (vfe32_ctrl->outpath.output_mode &
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch1]);
+		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
-			msm_camera_io_w(1, vfe32_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch2]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch0]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch1]);
+			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+				vfe32_AXI_WM_CFG[axi_ctrl->
+				share_ctrl->outpath.out1.ch2]);
 		}
 		break;
 	}
 }
 
-void axi_stop(void)
+void axi_stop(struct axi_ctrl_t *axi_ctrl)
 {
 	uint8_t  axiBusyFlag = true;
-		/* axi halt command. */
+	/* axi halt command. */
 	msm_camera_io_w(AXI_HALT,
-		vfe32_ctrl->vfebase + VFE_AXI_CMD);
+		axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
 	wmb();
 	while (axiBusyFlag) {
-		if (msm_camera_io_r(vfe32_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
+		if (msm_camera_io_r(
+			axi_ctrl->share_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
 			axiBusyFlag = false;
 	}
 	/* Ensure the write order while writing
 	to the command register using the barrier */
 	msm_camera_io_w_mb(AXI_HALT_CLEAR,
-		vfe32_ctrl->vfebase + VFE_AXI_CMD);
+		axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
 
 	/* after axi halt, then ok to apply global reset. */
 	/* enable reset_ack and async timer interrupt only while
 	stopping the pipeline.*/
 	msm_camera_io_w(0xf0000000,
-		vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
 	msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
-		vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
 
 	/* Ensure the write order while writing
 	to the command register using the barrier */
 	msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
-		vfe32_ctrl->vfebase + VFE_GLOBAL_RESET);
+		axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
 }
 
 static int msm_axi_config(struct v4l2_subdev *sd, void __user *arg)
@@ -4010,7 +4390,12 @@
 	struct msm_vfe_cfg_cmd cfgcmd;
 	struct msm_isp_cmd vfecmd;
 	int rc = 0;
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
 
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return -EFAULT;
+	}
 	if (NULL != arg) {
 		if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
 			ERR_COPY_FROM_USER();
@@ -4043,7 +4428,7 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_PRIM, axio);
+		vfe32_config_axi(axi_ctrl, OUTPUT_PRIM, axio);
 		kfree(axio);
 	}
 		break;
@@ -4062,7 +4447,7 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_PRIM_ALL_CHNLS, axio);
+		vfe32_config_axi(axi_ctrl, OUTPUT_PRIM_ALL_CHNLS, axio);
 		kfree(axio);
 	}
 		break;
@@ -4081,7 +4466,7 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_PRIM|OUTPUT_SEC, axio);
+		vfe32_config_axi(axi_ctrl, OUTPUT_PRIM|OUTPUT_SEC, axio);
 		kfree(axio);
 	}
 		break;
@@ -4100,7 +4485,8 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
+		vfe32_config_axi(axi_ctrl,
+			OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
 		kfree(axio);
 	}
 		break;
@@ -4119,7 +4505,8 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
+		vfe32_config_axi(axi_ctrl,
+			OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
 		kfree(axio);
 	}
 		break;
@@ -4128,10 +4515,10 @@
 			__func__, cfgcmd.cmd_type);
 		break;
 	case CMD_AXI_START:
-		axi_start();
+		axi_start(axi_ctrl);
 		break;
 	case CMD_AXI_STOP:
-		axi_stop();
+		axi_stop(axi_ctrl);
 		break;
 	default:
 		pr_err("%s Unsupported AXI configuration %x ", __func__,
@@ -4143,43 +4530,95 @@
 
 static void msm_axi_process_irq(struct v4l2_subdev *sd, void *arg)
 {
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
 	uint32_t irqstatus = (uint32_t) arg;
+
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return;
+	}
 	/* next, check output path related interrupts. */
 	if (irqstatus &
 		VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) {
 		CDBG("Image composite done 0 irq occured.\n");
-		vfe32_process_output_path_irq_0();
+		vfe32_process_output_path_irq_0(axi_ctrl);
 	}
 	if (irqstatus &
 		VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK) {
 		CDBG("Image composite done 1 irq occured.\n");
-		vfe32_process_output_path_irq_1();
+		vfe32_process_output_path_irq_1(axi_ctrl);
 	}
 	/* in snapshot mode if done then send
 	snapshot done message */
-	if (vfe32_ctrl->operation_mode ==
+	if (axi_ctrl->share_ctrl->operation_mode ==
 			VFE_OUTPUTS_THUMB_AND_MAIN ||
-		vfe32_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode ==
 			VFE_OUTPUTS_MAIN_AND_THUMB ||
-		vfe32_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode ==
 			VFE_OUTPUTS_THUMB_AND_JPEG ||
-		vfe32_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode ==
 			VFE_OUTPUTS_JPEG_AND_THUMB ||
-		vfe32_ctrl->operation_mode ==
+		axi_ctrl->share_ctrl->operation_mode ==
 			VFE_OUTPUTS_RAW) {
-		if ((vfe32_ctrl->outpath.out0.capture_cnt == 0)
-				&& (vfe32_ctrl->outpath.out1.
+		if ((axi_ctrl->share_ctrl->outpath.out0.capture_cnt == 0)
+				&& (axi_ctrl->share_ctrl->outpath.out1.
 				capture_cnt == 0)) {
 			msm_camera_io_w_mb(
 				CAMIF_COMMAND_STOP_IMMEDIATELY,
-				vfe32_ctrl->vfebase +
+				axi_ctrl->share_ctrl->vfebase +
 				VFE_CAMIF_COMMAND);
-			vfe32_send_isp_msg(vfe32_ctrl,
+			vfe32_send_isp_msg(&axi_ctrl->subdev,
+				axi_ctrl->share_ctrl->vfeFrameId,
 				MSG_ID_SNAPSHOT_DONE);
 		}
 	}
 }
 
+static int msm_axi_buf_cfg(struct v4l2_subdev *sd, void __user *arg)
+{
+	struct msm_camvfe_params *vfe_params =
+		(struct msm_camvfe_params *)arg;
+	struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	void *data = vfe_params->data;
+	int rc = 0;
+
+	if (!axi_ctrl->share_ctrl->vfebase) {
+		pr_err("%s: base address unmapped\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (cmd->cmd_type) {
+	case CMD_CONFIG_PING_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe32_output_ch *outch =
+			vfe32_get_ch(path, axi_ctrl->share_ctrl);
+		outch->ping = *((struct msm_free_buf *)data);
+	}
+		break;
+
+	case CMD_CONFIG_PONG_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe32_output_ch *outch =
+			vfe32_get_ch(path, axi_ctrl->share_ctrl);
+		outch->pong = *((struct msm_free_buf *)data);
+	}
+		break;
+
+	case CMD_CONFIG_FREE_BUF_ADDR: {
+		int path = *((int *)cmd->value);
+		struct vfe32_output_ch *outch =
+			vfe32_get_ch(path, axi_ctrl->share_ctrl);
+		outch->free_buf = *((struct msm_free_buf *)data);
+	}
+		break;
+	default:
+		pr_err("%s Unsupported AXI Buf config %x ", __func__,
+			cmd->cmd_type);
+	}
+	return rc;
+};
+
 static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
 
 static long msm_axi_subdev_ioctl(struct v4l2_subdev *sd,
@@ -4198,6 +4637,10 @@
 		msm_axi_process_irq(sd, arg);
 		rc = 0;
 		break;
+	case VIDIOC_MSM_AXI_BUF_CFG:
+		msm_axi_buf_cfg(sd, arg);
+		rc = 0;
+		break;
 	case VIDIOC_MSM_AXI_RELEASE:
 		msm_axi_subdev_release(sd);
 		rc = 0;
@@ -4227,14 +4670,36 @@
 {
 	int rc = 0;
 	struct axi_ctrl_t *axi_ctrl;
+	struct vfe32_ctrl_type *vfe32_ctrl;
+	struct vfe_share_ctrl_t *share_ctrl;
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
-	vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
-	if (!vfe32_ctrl) {
+
+	share_ctrl = kzalloc(sizeof(struct vfe_share_ctrl_t), GFP_KERNEL);
+	if (!share_ctrl) {
 		pr_err("%s: no enough memory\n", __func__);
 		return -ENOMEM;
 	}
 
 	axi_ctrl = kzalloc(sizeof(struct axi_ctrl_t), GFP_KERNEL);
+	if (!axi_ctrl) {
+		pr_err("%s: no enough memory\n", __func__);
+		kfree(share_ctrl);
+		return -ENOMEM;
+	}
+
+	vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
+	if (!vfe32_ctrl) {
+		pr_err("%s: no enough memory\n", __func__);
+		kfree(share_ctrl);
+		kfree(axi_ctrl);
+		return -ENOMEM;
+	}
+
+	share_ctrl->axi_ctrl = axi_ctrl;
+	share_ctrl->vfe32_ctrl = vfe32_ctrl;
+	axi_ctrl->share_ctrl = share_ctrl;
+	vfe32_ctrl->share_ctrl = share_ctrl;
+
 	v4l2_subdev_init(&axi_ctrl->subdev, &msm_axi_subdev_ops);
 	axi_ctrl->subdev.internal_ops = &msm_axi_internal_ops;
 	axi_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index d1faded..086600a 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -900,6 +900,30 @@
 	uint32_t droppedStatsFrameCount;
 	uint32_t bufToRender;
 };
+struct axi_ctrl_t;
+struct vfe32_ctrl_type;
+
+struct vfe_share_ctrl_t {
+	void __iomem *vfebase;
+	uint32_t register_total;
+
+	atomic_t vstate;
+	uint32_t vfeFrameId;
+	uint32_t stats_comp;
+	spinlock_t  stop_flag_lock;
+	int8_t stop_ack_pending;
+	enum vfe_output_state liveshot_state;
+	uint32_t vfe_capture_count;
+
+	uint16_t operation_mode;     /* streaming or snapshot */
+	struct vfe32_output_path outpath;
+
+	uint32_t ref_count;
+	spinlock_t  sd_notify_lock;
+
+	struct axi_ctrl_t *axi_ctrl;
+	struct vfe32_ctrl_type *vfe32_ctrl;
+};
 
 struct axi_ctrl_t {
 	struct v4l2_subdev subdev;
@@ -908,7 +932,6 @@
 	spinlock_t  tasklet_lock;
 	struct list_head tasklet_q;
 
-	void __iomem *vfebase;
 	void *syncdata;
 
 	struct resource	*vfemem;
@@ -916,15 +939,12 @@
 	struct regulator *fs_vfe;
 	struct clk *vfe_clk[3];
 	struct tasklet_struct vfe32_tasklet;
+	struct vfe_share_ctrl_t *share_ctrl;
 };
 
 struct vfe32_ctrl_type {
-	uint16_t operation_mode;     /* streaming or snapshot */
-	struct vfe32_output_path outpath;
-
 	uint32_t vfeImaskCompositePacked;
 
-	spinlock_t  stop_flag_lock;
 	spinlock_t  update_ack_lock;
 	spinlock_t  state_lock;
 	spinlock_t  io_lock;
@@ -941,7 +961,6 @@
 	void *extdata;
 
 	int8_t start_ack_pending;
-	int8_t stop_ack_pending;
 	int8_t reset_ack_pending;
 	int8_t update_ack_pending;
 	enum vfe_output_state recording_state;
@@ -949,19 +968,13 @@
 	int8_t update_rolloff;
 	int8_t update_la;
 	int8_t update_gamma;
-	enum vfe_output_state liveshot_state;
 
-	void __iomem *vfebase;
-	uint32_t register_total;
+	struct vfe_share_ctrl_t *share_ctrl;
 
-	uint32_t stats_comp;
-	atomic_t vstate;
-	uint32_t vfe_capture_count;
 	uint32_t sync_timer_repeat_count;
 	uint32_t sync_timer_state;
 	uint32_t sync_timer_number;
 
-	uint32_t vfeFrameId;
 	uint32_t output1Pattern;
 	uint32_t output1Period;
 	uint32_t output2Pattern;
@@ -978,7 +991,6 @@
 	/* v4l2 subdev */
 	struct v4l2_subdev subdev;
 	struct platform_device *pdev;
-	spinlock_t  sd_notify_lock;
 	uint32_t hfr_mode;
 	uint32_t frame_skip_cnt;
 	uint32_t frame_skip_pattern;
@@ -1015,4 +1027,7 @@
 #define VIDIOC_MSM_AXI_IRQ \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 21, void *)
 
+#define VIDIOC_MSM_AXI_BUF_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 22, void *)
+
 #endif /* __MSM_VFE32_H__ */
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index f9ce74b..54e9582 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -30,14 +30,19 @@
 #include "msm.h"
 #include "msm_vpe.h"
 
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define D(fmt, args...) pr_debug("msm_vpe: " fmt, ##args)
+#else
+#define D(fmt, args...) do {} while (0)
+#endif
+
 static int vpe_enable(uint32_t);
 static int vpe_disable(void);
 static int vpe_update_scaler(struct msm_pp_crop *pcrop);
 struct vpe_ctrl_type *vpe_ctrl;
 static atomic_t vpe_init_done = ATOMIC_INIT(0);
 
-static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd,
-	struct msm_mctl_pp_frame_info *pp_frame_info);
+static int msm_vpe_do_pp(struct msm_mctl_pp_frame_info *pp_frame_info);
 
 static long long vpe_do_div(long long num, long long den)
 {
@@ -57,8 +62,7 @@
 	msm_camera_io_dump(vpe_ctrl->vpebase + 0x50400, 0x10);
 
 	/* this triggers the operation. */
-	msm_camera_io_w(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET);
-	wmb();
+	msm_camera_io_w_mb(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET);
 	return 0;
 }
 
@@ -72,7 +76,7 @@
 static void vpe_config_axi_default(void)
 {
 	msm_camera_io_w(0x25, vpe_ctrl->vpebase + VPE_AXI_ARB_2_OFFSET);
-	CDBG("%s: yaddr %ld cbcraddr %ld", __func__,
+	D("%s: yaddr %ld cbcraddr %ld", __func__,
 		 vpe_ctrl->out_y_addr, vpe_ctrl->out_cbcr_addr);
 	if (!vpe_ctrl->out_y_addr || !vpe_ctrl->out_cbcr_addr)
 		return;
@@ -81,7 +85,6 @@
 	/* for video  CbCr address */
 	msm_camera_io_w(vpe_ctrl->out_cbcr_addr,
 		vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
-
 }
 
 static int vpe_reset(void)
@@ -92,7 +95,7 @@
 
 	spin_lock_irqsave(&vpe_ctrl->lock, flags);
 	if (vpe_ctrl->state == VPE_STATE_IDLE) {
-		CDBG("%s: VPE already disabled.", __func__);
+		D("%s: VPE already disabled.", __func__);
 		spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 		return rc;
 	}
@@ -101,7 +104,7 @@
 	vpe_reset_state_variables();
 	vpe_version = msm_camera_io_r(
 			vpe_ctrl->vpebase + VPE_HW_VERSION_OFFSET);
-	CDBG("vpe_version = 0x%x\n", vpe_version);
+	D("vpe_version = 0x%x\n", vpe_version);
 	/* disable all interrupts.*/
 	msm_camera_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
 	/* clear all pending interrupts*/
@@ -139,13 +142,13 @@
 	rot_flag = msm_camera_io_r(vpe_ctrl->vpebase +
 						VPE_OP_MODE_OFFSET) & 0xE00;
 	if (pinfo != NULL) {
-		CDBG("%s: Crop info in2_w = %d, in2_h = %d "
+		D("%s: Crop info in2_w = %d, in2_h = %d "
 			"out2_w = %d out2_h = %d\n",
 			__func__, pcrop->src_w, pcrop->src_h,
 			pcrop->dst_w, pcrop->dst_h);
 		rc = vpe_update_scaler(pcrop);
 	}
-	CDBG("return rc = %d rot_flag = %d\n", rc, rot_flag);
+	D("return rc = %d rot_flag = %d\n", rc, rot_flag);
 	rc |= rot_flag;
 
 	return rc;
@@ -200,7 +203,7 @@
 		vpe_ctrl->out_w = w;
 		vpe_ctrl->out_h = h;
 	}
-	CDBG("%s: out_w=%d, out_h=%d", __func__, vpe_ctrl->out_w,
+	D("%s: out_w=%d, out_h=%d", __func__, vpe_ctrl->out_w,
 		vpe_ctrl->out_h);
 	return 0;
 }
@@ -239,7 +242,7 @@
 	out_ROI_width = pcrop->dst_w;
 	out_ROI_height = pcrop->dst_h;
 
-	CDBG("src w = 0x%x, h=0x%x, dst w = 0x%x, h =0x%x.\n",
+	D("src w = 0x%x, h=0x%x, dst w = 0x%x, h =0x%x.\n",
 		src_ROI_width, src_ROI_height, out_ROI_width,
 		out_ROI_height);
 	src_roi = (src_ROI_height << 16) + src_ROI_width;
@@ -249,12 +252,12 @@
 	src_x = pcrop->src_x;
 	src_y = pcrop->src_y;
 
-	CDBG("src_x = %d, src_y=%d.\n", src_x, src_y);
+	D("src_x = %d, src_y=%d.\n", src_x, src_y);
 
 	src_xy = src_y*(1<<16) + src_x;
 	msm_camera_io_w(src_xy, vpe_ctrl->vpebase +
 			VPE_SRC_XY_OFFSET);
-	CDBG("src_xy = %d, src_roi=%d.\n", src_xy, src_roi);
+	D("src_xy = %d, src_roi=%d.\n", src_xy, src_roi);
 
 	/* decide whether to use FIR or M/N for scaling */
 	if ((out_ROI_width == 1 && src_ROI_width < 4) ||
@@ -387,9 +390,9 @@
 	} else if (scale_unit_sel_y == 1) /* M over N scalar   */
 		phase_init_y = 0;
 
-	CDBG("phase step x = %d, step y = %d.\n",
+	D("phase step x = %d, step y = %d.\n",
 		 phase_step_x, phase_step_y);
-	CDBG("phase init x = %d, init y = %d.\n",
+	D("phase init x = %d, init y = %d.\n",
 		 phase_init_x, phase_init_y);
 
 	msm_camera_io_w(phase_step_x, vpe_ctrl->vpebase +
@@ -416,24 +419,40 @@
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 	return busy;
 }
+
 static int msm_send_frame_to_vpe(void)
 {
 	int rc = 0;
 	unsigned long flags;
+	unsigned long srcP0, srcP1, outP0, outP1;
+	struct msm_mctl_pp_frame_info *frame = vpe_ctrl->pp_frame_info;
 
 	spin_lock_irqsave(&vpe_ctrl->lock, flags);
-	msm_camera_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
-			  vpe_ctrl->pp_frame_info->src_frame.sp.y_off),
-			vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
-	msm_camera_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
-			  vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off),
-			vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
-	msm_camera_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
-			  vpe_ctrl->pp_frame_info->dest_frame.sp.y_off),
-			vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
-	msm_camera_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
-			  vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off),
-			vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
+	if (frame->src_frame.num_planes > 1) {
+		srcP0 = vpe_ctrl->pp_frame_info->src_frame.mp[0].phy_addr +
+			vpe_ctrl->pp_frame_info->src_frame.mp[0].data_offset;
+		srcP1 = vpe_ctrl->pp_frame_info->src_frame.mp[1].phy_addr +
+			vpe_ctrl->pp_frame_info->src_frame.mp[1].data_offset;
+		outP0 = vpe_ctrl->pp_frame_info->dest_frame.mp[0].phy_addr +
+			vpe_ctrl->pp_frame_info->dest_frame.mp[0].data_offset;
+		outP1 = vpe_ctrl->pp_frame_info->dest_frame.mp[1].phy_addr +
+			vpe_ctrl->pp_frame_info->dest_frame.mp[1].data_offset;
+	} else {
+		srcP0 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
+			vpe_ctrl->pp_frame_info->src_frame.sp.y_off;
+		srcP1 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
+			vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off;
+		outP0 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
+			vpe_ctrl->pp_frame_info->dest_frame.sp.y_off;
+		outP1 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
+			vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off;
+	}
+
+	msm_camera_io_w(srcP0, vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
+	msm_camera_io_w(srcP1, vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
+	msm_camera_io_w(outP0, vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
+	msm_camera_io_w(outP1, vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
+
 	vpe_ctrl->state = VPE_STATE_ACTIVE;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 	vpe_start();
@@ -443,27 +462,33 @@
 static void vpe_send_outmsg(void)
 {
 	unsigned long flags;
-	struct msm_vpe_resp rp;
-	memset(&rp, 0, sizeof(rp));
+	struct v4l2_event v4l2_evt;
+	struct msm_queue_cmd *event_qcmd;
 	spin_lock_irqsave(&vpe_ctrl->lock, flags);
 	if (vpe_ctrl->state == VPE_STATE_IDLE) {
 		pr_err("%s VPE is in IDLE state. Ignore the ack msg", __func__);
 		spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 		return;
 	}
-	rp.type = vpe_ctrl->pp_frame_info->pp_frame_cmd.path;
-	rp.extdata = (void *)vpe_ctrl->pp_frame_info;
-	rp.extlen = sizeof(*vpe_ctrl->pp_frame_info);
-	vpe_ctrl->state = VPE_STATE_INIT;   /* put it back to idle. */
+	event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
+	atomic_set(&event_qcmd->on_heap, 1);
+	event_qcmd->command = (void *)vpe_ctrl->pp_frame_info;
 	vpe_ctrl->pp_frame_info = NULL;
+	vpe_ctrl->state = VPE_STATE_INIT;   /* put it back to idle. */
+
+	/* Enqueue the event payload. */
+	msm_enqueue(&vpe_ctrl->eventData_q, &event_qcmd->list_eventdata);
+	/* Now queue the event. */
+	v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_MCTL_PP_EVENT;
+	v4l2_evt.id = 0;
+	v4l2_event_queue(vpe_ctrl->subdev.devnode, &v4l2_evt);
+
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-	v4l2_subdev_notify(&vpe_ctrl->subdev,
-		NOTIFY_VPE_MSG_EVT, (void *)&rp);
 }
 
 static void vpe_do_tasklet(unsigned long data)
 {
-	CDBG("%s: irq_status = 0x%x",
+	D("%s: irq_status = 0x%x",
 		   __func__, vpe_ctrl->irq_status);
 	if (vpe_ctrl->irq_status & 0x1)
 		vpe_send_outmsg();
@@ -478,7 +503,7 @@
 	msm_camera_io_w_mb(vpe_ctrl->irq_status, vpe_ctrl->vpebase +
 				VPE_INTR_CLEAR_OFFSET);
 	msm_camera_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
-	CDBG("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status);
+	D("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status);
 	tasklet_schedule(&vpe_tasklet);
 	return IRQ_HANDLED;
 }
@@ -492,7 +517,7 @@
 {
 	int rc = 0;
 	unsigned long flags = 0;
-	CDBG("%s", __func__);
+	D("%s", __func__);
 	/* don't change the order of clock and irq.*/
 	spin_lock_irqsave(&vpe_ctrl->lock, flags);
 	if (vpe_ctrl->state != VPE_STATE_IDLE) {
@@ -536,10 +561,10 @@
 {
 	int rc = 0;
 	unsigned long flags = 0;
-	CDBG("%s", __func__);
+	D("%s", __func__);
 	spin_lock_irqsave(&vpe_ctrl->lock, flags);
 	if (vpe_ctrl->state == VPE_STATE_IDLE) {
-		CDBG("%s: VPE already disabled", __func__);
+		D("%s: VPE already disabled", __func__);
 		spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 		return rc;
 	}
@@ -559,8 +584,7 @@
 	return rc;
 }
 
-static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd,
-			struct msm_mctl_pp_frame_info *pp_frame_info)
+static int msm_vpe_do_pp(struct msm_mctl_pp_frame_info *pp_frame_info)
 {
 	int rc = 0;
 	unsigned long flags;
@@ -577,7 +601,7 @@
 	vpe_ctrl->pp_frame_info = pp_frame_info;
 	msm_vpe_cfg_update(
 		&vpe_ctrl->pp_frame_info->pp_frame_cmd.crop);
-	CDBG("%s Sending frame idx %d id %d to VPE ", __func__,
+	D("%s Sending frame idx %d id %d to VPE ", __func__,
 		pp_frame_info->src_frame.buf_idx,
 		pp_frame_info->src_frame.frame_id);
 	rc = msm_send_frame_to_vpe();
@@ -590,7 +614,7 @@
 		struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
-	CDBG("%s:begin", __func__);
+	D("%s:begin", __func__);
 	if (atomic_read(&vpe_init_done)) {
 		pr_err("%s: VPE has been initialized", __func__);
 		return -EBUSY;
@@ -604,7 +628,7 @@
 	}
 	v4l2_set_subdev_hostdata(sd, mctl);
 	spin_lock_init(&vpe_ctrl->lock);
-	CDBG("%s:end", __func__);
+	D("%s:end", __func__);
 	return rc;
 }
 EXPORT_SYMBOL(msm_vpe_subdev_init);
@@ -646,84 +670,310 @@
 }
 EXPORT_SYMBOL(msm_vpe_subdev_release);
 
-static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
-			unsigned int subdev_cmd, void *arg)
+static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
 {
-	struct msm_mctl_pp_params *vpe_params;
-	struct msm_mctl_pp_cmd *cmd;
 	int rc = 0;
 
-	if (subdev_cmd == VIDIOC_MSM_VPE_INIT) {
+	switch (vpe_cmd->cmd_type) {
+	case VPE_CMD_RESET:
+		rc = vpe_reset();
+		break;
+
+	case VPE_CMD_OPERATION_MODE_CFG: {
+		struct msm_vpe_op_mode_cfg op_mode_cfg;
+		if (sizeof(struct msm_vpe_op_mode_cfg) != vpe_cmd->length) {
+			pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+				__func__, vpe_cmd->cmd_type, vpe_cmd->length,
+				sizeof(struct msm_vpe_op_mode_cfg));
+			rc = -EINVAL;
+			break;
+		}
+		COPY_FROM_USER(rc, &op_mode_cfg, (void __user *)vpe_cmd->value,
+			sizeof(op_mode_cfg));
+		if (rc) {
+			ERR_COPY_FROM_USER();
+			break;
+		}
+
+		vpe_cmd->value = (void *)&op_mode_cfg;
+		rc = vpe_operation_config(vpe_cmd->value);
+		break;
+		}
+
+	case VPE_CMD_INPUT_PLANE_CFG: {
+		struct msm_vpe_input_plane_cfg input_cfg;
+		if (sizeof(struct msm_vpe_input_plane_cfg) != vpe_cmd->length) {
+			pr_err("%s: mismatch cmd = %d, len = %d, expected = %d",
+				__func__, vpe_cmd->cmd_type, vpe_cmd->length,
+				sizeof(struct msm_vpe_input_plane_cfg));
+			rc = -EINVAL;
+			break;
+		}
+		COPY_FROM_USER(rc, &input_cfg, (void __user *)vpe_cmd->value,
+			sizeof(input_cfg));
+		if (rc) {
+			ERR_COPY_FROM_USER();
+			break;
+		}
+
+		vpe_cmd->value = (void *)&input_cfg;
+		vpe_input_plane_config(vpe_cmd->value);
+		break;
+		}
+
+	case VPE_CMD_OUTPUT_PLANE_CFG: {
+		struct msm_vpe_output_plane_cfg output_cfg;
+		if (sizeof(struct msm_vpe_output_plane_cfg) !=
+			vpe_cmd->length) {
+			pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+				__func__, vpe_cmd->cmd_type, vpe_cmd->length,
+				sizeof(struct msm_vpe_output_plane_cfg));
+				rc = -EINVAL;
+				break;
+		}
+		COPY_FROM_USER(rc, &output_cfg, (void __user *)vpe_cmd->value,
+			sizeof(output_cfg));
+		if (rc) {
+			ERR_COPY_FROM_USER();
+			break;
+		}
+
+		vpe_cmd->value = (void *)&output_cfg;
+		vpe_output_plane_config(vpe_cmd->value);
+		break;
+		}
+
+	case VPE_CMD_SCALE_CFG_TYPE:{
+		struct msm_vpe_scaler_cfg scaler_cfg;
+		if (sizeof(struct msm_vpe_scaler_cfg) != vpe_cmd->length) {
+			pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+				__func__, vpe_cmd->cmd_type, vpe_cmd->length,
+				sizeof(struct msm_vpe_scaler_cfg));
+			rc = -EINVAL;
+			break;
+		}
+		COPY_FROM_USER(rc, &scaler_cfg, (void __user *)vpe_cmd->value,
+			sizeof(scaler_cfg));
+		if (rc) {
+			ERR_COPY_FROM_USER();
+			break;
+		}
+
+		vpe_cmd->value = (void *)&scaler_cfg;
+		vpe_update_scale_coef(vpe_cmd->value);
+		break;
+		}
+
+	case VPE_CMD_ZOOM: {
+		struct msm_mctl_pp_frame_info *zoom;
+		zoom = kmalloc(sizeof(struct msm_mctl_pp_frame_info),
+				GFP_ATOMIC);
+		if (!zoom) {
+			pr_err("%s Not enough memory ", __func__);
+			rc = -ENOMEM;
+			break;
+		}
+
+		if (sizeof(zoom->pp_frame_cmd) != vpe_cmd->length) {
+			pr_err("%s: size mismatch id=%d, len=%d, expected=%d",
+				__func__, vpe_cmd->cmd_type, vpe_cmd->length,
+				sizeof(zoom->pp_frame_cmd));
+			rc = -EINVAL;
+			kfree(zoom);
+			break;
+		}
+		COPY_FROM_USER(rc, &zoom->pp_frame_cmd,
+			(void __user *)vpe_cmd->value,
+			sizeof(zoom->pp_frame_cmd));
+		if (rc) {
+			ERR_COPY_FROM_USER();
+			kfree(zoom);
+			break;
+		}
+
+		zoom->user_cmd = vpe_cmd->cmd_type;
+		zoom->p_mctl = v4l2_get_subdev_hostdata(&vpe_ctrl->subdev);
+		D("%s: src=0x%x, dest=0x%x,cookie=0x%x,action=0x%x,path=0x%x",
+			__func__, zoom->pp_frame_cmd.src_buf_handle,
+			zoom->pp_frame_cmd.dest_buf_handle,
+			zoom->pp_frame_cmd.cookie,
+			zoom->pp_frame_cmd.vpe_output_action,
+			zoom->pp_frame_cmd.path);
+		rc = msm_mctl_pp_get_vpe_buf_info(zoom);
+		if (rc < 0) {
+			pr_err("%s Error getting buffer info from mctl rc = %d",
+				__func__, rc);
+			kfree(zoom);
+			break;
+		}
+		rc = msm_vpe_do_pp(zoom);
+		break;
+		}
+
+	case VPE_CMD_ENABLE: {
+		struct msm_vpe_clock_rate clk_rate;
+		int turbo_mode;
+		if (sizeof(struct msm_vpe_clock_rate) != vpe_cmd->length) {
+			pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+				__func__, vpe_cmd->cmd_type, vpe_cmd->length,
+				sizeof(struct msm_vpe_clock_rate));
+			rc = -EINVAL;
+			break;
+		}
+		if (copy_from_user(&clk_rate, (void __user *)vpe_cmd->value,
+			sizeof(struct msm_vpe_clock_rate))) {
+			pr_err("%s:clk_rate copy failed", __func__);
+			return -EFAULT;
+		}
+		turbo_mode = (int)clk_rate.rate;
+		rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
+				vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
+		break;
+		}
+
+	case VPE_CMD_DISABLE:
+		rc = vpe_disable();
+		break;
+
+	default:
+		break;
+	}
+
+	return rc;
+}
+
+static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct msm_vpe_cfg_cmd *vpe_cmd;
+	int rc = 0;
+
+	switch (cmd) {
+	case VIDIOC_MSM_VPE_INIT: {
 		struct msm_cam_media_controller *mctl =
 			(struct msm_cam_media_controller *)arg;
 		msm_vpe_subdev_init(sd, mctl);
-	} else if (subdev_cmd == VIDIOC_MSM_VPE_RELEASE) {
+		break;
+		}
+
+	case VIDIOC_MSM_VPE_RELEASE:
 		msm_vpe_subdev_release();
-	} else if (subdev_cmd == VIDIOC_MSM_VPE_CFG) {
-		vpe_params = (struct msm_mctl_pp_params *)arg;
-		cmd = vpe_params->cmd;
-		switch (cmd->id) {
-		case VPE_CMD_INIT:
-		case VPE_CMD_DEINIT:
-			break;
-		case VPE_CMD_RESET:
-			rc = vpe_reset();
-			break;
-		case VPE_CMD_OPERATION_MODE_CFG:
-			rc = vpe_operation_config(cmd->value);
-			break;
-		case VPE_CMD_INPUT_PLANE_CFG:
-			vpe_input_plane_config(cmd->value);
-			break;
-		case VPE_CMD_OUTPUT_PLANE_CFG:
-			vpe_output_plane_config(cmd->value);
-			break;
-		case VPE_CMD_SCALE_CFG_TYPE:
-			vpe_update_scale_coef(cmd->value);
-			break;
-		case VPE_CMD_ZOOM: {
-			rc = msm_vpe_do_pp(cmd,
-			(struct msm_mctl_pp_frame_info *)vpe_params->data);
+		break;
+
+	case MSM_CAM_V4L2_IOCTL_CFG_VPE: {
+		vpe_cmd = (struct msm_vpe_cfg_cmd *)arg;
+		rc = msm_vpe_process_vpe_cmd(vpe_cmd);
+		if (rc < 0) {
+			pr_err("%s Error processing VPE cmd %d ",
+				__func__, vpe_cmd->cmd_type);
 			break;
 		}
-		case VPE_CMD_ENABLE: {
-			struct msm_vpe_clock_rate *clk_rate = cmd->value;
-			int turbo_mode = (int)clk_rate->rate;
-			rc = turbo_mode ?
-				vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
-				vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
-			break;
+		break;
 		}
-		case VPE_CMD_DISABLE:
-			rc = vpe_disable();
-			break;
-		case VPE_CMD_INPUT_PLANE_UPDATE:
-		case VPE_CMD_FLUSH:
-		default:
-			break;
+
+	case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: {
+		struct msm_device_queue *queue = &vpe_ctrl->eventData_q;
+		struct msm_queue_cmd *event_qcmd;
+		struct msm_mctl_pp_event_info pp_event_info;
+		struct msm_mctl_pp_frame_info *pp_frame_info;
+		struct msm_camera_v4l2_ioctl_t *v4l2_ioctl = arg;
+
+		event_qcmd = msm_dequeue(queue, list_eventdata);
+		if (!event_qcmd) {
+			pr_err("%s No events in the queue", __func__);
+			return -EFAULT;
 		}
-		CDBG("%s: end, id = %d, rc = %d", __func__, cmd->id, rc);
+		pp_frame_info = event_qcmd->command;
+		pp_event_info.event = MCTL_PP_EVENT_CMD_ACK;
+		pp_event_info.ack.cmd = pp_frame_info->user_cmd;
+		pp_event_info.ack.status = 0;
+		pp_event_info.ack.cookie = pp_frame_info->pp_frame_cmd.cookie;
+		D("%s Sending payload %d %d %d", __func__,
+			pp_event_info.ack.cmd, pp_event_info.ack.status,
+			pp_event_info.ack.cookie);
+		if (copy_to_user((void __user *)v4l2_ioctl->ioctl_ptr,
+			&pp_event_info,
+			sizeof(struct msm_mctl_pp_event_info)))
+			pr_err("%s EVENTPAYLOAD Copy to user failed ",
+				__func__);
+		kfree(pp_frame_info);
+		kfree(event_qcmd);
+		break;
+		}
+
+	default:
+		break;
 	}
 	return rc;
 }
 
+int msm_vpe_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub)
+{
+	D("%s E\n", __func__);
+	return v4l2_event_subscribe(fh, sub, VPE_SUBDEV_MAX_EVENTS);
+}
+
+int msm_vpe_subdev_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub)
+{
+	D("%s E\n", __func__);
+	return v4l2_event_unsubscribe(fh, sub);
+}
+
 static const struct v4l2_subdev_core_ops msm_vpe_subdev_core_ops = {
 	.ioctl = msm_vpe_subdev_ioctl,
+	.subscribe_event = msm_vpe_subdev_subscribe_event,
+	.unsubscribe_event = msm_vpe_subdev_unsubscribe_event,
 };
 
 static const struct v4l2_subdev_ops msm_vpe_subdev_ops = {
 	.core = &msm_vpe_subdev_core_ops,
 };
 
-static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops;
+static int msm_vpe_subdev_open(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh)
+{
+	struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
+	/* Only one client of VPE allowed. */
+	if (atomic_read(&vpe_ctrl->active) != 0) {
+		pr_err("%s already opened\n", __func__);
+		return -EINVAL;
+	}
 
-static int __devinit vpe_probe(struct platform_device *pdev)
+	D("%s E ", __func__);
+	atomic_inc(&vpe_ctrl->active);
+	return 0;
+}
+
+static int msm_vpe_subdev_close(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh)
+{
+	struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
+	if (atomic_read(&vpe_ctrl->active) == 0) {
+		pr_err("%s already closed\n", __func__);
+		return -EINVAL;
+	}
+
+	D("%s E ", __func__);
+	/* Drain the payload queue. */
+	msm_queue_drain(&vpe_ctrl->eventData_q, list_eventdata);
+	atomic_dec(&vpe_ctrl->active);
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops = {
+	.open = msm_vpe_subdev_open,
+	.close = msm_vpe_subdev_close,
+};
+
+static int __devinit msm_vpe_probe(struct platform_device *pdev)
 {
 	int rc = 0;
-	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	D("%s: device id = %d\n", __func__, pdev->id);
 	vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
 	if (!vpe_ctrl) {
-		pr_err("%s: no enough memory\n", __func__);
+		pr_err("%s: not enough memory\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -734,6 +984,13 @@
 	snprintf(vpe_ctrl->subdev.name, sizeof(vpe_ctrl->subdev.name), "vpe");
 	platform_set_drvdata(pdev, &vpe_ctrl->subdev);
 
+	media_entity_init(&vpe_ctrl->subdev.entity, 0, NULL, 0);
+	vpe_ctrl->subdev.entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+	vpe_ctrl->subdev.entity.group_id = VPE_DEV;
+	vpe_ctrl->subdev.entity.name = vpe_ctrl->subdev.name;
+
+	vpe_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
+
 	vpe_ctrl->vpemem = platform_get_resource_byname(pdev,
 					IORESOURCE_MEM, "vpe");
 	if (!vpe_ctrl->vpemem) {
@@ -769,17 +1026,22 @@
 
 	disable_irq(vpe_ctrl->vpeirq->start);
 
+	atomic_set(&vpe_ctrl->active, 0);
 	vpe_ctrl->pdev = pdev;
 	msm_cam_register_subdev_node(&vpe_ctrl->subdev, VPE_DEV, pdev->id);
+	vpe_ctrl->subdev.entity.revision = vpe_ctrl->subdev.devnode->num;
+	msm_queue_init(&vpe_ctrl->eventData_q, "ackevents");
+
 	return 0;
 
 vpe_no_resource:
+	pr_err("%s: VPE Probe failed.\n", __func__);
 	kfree(vpe_ctrl);
 	return 0;
 }
 
-struct platform_driver vpe_driver = {
-	.probe = vpe_probe,
+struct platform_driver msm_vpe_driver = {
+	.probe = msm_vpe_probe,
 	.driver = {
 		.name = MSM_VPE_DRV_NAME,
 		.owner = THIS_MODULE,
@@ -788,9 +1050,15 @@
 
 static int __init msm_vpe_init_module(void)
 {
-	return platform_driver_register(&vpe_driver);
+	return platform_driver_register(&msm_vpe_driver);
+}
+
+static void __exit msm_vpe_exit_module(void)
+{
+	platform_driver_unregister(&msm_vpe_driver);
 }
 
 module_init(msm_vpe_init_module);
+module_exit(msm_vpe_exit_module);
 MODULE_DESCRIPTION("VPE driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 0d14626..5cf0309 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -79,8 +79,8 @@
 #define VPE_DEFAULT_SCALE_CONFIG      0x3c
 
 #define VPE_NORMAL_MODE_CLOCK_RATE   150000000
-#define VPE_TURBO_MODE_CLOCK_RATE   200000000
-
+#define VPE_TURBO_MODE_CLOCK_RATE    200000000
+#define VPE_SUBDEV_MAX_EVENTS        30
 
 /**************************************************/
 /*********** End of command id ********************/
@@ -119,6 +119,8 @@
 	struct regulator *fs_vpe;
 	struct clk	*vpe_clk[2];
 	struct msm_mctl_pp_frame_info *pp_frame_info;
+	atomic_t active;
+	struct msm_device_queue eventData_q; /*V4L2 Event Payload Queue*/
 };
 
 /*
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 5b9eb31..76981b0 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -770,8 +770,7 @@
 	struct v4l2_control *ctrl)
 {
 	int rc = -1, i = 0;
-	struct msm_sensor_ctrl_t *s_ctrl =
-		(struct msm_sensor_ctrl_t *) sd->dev_priv;
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
 	struct msm_sensor_v4l2_ctrl_info_t *v4l2_ctrl =
 		s_ctrl->msm_sensor_v4l2_ctrl_info;
 
@@ -779,10 +778,10 @@
 	CDBG("%d\n", ctrl->id);
 	if (v4l2_ctrl == NULL)
 		return rc;
-
 	for (i = 0; i < s_ctrl->num_v4l2_ctrl; i++) {
 		if (v4l2_ctrl[i].ctrl_id == ctrl->id) {
 			if (v4l2_ctrl[i].s_v4l2_ctrl != NULL) {
+				CDBG("\n calling msm_sensor_s_ctrl_by_enum\n");
 				rc = v4l2_ctrl[i].s_v4l2_ctrl(
 					s_ctrl,
 					&s_ctrl->msm_sensor_v4l2_ctrl_info[i],
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index c5fbea2..7ade827 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -84,6 +84,7 @@
 	struct msm_camera_i2c_conf_array *init_settings;
 	uint8_t init_size;
 	struct msm_camera_i2c_conf_array *mode_settings;
+	struct msm_camera_i2c_conf_array *no_effect_settings;
 	struct msm_sensor_output_info_t *output_settings;
 	uint8_t num_conf;
 };
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index aac2f2b..9dfbf8d 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -458,7 +458,7 @@
 	CDBG(KERN_ERR "snapshot exposure seting 0x%x, 0x%x, %d"
 		, gain, line, line);
 	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
-	if (line > 1964 && line <= 1968) {
+	if (line > 1964) {
 		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 			s_ctrl->sensor_output_reg_addr->frame_length_lines,
 			(uint8_t)((line+4) >> 8),
@@ -556,10 +556,10 @@
 static int32_t ov5647_write_prev_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
 						uint16_t gain, uint32_t line)
 {
-
-	static uint16_t max_line = 984;
 	u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
 	uint8_t gain_lsb, gain_hsb;
+	uint32_t fl_lines = s_ctrl->curr_frame_length_lines;
+	uint8_t offset = s_ctrl->sensor_exp_gain_info->vert_offset;
 
 	CDBG(KERN_ERR "preview exposure setting 0x%x, 0x%x, %d",
 		 gain, line, line);
@@ -567,33 +567,23 @@
 	gain_lsb = (uint8_t) (gain);
 	gain_hsb = (uint8_t)((gain & 0x300)>>8);
 
+	fl_lines = (fl_lines * s_ctrl->fps_divider) / Q10;
+
 	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
 
 	/* adjust frame rate */
-	if (line > 980 && line <= 984) {
-		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+	if (line > (fl_lines - offset))
+		fl_lines = line + offset;
+
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 		s_ctrl->sensor_output_reg_addr->frame_length_lines,
-		(uint8_t)((line+4) >> 8),
+		(uint8_t)(fl_lines >> 8),
 		MSM_CAMERA_I2C_BYTE_DATA);
 
-		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 		s_ctrl->sensor_output_reg_addr->frame_length_lines + 1,
-		(uint8_t)((line+4) & 0x00FF),
+		(uint8_t)(fl_lines & 0x00FF),
 		MSM_CAMERA_I2C_BYTE_DATA);
-		max_line = line + 4;
-	} else if (max_line > 984) {
-
-		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
-		s_ctrl->sensor_output_reg_addr->frame_length_lines,
-		(uint8_t)(984 >> 8),
-		MSM_CAMERA_I2C_BYTE_DATA);
-
-		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
-		s_ctrl->sensor_output_reg_addr->frame_length_lines + 1 ,
-		(uint8_t)(984 & 0x00FF),
-		MSM_CAMERA_I2C_BYTE_DATA);
-		max_line = 984;
-	}
 
 	line = line<<4;
 	/* ov5647 need this operation */
diff --git a/drivers/media/video/msm/sensors/ov7692_v4l2.c b/drivers/media/video/msm/sensors/ov7692_v4l2.c
index e7970d5..8c94e3b 100644
--- a/drivers/media/video/msm/sensors/ov7692_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov7692_v4l2.c
@@ -17,6 +17,10 @@
 DEFINE_MUTEX(ov7692_mut);
 static struct msm_sensor_ctrl_t ov7692_s_ctrl;
 
+static int effect_value = CAMERA_EFFECT_OFF;
+static unsigned int SAT_U = 0x80; /* DEFAULT SATURATION VALUES*/
+static unsigned int SAT_V = 0x80; /* DEFAULT SATURATION VALUES*/
+
 static struct msm_camera_i2c_reg_conf ov7692_start_settings[] = {
 	{0x0e, 0x00},
 };
@@ -168,6 +172,58 @@
 	ARRAY_SIZE(ov7692_full_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
 };
 
+static struct msm_camera_i2c_reg_conf ov7692_saturation[][4] = {
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x00, 0x00}, {0xd9, 0x00, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL0*/
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x10, 0x00}, {0xd9, 0x10, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL1*/
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x20, 0x00}, {0xd9, 0x20, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL2*/
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x30, 0x00}, {0xd9, 0x30, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL3*/
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x40, 0x00}, {0xd9, 0x40, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL4*/
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x50, 0x00}, {0xd9, 0x50, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL5*/
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x60, 0x00}, {0xd9, 0x60, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL6*/
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x70, 0x00}, {0xd9, 0x70, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL7*/
+	{{0x81, 0x33, 0xCC}, {0xd8, 0x80, 0x00}, {0xd9, 0x80, 0x00},
+		{0xd2, 0x02, 0x00},},	/* SATURATION LEVEL8*/
+};
+static struct msm_camera_i2c_conf_array ov7692_saturation_confs[][1] = {
+	{{ov7692_saturation[0], ARRAY_SIZE(ov7692_saturation[0]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_saturation[1], ARRAY_SIZE(ov7692_saturation[1]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_saturation[2], ARRAY_SIZE(ov7692_saturation[2]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_saturation[3], ARRAY_SIZE(ov7692_saturation[3]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_saturation[4], ARRAY_SIZE(ov7692_saturation[4]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_saturation[5], ARRAY_SIZE(ov7692_saturation[5]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_saturation[6], ARRAY_SIZE(ov7692_saturation[6]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_saturation[7], ARRAY_SIZE(ov7692_saturation[7]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_saturation[8], ARRAY_SIZE(ov7692_saturation[8]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+};
+
+static int ov7692_saturation_enum_map[] = {
+	MSM_V4L2_SATURATION_L0,
+	MSM_V4L2_SATURATION_L1,
+	MSM_V4L2_SATURATION_L2,
+	MSM_V4L2_SATURATION_L3,
+	MSM_V4L2_SATURATION_L4,
+	MSM_V4L2_SATURATION_L5,
+	MSM_V4L2_SATURATION_L6,
+	MSM_V4L2_SATURATION_L7,
+	MSM_V4L2_SATURATION_L8,
+};
 static struct msm_sensor_output_info_t ov7692_dimensions[] = {
 	{
 		.x_output = 0x280,
@@ -180,6 +236,562 @@
 	},
 };
 
+static struct msm_camera_i2c_enum_conf_array ov7692_saturation_enum_confs = {
+	.conf = &ov7692_saturation_confs[0][0],
+	.conf_enum = ov7692_saturation_enum_map,
+	.num_enum = ARRAY_SIZE(ov7692_saturation_enum_map),
+	.num_index = ARRAY_SIZE(ov7692_saturation_confs),
+	.num_conf = ARRAY_SIZE(ov7692_saturation_confs[0]),
+	.data_type = MSM_CAMERA_I2C_BYTE_DATA,
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_contrast[][16] = {
+	{{0xb2, 0x29}, {0xa3, 0x55}, {0xa4, 0x5b}, {0xa5, 0x67}, {0xa6, 0x7e},
+		{0xa7, 0x89}, {0xa8, 0x93}, {0xa9, 0x9c}, {0xaa, 0xa4},
+		{0xab, 0xac}, {0xac, 0xb3}, {0xad, 0xbe}, {0xae, 0xc7},
+		{0xaf, 0xd5}, {0xb0, 0xdd}, {0xb1, 0xe1},},	/* CONTRAST L0*/
+	{{0xb2, 0x20}, {0xa3, 0x43}, {0xa4, 0x4a}, {0xa5, 0x58}, {0xa6, 0x73},
+		{0xa7, 0x80}, {0xa8, 0x8b}, {0xa9, 0x96}, {0xaa, 0x9f},
+		{0xab, 0xa8}, {0xac, 0xb1}, {0xad, 0xbe}, {0xae, 0xc9},
+		{0xaf, 0xd8}, {0xb0, 0xe2}, {0xb1, 0xe8},},	/* CONTRAST L1*/
+	{{0xb2, 0x18}, {0xa3, 0x31}, {0xa4, 0x39}, {0xa5, 0x4a}, {0xa6, 0x68},
+		{0xa7, 0x77}, {0xa8, 0x84}, {0xa9, 0x90}, {0xaa, 0x9b},
+		{0xab, 0xa5}, {0xac, 0xaf}, {0xad, 0xbe}, {0xae, 0xca},
+		{0xaf, 0xdc}, {0xb0, 0xe7}, {0xb1, 0xee},},	/* CONTRAST L2*/
+	{{0xb2, 0x10}, {0xa3, 0x1f}, {0xa4, 0x28}, {0xa5, 0x3b}, {0xa6, 0x5d},
+		{0xa7, 0x6e}, {0xa8, 0x7d}, {0xa9, 0x8a}, {0xaa, 0x96},
+		{0xab, 0xa2}, {0xac, 0xad}, {0xad, 0xbe}, {0xae, 0xcc},
+		{0xaf, 0xe0}, {0xb0, 0xed}, {0xb1, 0xf4},},	/* CONTRAST L3*/
+	 {{0xb2, 0x6}, {0xa3, 0xb}, {0xa4, 0x15}, {0xa5, 0x2a}, {0xa6, 0x51},
+		{0xa7, 0x63}, {0xa8, 0x74}, {0xa9, 0x83}, {0xaa, 0x91},
+		{0xab, 0x9e}, {0xac, 0xaa}, {0xad, 0xbe}, {0xae, 0xce},
+		{0xaf, 0xe5}, {0xb0, 0xf3}, {0xb1, 0xfb},},	/* CONTRAST L4*/
+	{{0xb2, 0xc}, {0xa3, 0x4}, {0xa4, 0xc}, {0xa5, 0x1f}, {0xa6, 0x45},
+		{0xa7, 0x58}, {0xa8, 0x6b}, {0xa9, 0x7c}, {0xaa, 0x8d},
+		{0xab, 0x9d}, {0xac, 0xac}, {0xad, 0xc3}, {0xae, 0xd2},
+		{0xaf, 0xe8}, {0xb0, 0xf2}, {0xb1, 0xf7},},	/* CONTRAST L5*/
+	{{0xb2, 0x1}, {0xa3, 0x2}, {0xa4, 0x9}, {0xa5, 0x1a}, {0xa6, 0x3e},
+		{0xa7, 0x4a}, {0xa8, 0x59}, {0xa9, 0x6a}, {0xaa, 0x79},
+		{0xab, 0x8e}, {0xac, 0xa4}, {0xad, 0xc1}, {0xae, 0xdb},
+		{0xaf, 0xf4}, {0xb0, 0xff}, {0xb1, 0xff},},	/* CONTRAST L6*/
+	{{0xb2, 0xc}, {0xa3, 0x4}, {0xa4, 0x8}, {0xa5, 0x17}, {0xa6, 0x27},
+		{0xa7, 0x3d}, {0xa8, 0x54}, {0xa9, 0x60}, {0xaa, 0x77},
+		{0xab, 0x85}, {0xac, 0xa4}, {0xad, 0xc6}, {0xae, 0xd2},
+		{0xaf, 0xe9}, {0xb0, 0xf0}, {0xb1, 0xf7},},	/* CONTRAST L7*/
+	{{0xb2, 0x1}, {0xa3, 0x4}, {0xa4, 0x4}, {0xa5, 0x7}, {0xa6, 0xb},
+		{0xa7, 0x17}, {0xa8, 0x2a}, {0xa9, 0x41}, {0xaa, 0x59},
+		{0xab, 0x6b}, {0xac, 0x8b}, {0xad, 0xb1}, {0xae, 0xd2},
+		{0xaf, 0xea}, {0xb0, 0xf4}, {0xb1, 0xff},},	/* CONTRAST L8*/
+};
+
+static struct msm_camera_i2c_conf_array ov7692_contrast_confs[][1] = {
+	{{ov7692_contrast[0], ARRAY_SIZE(ov7692_contrast[0]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_contrast[1], ARRAY_SIZE(ov7692_contrast[1]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_contrast[2], ARRAY_SIZE(ov7692_contrast[2]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_contrast[3], ARRAY_SIZE(ov7692_contrast[3]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_contrast[4], ARRAY_SIZE(ov7692_contrast[4]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_contrast[5], ARRAY_SIZE(ov7692_contrast[5]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_contrast[6], ARRAY_SIZE(ov7692_contrast[6]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_contrast[7], ARRAY_SIZE(ov7692_contrast[7]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_contrast[8], ARRAY_SIZE(ov7692_contrast[8]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+};
+
+
+static int ov7692_contrast_enum_map[] = {
+	MSM_V4L2_CONTRAST_L0,
+	MSM_V4L2_CONTRAST_L1,
+	MSM_V4L2_CONTRAST_L2,
+	MSM_V4L2_CONTRAST_L3,
+	MSM_V4L2_CONTRAST_L4,
+	MSM_V4L2_CONTRAST_L5,
+	MSM_V4L2_CONTRAST_L6,
+	MSM_V4L2_CONTRAST_L7,
+	MSM_V4L2_CONTRAST_L8,
+};
+
+static struct msm_camera_i2c_enum_conf_array ov7692_contrast_enum_confs = {
+	.conf = &ov7692_contrast_confs[0][0],
+	.conf_enum = ov7692_contrast_enum_map,
+	.num_enum = ARRAY_SIZE(ov7692_contrast_enum_map),
+	.num_index = ARRAY_SIZE(ov7692_contrast_confs),
+	.num_conf = ARRAY_SIZE(ov7692_contrast_confs[0]),
+	.data_type = MSM_CAMERA_I2C_BYTE_DATA,
+};
+static struct msm_camera_i2c_reg_conf ov7692_sharpness[][2] = {
+	{{0xb4, 0x20, 0xDF}, {0xb6, 0x00, 0xE0},},    /* SHARPNESS LEVEL 0*/
+	{{0xb4, 0x20, 0xDF}, {0xb6, 0x01, 0xE0},},    /* SHARPNESS LEVEL 1*/
+	{{0xb4, 0x00, 0xDF}, {0xb6, 0x00, 0xE0},},    /* SHARPNESS LEVEL 2*/
+	{{0xb4, 0x20, 0xDF}, {0xb6, 0x66, 0xE0},},    /* SHARPNESS LEVEL 3*/
+	{{0xb4, 0x20, 0xDF}, {0xb6, 0x99, 0xE0},},    /* SHARPNESS LEVEL 4*/
+	{{0xb4, 0x20, 0xDF}, {0xb6, 0xcc, 0xE0},},    /* SHARPNESS LEVEL 5*/
+};
+
+static struct msm_camera_i2c_conf_array ov7692_sharpness_confs[][1] = {
+	{{ov7692_sharpness[0], ARRAY_SIZE(ov7692_sharpness[0]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_sharpness[1], ARRAY_SIZE(ov7692_sharpness[1]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_sharpness[2], ARRAY_SIZE(ov7692_sharpness[2]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_sharpness[3], ARRAY_SIZE(ov7692_sharpness[3]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_sharpness[4], ARRAY_SIZE(ov7692_sharpness[4]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_sharpness[5], ARRAY_SIZE(ov7692_sharpness[5]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+};
+
+static int ov7692_sharpness_enum_map[] = {
+	MSM_V4L2_SHARPNESS_L0,
+	MSM_V4L2_SHARPNESS_L1,
+	MSM_V4L2_SHARPNESS_L2,
+	MSM_V4L2_SHARPNESS_L3,
+	MSM_V4L2_SHARPNESS_L4,
+	MSM_V4L2_SHARPNESS_L5,
+};
+
+static struct msm_camera_i2c_enum_conf_array ov7692_sharpness_enum_confs = {
+	.conf = &ov7692_sharpness_confs[0][0],
+	.conf_enum = ov7692_sharpness_enum_map,
+	.num_enum = ARRAY_SIZE(ov7692_sharpness_enum_map),
+	.num_index = ARRAY_SIZE(ov7692_sharpness_confs),
+	.num_conf = ARRAY_SIZE(ov7692_sharpness_confs[0]),
+	.data_type = MSM_CAMERA_I2C_BYTE_DATA,
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_exposure[][3] = {
+	{{0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa2},}, /*EXPOSURECOMPENSATIONN2*/
+	{{0x24, 0x70}, {0x25, 0x60}, {0x26, 0xa2},}, /*EXPOSURECOMPENSATIONN1*/
+	{{0x24, 0x86}, {0x25, 0x76}, {0x26, 0xb3},}, /*EXPOSURECOMPENSATIOND*/
+	{{0x24, 0xa8}, {0x25, 0xa0}, {0x26, 0xc4},}, /*EXPOSURECOMPENSATIONp1*/
+	{{0x24, 0xc0}, {0x25, 0xb8}, {0x26, 0xe6},}, /*EXPOSURECOMPENSATIONP2*/
+};
+
+static struct msm_camera_i2c_conf_array ov7692_exposure_confs[][1] = {
+	{{ov7692_exposure[0], ARRAY_SIZE(ov7692_exposure[0]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_exposure[1], ARRAY_SIZE(ov7692_exposure[1]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_exposure[2], ARRAY_SIZE(ov7692_exposure[2]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_exposure[3], ARRAY_SIZE(ov7692_exposure[3]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_exposure[4], ARRAY_SIZE(ov7692_exposure[4]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+};
+
+static int ov7692_exposure_enum_map[] = {
+	MSM_V4L2_EXPOSURE_N2,
+	MSM_V4L2_EXPOSURE_N1,
+	MSM_V4L2_EXPOSURE_D,
+	MSM_V4L2_EXPOSURE_P1,
+	MSM_V4L2_EXPOSURE_P2,
+};
+
+static struct msm_camera_i2c_enum_conf_array ov7692_exposure_enum_confs = {
+	.conf = &ov7692_exposure_confs[0][0],
+	.conf_enum = ov7692_exposure_enum_map,
+	.num_enum = ARRAY_SIZE(ov7692_exposure_enum_map),
+	.num_index = ARRAY_SIZE(ov7692_exposure_confs),
+	.num_conf = ARRAY_SIZE(ov7692_exposure_confs[0]),
+	.data_type = MSM_CAMERA_I2C_BYTE_DATA,
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_iso[][1] = {
+	{{0x14, 0x20, 0x8F},},   /*ISO_AUTO*/
+	{{0x14, 0x20, 0x8F},},   /*ISO_DEBLUR*/
+	{{0x14, 0x00, 0x8F},},   /*ISO_100*/
+	{{0x14, 0x10, 0x8F},},   /*ISO_200*/
+	{{0x14, 0x20, 0x8F},},   /*ISO_400*/
+	{{0x14, 0x30, 0x8F},},   /*ISO_800*/
+	{{0x14, 0x40, 0x8F},},   /*ISO_1600*/
+};
+
+
+static struct msm_camera_i2c_conf_array ov7692_iso_confs[][1] = {
+	{{ov7692_iso[0], ARRAY_SIZE(ov7692_iso[0]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_iso[1], ARRAY_SIZE(ov7692_iso[1]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_iso[2], ARRAY_SIZE(ov7692_iso[2]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_iso[3], ARRAY_SIZE(ov7692_iso[3]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_iso[4], ARRAY_SIZE(ov7692_iso[4]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_iso[5], ARRAY_SIZE(ov7692_iso[5]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+};
+
+static int ov7692_iso_enum_map[] = {
+	MSM_V4L2_ISO_AUTO ,
+	MSM_V4L2_ISO_DEBLUR,
+	MSM_V4L2_ISO_100,
+	MSM_V4L2_ISO_200,
+	MSM_V4L2_ISO_400,
+	MSM_V4L2_ISO_800,
+	MSM_V4L2_ISO_1600,
+};
+
+
+static struct msm_camera_i2c_enum_conf_array ov7692_iso_enum_confs = {
+	.conf = &ov7692_iso_confs[0][0],
+	.conf_enum = ov7692_iso_enum_map,
+	.num_enum = ARRAY_SIZE(ov7692_iso_enum_map),
+	.num_index = ARRAY_SIZE(ov7692_iso_confs),
+	.num_conf = ARRAY_SIZE(ov7692_iso_confs[0]),
+	.data_type = MSM_CAMERA_I2C_BYTE_DATA,
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_no_effect[] = {
+	{0x81, 0x00, 0xDF},
+	{0x28, 0x00,},
+	{0xd2, 0x00,},
+	{0xda, 0x80,},
+	{0xdb, 0x80,},
+};
+
+static struct msm_camera_i2c_conf_array ov7692_no_effect_confs[] = {
+	{&ov7692_no_effect[0],
+	ARRAY_SIZE(ov7692_no_effect), 0,
+	MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_special_effect[][5] = {
+	{{0x81, 0x20, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,}, {0xda, 0x80,},
+		{0xdb, 0x80,},},	/*for special effect OFF*/
+	{{0x81, 0x20, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,}, {0xda, 0x80,},
+		{0xdb, 0x80,},},	/*for special effect MONO*/
+	{{0x81, 0x20, 0xDF}, {0x28, 0x80,}, {0xd2, 0x40,}, {0xda, 0x80,},
+		{0xdb, 0x80,},},	/*for special efefct Negative*/
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/*Solarize is not supported by sensor*/
+	{{0x81, 0x20, 0xDF}, {0x28, 0x00,}, {0xd2, 0x18,}, {0xda, 0x40,},
+		{0xdb, 0xa0,},},	/*for sepia*/
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/* Posteraize not supported */
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/* White board not supported*/
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/*Blackboard not supported*/
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/*Aqua not supported*/
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/*Emboss not supported */
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/*sketch not supported*/
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/*Neon not supported*/
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},		/*MAX value*/
+};
+
+static struct msm_camera_i2c_conf_array ov7692_special_effect_confs[][1] = {
+	{{ov7692_special_effect[0],  ARRAY_SIZE(ov7692_special_effect[0]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[1],  ARRAY_SIZE(ov7692_special_effect[1]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[2],  ARRAY_SIZE(ov7692_special_effect[2]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[3],  ARRAY_SIZE(ov7692_special_effect[3]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[4],  ARRAY_SIZE(ov7692_special_effect[4]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[5],  ARRAY_SIZE(ov7692_special_effect[5]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[6],  ARRAY_SIZE(ov7692_special_effect[6]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[7],  ARRAY_SIZE(ov7692_special_effect[7]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[8],  ARRAY_SIZE(ov7692_special_effect[8]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[9],  ARRAY_SIZE(ov7692_special_effect[9]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[10], ARRAY_SIZE(ov7692_special_effect[10]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[11], ARRAY_SIZE(ov7692_special_effect[11]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_special_effect[12], ARRAY_SIZE(ov7692_special_effect[12]), 0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+};
+
+static int ov7692_special_effect_enum_map[] = {
+	MSM_V4L2_EFFECT_OFF,
+	MSM_V4L2_EFFECT_MONO,
+	MSM_V4L2_EFFECT_NEGATIVE,
+	MSM_V4L2_EFFECT_SOLARIZE,
+	MSM_V4L2_EFFECT_SEPIA,
+	MSM_V4L2_EFFECT_POSTERAIZE,
+	MSM_V4L2_EFFECT_WHITEBOARD,
+	MSM_V4L2_EFFECT_BLACKBOARD,
+	MSM_V4L2_EFFECT_AQUA,
+	MSM_V4L2_EFFECT_EMBOSS,
+	MSM_V4L2_EFFECT_SKETCH,
+	MSM_V4L2_EFFECT_NEON,
+	MSM_V4L2_EFFECT_MAX,
+};
+
+static struct msm_camera_i2c_enum_conf_array
+		 ov7692_special_effect_enum_confs = {
+	.conf = &ov7692_special_effect_confs[0][0],
+	.conf_enum = ov7692_special_effect_enum_map,
+	.num_enum = ARRAY_SIZE(ov7692_special_effect_enum_map),
+	.num_index = ARRAY_SIZE(ov7692_special_effect_confs),
+	.num_conf = ARRAY_SIZE(ov7692_special_effect_confs[0]),
+	.data_type = MSM_CAMERA_I2C_BYTE_DATA,
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_antibanding[][2] = {
+	{{0x13, 0x20, 0xDF}, {0x14, 0x16, 0xE8},},   /*ANTIBANDING 60HZ*/
+	{{0x13, 0x20, 0xDF}, {0x14, 0x17, 0xE8},},   /*ANTIBANDING 50HZ*/
+	{{0x13, 0x20, 0xDF}, {0x14, 0x14, 0xE8},},   /* ANTIBANDING AUTO*/
+};
+
+
+static struct msm_camera_i2c_conf_array ov7692_antibanding_confs[][1] = {
+	{{ov7692_antibanding[0], ARRAY_SIZE(ov7692_antibanding[0]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_antibanding[1], ARRAY_SIZE(ov7692_antibanding[1]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_antibanding[2], ARRAY_SIZE(ov7692_antibanding[2]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+};
+
+static int ov7692_antibanding_enum_map[] = {
+	MSM_V4L2_POWER_LINE_60HZ,
+	MSM_V4L2_POWER_LINE_50HZ,
+	MSM_V4L2_POWER_LINE_AUTO,
+};
+
+
+static struct msm_camera_i2c_enum_conf_array ov7692_antibanding_enum_confs = {
+	.conf = &ov7692_antibanding_confs[0][0],
+	.conf_enum = ov7692_antibanding_enum_map,
+	.num_enum = ARRAY_SIZE(ov7692_antibanding_enum_map),
+	.num_index = ARRAY_SIZE(ov7692_antibanding_confs),
+	.num_conf = ARRAY_SIZE(ov7692_antibanding_confs[0]),
+	.data_type = MSM_CAMERA_I2C_BYTE_DATA,
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_wb_oem[][4] = {
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},/*WHITEBALNACE OFF*/
+	{{0x13, 0xf7}, {0x15, 0x00},},		/*WHITEBALNACE AUTO*/
+	{{0x13, 0xf5}, {0x01, 0x56}, {0x02, 0x50},
+		{0x15, 0x00},},	/*WHITEBALNACE CUSTOM*/
+	{{0x13, 0xf5}, {0x01, 0x66}, {0x02, 0x40},
+		{0x15, 0x00},},	/*INCANDISCENT*/
+	{{-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
+		{-1, -1, -1},},	/*FLOURESECT NOT SUPPORTED */
+	{{0x13, 0xf5}, {0x01, 0x43}, {0x02, 0x5d},
+		{0x15, 0x00},},	/*DAYLIGHT*/
+	{{0x13, 0xf5}, {0x01, 0x48}, {0x02, 0x63},
+		{0x15, 0x00},},	/*CLOUDY*/
+};
+
+static struct msm_camera_i2c_conf_array ov7692_wb_oem_confs[][1] = {
+	{{ov7692_wb_oem[0], ARRAY_SIZE(ov7692_wb_oem[0]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_wb_oem[1], ARRAY_SIZE(ov7692_wb_oem[1]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_wb_oem[2], ARRAY_SIZE(ov7692_wb_oem[2]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_wb_oem[3], ARRAY_SIZE(ov7692_wb_oem[3]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_wb_oem[4], ARRAY_SIZE(ov7692_wb_oem[4]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_wb_oem[5], ARRAY_SIZE(ov7692_wb_oem[5]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+	{{ov7692_wb_oem[6], ARRAY_SIZE(ov7692_wb_oem[6]),  0,
+		MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA},},
+};
+
+static int ov7692_wb_oem_enum_map[] = {
+	MSM_V4L2_WB_OFF,
+	MSM_V4L2_WB_AUTO ,
+	MSM_V4L2_WB_CUSTOM,
+	MSM_V4L2_WB_INCANDESCENT,
+	MSM_V4L2_WB_FLUORESCENT,
+	MSM_V4L2_WB_DAYLIGHT,
+	MSM_V4L2_WB_CLOUDY_DAYLIGHT,
+};
+
+static struct msm_camera_i2c_enum_conf_array ov7692_wb_oem_enum_confs = {
+	.conf = &ov7692_wb_oem_confs[0][0],
+	.conf_enum = ov7692_wb_oem_enum_map,
+	.num_enum = ARRAY_SIZE(ov7692_wb_oem_enum_map),
+	.num_index = ARRAY_SIZE(ov7692_wb_oem_confs),
+	.num_conf = ARRAY_SIZE(ov7692_wb_oem_confs[0]),
+	.data_type = MSM_CAMERA_I2C_BYTE_DATA,
+};
+
+
+int ov7692_saturation_msm_sensor_s_ctrl_by_enum(
+		struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+	int rc = 0;
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		rc = msm_sensor_write_enum_conf_array(
+			s_ctrl->sensor_i2c_client,
+			ctrl_info->enum_cfg_settings, value);
+	}
+	if (value <= MSM_V4L2_SATURATION_L8)
+		SAT_U = SAT_V = value * 0x10;
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+
+int ov7692_contrast_msm_sensor_s_ctrl_by_enum(
+		struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+	int rc = 0;
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		rc = msm_sensor_write_enum_conf_array(
+			s_ctrl->sensor_i2c_client,
+			ctrl_info->enum_cfg_settings, value);
+	}
+	return rc;
+}
+
+int ov7692_sharpness_msm_sensor_s_ctrl_by_enum(
+		struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+	int rc = 0;
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		rc = msm_sensor_write_enum_conf_array(
+			s_ctrl->sensor_i2c_client,
+			ctrl_info->enum_cfg_settings, value);
+	}
+	return rc;
+}
+
+int ov7692_effect_msm_sensor_s_ctrl_by_enum(struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+	int rc = 0;
+	effect_value = value;
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		rc = msm_sensor_write_conf_array(
+			s_ctrl->sensor_i2c_client,
+			s_ctrl->msm_sensor_reg->no_effect_settings, 0);
+		if (rc < 0) {
+			CDBG("write faield\n");
+			return rc;
+		}
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client, 0xda, SAT_U,
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client, 0xdb, SAT_V,
+			MSM_CAMERA_I2C_BYTE_DATA);
+	} else {
+		rc = msm_sensor_write_enum_conf_array(
+			s_ctrl->sensor_i2c_client,
+			ctrl_info->enum_cfg_settings, value);
+	}
+	return rc;
+}
+
+int ov7692_antibanding_msm_sensor_s_ctrl_by_enum(
+		struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+	int rc = 0;
+		return rc;
+}
+
+int ov7692_msm_sensor_s_ctrl_by_enum(struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+	int rc = 0;
+	rc = msm_sensor_write_enum_conf_array(
+		s_ctrl->sensor_i2c_client,
+		ctrl_info->enum_cfg_settings, value);
+	if (rc < 0) {
+		CDBG("write faield\n");
+		return rc;
+	}
+	return rc;
+}
+
+struct msm_sensor_v4l2_ctrl_info_t ov7692_v4l2_ctrl_info[] = {
+	{
+		.ctrl_id = V4L2_CID_SATURATION,
+		.min = MSM_V4L2_SATURATION_L0,
+		.max = MSM_V4L2_SATURATION_L8,
+		.step = 1,
+		.enum_cfg_settings = &ov7692_saturation_enum_confs,
+		.s_v4l2_ctrl = ov7692_saturation_msm_sensor_s_ctrl_by_enum,
+	},
+	{
+		.ctrl_id = V4L2_CID_CONTRAST,
+		.min = MSM_V4L2_CONTRAST_L0,
+		.max = MSM_V4L2_CONTRAST_L8,
+		.step = 1,
+		.enum_cfg_settings = &ov7692_contrast_enum_confs,
+		.s_v4l2_ctrl = ov7692_contrast_msm_sensor_s_ctrl_by_enum,
+	},
+	{
+		.ctrl_id = V4L2_CID_SHARPNESS,
+		.min = MSM_V4L2_SHARPNESS_L0,
+		.max = MSM_V4L2_SHARPNESS_L5,
+		.step = 1,
+		.enum_cfg_settings = &ov7692_sharpness_enum_confs,
+		.s_v4l2_ctrl = ov7692_sharpness_msm_sensor_s_ctrl_by_enum,
+	},
+	{
+		.ctrl_id = V4L2_CID_EXPOSURE,
+		.min = MSM_V4L2_EXPOSURE_N2,
+		.max = MSM_V4L2_EXPOSURE_P2,
+		.step = 1,
+		.enum_cfg_settings = &ov7692_exposure_enum_confs,
+		.s_v4l2_ctrl = ov7692_msm_sensor_s_ctrl_by_enum,
+	},
+	{
+		.ctrl_id = MSM_V4L2_PID_ISO,
+		.min = MSM_V4L2_ISO_AUTO,
+		.max = MSM_V4L2_ISO_1600,
+		.step = 1,
+		.enum_cfg_settings = &ov7692_iso_enum_confs,
+		.s_v4l2_ctrl = ov7692_msm_sensor_s_ctrl_by_enum,
+	},
+	{
+		.ctrl_id = V4L2_CID_SPECIAL_EFFECT,
+		.min = MSM_V4L2_EFFECT_OFF,
+		.max = MSM_V4L2_EFFECT_NEGATIVE,
+		.step = 1,
+		.enum_cfg_settings = &ov7692_special_effect_enum_confs,
+		.s_v4l2_ctrl = ov7692_effect_msm_sensor_s_ctrl_by_enum,
+	},
+	{
+		.ctrl_id = V4L2_CID_POWER_LINE_FREQUENCY,
+		.min = MSM_V4L2_POWER_LINE_60HZ,
+		.max = MSM_V4L2_POWER_LINE_AUTO,
+		.step = 1,
+		.enum_cfg_settings = &ov7692_antibanding_enum_confs,
+		.s_v4l2_ctrl = ov7692_antibanding_msm_sensor_s_ctrl_by_enum,
+	},
+	{
+		.ctrl_id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+		.min = MSM_V4L2_WB_OFF,
+		.max = MSM_V4L2_WB_CLOUDY_DAYLIGHT,
+		.step = 1,
+		.enum_cfg_settings = &ov7692_wb_oem_enum_confs,
+		.s_v4l2_ctrl = ov7692_msm_sensor_s_ctrl_by_enum,
+	},
+
+};
 
 static struct msm_camera_csi_params ov7692_csi_params = {
 	.data_format = CSI_8BIT,
@@ -234,6 +846,8 @@
 }
 
 static struct v4l2_subdev_core_ops ov7692_subdev_core_ops = {
+	.s_ctrl = msm_sensor_v4l2_s_ctrl,
+	.queryctrl = msm_sensor_v4l2_query_ctrl,
 	.ioctl = msm_sensor_subdev_ioctl,
 	.s_power = msm_sensor_power,
 };
@@ -306,12 +920,15 @@
 	.init_settings = &ov7692_init_conf[0],
 	.init_size = ARRAY_SIZE(ov7692_init_conf),
 	.mode_settings = &ov7692_confs[0],
+	.no_effect_settings = &ov7692_no_effect_confs[0],
 	.output_settings = &ov7692_dimensions[0],
 	.num_conf = ARRAY_SIZE(ov7692_confs),
 };
 
 static struct msm_sensor_ctrl_t ov7692_s_ctrl = {
 	.msm_sensor_reg = &ov7692_regs,
+	.msm_sensor_v4l2_ctrl_info = ov7692_v4l2_ctrl_info,
+	.num_v4l2_ctrl = ARRAY_SIZE(ov7692_v4l2_ctrl_info),
 	.sensor_i2c_client = &ov7692_sensor_i2c_client,
 	.sensor_i2c_addr = 0x78,
 	.sensor_output_reg_addr = &ov7692_reg_addr,
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index debda88..1d7da0d 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -80,7 +80,7 @@
 	{0x0202, 0x06}, /* coarse_integration_time */
 	{0x0203, 0x00}, /* coarse_integration_time */
 	{0x0340, 0x09}, /* frame_length_lines */
-	{0x0341, 0x98}, /* frame_length_lines */
+	{0x0341, 0x6C}, /* frame_length_lines */
 	{0x0342, 0x11}, /* line_length_pck */
 	{0x0343, 0x80}, /* line_length_pck */
 	{0x0344, 0x00}, /* x_addr_start */
@@ -489,7 +489,7 @@
 		.x_output = 1984,
 		.y_output = 1508,
 		.line_length_pclk = 4480,
-		.frame_length_lines = 2456,
+		.frame_length_lines = 2412,
 		.vt_pixel_clk = 330000000,
 		.op_pixel_clk = 320000000,
 		.binning_factor = 1,
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 8d004f6..cb59737 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -34,7 +34,7 @@
 static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
 	unsigned int notification, void *arg);
 
-static void msm_queue_init(struct msm_device_queue *queue, const char *name)
+void msm_queue_init(struct msm_device_queue *queue, const char *name)
 {
 	D("%s\n", __func__);
 	spin_lock_init(&queue->lock);
@@ -45,7 +45,7 @@
 	init_waitqueue_head(&queue->wait);
 }
 
-static void msm_enqueue(struct msm_device_queue *queue,
+void msm_enqueue(struct msm_device_queue *queue,
 			struct list_head *entry)
 {
 	unsigned long flags;
@@ -62,7 +62,7 @@
 	spin_unlock_irqrestore(&queue->lock, flags);
 }
 
-static void msm_drain_eventq(struct msm_device_queue *queue)
+void msm_drain_eventq(struct msm_device_queue *queue)
 {
 	unsigned long flags;
 	struct msm_queue_cmd *qcmd;
@@ -560,55 +560,52 @@
 }
 
 int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
-				 struct v4l2_control *ctrl, int is_set_cmd)
+		struct msm_camera_v4l2_ioctl_t *ioctl_ptr, int is_set_cmd)
 {
 	int rc = 0;
-	struct msm_ctrl_cmd ctrlcmd, *tmp_cmd;
+	struct msm_ctrl_cmd ctrlcmd, tmp_cmd, *cmd_ptr;
 	uint8_t *ctrl_data = NULL;
-	void __user *uptr_cmd;
-	void __user *uptr_value;
 	uint32_t cmd_len = sizeof(struct msm_ctrl_cmd);
 	uint32_t value_len;
 
-	tmp_cmd = (struct msm_ctrl_cmd *)ctrl->value;
-	uptr_cmd = (void __user *)ctrl->value;
-	uptr_value = (void __user *)tmp_cmd->value;
-	value_len = tmp_cmd->length;
-
-	D("%s: cmd type = %d, up1=0x%x, ulen1=%d, up2=0x%x, ulen2=%d\n",
-		__func__, tmp_cmd->type, (uint32_t)uptr_cmd, cmd_len,
-		(uint32_t)uptr_value, tmp_cmd->length);
-
-	ctrl_data = kzalloc(value_len+cmd_len, GFP_KERNEL);
-	if (ctrl_data == 0) {
-		pr_err("%s could not allocate memory\n", __func__);
-		rc = -ENOMEM;
-		goto end;
-	}
-	tmp_cmd = (struct msm_ctrl_cmd *)ctrl_data;
-	if (copy_from_user((void *)ctrl_data, uptr_cmd,
-					cmd_len)) {
+	if (copy_from_user(&tmp_cmd,
+		(void __user *)ioctl_ptr->ioctl_ptr, cmd_len)) {
 		pr_err("%s: copy_from_user failed.\n", __func__);
 		rc = -EINVAL;
 		goto end;
 	}
-	tmp_cmd->value = (void *)(ctrl_data+cmd_len);
-	if (uptr_value && tmp_cmd->length > 0) {
-		if (copy_from_user((void *)tmp_cmd->value, uptr_value,
-						value_len)) {
-			pr_err("%s: copy_from_user failed, size=%d\n",
-				__func__, value_len);
+	value_len = tmp_cmd.length;
+	ctrl_data = kzalloc(value_len+cmd_len, GFP_KERNEL);
+	if (!ctrl_data) {
+		pr_err("%s could not allocate memory\n", __func__);
+		rc = -ENOMEM;
+		goto end;
+	}
+
+	cmd_ptr = (struct msm_ctrl_cmd *) ctrl_data;
+	*cmd_ptr = tmp_cmd;
+	if (tmp_cmd.value && tmp_cmd.length > 0) {
+		cmd_ptr->value = (void *)(ctrl_data+cmd_len);
+		if (copy_from_user((void *)cmd_ptr->value,
+				   (void __user *)tmp_cmd.value,
+				   value_len)) {
+			pr_err("%s: copy_from_user failed.\n", __func__);
 			rc = -EINVAL;
 			goto end;
 		}
-	} else
-	tmp_cmd->value = NULL;
+	} else {
+		cmd_ptr->value = NULL;
+	}
+
+	D("%s: cmd type = %d, up1=0x%x, ulen1=%d, up2=0x%x, ulen2=%d\n",
+		__func__, tmp_cmd.type, (uint32_t)ioctl_ptr->ioctl_ptr, cmd_len,
+		(uint32_t)tmp_cmd.value, tmp_cmd.length);
 
 	ctrlcmd.type = MSM_V4L2_SET_CTRL_CMD;
 	ctrlcmd.length = cmd_len + value_len;
 	ctrlcmd.value = (void *)ctrl_data;
-	if (tmp_cmd->timeout_ms > 0)
-		ctrlcmd.timeout_ms = tmp_cmd->timeout_ms;
+	if (tmp_cmd.timeout_ms > 0)
+		ctrlcmd.timeout_ms = tmp_cmd.timeout_ms;
 	else
 		ctrlcmd.timeout_ms = 1000;
 	ctrlcmd.vnode_id = pcam->vnode_id;
@@ -618,17 +615,17 @@
 	rc = msm_server_control(&g_server_dev, &ctrlcmd);
 	D("%s: msm_server_control rc=%d\n", __func__, rc);
 	if (rc == 0) {
-		if (uptr_value && tmp_cmd->length > 0 &&
-			copy_to_user((void __user *)uptr_value,
-				(void *)(ctrl_data+cmd_len), tmp_cmd->length)) {
+		if (tmp_cmd.value && tmp_cmd.length > 0 &&
+			copy_to_user((void __user *)tmp_cmd.value,
+				(void *)(ctrl_data+cmd_len), tmp_cmd.length)) {
 			pr_err("%s: copy_to_user failed, size=%d\n",
-				__func__, tmp_cmd->length);
+				__func__, tmp_cmd.length);
 			rc = -EINVAL;
 			goto end;
 		}
-		tmp_cmd->value = uptr_value;
-		if (copy_to_user((void __user *)uptr_cmd,
-			(void *)tmp_cmd, cmd_len)) {
+
+		if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+			(void *)&tmp_cmd, cmd_len)) {
 			pr_err("%s: copy_to_user failed in cpy, size=%d\n",
 				__func__, cmd_len);
 			rc = -EINVAL;
@@ -637,8 +634,8 @@
 	}
 end:
 	D("%s: END, type = %d, vaddr = 0x%x, vlen = %d, status = %d, rc = %d\n",
-		__func__, tmp_cmd->type, (uint32_t)tmp_cmd->value,
-		tmp_cmd->length, tmp_cmd->status, rc);
+		__func__, tmp_cmd.type, (uint32_t)tmp_cmd.value,
+		tmp_cmd.length, tmp_cmd.status, rc);
 	kfree(ctrl_data);
 	return rc;
 }
@@ -655,8 +652,6 @@
 		pr_err("%s Invalid control\n", __func__);
 		return -EINVAL;
 	}
-	if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
-		return msm_server_proc_ctrl_cmd(pcam, ctrl, 1);
 
 	memset(ctrl_data, 0, sizeof(ctrl_data));
 
@@ -687,8 +682,6 @@
 		pr_err("%s Invalid control\n", __func__);
 		return -EINVAL;
 	}
-	if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
-		return msm_server_proc_ctrl_cmd(pcam, ctrl, 0);
 
 	memset(ctrl_data, 0, sizeof(ctrl_data));
 
@@ -1421,16 +1414,6 @@
 				g_server_dev.vfe_device[0], notification, arg);
 		}
 		break;
-	case NOTIFY_VPE_MSG_EVT: {
-		struct msm_cam_media_controller *pmctl =
-		(struct msm_cam_media_controller *)
-		v4l2_get_subdev_hostdata(sd);
-		struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
-		msm_mctl_pp_notify(pmctl,
-		(struct msm_mctl_pp_frame_info *)
-		vdata->extdata);
-		break;
-	}
 	case NOTIFY_VFE_IRQ:{
 		struct msm_vfe_cfg_cmd cfg_cmd;
 		struct msm_camvfe_params vfe_params;
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index 2fe4c2b..677feaa 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -36,7 +36,7 @@
 int msm_server_get_usecount(void);
 int32_t msm_find_free_queue(void);
 int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
-	struct v4l2_control *ctrl, int is_set_cmd);
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr, int is_set_cmd);
 int msm_server_s_ctrl(struct msm_cam_v4l2_device *pcam,
 	struct v4l2_control *ctrl);
 int msm_server_g_ctrl(struct msm_cam_v4l2_device *pcam,
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index c94fa13..a5f2634 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -1297,17 +1297,33 @@
 	return rc;
 }
 static long venc_set_max_perf_level(struct video_client_ctx *client_ctx,
-		int val)
+		__s32 value)
 {
 	int rc = 0;
 	struct vcd_property_hdr vcd_property_hdr;
 	struct vcd_property_perf_level perf;
+	int level = 0;
+
+	switch (value) {
+	case V4L2_CID_MPEG_QCOM_PERF_LEVEL_PERFORMANCE:
+		level = VCD_PERF_LEVEL2;
+		break;
+	case V4L2_CID_MPEG_QCOM_PERF_LEVEL_TURBO:
+		level = VCD_PERF_LEVEL_TURBO;
+		break;
+	default:
+		WFD_MSG_ERR("Unknown performance level: %d\n", value);
+		rc = -ENOTSUPP;
+		goto err_set_perf_level;
+	}
+
 	vcd_property_hdr.prop_id = VCD_REQ_PERF_LEVEL;
 	vcd_property_hdr.sz =
 		sizeof(struct vcd_property_perf_level);
-	perf.level = VCD_PERF_LEVEL2;
+	perf.level = level;
 	rc = vcd_set_property(client_ctx->vcd_handle,
 				&vcd_property_hdr, &perf);
+err_set_perf_level:
 	return rc;
 }
 static long venc_set_header_mode(struct video_client_ctx *client_ctx,
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 7c61bf3..8c392fc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -936,6 +936,14 @@
 	  This is required to use certain other PM 8xxx features, such as GPIO
 	  and MPP.
 
+config MFD_PM8821_IRQ
+	bool "Support for Qualcomm PM8821 IRQ features"
+	default y if MFD_PM8821_CORE
+	help
+	  This is the IRQ driver for Qualcomm PM 8821 PMIC chips.
+
+	  This is required to use certain other PM 8821 features, such as MPPs.
+
 config TPS65911_COMPARATOR
 	tristate
 
@@ -1035,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 e81e4b1..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
@@ -137,6 +139,7 @@
 obj-$(CONFIG_MFD_PM8018_CORE) 	+= pm8018-core.o
 obj-$(CONFIG_MFD_PM8038_CORE) 	+= pm8038-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
+obj-$(CONFIG_MFD_PM8821_IRQ) 	+= pm8821-irq.o
 obj-$(CONFIG_MFD_PM8XXX_DEBUG) 	+= pm8xxx-debug.o
 obj-$(CONFIG_MFD_PM8XXX_PWM) 	+= pm8xxx-pwm.o
 obj-$(CONFIG_MFD_PM8XXX_MISC) 	+= pm8xxx-misc.o
diff --git a/drivers/mfd/marimba-tsadc.c b/drivers/mfd/marimba-tsadc.c
index 8a7b781..32b93e1 100644
--- a/drivers/mfd/marimba-tsadc.c
+++ b/drivers/mfd/marimba-tsadc.c
@@ -437,7 +437,7 @@
 	struct marimba_tsadc *tsadc = dev_get_drvdata(dev);
 
 	if (tsadc->clk_enabled == true) {
-		clk_disable(tsadc->codec_ssbi);
+		clk_disable_unprepare(tsadc->codec_ssbi);
 		tsadc->clk_enabled = false;
 	}
 
@@ -462,7 +462,7 @@
 	marimba_tsadc_configure(tsadc_dev);
 fail_shutdown:
 	if (tsadc->clk_enabled == false) {
-		ret = clk_enable(tsadc->codec_ssbi);
+		ret = clk_prepare_enable(tsadc->codec_ssbi);
 		if (ret == 0)
 			tsadc->clk_enabled = true;
 	}
@@ -475,7 +475,7 @@
 	struct marimba_tsadc *tsadc = dev_get_drvdata(dev);
 
 	if (tsadc->clk_enabled == false) {
-		rc = clk_enable(tsadc->codec_ssbi);
+		rc = clk_prepare_enable(tsadc->codec_ssbi);
 		if (rc != 0) {
 			pr_err("%s: Clk enable failed\n", __func__);
 			return rc;
@@ -515,7 +515,7 @@
 		tsadc->pdata->marimba_tsadc_power(0);
 fail_tsadc_power:
 	if (tsadc->clk_enabled == true) {
-		clk_disable(tsadc->codec_ssbi);
+		clk_disable_unprepare(tsadc->codec_ssbi);
 		tsadc->clk_enabled = false;
 	}
 	return rc;
@@ -591,7 +591,7 @@
 		rc = PTR_ERR(tsadc->codec_ssbi);
 		goto fail_clk_get;
 	}
-	rc = clk_enable(tsadc->codec_ssbi);
+	rc = clk_prepare_enable(tsadc->codec_ssbi);
 	if (rc != 0)
 		goto fail_clk_enable;
 
@@ -623,7 +623,7 @@
 	return rc;
 
 fail_add_subdev:
-	clk_disable(tsadc->codec_ssbi);
+	clk_disable_unprepare(tsadc->codec_ssbi);
 
 fail_clk_enable:
 	clk_put(tsadc->codec_ssbi);
@@ -647,7 +647,7 @@
 	device_init_wakeup(&pdev->dev, 0);
 
 	if (tsadc->clk_enabled == true)
-		clk_disable(tsadc->codec_ssbi);
+		clk_disable_unprepare(tsadc->codec_ssbi);
 
 	clk_put(tsadc->codec_ssbi);
 
diff --git a/drivers/mfd/pm8821-core.c b/drivers/mfd/pm8821-core.c
index df9d2e1..1d3c927a 100644
--- a/drivers/mfd/pm8821-core.c
+++ b/drivers/mfd/pm8821-core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,7 +27,7 @@
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
 #define REG_MPP_BASE		0x050
-#define REG_IRQ_BASE		0x1BB
+#define REG_IRQ_BASE		0x100
 
 #define PM8821_VERSION_MASK	0xFFF0
 #define PM8821_VERSION_VALUE	0x0BF0
@@ -86,7 +86,7 @@
 	const struct pm8xxx_drvdata *pm8821_drvdata = dev_get_drvdata(dev);
 	const struct pm8821 *pmic = pm8821_drvdata->pm_chip_data;
 
-	return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
+	return pm8821_get_irq_stat(pmic->irq_chip, irq);
 }
 
 static enum pm8xxx_version pm8821_get_version(const struct device *dev)
@@ -154,7 +154,7 @@
 		pdata->irq_pdata->irq_cdata.nirqs = PM8821_NR_IRQS;
 		pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
 		irq_base = pdata->irq_pdata->irq_base;
-		irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
+		irq_chip = pm8821_irq_init(pmic->dev, pdata->irq_pdata);
 
 		if (IS_ERR(irq_chip)) {
 			pr_err("Failed to init interrupts ret=%ld\n",
@@ -186,7 +186,7 @@
 	return 0;
 bail:
 	if (pmic->irq_chip) {
-		pm8xxx_irq_exit(pmic->irq_chip);
+		pm8821_irq_exit(pmic->irq_chip);
 		pmic->irq_chip = NULL;
 	}
 	return ret;
@@ -281,7 +281,7 @@
 	if (pmic)
 		mfd_remove_devices(pmic->dev);
 	if (pmic->irq_chip) {
-		pm8xxx_irq_exit(pmic->irq_chip);
+		pm8821_irq_exit(pmic->irq_chip);
 		pmic->irq_chip = NULL;
 	}
 	platform_set_drvdata(pdev, NULL);
diff --git a/drivers/mfd/pm8821-irq.c b/drivers/mfd/pm8821-irq.c
new file mode 100644
index 0000000..2dcc792
--- /dev/null
+++ b/drivers/mfd/pm8821-irq.c
@@ -0,0 +1,425 @@
+/*
+ * 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/export.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/pm8821-irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define PM8821_TOTAL_IRQ_MASTERS	2
+#define PM8821_BLOCKS_PER_MASTER	7
+#define PM8821_IRQ_MASTER1_SET		0x01
+#define PM8821_IRQ_CLEAR_OFFSET		0x01
+#define PM8821_IRQ_RT_STATUS_OFFSET	0x0F
+#define PM8821_IRQ_MASK_REG_OFFSET	0x08
+#define SSBI_REG_ADDR_IRQ_MASTER0	0x30
+#define SSBI_REG_ADDR_IRQ_MASTER1	0xB0
+
+#define SSBI_REG_ADDR_IRQ_IT_STATUS(master_base, block) (master_base + block)
+
+/*
+ * Block 0 does not exist in PM8821 IRQ SSBI address space,
+ * IRQ0 is assigned to bit0 of block1.
+ */
+#define SSBI_REG_ADDR_IRQ_IT_CLEAR(master_base, block) \
+	(master_base + PM8821_IRQ_CLEAR_OFFSET + block)
+
+#define SSBI_REG_ADDR_IRQ_RT_STATUS(master_base, block) \
+	(master_base + PM8821_IRQ_RT_STATUS_OFFSET + block)
+
+#define SSBI_REG_ADDR_IRQ_MASK(master_base, block) \
+	(master_base + PM8821_IRQ_MASK_REG_OFFSET + block)
+
+struct pm_irq_chip {
+	struct device		*dev;
+	spinlock_t		pm_irq_lock;
+	unsigned int		base_addr;
+	unsigned int		devirq;
+	unsigned int		irq_base;
+	unsigned int		num_irqs;
+	int			masters[PM8821_TOTAL_IRQ_MASTERS];
+};
+
+static int pm8821_irq_masked_write(struct pm_irq_chip *chip, u16 addr,
+							u8 mask, u8 val)
+{
+	int rc;
+	u8 reg;
+
+	rc = pm8xxx_readb(chip->dev, addr, &reg);
+	if (rc) {
+		pr_err("read failed addr = %03X, rc = %d\n", addr, rc);
+		return rc;
+	}
+
+	reg &= ~mask;
+	reg |= val & mask;
+
+	rc = pm8xxx_writeb(chip->dev, addr, reg);
+	if (rc) {
+		pr_err("write failed addr = %03X, rc = %d\n", addr, rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int pm8821_read_master_irq(const struct pm_irq_chip *chip,
+						int m, u8 *master)
+{
+	return pm8xxx_readb(chip->dev, chip->masters[m], master);
+}
+
+static int pm8821_read_block_irq(struct pm_irq_chip *chip, int master,
+						u8 block, u8 *bits)
+{
+	int rc;
+
+	spin_lock(&chip->pm_irq_lock);
+
+	rc = pm8xxx_readb(chip->dev,
+	    SSBI_REG_ADDR_IRQ_IT_STATUS(chip->masters[master], block), bits);
+	if (rc)
+		pr_err("Failed Reading Status rc=%d\n", rc);
+
+	spin_unlock(&chip->pm_irq_lock);
+	return rc;
+}
+
+
+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
+					int master_number, int block)
+{
+	int pmirq, irq, i, ret;
+	u8 bits;
+
+	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
+	if (ret) {
+		pr_err("Failed reading %d block ret=%d", block, ret);
+		return ret;
+	}
+	if (!bits) {
+		pr_err("block bit set in master but no irqs: %d", block);
+		return 0;
+	}
+
+	/* Convert block offset to global block number */
+	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
+
+	/* Check IRQ bits */
+	for (i = 0; i < 8; i++) {
+		if (bits & BIT(i)) {
+			pmirq = (block << 3) + i;
+			irq = pmirq + chip->irq_base;
+			generic_handle_irq(irq);
+		}
+	}
+	return 0;
+}
+
+static int pm8821_irq_read_master(struct pm_irq_chip *chip,
+				int master_number, u8 master_val)
+{
+	int ret = 0;
+	int block;
+
+	for (block = 1; block < 8; block++) {
+		if (master_val & BIT(block)) {
+			ret |= pm8821_irq_block_handler(chip,
+					master_number, block);
+		}
+	}
+
+	return ret;
+}
+
+static irqreturn_t pm8821_irq_handler(int irq, void *data)
+{
+	struct pm_irq_chip *chip = data;
+	int ret;
+	u8 master;
+
+	ret = pm8821_read_master_irq(chip, 0, &master);
+	if (ret) {
+		pr_err("Failed to read master 0 ret=%d\n", ret);
+		return ret;
+	}
+
+	if (master & ~PM8821_IRQ_MASTER1_SET)
+		pm8821_irq_read_master(chip, 0, master);
+
+	if (!(master & PM8821_IRQ_MASTER1_SET))
+		goto done;
+
+	ret = pm8821_read_master_irq(chip, 1, &master);
+	if (ret) {
+		pr_err("Failed to read master 1 ret=%d\n", ret);
+		return ret;
+	}
+
+	pm8821_irq_read_master(chip, 1, master);
+
+done:
+	return IRQ_HANDLED;
+}
+
+static void pm8821_irq_mask(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = d->irq - chip->irq_base;
+	int irq_bit, rc;
+	u8 block, master;
+
+	block = pmirq >> 3;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	spin_lock(&chip->pm_irq_lock);
+
+	rc = pm8821_irq_masked_write(chip,
+		SSBI_REG_ADDR_IRQ_MASK(chip->masters[master], block),
+		BIT(irq_bit), BIT(irq_bit));
+
+	if (rc)
+		pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
+
+	spin_unlock(&chip->pm_irq_lock);
+}
+
+static void pm8821_irq_mask_ack(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = d->irq - chip->irq_base;
+	int irq_bit, rc;
+	u8 block, master;
+
+	block = pmirq >> 3;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	spin_lock(&chip->pm_irq_lock);
+
+	rc = pm8821_irq_masked_write(chip,
+		SSBI_REG_ADDR_IRQ_MASK(chip->masters[master], block),
+		BIT(irq_bit), BIT(irq_bit));
+
+	if (rc) {
+		pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
+		goto fail;
+	}
+
+	rc = pm8821_irq_masked_write(chip,
+		SSBI_REG_ADDR_IRQ_IT_CLEAR(chip->masters[master], block),
+		BIT(irq_bit), BIT(irq_bit));
+
+	if (rc) {
+		pr_err("Failed to read/write IT_CLEAR IRQ:%d rc=%d\n",
+								pmirq, rc);
+	}
+
+fail:
+	spin_unlock(&chip->pm_irq_lock);
+}
+
+static void pm8821_irq_unmask(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = d->irq - chip->irq_base;
+	int irq_bit, rc;
+	u8 block, master;
+
+	block = pmirq >> 3;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	spin_lock(&chip->pm_irq_lock);
+
+	rc = pm8821_irq_masked_write(chip,
+		SSBI_REG_ADDR_IRQ_MASK(chip->masters[master], block),
+		BIT(irq_bit), ~BIT(irq_bit));
+
+	if (rc)
+		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
+
+	spin_unlock(&chip->pm_irq_lock);
+}
+
+static int pm8821_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	/*
+	 * PM8821 IRQ controller does not have explicit software support for
+	 * IRQ flow type.
+	 */
+	return 0;
+}
+
+static int pm8821_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	return 0;
+}
+
+static int pm8821_irq_read_line(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+
+	return pm8821_get_irq_stat(chip, d->irq);
+}
+
+static struct irq_chip pm_irq_chip = {
+	.name		= "pm8821-irq",
+	.irq_mask	= pm8821_irq_mask,
+	.irq_mask_ack	= pm8821_irq_mask_ack,
+	.irq_unmask	= pm8821_irq_unmask,
+	.irq_set_type	= pm8821_irq_set_type,
+	.irq_set_wake	= pm8821_irq_set_wake,
+	.irq_read_line	= pm8821_irq_read_line,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND,
+};
+
+/**
+ * pm8821_get_irq_stat - get the status of the irq line
+ * @chip: pointer to identify a pmic irq controller
+ * @irq: the irq number
+ *
+ * The pm8821 gpio and mpp rely on the interrupt block to read
+ * the values on their pins. This function is to facilitate reading
+ * the status of a gpio or an mpp line. The caller has to convert the
+ * gpio number to irq number.
+ *
+ * RETURNS:
+ * an int indicating the value read on that line
+ */
+int pm8821_get_irq_stat(struct pm_irq_chip *chip, int irq)
+{
+	int pmirq, rc;
+	u8 block, bits, bit, master;
+	unsigned long flags;
+
+	if (chip == NULL || irq < chip->irq_base
+	    || irq >= chip->irq_base + chip->num_irqs)
+		return -EINVAL;
+
+	pmirq = irq - chip->irq_base;
+
+	block = pmirq >> 3;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	spin_lock_irqsave(&chip->pm_irq_lock, flags);
+
+	rc = pm8xxx_readb(chip->dev,
+		SSBI_REG_ADDR_IRQ_RT_STATUS(chip->masters[master], block),
+		&bits);
+	if (rc) {
+		pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
+						irq, pmirq, block, rc);
+		goto bail_out;
+	}
+
+	rc = (bits & BIT(bit)) ? 1 : 0;
+
+bail_out:
+	spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(pm8821_get_irq_stat);
+
+struct pm_irq_chip *  __devinit pm8821_irq_init(struct device *dev,
+				const struct pm8xxx_irq_platform_data *pdata)
+{
+	struct pm_irq_chip	*chip;
+	int			devirq, rc, blocks, masters;
+	unsigned int		pmirq;
+
+	if (!pdata) {
+		pr_err("No platform data\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	devirq = pdata->devirq;
+	if (devirq < 0) {
+		pr_err("missing devirq\n");
+		rc = devirq;
+		return ERR_PTR(-EINVAL);
+	}
+
+	chip = kzalloc(sizeof(struct pm_irq_chip)
+			+ sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
+	if (!chip) {
+		pr_err("Cannot alloc pm_irq_chip struct\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	chip->dev	= dev;
+	chip->devirq	= devirq;
+	chip->irq_base	= pdata->irq_base;
+	chip->num_irqs	= pdata->irq_cdata.nirqs;
+	chip->base_addr = pdata->irq_cdata.base_addr;
+	blocks		= DIV_ROUND_UP(pdata->irq_cdata.nirqs, 8);
+	masters		= DIV_ROUND_UP(blocks, PM8821_BLOCKS_PER_MASTER);
+	chip->masters[0] = chip->base_addr + SSBI_REG_ADDR_IRQ_MASTER0;
+	chip->masters[1] = chip->base_addr + SSBI_REG_ADDR_IRQ_MASTER1;
+
+	if (masters != PM8821_TOTAL_IRQ_MASTERS) {
+		pr_err("Unequal number of masters, passed: %d, "
+		"should have been: %d\n", masters, PM8821_TOTAL_IRQ_MASTERS);
+		kfree(chip);
+		return ERR_PTR(-EINVAL);
+	}
+
+	spin_lock_init(&chip->pm_irq_lock);
+
+	for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
+		irq_set_chip_and_handler(chip->irq_base + pmirq,
+				&pm_irq_chip, handle_level_irq);
+		irq_set_chip_data(chip->irq_base + pmirq, chip);
+#ifdef CONFIG_ARM
+		set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
+#else
+		irq_set_noprobe(chip->irq_base + pmirq);
+#endif
+	}
+
+	if (devirq != 0) {
+		rc = request_irq(devirq, pm8821_irq_handler,
+			pdata->irq_trigger_flag, "pm8821_sec_irq", chip);
+		if (rc) {
+			pr_err("failed to request_irq for %d rc=%d\n",
+							devirq, rc);
+			kfree(chip);
+			return ERR_PTR(rc);
+		} else
+			irq_set_irq_wake(devirq, 1);
+	}
+
+	return chip;
+}
+
+int pm8821_irq_exit(struct pm_irq_chip *chip)
+{
+	irq_set_chained_handler(chip->devirq, NULL);
+	kfree(chip);
+	return 0;
+}
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 538ca7c..705a57b 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -510,7 +510,6 @@
 		sph[i] = tx[idx].sph;
 		grph = tx[idx].grph;
 	}
-
 	/* slim_control_ch (REMOVE) */
 	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
 	if (ret < 0) {
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 990faeb..1331aa4 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -606,7 +606,6 @@
 	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
-	unsigned int timeout_us;
 
 	struct scatterlist sg;
 
@@ -626,23 +625,12 @@
 	cmd.arg = 0;
 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
 
-	data.timeout_ns = card->csd.tacc_ns * 100;
-	data.timeout_clks = card->csd.tacc_clks * 100;
-
-	timeout_us = data.timeout_ns / 1000;
-	timeout_us += data.timeout_clks * 1000 /
-		(card->host->ios.clock / 1000);
-
-	if (timeout_us > 100000) {
-		data.timeout_ns = 100000000;
-		data.timeout_clks = 0;
-	}
-
 	data.blksz = 4;
 	data.blocks = 1;
 	data.flags = MMC_DATA_READ;
 	data.sg = &sg;
 	data.sg_len = 1;
+	mmc_set_data_timeout(&data, card);
 
 	mrq.cmd = &cmd;
 	mrq.data = &data;
@@ -918,9 +906,7 @@
 		goto retry;
 	if (!err)
 		mmc_blk_reset_success(md, type);
-	spin_lock_irq(&md->lock);
-	__blk_end_request(req, err, blk_rq_bytes(req));
-	spin_unlock_irq(&md->lock);
+	blk_end_request(req, err, blk_rq_bytes(req));
 
 	return err ? 0 : 1;
 }
@@ -989,9 +975,7 @@
 	if (!err)
 		mmc_blk_reset_success(md, type);
 out:
-	spin_lock_irq(&md->lock);
-	__blk_end_request(req, err, blk_rq_bytes(req));
-	spin_unlock_irq(&md->lock);
+	blk_end_request(req, err, blk_rq_bytes(req));
 
 	return err ? 0 : 1;
 }
@@ -1030,9 +1014,7 @@
 					     __func__);
 
 out:
-	spin_lock_irq(&md->lock);
-	__blk_end_request(req, err, blk_rq_bytes(req));
-	spin_unlock_irq(&md->lock);
+	blk_end_request(req, err, blk_rq_bytes(req));
 
 	return err ? 0 : 1;
 }
@@ -1047,9 +1029,7 @@
 	if (ret)
 		ret = -EIO;
 
-	spin_lock_irq(&md->lock);
-	__blk_end_request_all(req, ret);
-	spin_unlock_irq(&md->lock);
+	blk_end_request_all(req, ret);
 
 	return ret ? 0 : 1;
 }
@@ -1402,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;
 	}
 
@@ -1672,15 +1653,11 @@
 
 		blocks = mmc_sd_num_wr_blocks(card);
 		if (blocks != (u32)-1) {
-			spin_lock_irq(&md->lock);
-			ret = __blk_end_request(req, 0, blocks << 9);
-			spin_unlock_irq(&md->lock);
+			ret = blk_end_request(req, 0, blocks << 9);
 		}
 	} else {
 		if (mq_rq->packed_cmd == MMC_PACKED_NONE) {
-			spin_lock_irq(&md->lock);
-			ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
-			spin_unlock_irq(&md->lock);
+			ret = blk_end_request(req, 0, brq->data.bytes_xfered);
 		}
 	}
 	return ret;
@@ -1689,7 +1666,6 @@
 static int mmc_blk_end_packed_req(struct mmc_queue *mq,
 				  struct mmc_queue_req *mq_rq)
 {
-	struct mmc_blk_data *md = mq->data;
 	struct request *prq;
 	int idx = mq_rq->packed_fail_idx, i = 0;
 	int ret = 0;
@@ -1709,9 +1685,7 @@
 			return ret;
 		}
 		list_del_init(&prq->queuelist);
-		spin_lock_irq(&md->lock);
-		__blk_end_request(prq, 0, blk_rq_bytes(prq));
-		spin_unlock_irq(&md->lock);
+		blk_end_request(prq, 0, blk_rq_bytes(prq));
 		i++;
 	}
 
@@ -1777,10 +1751,8 @@
 				ret = mmc_blk_end_packed_req(mq, mq_rq);
 				break;
 			} else {
-				spin_lock_irq(&md->lock);
-				ret = __blk_end_request(req, 0,
+				ret = blk_end_request(req, 0,
 						brq->data.bytes_xfered);
-				spin_unlock_irq(&md->lock);
 			}
 
 			/*
@@ -1833,10 +1805,8 @@
 			 * time, so we only reach here after trying to
 			 * read a single sector.
 			 */
-			spin_lock_irq(&md->lock);
-			ret = __blk_end_request(req, -EIO,
+			ret = blk_end_request(req, -EIO,
 						brq->data.blksz);
-			spin_unlock_irq(&md->lock);
 			if (!ret)
 				goto start_new_req;
 			break;
@@ -1866,20 +1836,16 @@
 
  cmd_abort:
 	if (mq_rq->packed_cmd == MMC_PACKED_NONE) {
-		spin_lock_irq(&md->lock);
 		if (mmc_card_removed(card))
 			req->cmd_flags |= REQ_QUIET;
 		while (ret)
-			ret = __blk_end_request(req, -EIO,
+			ret = blk_end_request(req, -EIO,
 					blk_rq_cur_bytes(req));
-		spin_unlock_irq(&md->lock);
 	} else {
 		while (!list_empty(&mq_rq->packed_list)) {
 			prq = list_entry_rq(mq_rq->packed_list.next);
 			list_del_init(&prq->queuelist);
-			spin_lock_irq(&md->lock);
-			__blk_end_request(prq, -EIO, blk_rq_bytes(prq));
-			spin_unlock_irq(&md->lock);
+			blk_end_request(prq, -EIO, blk_rq_bytes(prq));
 		}
 		mmc_blk_clear_packed(mq_rq);
 	}
@@ -1932,9 +1898,7 @@
 	ret = mmc_blk_part_switch(card, md);
 	if (ret) {
 		if (req) {
-			spin_lock_irq(&md->lock);
-			__blk_end_request_all(req, -EIO);
-			spin_unlock_irq(&md->lock);
+			blk_end_request_all(req, -EIO);
 		}
 		ret = 0;
 		goto out;
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 3438bc91..a21b39d 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -235,6 +235,36 @@
 	return err;
 }
 
+static void mmc_select_card_type(struct mmc_card *card)
+{
+	struct mmc_host *host = card->host;
+	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
+	unsigned int caps = host->caps, caps2 = host->caps2;
+	unsigned int hs_max_dtr = 0;
+
+	if (card_type & EXT_CSD_CARD_TYPE_26)
+		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+			card_type & EXT_CSD_CARD_TYPE_52)
+		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+
+	if ((caps & MMC_CAP_1_8V_DDR &&
+			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
+	    (caps & MMC_CAP_1_2V_DDR &&
+			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+
+	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
+	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+
+	card->ext_csd.hs_max_dtr = hs_max_dtr;
+	card->ext_csd.card_type = card_type;
+}
+
 /*
  * Decode extended CSD.
  */
@@ -284,56 +314,9 @@
 		if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512)
 			mmc_card_set_blockaddr(card);
 	}
+
 	card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
-	switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
-	case EXT_CSD_CARD_TYPE_SDR_ALL:
-	case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V:
-	case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V:
-	case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52:
-		card->ext_csd.hs_max_dtr = 200000000;
-		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200;
-		break;
-	case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL:
-	case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V:
-	case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V:
-	case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52:
-		card->ext_csd.hs_max_dtr = 200000000;
-		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V;
-		break;
-	case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL:
-	case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V:
-	case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V:
-	case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52:
-		card->ext_csd.hs_max_dtr = 200000000;
-		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V;
-		break;
-	case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 |
-	     EXT_CSD_CARD_TYPE_26:
-		card->ext_csd.hs_max_dtr = 52000000;
-		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52;
-		break;
-	case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 |
-	     EXT_CSD_CARD_TYPE_26:
-		card->ext_csd.hs_max_dtr = 52000000;
-		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V;
-		break;
-	case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 |
-	     EXT_CSD_CARD_TYPE_26:
-		card->ext_csd.hs_max_dtr = 52000000;
-		card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V;
-		break;
-	case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
-		card->ext_csd.hs_max_dtr = 52000000;
-		break;
-	case EXT_CSD_CARD_TYPE_26:
-		card->ext_csd.hs_max_dtr = 26000000;
-		break;
-	default:
-		/* MMC v4 spec says this cannot happen */
-		pr_warning("%s: card is mmc v4 but doesn't "
-			"support any high-speed modes.\n",
-			mmc_hostname(card->host));
-	}
+	mmc_select_card_type(card);
 
 	card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT];
 	card->ext_csd.raw_erase_timeout_mult =
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index ac8b164..eba80c5 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -376,8 +376,8 @@
 {
 	host->curr.data = NULL;
 	host->curr.got_dataend = 0;
-	host->curr.wait_for_auto_prog_done = 0;
-	host->curr.got_auto_prog_done = 0;
+	host->curr.wait_for_auto_prog_done = false;
+	host->curr.got_auto_prog_done = false;
 	writel_relaxed(readl_relaxed(host->base + MMCIDATACTRL) &
 			(~(MCI_DPSM_ENABLE)), host->base + MMCIDATACTRL);
 	msmsdcc_sync_reg_wr(host); /* Allow the DPSM to be reset */
@@ -1118,7 +1118,7 @@
 	host->curr.xfer_remain = host->curr.xfer_size;
 	host->curr.data_xfered = 0;
 	host->curr.got_dataend = 0;
-	host->curr.got_auto_prog_done = 0;
+	host->curr.got_auto_prog_done = false;
 
 	datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
 
@@ -1173,6 +1173,9 @@
 	clks = (unsigned long long)data->timeout_ns * host->clk_rate;
 	do_div(clks, 1000000000UL);
 	timeout = data->timeout_clks + (unsigned int)clks*2 ;
+	WARN(!timeout,
+	     "%s: data timeout is zero. timeout_ns=0x%x, timeout_clks=0x%x\n",
+	     mmc_hostname(host->mmc), data->timeout_ns, data->timeout_clks);
 
 	if (host->is_dma_mode && (datactrl & MCI_DPSM_DMAENABLE)) {
 		/* Use ADM (Application Data Mover) HW for Data transfer */
@@ -1644,7 +1647,7 @@
 					host->curr.cmd = cmd;
 			} else {
 				host->prog_enable = 0;
-				host->curr.wait_for_auto_prog_done = 0;
+				host->curr.wait_for_auto_prog_done = false;
 				if (host->dummy_52_needed)
 					host->dummy_52_needed = 0;
 				if (cmd->data && cmd->error)
@@ -1808,7 +1811,7 @@
 			/* Check for prog done */
 			if (host->curr.wait_for_auto_prog_done &&
 				(status & MCI_PROGDONE))
-				host->curr.got_auto_prog_done = 1;
+				host->curr.got_auto_prog_done = true;
 
 			/* Check for data done */
 			if (!host->curr.got_dataend && (status & MCI_DATAEND))
@@ -2026,35 +2029,26 @@
 			 msecs_to_jiffies(host->curr.req_tout_ms)));
 
 	host->curr.mrq = mrq;
+	if (mrq->sbc) {
+		mrq->sbc->mrq = mrq;
+		mrq->sbc->data = mrq->data;
+	}
+
 	if (mrq->data && (mrq->data->flags & MMC_DATA_WRITE)) {
-		if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
-			mrq->cmd->opcode == 54) {
-			if (!host->sdcc_version)
+		if (host->sdcc_version) {
+			if (!mrq->stop)
+				host->curr.wait_for_auto_prog_done = true;
+		} else {
+			if ((mrq->cmd->opcode == SD_IO_RW_EXTENDED) ||
+			    (mrq->cmd->opcode == 54))
 				host->dummy_52_needed = 1;
-			else
-				/*
-				 * SDCCv4 supports AUTO_PROG_DONE bit for SDIO
-				 * write operations using CMD53 and CMD54.
-				 * Setting this bit with CMD53 would
-				 * automatically triggers PROG_DONE interrupt
-				 * without the need of sending dummy CMD52.
-				 */
-				host->curr.wait_for_auto_prog_done = 1;
-		} else if (mrq->cmd->opcode == MMC_WRITE_BLOCK &&
-				host->sdcc_version) {
-			host->curr.wait_for_auto_prog_done = 1;
 		}
+
 		if ((mrq->cmd->opcode == MMC_WRITE_BLOCK) ||
 		    (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK))
 			host->curr.use_wr_data_pend = true;
 	}
 
-	if (mrq->data && mrq->sbc) {
-		mrq->sbc->mrq = mrq;
-		mrq->sbc->data = mrq->data;
-		if (mrq->data->flags & MMC_DATA_WRITE)
-			host->curr.wait_for_auto_prog_done = 1;
-	}
 	msmsdcc_request_start(host, mrq);
 
 	spin_unlock_irqrestore(&host->lock, flags);
@@ -2136,7 +2130,7 @@
 {
 	int rc = 0;
 	struct msm_mmc_slot_reg_data *curr_slot;
-	struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
+	struct msm_mmc_reg_data *curr_vdd_reg, *curr_vdd_io_reg;
 	struct device *dev = mmc_dev(host->mmc);
 
 	curr_slot = host->plat->vreg_data;
@@ -2144,8 +2138,7 @@
 		goto out;
 
 	curr_vdd_reg = curr_slot->vdd_data;
-	curr_vccq_reg = curr_slot->vccq_data;
-	curr_vddp_reg = curr_slot->vddp_data;
+	curr_vdd_io_reg = curr_slot->vdd_io_data;
 
 	if (is_init) {
 		/*
@@ -2157,16 +2150,11 @@
 			if (rc)
 				goto out;
 		}
-		if (curr_vccq_reg) {
-			rc = msmsdcc_vreg_init_reg(curr_vccq_reg, dev);
+		if (curr_vdd_io_reg) {
+			rc = msmsdcc_vreg_init_reg(curr_vdd_io_reg, dev);
 			if (rc)
 				goto vdd_reg_deinit;
 		}
-		if (curr_vddp_reg) {
-			rc = msmsdcc_vreg_init_reg(curr_vddp_reg, dev);
-			if (rc)
-				goto vccq_reg_deinit;
-		}
 		rc = msmsdcc_vreg_reset(host);
 		if (rc)
 			pr_err("msmsdcc.%d vreg reset failed (%d)\n",
@@ -2174,14 +2162,11 @@
 		goto out;
 	} else {
 		/* Deregister all regulators from regulator framework */
-		goto vddp_reg_deinit;
+		goto vdd_io_reg_deinit;
 	}
-vddp_reg_deinit:
-	if (curr_vddp_reg)
-		msmsdcc_vreg_deinit_reg(curr_vddp_reg);
-vccq_reg_deinit:
-	if (curr_vccq_reg)
-		msmsdcc_vreg_deinit_reg(curr_vccq_reg);
+vdd_io_reg_deinit:
+	if (curr_vdd_io_reg)
+		msmsdcc_vreg_deinit_reg(curr_vdd_io_reg);
 vdd_reg_deinit:
 	if (curr_vdd_reg)
 		msmsdcc_vreg_deinit_reg(curr_vdd_reg);
@@ -2254,16 +2239,14 @@
 {
 	int rc = 0, i;
 	struct msm_mmc_slot_reg_data *curr_slot;
-	struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
-	struct msm_mmc_reg_data *vreg_table[3];
+	struct msm_mmc_reg_data *vreg_table[2];
 
 	curr_slot = host->plat->vreg_data;
 	if (!curr_slot)
 		goto out;
 
-	curr_vdd_reg = vreg_table[0] = curr_slot->vdd_data;
-	curr_vccq_reg = vreg_table[1] = curr_slot->vccq_data;
-	curr_vddp_reg = vreg_table[2] = curr_slot->vddp_data;
+	vreg_table[0] = curr_slot->vdd_data;
+	vreg_table[1] = curr_slot->vdd_io_data;
 
 	for (i = 0; i < ARRAY_SIZE(vreg_table); i++) {
 		if (vreg_table[i]) {
@@ -2294,70 +2277,53 @@
 	return rc;
 }
 
-static int msmsdcc_set_vddp_level(struct msmsdcc_host *host, int level)
+enum vdd_io_level {
+	/* set vdd_io_data->low_vol_level */
+	VDD_IO_LOW,
+	/* set vdd_io_data->high_vol_level */
+	VDD_IO_HIGH,
+	/*
+	 * set whatever there in voltage_level (third argument) of
+	 * msmsdcc_set_vdd_io_vol() function.
+	 */
+	VDD_IO_SET_LEVEL,
+};
+
+static int msmsdcc_set_vdd_io_vol(struct msmsdcc_host *host,
+				  enum vdd_io_level level,
+				  unsigned int voltage_level)
 {
 	int rc = 0;
+	int set_level;
 
 	if (host->plat->vreg_data) {
-		struct msm_mmc_reg_data *vddp_reg =
-			host->plat->vreg_data->vddp_data;
+		struct msm_mmc_reg_data *vdd_io_reg =
+			host->plat->vreg_data->vdd_io_data;
 
-		if (vddp_reg && vddp_reg->is_enabled)
-			rc = msmsdcc_vreg_set_voltage(vddp_reg, level, level);
+		if (vdd_io_reg && vdd_io_reg->is_enabled) {
+			switch (level) {
+			case VDD_IO_LOW:
+				set_level = vdd_io_reg->low_vol_level;
+				break;
+			case VDD_IO_HIGH:
+				set_level = vdd_io_reg->high_vol_level;
+				break;
+			case VDD_IO_SET_LEVEL:
+				set_level = voltage_level;
+				break;
+			default:
+				pr_err("%s: %s: invalid argument level = %d",
+				       mmc_hostname(host->mmc), __func__,
+				       level);
+				rc = -EINVAL;
+				goto out;
+			}
+			rc = msmsdcc_vreg_set_voltage(vdd_io_reg,
+						      set_level, set_level);
+		}
 	}
 
-	return rc;
-}
-
-static inline int msmsdcc_set_vddp_low_vol(struct msmsdcc_host *host)
-{
-	struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
-	int rc = 0;
-
-	if (curr_slot && curr_slot->vddp_data) {
-		rc = msmsdcc_set_vddp_level(host,
-			curr_slot->vddp_data->low_vol_level);
-
-		if (rc)
-			pr_err("%s: %s: failed to change vddp level to %d",
-				mmc_hostname(host->mmc), __func__,
-				curr_slot->vddp_data->low_vol_level);
-	}
-
-	return rc;
-}
-
-static inline int msmsdcc_set_vddp_high_vol(struct msmsdcc_host *host)
-{
-	struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
-	int rc = 0;
-
-	if (curr_slot && curr_slot->vddp_data) {
-		rc = msmsdcc_set_vddp_level(host,
-			curr_slot->vddp_data->high_vol_level);
-
-		if (rc)
-			pr_err("%s: %s: failed to change vddp level to %d",
-				mmc_hostname(host->mmc), __func__,
-				curr_slot->vddp_data->high_vol_level);
-	}
-
-	return rc;
-}
-
-static inline int msmsdcc_set_vccq_vol(struct msmsdcc_host *host, int level)
-{
-	struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
-	int rc = 0;
-
-	if (curr_slot && curr_slot->vccq_data) {
-		rc = msmsdcc_vreg_set_voltage(curr_slot->vccq_data,
-				level, level);
-		if (rc)
-			pr_err("%s: %s: failed to change vccq level to %d",
-				mmc_hostname(host->mmc), __func__, level);
-	}
-
+out:
 	return rc;
 }
 
@@ -2375,8 +2341,8 @@
 static inline void msmsdcc_setup_clocks(struct msmsdcc_host *host, bool enable)
 {
 	if (enable) {
-		if (!IS_ERR_OR_NULL(host->dfab_pclk))
-			clk_prepare_enable(host->dfab_pclk);
+		if (!IS_ERR_OR_NULL(host->bus_clk))
+			clk_prepare_enable(host->bus_clk);
 		if (!IS_ERR(host->pclk))
 			clk_prepare_enable(host->pclk);
 		clk_prepare_enable(host->clk);
@@ -2388,8 +2354,8 @@
 		clk_disable_unprepare(host->clk);
 		if (!IS_ERR(host->pclk))
 			clk_disable_unprepare(host->pclk);
-		if (!IS_ERR_OR_NULL(host->dfab_pclk))
-			clk_disable_unprepare(host->dfab_pclk);
+		if (!IS_ERR_OR_NULL(host->bus_clk))
+			clk_disable_unprepare(host->bus_clk);
 	}
 }
 
@@ -2582,11 +2548,11 @@
 		pwr = MCI_PWR_OFF;
 		msmsdcc_cfg_mpm_sdiowakeup(host, SDC_DAT1_DISABLE);
 		/*
-		 * As VDD pad rail is always on, set low voltage for VDD
-		 * pad rail when slot is unused (when card is not present
-		 * or during system suspend).
+		 * If VDD IO rail is always on, set low voltage for VDD
+		 * IO rail when slot is not in use (like when card is not
+		 * present or during system suspend).
 		 */
-		msmsdcc_set_vddp_low_vol(host);
+		msmsdcc_set_vdd_io_vol(host, VDD_IO_LOW, 0);
 		msmsdcc_setup_pins(host, false);
 		break;
 	case MMC_POWER_UP:
@@ -2594,7 +2560,7 @@
 		pwr = MCI_PWR_UP;
 		msmsdcc_cfg_mpm_sdiowakeup(host, SDC_DAT1_ENABLE);
 
-		msmsdcc_set_vddp_high_vol(host);
+		msmsdcc_set_vdd_io_vol(host, VDD_IO_HIGH, 0);
 		msmsdcc_setup_pins(host, true);
 		break;
 	case MMC_POWER_ON:
@@ -2911,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);
@@ -3298,8 +3265,8 @@
 }
 #endif
 
-static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
-						struct mmc_ios *ios)
+static int msmsdcc_switch_io_voltage(struct mmc_host *mmc,
+				     struct mmc_ios *ios)
 {
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	unsigned long flags;
@@ -3309,31 +3276,32 @@
 	host->io_pad_pwr_switch = 0;
 	spin_unlock_irqrestore(&host->lock, flags);
 
-	/*
-	 * For eMMC cards, VccQ voltage range must be changed
-	 * only if it operates in HS200 SDR 1.2V mode or in
-	 * DDR 1.2V mode.
-	 */
-	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120) {
-		rc = msmsdcc_set_vccq_vol(host, 1200000);
+	switch (ios->signal_voltage) {
+	case MMC_SIGNAL_VOLTAGE_330:
+		/* Set VDD IO to high voltage range (2.7v - 3.6v) */
+		rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_HIGH, 0);
 		goto out;
-	 }
-
-	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
-		/* Change voltage level of VDDPX to high voltage */
-		rc = msmsdcc_set_vddp_high_vol(host);
+	case MMC_SIGNAL_VOLTAGE_180:
+		break;
+	case MMC_SIGNAL_VOLTAGE_120:
+		/*
+		 * For eMMC cards, VDD_IO voltage range must be changed
+		 * only if it operates in HS200 SDR 1.2V mode or in
+		 * DDR 1.2V mode.
+		 */
+		rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_SET_LEVEL, 1200000);
 		goto out;
-	} else if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
+	default:
 		/* invalid selection. don't do anything */
 		rc = -EINVAL;
 		goto out;
 	}
 
-	spin_lock_irqsave(&host->lock, flags);
 	/*
 	 * If we are here means voltage switch from high voltage to
 	 * low voltage is required
 	 */
+	spin_lock_irqsave(&host->lock, flags);
 
 	/*
 	 * Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
@@ -3353,10 +3321,10 @@
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	/*
-	 * Switch VDDPX from high voltage to low voltage
-	 * to change the VDD of the SD IO pads.
+	 * Switch VDD Io from high voltage range (2.7v - 3.6v) to
+	 * low voltage range (1.7v - 1.95v).
 	 */
-	rc = msmsdcc_set_vddp_low_vol(host);
+	rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_LOW, 0);
 	if (rc)
 		goto out;
 
@@ -3855,7 +3823,7 @@
 	.set_ios	= msmsdcc_set_ios,
 	.get_ro		= msmsdcc_get_ro,
 	.enable_sdio_irq = msmsdcc_enable_sdio_irq,
-	.start_signal_voltage_switch = msmsdcc_start_signal_voltage_switch,
+	.start_signal_voltage_switch = msmsdcc_switch_io_voltage,
 	.execute_tuning = msmsdcc_execute_tuning
 };
 
@@ -4390,7 +4358,7 @@
 }
 
 static ssize_t
-set_polling(struct device *dev, struct device_attribute *attr,
+store_polling(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -4414,9 +4382,6 @@
 	return count;
 }
 
-static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR,
-		show_polling, set_polling);
-
 static ssize_t
 show_sdcc_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
 			char *buf)
@@ -4429,7 +4394,7 @@
 }
 
 static ssize_t
-set_sdcc_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
+store_sdcc_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -4446,20 +4411,6 @@
 	return count;
 }
 
-static DEVICE_ATTR(max_bus_bw, S_IRUGO | S_IWUSR,
-		show_sdcc_to_mem_max_bus_bw, set_sdcc_to_mem_max_bus_bw);
-
-static struct attribute *dev_attrs[] = {
-	&dev_attr_max_bus_bw.attr,
-	/* if polling is enabled, this will be filled with dev_attr_polling */
-	NULL,
-	NULL,
-};
-
-static struct attribute_group dev_attr_grp = {
-	.attrs = dev_attrs,
-};
-
 #ifdef CONFIG_HAS_EARLYSUSPEND
 static void msmsdcc_early_suspend(struct early_suspend *h)
 {
@@ -4595,7 +4546,7 @@
 			}
 		} else {
 			host->prog_enable = 0;
-			host->curr.wait_for_auto_prog_done = 0;
+			host->curr.wait_for_auto_prog_done = false;
 			msmsdcc_reset_and_restore(host);
 			msmsdcc_request_end(host, mrq);
 		}
@@ -4878,21 +4829,17 @@
 	}
 
 	/*
-	 * Setup SDCC clock if derived from Dayatona
-	 * fabric core clock.
+	 * Setup SDCC bus voter clock.
 	 */
-	if (plat->pclk_src_dfab) {
-		host->dfab_pclk = clk_get(&pdev->dev, "bus_clk");
-		if (!IS_ERR(host->dfab_pclk)) {
-			/* Set the clock rate to 64MHz for max. performance */
-			ret = clk_set_rate(host->dfab_pclk, 64000000);
-			if (ret)
-				goto dfab_pclk_put;
-			ret = clk_prepare_enable(host->dfab_pclk);
-			if (ret)
-				goto dfab_pclk_put;
-		} else
-			goto dma_free;
+	host->bus_clk = clk_get(&pdev->dev, "bus_clk");
+	if (!IS_ERR_OR_NULL(host->bus_clk)) {
+		/* Vote for max. clk rate for max. performance */
+		ret = clk_set_rate(host->bus_clk, INT_MAX);
+		if (ret)
+			goto bus_clk_put;
+		ret = clk_prepare_enable(host->bus_clk);
+		if (ret)
+			goto bus_clk_put;
 	}
 
 	/*
@@ -5216,14 +5163,30 @@
 #if defined(CONFIG_DEBUG_FS)
 	msmsdcc_dbg_createhost(host);
 #endif
-	if (!plat->status_irq)
-		dev_attrs[1] = &dev_attr_polling.attr;
 
-	ret = sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);
+	host->max_bus_bw.show = show_sdcc_to_mem_max_bus_bw;
+	host->max_bus_bw.store = store_sdcc_to_mem_max_bus_bw;
+	sysfs_attr_init(&host->max_bus_bw.attr);
+	host->max_bus_bw.attr.name = "max_bus_bw";
+	host->max_bus_bw.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(&pdev->dev, &host->max_bus_bw);
 	if (ret)
 		goto platform_irq_free;
+
+	if (!plat->status_irq) {
+		host->polling.show = show_polling;
+		host->polling.store = store_polling;
+		sysfs_attr_init(&host->polling.attr);
+		host->polling.attr.name = "polling";
+		host->polling.attr.mode = S_IRUGO | S_IWUSR;
+		ret = device_create_file(&pdev->dev, &host->polling);
+		if (ret)
+			goto remove_max_bus_bw_file;
+	}
 	return 0;
 
+ remove_max_bus_bw_file:
+	device_remove_file(&pdev->dev, &host->max_bus_bw);
  platform_irq_free:
 	del_timer_sync(&host->req_tout_timer);
 	pm_runtime_disable(&(pdev)->dev);
@@ -5263,12 +5226,11 @@
  pclk_put:
 	if (!IS_ERR(host->pclk))
 		clk_put(host->pclk);
-	if (!IS_ERR_OR_NULL(host->dfab_pclk))
-		clk_disable_unprepare(host->dfab_pclk);
- dfab_pclk_put:
-	if (!IS_ERR_OR_NULL(host->dfab_pclk))
-		clk_put(host->dfab_pclk);
- dma_free:
+	if (!IS_ERR_OR_NULL(host->bus_clk))
+		clk_disable_unprepare(host->bus_clk);
+ bus_clk_put:
+	if (!IS_ERR_OR_NULL(host->bus_clk))
+		clk_put(host->bus_clk);
 	if (host->is_dma_mode) {
 		if (host->dmares)
 			dma_free_coherent(NULL,
@@ -5300,8 +5262,9 @@
 	DBG(host, "Removing SDCC device = %d\n", pdev->id);
 	plat = host->plat;
 
+	device_remove_file(&pdev->dev, &host->max_bus_bw);
 	if (!plat->status_irq)
-		sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
+		device_remove_file(&pdev->dev, &host->polling);
 
 	del_timer_sync(&host->req_tout_timer);
 	tasklet_kill(&host->dma_tlet);
@@ -5324,8 +5287,8 @@
 	clk_put(host->clk);
 	if (!IS_ERR(host->pclk))
 		clk_put(host->pclk);
-	if (!IS_ERR_OR_NULL(host->dfab_pclk))
-		clk_put(host->dfab_pclk);
+	if (!IS_ERR_OR_NULL(host->bus_clk))
+		clk_put(host->bus_clk);
 
 	if (host->cpu_dma_latency)
 		pm_qos_remove_request(&host->pm_qos_req_dma);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index ecf4950..2222337 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -293,8 +293,8 @@
 	unsigned int		xfer_remain;	/* Bytes remaining to send */
 	unsigned int		data_xfered;	/* Bytes acked by BLKEND irq */
 	int			got_dataend;
-	int			wait_for_auto_prog_done;
-	int			got_auto_prog_done;
+	bool			wait_for_auto_prog_done;
+	bool			got_auto_prog_done;
 	bool			use_wr_data_pend;
 	int			user_pages;
 	u32			req_tout_ms;
@@ -350,7 +350,7 @@
 	struct mmc_host		*mmc;
 	struct clk		*clk;		/* main MMC bus clock */
 	struct clk		*pclk;		/* SDCC peripheral bus clock */
-	struct clk		*dfab_pclk;	/* Daytona Fabric SDCC clock */
+	struct clk		*bus_clk;	/* SDCC bus voter clock */
 	unsigned int		clks_on;	/* set if clocks are enabled */
 
 	unsigned int		eject;		/* eject state */
@@ -411,6 +411,8 @@
 	struct mutex clk_mutex;
 	bool pending_resume;
 	struct msmsdcc_msm_bus_vote msm_bus_vote;
+	struct device_attribute	max_bus_bw;
+	struct device_attribute	polling;
 };
 
 int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/mtd/devices/msm_nand.c b/drivers/mtd/devices/msm_nand.c
index bd36aea..c43abca 100644
--- a/drivers/mtd/devices/msm_nand.c
+++ b/drivers/mtd/devices/msm_nand.c
@@ -1990,20 +1990,74 @@
 {
 	int ret;
 	struct mtd_oob_ops ops;
+	int (*read_oob)(struct mtd_info *, loff_t, struct mtd_oob_ops *);
 
-	/* printk("msm_nand_read %llx %x\n", from, len); */
+	if (!dual_nand_ctlr_present)
+		read_oob = msm_nand_read_oob;
+	else
+		read_oob = msm_nand_read_oob_dualnandc;
 
 	ops.mode = MTD_OPS_PLACE_OOB;
-	ops.len = len;
 	ops.retlen = 0;
 	ops.ooblen = 0;
-	ops.datbuf = buf;
 	ops.oobbuf = NULL;
-	if (!dual_nand_ctlr_present)
-		ret =  msm_nand_read_oob(mtd, from, &ops);
-	else
-		ret = msm_nand_read_oob_dualnandc(mtd, from, &ops);
-	*retlen = ops.retlen;
+	ret = 0;
+	*retlen = 0;
+
+	if ((from & (mtd->writesize - 1)) == 0 && len == mtd->writesize) {
+		/* reading a page on page boundary */
+		ops.len = len;
+		ops.datbuf = buf;
+		ret = read_oob(mtd, from, &ops);
+		*retlen = ops.retlen;
+	} else if (len > 0) {
+		/* reading any size on any offset. partial page is supported */
+		u8 *bounce_buf;
+		loff_t aligned_from;
+		loff_t offset;
+		size_t actual_len;
+
+		bounce_buf = kmalloc(mtd->writesize, GFP_KERNEL);
+		if (!bounce_buf) {
+			pr_err("%s: could not allocate memory\n", __func__);
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		ops.len = mtd->writesize;
+		offset = from & (mtd->writesize - 1);
+		aligned_from = from - offset;
+
+		for (;;) {
+			int no_copy;
+
+			actual_len = mtd->writesize - offset;
+			if (actual_len > len)
+				actual_len = len;
+
+			no_copy = (offset == 0 && actual_len == mtd->writesize);
+			ops.datbuf = (no_copy) ? buf : bounce_buf;
+			ret = read_oob(mtd, aligned_from, &ops);
+			if (ret < 0)
+				break;
+
+			if (!no_copy)
+				memcpy(buf, bounce_buf + offset, actual_len);
+
+			len -= actual_len;
+			*retlen += actual_len;
+			if (len == 0)
+				break;
+
+			buf += actual_len;
+			offset = 0;
+			aligned_from += mtd->writesize;
+		}
+
+		kfree(bounce_buf);
+	}
+
+out:
 	return ret;
 }
 
@@ -2963,18 +3017,54 @@
 {
 	int ret;
 	struct mtd_oob_ops ops;
+	int (*write_oob)(struct mtd_info *, loff_t, struct mtd_oob_ops *);
+
+	if (!dual_nand_ctlr_present)
+		write_oob = msm_nand_write_oob;
+	else
+		write_oob = msm_nand_write_oob_dualnandc;
 
 	ops.mode = MTD_OPS_PLACE_OOB;
-	ops.len = len;
 	ops.retlen = 0;
 	ops.ooblen = 0;
-	ops.datbuf = (uint8_t *)buf;
 	ops.oobbuf = NULL;
-	if (!dual_nand_ctlr_present)
-		ret =  msm_nand_write_oob(mtd, to, &ops);
-	else
-		ret =  msm_nand_write_oob_dualnandc(mtd, to, &ops);
-	*retlen = ops.retlen;
+	ret = 0;
+	*retlen = 0;
+
+	if (!virt_addr_valid(buf) &&
+	    ((to | len) & (mtd->writesize - 1)) == 0 &&
+	    ((unsigned long) buf & ~PAGE_MASK) + len > PAGE_SIZE) {
+		/*
+		 * Handle writing of large size write buffer in vmalloc
+		 * address space that does not fit in an MMU page.
+		 * The destination address must be on page boundary,
+		 * and the size must be multiple of NAND page size.
+		 * Writing partial page is not supported.
+		 */
+		ops.len = mtd->writesize;
+
+		for (;;) {
+			ops.datbuf = (uint8_t *) buf;
+
+			ret = write_oob(mtd, to, &ops);
+			if (ret < 0)
+				break;
+
+			len -= mtd->writesize;
+			*retlen += mtd->writesize;
+			if (len == 0)
+				break;
+
+			buf += mtd->writesize;
+			to += mtd->writesize;
+		}
+	} else {
+		ops.len = len;
+		ops.datbuf = (uint8_t *) buf;
+		ret = write_oob(mtd, to, &ops);
+		*retlen = ops.retlen;
+	}
+
 	return ret;
 }
 
@@ -6747,6 +6837,7 @@
 		mtd->writesize = supported_flash.pagesize * i;
 		mtd->oobsize   = supported_flash.oobsize  * i;
 		mtd->erasesize = supported_flash.blksize  * i;
+		mtd->writebufsize = mtd->writesize;
 
 		if (!interleave_enable)
 			mtd_writesize = mtd->writesize;
diff --git a/drivers/regulator/msm-gpio-regulator.c b/drivers/regulator/msm-gpio-regulator.c
index 5c99f4c..15e5b53 100644
--- a/drivers/regulator/msm-gpio-regulator.c
+++ b/drivers/regulator/msm-gpio-regulator.c
@@ -42,11 +42,13 @@
 	/* Request GPIO now if it hasn't been requested before. */
 	if (!vreg->gpio_requested) {
 		rc = gpio_request(vreg->gpio, vreg->gpio_label);
-		if (rc < 0)
+		if (rc < 0) {
 			pr_err("failed to request gpio %u (%s), rc=%d\n",
 				vreg->gpio, vreg->gpio_label, rc);
-		else
+			return rc;
+		} else {
 			vreg->gpio_requested = true;
+		}
 
 		rc = gpio_sysfs_set_active_low(vreg->gpio, vreg->active_low);
 		if (rc < 0)
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 3f63532..0342b97 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/spmi.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 
 struct spmii_boardinfo {
 	struct list_head	list;
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index df335d2..65bcb08 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -25,13 +25,14 @@
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <mach/subsystem_notif.h>
+#include <mach/subsystem_restart.h>
 #include <mach/msm_serial_hs.h>
 #include "smux_private.h"
 #include "smux_loopback.h"
 
 #define SMUX_NOTIFY_FIFO_SIZE	128
 #define SMUX_TX_QUEUE_SIZE	256
-#define SMUX_GET_RX_BUFF_MAX_RETRY_CNT 2
 #define SMUX_WM_LOW 2
 #define SMUX_WM_HIGH 4
 #define SMUX_PKT_LOG_SIZE 80
@@ -49,6 +50,10 @@
 /* inactivity timeout for no rx/tx activity */
 #define SMUX_INACTIVITY_TIMEOUT_MS 1000
 
+/* RX get_rx_buffer retry timeout values */
+#define SMUX_RX_RETRY_MIN_MS (1 << 0)  /* 1 ms */
+#define SMUX_RX_RETRY_MAX_MS (1 << 10) /* 1024 ms */
+
 enum {
 	MSM_SMUX_DEBUG = 1U << 0,
 	MSM_SMUX_INFO = 1U << 1,
@@ -175,6 +180,11 @@
 	int (*get_rx_buffer)(void *priv, void **pkt_priv, void **buffer,
 								int size);
 
+	/* RX Info */
+	struct list_head rx_retry_queue;
+	unsigned rx_retry_queue_cnt;
+	struct delayed_work rx_retry_work;
+
 	/* TX Info */
 	spinlock_t tx_lock_lhb2;
 	struct list_head tx_queue;
@@ -198,25 +208,54 @@
 };
 
 /**
+ * Get RX Buffer Retry structure.
+ *
+ * This is used for clients that are unable to provide an RX buffer
+ * immediately.  This temporary structure will be used to temporarily hold the
+ * data and perform a retry.
+ */
+struct smux_rx_pkt_retry {
+	struct smux_pkt_t *pkt;
+	struct list_head rx_retry_list;
+	unsigned timeout_in_ms;
+};
+
+/**
+ * Receive worker data structure.
+ *
+ * One instance is created for every call to smux_rx_state_machine.
+ */
+struct smux_rx_worker_data {
+	const unsigned char *data;
+	int len;
+	int flag;
+
+	struct work_struct work;
+	struct completion work_complete;
+};
+
+/**
  * Line discipline and module structure.
  *
  * Only one instance since multiple instances of line discipline are not
  * allowed.
  */
 struct smux_ldisc_t {
-	spinlock_t lock_lha0;
+	struct mutex mutex_lha0;
 
 	int is_initialized;
 	int in_reset;
 	int ld_open_count;
 	struct tty_struct *tty;
 
-	/* RX State Machine */
-	spinlock_t rx_lock_lha1;
+	/* RX State Machine (singled-threaded access by smux_rx_wq) */
 	unsigned char recv_buf[SMUX_MAX_PKT_SIZE];
 	unsigned int recv_len;
 	unsigned int pkt_remain;
 	unsigned rx_state;
+
+	/* RX Activity - accessed by multiple threads */
+	spinlock_t rx_lock_lha1;
 	unsigned rx_activity_flag;
 
 	/* TX / Power */
@@ -226,6 +265,7 @@
 	unsigned pwr_wakeup_delay_us;
 	unsigned tx_activity_flag;
 	unsigned powerdown_enabled;
+	struct list_head power_queue;
 };
 
 
@@ -259,10 +299,13 @@
 static DEFINE_SPINLOCK(notify_lock_lhc1);
 
 static struct workqueue_struct *smux_tx_wq;
+static struct workqueue_struct *smux_rx_wq;
 static void smux_tx_worker(struct work_struct *work);
 static DECLARE_WORK(smux_tx_work, smux_tx_worker);
 
 static void smux_wakeup_worker(struct work_struct *work);
+static void smux_rx_retry_worker(struct work_struct *work);
+static void smux_rx_worker(struct work_struct *work);
 static DECLARE_WORK(smux_wakeup_work, smux_wakeup_worker);
 static DECLARE_DELAYED_WORK(smux_wakeup_delayed_work, smux_wakeup_worker);
 
@@ -275,6 +318,13 @@
 static void list_channel(struct smux_lch_t *ch);
 static int smux_send_status_cmd(struct smux_lch_t *ch);
 static int smux_dispatch_rx_pkt(struct smux_pkt_t *pkt);
+static void smux_flush_tty(void);
+static void smux_purge_ch_tx_queue(struct smux_lch_t *ch);
+static int schedule_notify(uint8_t lcid, int event,
+			const union notifier_metadata *metadata);
+static int ssr_notifier_cb(struct notifier_block *this,
+				unsigned long code,
+				void *data);
 
 /**
  * Convert TTY Error Flags to string for logging purposes.
@@ -321,6 +371,7 @@
 
 	smux_notify_wq = create_singlethread_workqueue("smux_notify_wq");
 	smux_tx_wq = create_singlethread_workqueue("smux_tx_wq");
+	smux_rx_wq = create_singlethread_workqueue("smux_rx_wq");
 
 	if (IS_ERR(smux_notify_wq) || IS_ERR(smux_tx_wq)) {
 		SMUX_DBG("%s: create_singlethread_workqueue ENOMEM\n",
@@ -354,6 +405,10 @@
 		ch->notify = 0;
 		ch->get_rx_buffer = 0;
 
+		INIT_LIST_HEAD(&ch->rx_retry_queue);
+		ch->rx_retry_queue_cnt = 0;
+		INIT_DELAYED_WORK(&ch->rx_retry_work, smux_rx_retry_worker);
+
 		spin_lock_init(&ch->tx_lock_lhb2);
 		INIT_LIST_HEAD(&ch->tx_queue);
 		INIT_LIST_HEAD(&ch->tx_ready_list);
@@ -364,6 +419,82 @@
 	return 0;
 }
 
+/**
+ * Empty and cleanup all SMUX logical channels for subsystem restart or line
+ * discipline disconnect.
+ */
+static void smux_lch_purge(void)
+{
+	struct smux_lch_t *ch;
+	unsigned long flags;
+	int i;
+
+	/* Empty TX ready list */
+	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+	while (!list_empty(&smux.lch_tx_ready_list)) {
+		SMUX_DBG("%s: emptying ready list %p\n",
+				__func__, smux.lch_tx_ready_list.next);
+		ch = list_first_entry(&smux.lch_tx_ready_list,
+						struct smux_lch_t,
+						tx_ready_list);
+		list_del(&ch->tx_ready_list);
+		INIT_LIST_HEAD(&ch->tx_ready_list);
+	}
+
+	/* Purge Power Queue */
+	while (!list_empty(&smux.power_queue)) {
+		struct smux_pkt_t *pkt;
+
+		pkt =  list_first_entry(&smux.power_queue,
+						struct smux_pkt_t,
+						list);
+		SMUX_DBG("%s: emptying power queue pkt=%p\n",
+				__func__, pkt);
+		smux_free_pkt(pkt);
+	}
+	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+
+	/* Close all ports */
+	for (i = 0 ; i < SMUX_NUM_LOGICAL_CHANNELS; i++) {
+		ch = &smux_lch[i];
+		SMUX_DBG("%s: cleaning up lcid %d\n", __func__, i);
+
+		spin_lock_irqsave(&ch->state_lock_lhb1, flags);
+
+		/* Purge TX queue */
+		spin_lock(&ch->tx_lock_lhb2);
+		smux_purge_ch_tx_queue(ch);
+		spin_unlock(&ch->tx_lock_lhb2);
+
+		/* Notify user of disconnect and reset channel state */
+		if (ch->local_state == SMUX_LCH_LOCAL_OPENED ||
+			ch->local_state == SMUX_LCH_LOCAL_CLOSING) {
+			union notifier_metadata meta;
+
+			meta.disconnected.is_ssr = smux.in_reset;
+			schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
+		}
+
+		ch->local_state = SMUX_LCH_LOCAL_CLOSED;
+		ch->local_mode = SMUX_LCH_MODE_NORMAL;
+		ch->remote_state = SMUX_LCH_REMOTE_CLOSED;
+		ch->remote_mode = SMUX_LCH_MODE_NORMAL;
+		ch->tx_flow_control = 0;
+
+		/* Purge RX retry queue */
+		if (ch->rx_retry_queue_cnt)
+			queue_delayed_work(smux_rx_wq, &ch->rx_retry_work, 0);
+
+		spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+	}
+
+	/* Flush TX/RX workqueues */
+	SMUX_DBG("%s: flushing tx wq\n", __func__);
+	flush_workqueue(smux_tx_wq);
+	SMUX_DBG("%s: flushing rx wq\n", __func__);
+	flush_workqueue(smux_rx_wq);
+}
+
 int smux_assert_lch_id(uint32_t lcid)
 {
 	if (lcid >= SMUX_NUM_LOGICAL_CHANNELS)
@@ -785,7 +916,7 @@
 	if (!data)
 		return 0;
 
-	while (len > 0) {
+	while (len > 0 && !smux.in_reset) {
 		data_written = smux.tty->ops->write(smux.tty, data, len);
 		if (data_written >= 0) {
 			len -= data_written;
@@ -799,8 +930,6 @@
 		if (len)
 			tty_wait_until_sent(smux.tty,
 				msecs_to_jiffies(TTY_BUFFER_FULL_WAIT_MS));
-
-		/* FUTURE - add SSR logic */
 	}
 	return 0;
 }
@@ -866,19 +995,20 @@
  */
 static void smux_send_byte(char ch)
 {
-	struct smux_pkt_t pkt;
+	struct smux_pkt_t *pkt;
 
-	smux_init_pkt(&pkt);
+	pkt = smux_alloc_pkt();
+	if (!pkt) {
+		pr_err("%s: alloc failure for byte %x\n", __func__, ch);
+		return;
+	}
+	pkt->hdr.cmd = SMUX_CMD_BYTE;
+	pkt->hdr.flags = ch;
+	pkt->hdr.lcid = SMUX_BROADCAST_LCID;
+	pkt->hdr.flags = ch;
 
-	pkt.hdr.cmd = SMUX_CMD_BYTE;
-	pkt.hdr.flags = ch;
-	pkt.hdr.lcid = 0;
-	pkt.hdr.flags = ch;
-	SMUX_LOG_PKT_TX(&pkt);
-	if (!smux_byte_loopback)
-		smux_tx_tty(&pkt);
-	else
-		smux_tx_loopback(&pkt);
+	list_add_tail(&pkt->list, &smux.power_queue);
+	queue_work(smux_tx_wq, &smux_tx_work);
 }
 
 /**
@@ -888,8 +1018,6 @@
  * @lcid Logical channel ID for packet
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 locked.
  */
 static int smux_receive_byte(char ch, int lcid)
 {
@@ -931,8 +1059,6 @@
  * @pkt  Received packet
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 already locked.
  */
 static int smux_handle_rx_open_ack(struct smux_pkt_t *pkt)
 {
@@ -1021,8 +1147,6 @@
  * @pkt  Received packet
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 already locked.
  */
 static int smux_handle_rx_open_cmd(struct smux_pkt_t *pkt)
 {
@@ -1030,6 +1154,7 @@
 	int ret;
 	struct smux_lch_t *ch;
 	struct smux_pkt_t *ack_pkt;
+	unsigned long flags;
 	int tx_ready = 0;
 	int enable_powerdown = 0;
 
@@ -1039,7 +1164,7 @@
 	lcid = pkt->hdr.lcid;
 	ch = &smux_lch[lcid];
 
-	spin_lock(&ch->state_lock_lhb1);
+	spin_lock_irqsave(&ch->state_lock_lhb1, flags);
 
 	if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED) {
 		SMUX_DBG("lcid %d remote state 0x%x -> 0x%x\n", lcid,
@@ -1100,13 +1225,16 @@
 	}
 
 out:
-	spin_unlock(&ch->state_lock_lhb1);
+	spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
 
 	if (enable_powerdown) {
-		spin_lock(&smux.tx_lock_lha2);
-		smux.powerdown_enabled = 1;
-		SMUX_DBG("%s: enabling power-collapse support\n", __func__);
-		spin_unlock(&smux.tx_lock_lha2);
+		spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+		if (!smux.powerdown_enabled) {
+			smux.powerdown_enabled = 1;
+			SMUX_DBG("%s: enabling power-collapse support\n",
+					__func__);
+		}
+		spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 	}
 
 	if (tx_ready)
@@ -1121,8 +1249,6 @@
  * @pkt  Received packet
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 already locked.
  */
 static int smux_handle_rx_close_cmd(struct smux_pkt_t *pkt)
 {
@@ -1131,6 +1257,7 @@
 	struct smux_lch_t *ch;
 	struct smux_pkt_t *ack_pkt;
 	union notifier_metadata meta_disconnected;
+	unsigned long flags;
 	int tx_ready = 0;
 
 	if (pkt->hdr.flags & SMUX_CMD_CLOSE_ACK)
@@ -1140,7 +1267,7 @@
 	ch = &smux_lch[lcid];
 	meta_disconnected.disconnected.is_ssr = 0;
 
-	spin_lock(&ch->state_lock_lhb1);
+	spin_lock_irqsave(&ch->state_lock_lhb1, flags);
 	if (ch->remote_state == SMUX_LCH_REMOTE_OPENED) {
 		SMUX_DBG("lcid %d remote state 0x%x -> 0x%x\n", lcid,
 				SMUX_LCH_REMOTE_OPENED,
@@ -1191,7 +1318,7 @@
 		ret = -EINVAL;
 	}
 out:
-	spin_unlock(&ch->state_lock_lhb1);
+	spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
 	if (tx_ready)
 		list_channel(ch);
 
@@ -1204,25 +1331,30 @@
  * @pkt  Received packet
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 already locked.
  */
 static int smux_handle_rx_data_cmd(struct smux_pkt_t *pkt)
 {
 	uint8_t lcid;
-	int ret;
-	int i;
+	int ret = 0;
+	int do_retry = 0;
 	int tmp;
 	int rx_len;
 	struct smux_lch_t *ch;
 	union notifier_metadata metadata;
 	int remote_loopback;
-	int tx_ready = 0;
 	struct smux_pkt_t *ack_pkt;
 	unsigned long flags;
 
-	if (!pkt || smux_assert_lch_id(pkt->hdr.lcid))
-		return -ENXIO;
+	if (!pkt || smux_assert_lch_id(pkt->hdr.lcid)) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	rx_len = pkt->hdr.payload_len;
+	if (rx_len == 0) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	lcid = pkt->hdr.lcid;
 	ch = &smux_lch[lcid];
@@ -1234,6 +1366,7 @@
 		pr_err("smux: ch %d error data on local state 0x%x",
 					lcid, ch->local_state);
 		ret = -EIO;
+		spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
 		goto out;
 	}
 
@@ -1241,69 +1374,110 @@
 		pr_err("smux: ch %d error data on remote state 0x%x",
 					lcid, ch->remote_state);
 		ret = -EIO;
+		spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
 		goto out;
 	}
 
-	rx_len = pkt->hdr.payload_len;
-	if (rx_len == 0) {
-		ret = -EINVAL;
-		goto out;
+	if (!list_empty(&ch->rx_retry_queue)) {
+		do_retry = 1;
+		if ((ch->rx_retry_queue_cnt + 1) > SMUX_RX_RETRY_MAX_PKTS) {
+			/* retry queue full */
+			schedule_notify(lcid, SMUX_READ_FAIL, NULL);
+			ret = -ENOMEM;
+			spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+			goto out;
+		}
 	}
+	spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
 
-	for (i = 0; i < SMUX_GET_RX_BUFF_MAX_RETRY_CNT; ++i) {
+	if (remote_loopback) {
+		/* Echo the data back to the remote client. */
+		ack_pkt = smux_alloc_pkt();
+		if (ack_pkt) {
+			ack_pkt->hdr.lcid = lcid;
+			ack_pkt->hdr.cmd = SMUX_CMD_DATA;
+			ack_pkt->hdr.flags = 0;
+			ack_pkt->hdr.payload_len = pkt->hdr.payload_len;
+			if (ack_pkt->hdr.payload_len) {
+				smux_alloc_pkt_payload(ack_pkt);
+				memcpy(ack_pkt->payload, pkt->payload,
+						ack_pkt->hdr.payload_len);
+			}
+			ack_pkt->hdr.pad_len = pkt->hdr.pad_len;
+			smux_tx_queue(ack_pkt, ch, 0);
+			list_channel(ch);
+		} else {
+			pr_err("%s: Remote loopack allocation failure\n",
+					__func__);
+		}
+	} else if (!do_retry) {
+		/* request buffer from client */
 		metadata.read.pkt_priv = 0;
 		metadata.read.buffer = 0;
+		tmp = ch->get_rx_buffer(ch->priv,
+				(void **)&metadata.read.pkt_priv,
+				(void **)&metadata.read.buffer,
+				rx_len);
 
-		if (!remote_loopback) {
-			tmp = ch->get_rx_buffer(ch->priv,
-					(void **)&metadata.read.pkt_priv,
-					(void **)&metadata.read.buffer,
+		if (tmp == 0 && metadata.read.buffer) {
+			/* place data into RX buffer */
+			memcpy(metadata.read.buffer, pkt->payload,
 					rx_len);
-			if (tmp == 0 && metadata.read.buffer) {
-				/* place data into RX buffer */
-				memcpy(metadata.read.buffer, pkt->payload,
-								rx_len);
-				metadata.read.len = rx_len;
-				schedule_notify(lcid, SMUX_READ_DONE,
-								&metadata);
-				ret = 0;
-				break;
-			} else if (tmp == -EAGAIN) {
-				ret = -ENOMEM;
-			} else if (tmp < 0) {
-				schedule_notify(lcid, SMUX_READ_FAIL, NULL);
-				ret = -ENOMEM;
-				break;
-			} else if (!metadata.read.buffer) {
-				pr_err("%s: get_rx_buffer() buffer is NULL\n",
-					__func__);
-				ret = -ENOMEM;
-			}
-		} else {
-			/* Echo the data back to the remote client. */
-			ack_pkt = smux_alloc_pkt();
-			if (ack_pkt) {
-				ack_pkt->hdr.lcid = lcid;
-				ack_pkt->hdr.cmd = SMUX_CMD_DATA;
-				ack_pkt->hdr.flags = 0;
-				ack_pkt->hdr.payload_len = pkt->hdr.payload_len;
-				ack_pkt->payload = pkt->payload;
-				ack_pkt->hdr.pad_len = pkt->hdr.pad_len;
-				smux_tx_queue(ack_pkt, ch, 0);
-				tx_ready = 1;
-			} else {
-				pr_err("%s: Remote loopack allocation failure\n",
-						__func__);
-			}
+			metadata.read.len = rx_len;
+			schedule_notify(lcid, SMUX_READ_DONE,
+							&metadata);
+		} else if (tmp == -EAGAIN ||
+				(tmp == 0 && !metadata.read.buffer)) {
+			/* buffer allocation failed - add to retry queue */
+			do_retry = 1;
+		} else if (tmp < 0) {
+			schedule_notify(lcid, SMUX_READ_FAIL, NULL);
+			ret = -ENOMEM;
 		}
 	}
 
+	if (do_retry) {
+		struct smux_rx_pkt_retry *retry;
+
+		retry = kmalloc(sizeof(struct smux_rx_pkt_retry), GFP_KERNEL);
+		if (!retry) {
+			pr_err("%s: retry alloc failure\n", __func__);
+			ret = -ENOMEM;
+			schedule_notify(lcid, SMUX_READ_FAIL, NULL);
+			goto out;
+		}
+		INIT_LIST_HEAD(&retry->rx_retry_list);
+		retry->timeout_in_ms = SMUX_RX_RETRY_MIN_MS;
+
+		/* copy packet */
+		retry->pkt = smux_alloc_pkt();
+		if (!retry->pkt) {
+			kfree(retry);
+			pr_err("%s: pkt alloc failure\n", __func__);
+			ret = -ENOMEM;
+			schedule_notify(lcid, SMUX_READ_FAIL, NULL);
+			goto out;
+		}
+		retry->pkt->hdr.lcid = lcid;
+		retry->pkt->hdr.payload_len = pkt->hdr.payload_len;
+		retry->pkt->hdr.pad_len = pkt->hdr.pad_len;
+		if (retry->pkt->hdr.payload_len) {
+			smux_alloc_pkt_payload(retry->pkt);
+			memcpy(retry->pkt->payload, pkt->payload,
+					retry->pkt->hdr.payload_len);
+		}
+
+		/* add to retry queue */
+		spin_lock_irqsave(&ch->state_lock_lhb1, flags);
+		list_add_tail(&retry->rx_retry_list, &ch->rx_retry_queue);
+		++ch->rx_retry_queue_cnt;
+		if (ch->rx_retry_queue_cnt == 1)
+			queue_delayed_work(smux_rx_wq, &ch->rx_retry_work,
+				msecs_to_jiffies(retry->timeout_in_ms));
+		spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+	}
+
 out:
-	spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
-
-	if (tx_ready)
-		list_channel(ch);
-
 	return ret;
 }
 
@@ -1322,8 +1496,10 @@
 	union notifier_metadata metadata;
 	unsigned long flags;
 
-	if (!pkt || smux_assert_lch_id(pkt->hdr.lcid))
+	if (!pkt || smux_assert_lch_id(pkt->hdr.lcid)) {
+		pr_err("%s: invalid packet or channel id\n", __func__);
 		return -ENXIO;
+	}
 
 	lcid = pkt->hdr.lcid;
 	ch = &smux_lch[lcid];
@@ -1359,8 +1535,6 @@
  * @pkt  Received packet
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 already locked.
  */
 static int smux_handle_rx_status_cmd(struct smux_pkt_t *pkt)
 {
@@ -1416,15 +1590,13 @@
  * @pkt  Received packet
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 already locked.
  */
 static int smux_handle_rx_power_cmd(struct smux_pkt_t *pkt)
 {
-	int tx_ready = 0;
 	struct smux_pkt_t *ack_pkt = NULL;
+	unsigned long flags;
 
-	spin_lock(&smux.tx_lock_lha2);
+	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
 	if (pkt->hdr.flags & SMUX_CMD_PWR_CTL_ACK) {
 		/* local sleep request ack */
 		if (smux.power_state == SMUX_PWR_TURNING_OFF) {
@@ -1438,7 +1610,17 @@
 					__func__, smux.power_state);
 		}
 	} else {
-		/* remote sleep request */
+		/*
+		 * Remote sleep request
+		 *
+		 * Even if we have data pending, we need to transition to the
+		 * POWER_OFF state and then perform a wakeup since the remote
+		 * side has requested a power-down.
+		 *
+		 * The state here is set to SMUX_PWR_TURNING_OFF_FLUSH and
+		 * the TX thread will set the state to SMUX_PWR_TURNING_OFF
+		 * when it sends the packet.
+		 */
 		if (smux.power_state == SMUX_PWR_ON
 			|| smux.power_state == SMUX_PWR_TURNING_OFF) {
 			ack_pkt = smux_alloc_pkt();
@@ -1447,28 +1629,22 @@
 						smux.power_state,
 						SMUX_PWR_TURNING_OFF_FLUSH);
 
-				/* send power-down request */
+				smux.power_state = SMUX_PWR_TURNING_OFF_FLUSH;
+
+				/* send power-down ack */
 				ack_pkt->hdr.cmd = SMUX_CMD_PWR_CTL;
 				ack_pkt->hdr.flags = SMUX_CMD_PWR_CTL_ACK;
-				ack_pkt->hdr.lcid = pkt->hdr.lcid;
-				smux_tx_queue(ack_pkt,
-					      &smux_lch[ack_pkt->hdr.lcid], 0);
-				tx_ready = 1;
-				smux.power_state = SMUX_PWR_TURNING_OFF_FLUSH;
-				queue_delayed_work(smux_tx_wq,
-					&smux_delayed_inactivity_work,
-					msecs_to_jiffies(
-						SMUX_INACTIVITY_TIMEOUT_MS));
+				ack_pkt->hdr.lcid = SMUX_BROADCAST_LCID;
+				list_add_tail(&ack_pkt->list,
+						&smux.power_queue);
+				queue_work(smux_tx_wq, &smux_tx_work);
 			}
 		} else {
 			pr_err("%s: sleep request invalid in state %d\n",
 					__func__, smux.power_state);
 		}
 	}
-	spin_unlock(&smux.tx_lock_lha2);
-
-	if (tx_ready)
-		list_channel(&smux_lch[ack_pkt->hdr.lcid]);
+	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 
 	return 0;
 }
@@ -1479,8 +1655,6 @@
  * @pkt Packet to process
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 already locked.
  */
 static int smux_dispatch_rx_pkt(struct smux_pkt_t *pkt)
 {
@@ -1527,8 +1701,6 @@
  * @len     Length of the data
  *
  * @returns 0 for success
- *
- * Called with rx_lock_lha1 already locked.
  */
 static int smux_deserialize(unsigned char *data, int len)
 {
@@ -1562,12 +1734,12 @@
 
 /**
  * Handle wakeup request byte.
- *
- * Called with rx_lock_lha1 already locked.
  */
 static void smux_handle_wakeup_req(void)
 {
-	spin_lock(&smux.tx_lock_lha2);
+	unsigned long flags;
+
+	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
 	if (smux.power_state == SMUX_PWR_OFF
 		|| smux.power_state == SMUX_PWR_TURNING_ON) {
 		/* wakeup system */
@@ -1582,17 +1754,17 @@
 	} else {
 		smux_send_byte(SMUX_WAKEUP_ACK);
 	}
-	spin_unlock(&smux.tx_lock_lha2);
+	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 }
 
 /**
  * Handle wakeup request ack.
- *
- * Called with rx_lock_lha1 already locked.
  */
 static void smux_handle_wakeup_ack(void)
 {
-	spin_lock(&smux.tx_lock_lha2);
+	unsigned long flags;
+
+	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__,
@@ -1607,7 +1779,7 @@
 		pr_err("%s: wakeup request ack invalid in state %d\n",
 				__func__, smux.power_state);
 	}
-	spin_unlock(&smux.tx_lock_lha2);
+	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 }
 
 /**
@@ -1617,8 +1789,6 @@
  * @len   Length of the data
  * @used  Return value of length processed
  * @flag  Error flag - TTY_NORMAL 0 for no failure
- *
- * Called with rx_lock_lha1 locked.
  */
 static void smux_rx_handle_idle(const unsigned char *data,
 		int len, int *used, int flag)
@@ -1666,8 +1836,6 @@
  * @len   Length of the data
  * @used  Return value of length processed
  * @flag  Error flag - TTY_NORMAL 0 for no failure
- *
- * Called with rx_lock_lha1 locked.
  */
 static void smux_rx_handle_magic(const unsigned char *data,
 		int len, int *used, int flag)
@@ -1707,8 +1875,6 @@
  * @len   Length of the data
  * @used  Return value of length processed
  * @flag  Error flag - TTY_NORMAL 0 for no failure
- *
- * Called with rx_lock_lha1 locked.
  */
 static void smux_rx_handle_hdr(const unsigned char *data,
 		int len, int *used, int flag)
@@ -1744,8 +1910,6 @@
  * @len   Length of the data
  * @used  Return value of length processed
  * @flag  Error flag - TTY_NORMAL 0 for no failure
- *
- * Called with rx_lock_lha1 locked.
  */
 static void smux_rx_handle_pkt_payload(const unsigned char *data,
 		int len, int *used, int flag)
@@ -1784,47 +1948,20 @@
  * @data Pointer to data block
  * @len  Length of data
  * @flag TTY_NORMAL (0) for no error, otherwise TTY Error Flag
- *
- * Called with rx_lock_lha1 locked.
  */
 void smux_rx_state_machine(const unsigned char *data,
 						int len, int flag)
 {
-	unsigned long flags;
-	int used;
-	int initial_rx_state;
+	struct smux_rx_worker_data work;
 
+	work.data = data;
+	work.len = len;
+	work.flag = flag;
+	INIT_WORK_ONSTACK(&work.work, smux_rx_worker);
+	work.work_complete = COMPLETION_INITIALIZER_ONSTACK(work.work_complete);
 
-	SMUX_DBG("%s: %p, len=%d, flag=%d\n", __func__, data, len, flag);
-	spin_lock_irqsave(&smux.rx_lock_lha1, flags);
-	used = 0;
-	smux.rx_activity_flag = 1;
-	do {
-		SMUX_DBG("%s: state %d; %d of %d\n",
-				__func__, smux.rx_state, used, len);
-		initial_rx_state = smux.rx_state;
-
-		switch (smux.rx_state) {
-		case SMUX_RX_IDLE:
-			smux_rx_handle_idle(data, len, &used, flag);
-			break;
-		case SMUX_RX_MAGIC:
-			smux_rx_handle_magic(data, len, &used, flag);
-			break;
-		case SMUX_RX_HDR:
-			smux_rx_handle_hdr(data, len, &used, flag);
-			break;
-		case SMUX_RX_PAYLOAD:
-			smux_rx_handle_pkt_payload(data, len, &used, flag);
-			break;
-		default:
-			SMUX_DBG("%s: invalid state %d\n",
-					__func__, smux.rx_state);
-			smux.rx_state = SMUX_RX_IDLE;
-			break;
-		}
-	} while (used < len || smux.rx_state != initial_rx_state);
-	spin_unlock_irqrestore(&smux.rx_lock_lha1, flags);
+	queue_work(smux_rx_wq, &work.work);
+	wait_for_completion(&work.work_complete);
 }
 
 /**
@@ -1889,6 +2026,67 @@
 }
 
 /**
+ * Flush pending TTY TX data.
+ */
+static void smux_flush_tty(void)
+{
+	if (!smux.tty) {
+		pr_err("%s: ldisc not loaded\n", __func__);
+		return;
+	}
+
+	tty_wait_until_sent(smux.tty,
+			msecs_to_jiffies(TTY_BUFFER_FULL_WAIT_MS));
+
+	if (tty_chars_in_buffer(smux.tty) > 0)
+		pr_err("%s: unable to flush UART queue\n", __func__);
+}
+
+/**
+ * Purge TX queue for logical channel.
+ *
+ * @ch     Logical channel pointer
+ *
+ * Must be called with the following spinlocks locked:
+ *  state_lock_lhb1
+ *  tx_lock_lhb2
+ */
+static void smux_purge_ch_tx_queue(struct smux_lch_t *ch)
+{
+	struct smux_pkt_t *pkt;
+	int send_disconnect = 0;
+
+	while (!list_empty(&ch->tx_queue)) {
+		pkt = list_first_entry(&ch->tx_queue, struct smux_pkt_t,
+							list);
+		list_del(&pkt->list);
+
+		if (pkt->hdr.cmd == SMUX_CMD_OPEN_LCH) {
+			/* Open was never sent, just force to closed state */
+			ch->local_state = SMUX_LCH_LOCAL_CLOSED;
+			send_disconnect = 1;
+		} else if (pkt->hdr.cmd == SMUX_CMD_DATA) {
+			/* Notify client of failed write */
+			union notifier_metadata meta_write;
+
+			meta_write.write.pkt_priv = pkt->priv;
+			meta_write.write.buffer = pkt->payload;
+			meta_write.write.len = pkt->hdr.payload_len;
+			schedule_notify(ch->lcid, SMUX_WRITE_FAIL, &meta_write);
+		}
+		smux_free_pkt(pkt);
+	}
+
+	if (send_disconnect) {
+		union notifier_metadata meta_disconnected;
+
+		meta_disconnected.disconnected.is_ssr = smux.in_reset;
+		schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+			&meta_disconnected);
+	}
+}
+
+/**
  * Power-up the UART.
  */
 static void smux_uart_power_on(void)
@@ -1934,7 +2132,7 @@
 	unsigned wakeup_delay;
 	int complete = 0;
 
-	for (;;) {
+	while (!smux.in_reset) {
 		spin_lock_irqsave(&smux.tx_lock_lha2, flags);
 		if (smux.power_state == SMUX_PWR_ON) {
 			/* wakeup complete */
@@ -1990,7 +2188,6 @@
  */
 static void smux_inactivity_worker(struct work_struct *work)
 {
-	int tx_ready = 0;
 	struct smux_pkt_t *pkt;
 	unsigned long flags;
 
@@ -2012,11 +2209,13 @@
 					/* send power-down request */
 					pkt->hdr.cmd = SMUX_CMD_PWR_CTL;
 					pkt->hdr.flags = 0;
-					pkt->hdr.lcid = 0;
-					smux_tx_queue(pkt,
-						&smux_lch[SMUX_TEST_LCID],
-						0);
-					tx_ready = 1;
+					pkt->hdr.lcid = SMUX_BROADCAST_LCID;
+					list_add_tail(&pkt->list,
+							&smux.power_queue);
+					queue_work(smux_tx_wq, &smux_tx_work);
+				} else {
+					pr_err("%s: packet alloc failed\n",
+							__func__);
 				}
 			}
 		} else {
@@ -2027,21 +2226,26 @@
 	smux.tx_activity_flag = 0;
 	smux.rx_activity_flag = 0;
 
-	spin_unlock(&smux.tx_lock_lha2);
-	spin_unlock_irqrestore(&smux.rx_lock_lha1, flags);
-
-	if (tx_ready)
-		list_channel(&smux_lch[SMUX_TEST_LCID]);
-
-	if ((smux.power_state == SMUX_PWR_OFF_FLUSH) ||
-	    (smux.power_state == SMUX_PWR_TURNING_OFF_FLUSH)) {
+	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.power_state, SMUX_PWR_OFF);
+
+		/* if data is pending, schedule a new wakeup */
+		if (!list_empty(&smux.lch_tx_ready_list) ||
+		   !list_empty(&smux.power_queue))
+			queue_work(smux_tx_wq, &smux_tx_work);
+
+		spin_unlock(&smux.tx_lock_lha2);
+		spin_unlock_irqrestore(&smux.rx_lock_lha1, flags);
+
+		/* flush UART output queue and power down */
+		smux_flush_tty();
 		smux_uart_power_off();
-		spin_lock_irqsave(&smux.tx_lock_lha2, flags);
-		smux.power_state = SMUX_PWR_OFF;
-		spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+	} else {
+		spin_unlock(&smux.tx_lock_lha2);
+		spin_unlock_irqrestore(&smux.rx_lock_lha1, flags);
 	}
 
 	/* reschedule inactivity worker */
@@ -2051,6 +2255,167 @@
 }
 
 /**
+ * Remove RX retry packet from channel and free it.
+ *
+ * Must be called with state_lock_lhb1 locked.
+ *
+ * @ch    Channel for retry packet
+ * @retry Retry packet to remove
+ */
+void smux_remove_rx_retry(struct smux_lch_t *ch,
+		struct smux_rx_pkt_retry *retry)
+{
+	list_del(&retry->rx_retry_list);
+	--ch->rx_retry_queue_cnt;
+	smux_free_pkt(retry->pkt);
+	kfree(retry);
+}
+
+/**
+ * RX worker handles all receive operations.
+ *
+ * @work  Work structure contained in TBD structure
+ */
+static void smux_rx_worker(struct work_struct *work)
+{
+	unsigned long flags;
+	int used;
+	int initial_rx_state;
+	struct smux_rx_worker_data *w;
+	const unsigned char *data;
+	int len;
+	int flag;
+
+	w =  container_of(work, struct smux_rx_worker_data, work);
+	data = w->data;
+	len = w->len;
+	flag = w->flag;
+
+	spin_lock_irqsave(&smux.rx_lock_lha1, flags);
+	smux.rx_activity_flag = 1;
+	spin_unlock_irqrestore(&smux.rx_lock_lha1, flags);
+
+	SMUX_DBG("%s: %p, len=%d, flag=%d\n", __func__, data, len, flag);
+	used = 0;
+	do {
+		SMUX_DBG("%s: state %d; %d of %d\n",
+				__func__, smux.rx_state, used, len);
+		initial_rx_state = smux.rx_state;
+
+		switch (smux.rx_state) {
+		case SMUX_RX_IDLE:
+			smux_rx_handle_idle(data, len, &used, flag);
+			break;
+		case SMUX_RX_MAGIC:
+			smux_rx_handle_magic(data, len, &used, flag);
+			break;
+		case SMUX_RX_HDR:
+			smux_rx_handle_hdr(data, len, &used, flag);
+			break;
+		case SMUX_RX_PAYLOAD:
+			smux_rx_handle_pkt_payload(data, len, &used, flag);
+			break;
+		default:
+			SMUX_DBG("%s: invalid state %d\n",
+					__func__, smux.rx_state);
+			smux.rx_state = SMUX_RX_IDLE;
+			break;
+		}
+	} while (used < len || smux.rx_state != initial_rx_state);
+
+	complete(&w->work_complete);
+}
+
+/**
+ * RX Retry worker handles retrying get_rx_buffer calls that previously failed
+ * because the client was not ready (-EAGAIN).
+ *
+ * @work  Work structure contained in smux_lch_t structure
+ */
+static void smux_rx_retry_worker(struct work_struct *work)
+{
+	struct smux_lch_t *ch;
+	struct smux_rx_pkt_retry *retry;
+	union notifier_metadata metadata;
+	int tmp;
+	unsigned long flags;
+
+	ch = container_of(work, struct smux_lch_t, rx_retry_work.work);
+
+	/* get next retry packet */
+	spin_lock_irqsave(&ch->state_lock_lhb1, flags);
+	if (ch->local_state != SMUX_LCH_LOCAL_OPENED) {
+		/* port has been closed - remove all retries */
+		while (!list_empty(&ch->rx_retry_queue)) {
+			retry = list_first_entry(&ch->rx_retry_queue,
+						struct smux_rx_pkt_retry,
+						rx_retry_list);
+			smux_remove_rx_retry(ch, retry);
+		}
+	}
+
+	if (list_empty(&ch->rx_retry_queue)) {
+		SMUX_DBG("%s: retry list empty for channel %d\n",
+				__func__, ch->lcid);
+		spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+		return;
+	}
+	retry = list_first_entry(&ch->rx_retry_queue,
+					struct smux_rx_pkt_retry,
+					rx_retry_list);
+	spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+
+	SMUX_DBG("%s: retrying rx pkt %p\n", __func__, retry);
+	metadata.read.pkt_priv = 0;
+	metadata.read.buffer = 0;
+	tmp = ch->get_rx_buffer(ch->priv,
+			(void **)&metadata.read.pkt_priv,
+			(void **)&metadata.read.buffer,
+			retry->pkt->hdr.payload_len);
+	if (tmp == 0 && metadata.read.buffer) {
+		/* have valid RX buffer */
+		memcpy(metadata.read.buffer, retry->pkt->payload,
+						retry->pkt->hdr.payload_len);
+		metadata.read.len = retry->pkt->hdr.payload_len;
+
+		spin_lock_irqsave(&ch->state_lock_lhb1, flags);
+		smux_remove_rx_retry(ch, retry);
+		spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+
+		schedule_notify(ch->lcid, SMUX_READ_DONE, &metadata);
+	} else if (tmp == -EAGAIN ||
+			(tmp == 0 && !metadata.read.buffer)) {
+		/* retry again */
+		retry->timeout_in_ms <<= 1;
+		if (retry->timeout_in_ms > SMUX_RX_RETRY_MAX_MS) {
+			/* timed out */
+			spin_lock_irqsave(&ch->state_lock_lhb1, flags);
+			smux_remove_rx_retry(ch, retry);
+			schedule_notify(ch->lcid, SMUX_READ_FAIL, NULL);
+			spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+		}
+	} else {
+		/* client error - drop packet */
+		spin_lock_irqsave(&ch->state_lock_lhb1, flags);
+		smux_remove_rx_retry(ch, retry);
+		spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+
+		schedule_notify(ch->lcid, SMUX_READ_FAIL, NULL);
+	}
+
+	/* schedule next retry */
+	spin_lock_irqsave(&ch->state_lock_lhb1, flags);
+	if (!list_empty(&ch->rx_retry_queue)) {
+		retry = list_first_entry(&ch->rx_retry_queue,
+						struct smux_rx_pkt_retry,
+						rx_retry_list);
+		queue_delayed_work(smux_rx_wq, &ch->rx_retry_work,
+				msecs_to_jiffies(retry->timeout_in_ms));
+	}
+	spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
+}
+
+/**
  * Transmit worker handles serializing and transmitting packets onto the
  * underlying transport.
  *
@@ -2078,27 +2443,17 @@
 	 * inserting after the tail.  The locks can then be released
 	 * while the packet is processed.
 	 */
-	for (;;) {
+	while (!smux.in_reset) {
 		pkt = NULL;
 		low_wm_notif = 0;
 
-		/* get the next ready channel */
 		spin_lock_irqsave(&smux.tx_lock_lha2, flags);
-		if (list_empty(&smux.lch_tx_ready_list)) {
-			/* no ready channels */
-			SMUX_DBG("%s: no more ready channels, exiting\n",
-					__func__);
-			spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
-			break;
-		}
-		smux.tx_activity_flag = 1;
 
-		if (smux.power_state != SMUX_PWR_ON
-			&& smux.power_state != SMUX_PWR_TURNING_OFF
-			&& smux.power_state != SMUX_PWR_TURNING_OFF_FLUSH) {
-			/* Link isn't ready to transmit */
-			if (smux.power_state == SMUX_PWR_OFF) {
-				/* link is off, trigger wakeup */
+		/* handle wakeup if needed */
+		if (smux.power_state == SMUX_PWR_OFF) {
+			if (!list_empty(&smux.lch_tx_ready_list) ||
+			   !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.power_state,
@@ -2109,15 +2464,65 @@
 				smux_uart_power_on();
 				queue_work(smux_tx_wq, &smux_wakeup_work);
 			} else {
-				SMUX_DBG("%s: can not tx with power state %d\n",
-						__func__,
-						smux.power_state);
+				/* no activity -- stay asleep */
 				spin_unlock_irqrestore(&smux.tx_lock_lha2,
 						flags);
 			}
 			break;
 		}
 
+		/* process any pending power packets */
+		if (!list_empty(&smux.power_queue)) {
+			pkt = list_first_entry(&smux.power_queue,
+					struct smux_pkt_t, list);
+			list_del(&pkt->list);
+			spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+
+			/* send the packet */
+			SMUX_LOG_PKT_TX(pkt);
+			if (!smux_byte_loopback) {
+				smux_tx_tty(pkt);
+				smux_flush_tty();
+			} else {
+				smux_tx_loopback(pkt);
+			}
+
+			/* Adjust power state if this is a flush command */
+			spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+			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.power_state,
+						SMUX_PWR_OFF_FLUSH);
+				smux.power_state = SMUX_PWR_OFF_FLUSH;
+				queue_work(smux_tx_wq, &smux_inactivity_work);
+			}
+			spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+
+			smux_free_pkt(pkt);
+			continue;
+		}
+
+		/* get the next ready channel */
+		if (list_empty(&smux.lch_tx_ready_list)) {
+			/* no ready channels */
+			SMUX_DBG("%s: no more ready channels, exiting\n",
+					__func__);
+			spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+			break;
+		}
+		smux.tx_activity_flag = 1;
+
+		if (smux.power_state != SMUX_PWR_ON) {
+			/* channel not ready to transmit */
+			SMUX_DBG("%s: can not tx with power state %d\n",
+					__func__,
+					smux.power_state);
+			spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+			break;
+		}
+
 		/* get the next packet to send and rotate channel list */
 		ch = list_first_entry(&smux.lch_tx_ready_list,
 						struct smux_lch_t,
@@ -2355,30 +2760,7 @@
 
 	/* Purge TX queue */
 	spin_lock(&ch->tx_lock_lhb2);
-	while (!list_empty(&ch->tx_queue)) {
-		pkt = list_first_entry(&ch->tx_queue, struct smux_pkt_t,
-							list);
-		list_del(&pkt->list);
-
-		if (pkt->hdr.cmd == SMUX_CMD_OPEN_LCH) {
-			/* Open was never sent, just force to closed state */
-			union notifier_metadata meta_disconnected;
-
-			ch->local_state = SMUX_LCH_LOCAL_CLOSED;
-			meta_disconnected.disconnected.is_ssr = 0;
-			schedule_notify(lcid, SMUX_DISCONNECTED,
-				&meta_disconnected);
-		} else if (pkt->hdr.cmd == SMUX_CMD_DATA) {
-			/* Notify client of failed write */
-			union notifier_metadata meta_write;
-
-			meta_write.write.pkt_priv = pkt->priv;
-			meta_write.write.buffer = pkt->payload;
-			meta_write.write.len = pkt->hdr.payload_len;
-			schedule_notify(ch->lcid, SMUX_WRITE_FAIL, &meta_write);
-		}
-		smux_free_pkt(pkt);
-	}
+	smux_purge_ch_tx_queue(ch);
 	spin_unlock(&ch->tx_lock_lhb2);
 
 	/* Send Close Command */
@@ -2402,6 +2784,10 @@
 			pr_err("%s: pkt allocation failed\n", __func__);
 			ret = -ENOMEM;
 		}
+
+		/* Purge RX retry queue */
+		if (ch->rx_retry_queue_cnt)
+			queue_delayed_work(smux_rx_wq, &ch->rx_retry_work, 0);
 	}
 	spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
 
@@ -2700,8 +3086,59 @@
 }
 
 /**********************************************************************/
+/* Subsystem Restart                                                  */
+/**********************************************************************/
+static struct notifier_block ssr_notifier = {
+	.notifier_call = ssr_notifier_cb,
+};
+
+/**
+ * Handle Subsystem Restart (SSR) notifications.
+ *
+ * @this Pointer to ssr_notifier
+ * @code SSR Code
+ * @data Data pointer (not used)
+ */
+static int ssr_notifier_cb(struct notifier_block *this,
+				unsigned long code,
+				void *data)
+{
+	unsigned long flags;
+	int power_off_uart = 0;
+
+	if (code != SUBSYS_AFTER_SHUTDOWN)
+		return NOTIFY_DONE;
+
+	/* Cleanup channels */
+	smux_lch_purge();
+
+	/* 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.power_state = SMUX_PWR_OFF;
+		power_off_uart = 1;
+	}
+	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+
+	if (power_off_uart)
+		smux_uart_power_off();
+
+	return NOTIFY_DONE;
+}
+
+/**********************************************************************/
 /* Line Discipline Interface                                          */
 /**********************************************************************/
+static void smux_pdev_release(struct device *dev)
+{
+	struct platform_device *pdev;
+
+	pdev = container_of(dev, struct platform_device, dev);
+	SMUX_DBG("%s: releasing pdev %p '%s'\n", __func__, pdev, pdev->name);
+	memset(&pdev->dev, 0x0, sizeof(pdev->dev));
+}
+
 static int smuxld_open(struct tty_struct *tty)
 {
 	int i;
@@ -2711,66 +3148,94 @@
 	if (!smux.is_initialized)
 		return -ENODEV;
 
-	spin_lock_irqsave(&smux.lock_lha0, flags);
+	mutex_lock(&smux.mutex_lha0);
 	if (smux.ld_open_count) {
 		pr_err("%s: %p multiple instances not supported\n",
 			__func__, tty);
-		spin_unlock_irqrestore(&smux.lock_lha0, flags);
+		mutex_unlock(&smux.mutex_lha0);
 		return -EEXIST;
 	}
 
-	++smux.ld_open_count;
 	if (tty->ops->write == NULL) {
-		spin_unlock_irqrestore(&smux.lock_lha0, flags);
+		pr_err("%s: tty->ops->write already NULL\n", __func__);
+		mutex_unlock(&smux.mutex_lha0);
 		return -EINVAL;
 	}
 
 	/* connect to TTY */
+	++smux.ld_open_count;
+	smux.in_reset = 0;
 	smux.tty = tty;
 	tty->disc_data = &smux;
 	tty->receive_room = TTY_RECEIVE_ROOM;
 	tty_driver_flush_buffer(tty);
 
 	/* power-down the UART if we are idle */
-	spin_lock(&smux.tx_lock_lha2);
+	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
 	if (smux.power_state == SMUX_PWR_OFF) {
 		SMUX_DBG("%s: powering off uart\n", __func__);
 		smux.power_state = SMUX_PWR_OFF_FLUSH;
-		spin_unlock(&smux.tx_lock_lha2);
+		spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 		queue_work(smux_tx_wq, &smux_inactivity_work);
 	} else {
-		spin_unlock(&smux.tx_lock_lha2);
+		spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
 	}
-	spin_unlock_irqrestore(&smux.lock_lha0, flags);
 
 	/* register platform devices */
 	for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+		SMUX_DBG("%s: register pdev '%s'\n",
+				__func__, smux_devs[i].name);
+		smux_devs[i].dev.release = smux_pdev_release;
 		tmp = platform_device_register(&smux_devs[i]);
 		if (tmp)
 			pr_err("%s: error %d registering device %s\n",
 				   __func__, tmp, smux_devs[i].name);
 	}
+	mutex_unlock(&smux.mutex_lha0);
 	return 0;
 }
 
 static void smuxld_close(struct tty_struct *tty)
 {
 	unsigned long flags;
+	int power_up_uart = 0;
 	int i;
 
-	spin_lock_irqsave(&smux.lock_lha0, flags);
+	SMUX_DBG("%s: ldisc unload\n", __func__);
+	mutex_lock(&smux.mutex_lha0);
 	if (smux.ld_open_count <= 0) {
 		pr_err("%s: invalid ld count %d\n", __func__,
 			smux.ld_open_count);
-		spin_unlock_irqrestore(&smux.lock_lha0, flags);
+		mutex_unlock(&smux.mutex_lha0);
 		return;
 	}
-	spin_unlock_irqrestore(&smux.lock_lha0, flags);
-
-	for (i = 0; i < ARRAY_SIZE(smux_devs); ++i)
-		platform_device_unregister(&smux_devs[i]);
-
+	smux.in_reset = 1;
 	--smux.ld_open_count;
+
+	/* Cleanup channels */
+	smux_lch_purge();
+
+	/* Unregister platform devices */
+	for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+		SMUX_DBG("%s: unregister pdev '%s'\n",
+				__func__, smux_devs[i].name);
+		platform_device_unregister(&smux_devs[i]);
+	}
+
+	/* Schedule UART power-up if it's down */
+	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+	if (smux.power_state == SMUX_PWR_OFF)
+		power_up_uart = 1;
+	smux.power_state = SMUX_PWR_OFF;
+	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+
+	if (power_up_uart)
+		smux_uart_power_on();
+
+	/* Disconnect from TTY */
+	smux.tty = NULL;
+	mutex_unlock(&smux.mutex_lha0);
+	SMUX_DBG("%s: ldisc complete\n", __func__);
 }
 
 /**
@@ -2879,13 +3344,14 @@
 {
 	int ret;
 
-	spin_lock_init(&smux.lock_lha0);
+	mutex_init(&smux.mutex_lha0);
 
 	spin_lock_init(&smux.rx_lock_lha1);
 	smux.rx_state = SMUX_RX_IDLE;
 	smux.power_state = SMUX_PWR_OFF;
 	smux.pwr_wakeup_delay_us = 1;
 	smux.powerdown_enabled = 0;
+	INIT_LIST_HEAD(&smux.power_queue);
 	smux.rx_activity_flag = 0;
 	smux.tx_activity_flag = 0;
 	smux.recv_len = 0;
@@ -2905,6 +3371,8 @@
 		return ret;
 	}
 
+	subsys_notif_register_notifier("qsc", &ssr_notifier);
+
 	ret = lch_init();
 	if (ret != 0) {
 		pr_err("%s: lch_init failed\n", __func__);
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 59104ed..4a65177 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -1220,6 +1220,9 @@
 	msm_hsl_write(port, CR_PROTECTION_EN, regmap[vid][UARTDM_CR]);
 	msm_hsl_write(port, UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]);
 
+	msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]);
+	msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
+
 	printk(KERN_INFO "msm_serial_hsl: console setup on port #%d\n",
 	       port->line);
 
diff --git a/drivers/tty/smux_private.h b/drivers/tty/smux_private.h
index 6bd9713..f644ff0 100644
--- a/drivers/tty/smux_private.h
+++ b/drivers/tty/smux_private.h
@@ -16,6 +16,7 @@
 #define SMUX_PRIVATE_H
 
 #define SMUX_MAX_PKT_SIZE   8192
+#define SMUX_BROADCAST_LCID 0xFF
 
 /* SMUX Protocol Characters */
 #define SMUX_MAGIC          0x33FC
@@ -29,6 +30,9 @@
 #define SMUX_UT_ECHO_ACK_OK 0xF1
 #define SMUX_UT_ECHO_ACK_FAIL 0xF2
 
+/* Maximum number of packets in retry queue */
+#define SMUX_RX_RETRY_MAX_PKTS 32
+
 struct tty_struct;
 
 /* Packet header. */
diff --git a/drivers/tty/smux_test.c b/drivers/tty/smux_test.c
index 242c66e..62e9465 100644
--- a/drivers/tty/smux_test.c
+++ b/drivers/tty/smux_test.c
@@ -75,9 +75,44 @@
 	} \
 	do {} while (0)
 
+/**
+ * In-range unit test assertion for test cases.
+ *
+ * @a lval
+ * @minv Minimum value
+ * @maxv Maximum value
+ *
+ * Assertion fails if @a is not on the exclusive range minv, maxv
+ * ((@a < @minv) or (@a > @maxv)).  In the failure case, the macro
+ * logs the function and line number where the error occurred along
+ * with the values of @a and @minv, @maxv.
+ *
+ * Assumes that the following local variables exist:
+ * @buf - buffer to write failure message to
+ * @i - number of bytes written to buffer
+ * @max - maximum size of the buffer
+ * @failed - set to true if test fails
+ */
+#define UT_ASSERT_INT_IN_RANGE(a, minv, maxv) \
+	if (((a) < (minv)) || ((a) > (maxv))) { \
+		i += scnprintf(buf + i, max - i, \
+			"%s:%d Fail: " #a "(%d) < " #minv "(%d) or " \
+				 #a "(%d) > " #maxv "(%d)\n", \
+				__func__, __LINE__, \
+				a, minv, a, maxv); \
+		failed = 1; \
+		break; \
+	} \
+	do {} while (0)
+
+
 static unsigned char test_array[] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55,
 					89, 144, 233};
 
+/* when 1, forces failure of get_rx_buffer_mock function */
+static int get_rx_buffer_mock_fail;
+
+
 /* Used for mapping local to remote TIOCM signals */
 struct tiocm_test_vector {
 	uint32_t input;
@@ -93,7 +128,7 @@
 {
 	void *rx_buf;
 
-	rx_buf = kmalloc(size, GFP_ATOMIC);
+	rx_buf = kmalloc(size, GFP_KERNEL);
 	*pkt_priv = (void *)0x1234;
 	*buffer = rx_buf;
 
@@ -118,6 +153,13 @@
 	struct smux_meta_write meta;
 };
 
+/* Mock object metadata for get_rx_buffer failure event */
+struct mock_get_rx_buff_event {
+	struct list_head list;
+	int size;
+	unsigned long jiffies;
+};
+
 /* Mock object for all SMUX callback events */
 struct smux_mock_callback {
 	int cb_count;
@@ -140,6 +182,10 @@
 	int event_read_failed;
 	struct list_head read_events;
 
+	/* read retry data */
+	int get_rx_buff_retry_count;
+	struct list_head get_rx_buff_retry_events;
+
 	/* write event data */
 	int event_write_done;
 	int event_write_failed;
@@ -156,6 +202,7 @@
 	init_completion(&cb->cb_completion);
 	spin_lock_init(&cb->lock);
 	INIT_LIST_HEAD(&cb->read_events);
+	INIT_LIST_HEAD(&cb->get_rx_buff_retry_events);
 	INIT_LIST_HEAD(&cb->write_events);
 }
 
@@ -191,6 +238,16 @@
 		kfree(meta);
 	}
 
+	cb->get_rx_buff_retry_count = 0;
+	while (!list_empty(&cb->get_rx_buff_retry_events)) {
+		struct mock_get_rx_buff_event *meta;
+		meta = list_first_entry(&cb->get_rx_buff_retry_events,
+				struct mock_get_rx_buff_event,
+				list);
+		list_del(&meta->list);
+		kfree(meta);
+	}
+
 	cb->event_write_done = 0;
 	cb->event_write_failed = 0;
 	while (!list_empty(&cb->write_events)) {
@@ -229,6 +286,8 @@
 		"\tevent_read_done=%d\n"
 		"\tevent_read_failed=%d\n"
 		"\tread_events=%d\n"
+		"\tget_rx_retry=%d\n"
+		"\tget_rx_retry_events=%d\n"
 		"\tevent_write_done=%d\n"
 		"\tevent_write_failed=%d\n"
 		"\twrite_events=%d\n",
@@ -243,6 +302,8 @@
 		cb->event_read_done,
 		cb->event_read_failed,
 		!list_empty(&cb->read_events),
+		cb->get_rx_buff_retry_count,
+		!list_empty(&cb->get_rx_buff_retry_events),
 		cb->event_write_done,
 		cb->event_write_failed,
 		list_empty(&cb->write_events)
@@ -268,83 +329,105 @@
 		return;
 	}
 
-	spin_lock_irqsave(&cb_data_ptr->lock, flags);
 	switch (event) {
 	case SMUX_CONNECTED:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
 		++cb_data_ptr->event_connected;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	case SMUX_DISCONNECTED:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
 		++cb_data_ptr->event_disconnected;
 		cb_data_ptr->event_disconnected_ssr =
 			((struct smux_meta_disconnected *)metadata)->is_ssr;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	case SMUX_READ_DONE:
-		++cb_data_ptr->event_read_done;
 		read_event_meta = kmalloc(sizeof(struct mock_read_event),
-						GFP_ATOMIC);
+						GFP_KERNEL);
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
+		++cb_data_ptr->event_read_done;
 		if (read_event_meta) {
 			read_event_meta->meta =
 				*(struct smux_meta_read *)metadata;
 			list_add_tail(&read_event_meta->list,
 						&cb_data_ptr->read_events);
 		}
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	case SMUX_READ_FAIL:
-		++cb_data_ptr->event_read_failed;
 		read_event_meta = kmalloc(sizeof(struct mock_read_event),
-						GFP_ATOMIC);
+						GFP_KERNEL);
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
+		++cb_data_ptr->event_read_failed;
 		if (read_event_meta) {
-			read_event_meta->meta =
+			if (metadata)
+				read_event_meta->meta =
 					*(struct smux_meta_read *)metadata;
+			else
+				memset(&read_event_meta->meta, 0x0,
+						sizeof(struct smux_meta_read));
 			list_add_tail(&read_event_meta->list,
 					&cb_data_ptr->read_events);
 		}
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	case SMUX_WRITE_DONE:
-		++cb_data_ptr->event_write_done;
 		write_event_meta = kmalloc(sizeof(struct mock_write_event),
-						GFP_ATOMIC);
+						GFP_KERNEL);
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
+		++cb_data_ptr->event_write_done;
 		if (write_event_meta) {
 			write_event_meta->meta =
 					*(struct smux_meta_write *)metadata;
 			list_add_tail(&write_event_meta->list,
 					&cb_data_ptr->write_events);
 		}
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	case SMUX_WRITE_FAIL:
-		++cb_data_ptr->event_write_failed;
 		write_event_meta = kmalloc(sizeof(struct mock_write_event),
-						GFP_ATOMIC);
+						GFP_KERNEL);
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
+		++cb_data_ptr->event_write_failed;
 		if (write_event_meta) {
 			write_event_meta->meta =
 				*(struct smux_meta_write *)metadata;
 			list_add_tail(&write_event_meta->list,
 					&cb_data_ptr->write_events);
 		}
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	case SMUX_LOW_WM_HIT:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
 		++cb_data_ptr->event_low_wm;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	case SMUX_HIGH_WM_HIT:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
 		++cb_data_ptr->event_high_wm;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	case SMUX_TIOCM_UPDATE:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
 		++cb_data_ptr->event_tiocm;
 		cb_data_ptr->tiocm_meta = *(struct smux_meta_tiocm *)metadata;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
 	default:
 		pr_err("%s: unknown event %d\n", __func__, event);
 	};
 
+	spin_lock_irqsave(&cb_data_ptr->lock, flags);
 	++cb_data_ptr->cb_count;
 	complete(&cb_data_ptr->cb_completion);
 	spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
@@ -1153,6 +1236,338 @@
 	return i;
 }
 
+/**
+ * Allocates a new buffer or returns a failure based upon the
+ * global @get_rx_buffer_mock_fail.
+ */
+static int get_rx_buffer_mock(void *priv, void **pkt_priv,
+		void **buffer, int size)
+{
+	void *rx_buf;
+	unsigned long flags;
+	struct smux_mock_callback *cb_ptr;
+
+	cb_ptr = (struct smux_mock_callback *)priv;
+	if (!cb_ptr) {
+		pr_err("%s: no callback data\n", __func__);
+		return -ENXIO;
+	}
+
+	if (get_rx_buffer_mock_fail) {
+		/* force failure and log failure event */
+		struct mock_get_rx_buff_event *meta;
+		meta = kmalloc(sizeof(struct mock_get_rx_buff_event),
+				GFP_KERNEL);
+		if (!meta) {
+			pr_err("%s: unable to allocate metadata\n", __func__);
+			return -ENOMEM;
+		}
+		INIT_LIST_HEAD(&meta->list);
+		meta->size = size;
+		meta->jiffies = jiffies;
+
+		spin_lock_irqsave(&cb_ptr->lock, flags);
+		++cb_ptr->get_rx_buff_retry_count;
+		list_add_tail(&meta->list, &cb_ptr->get_rx_buff_retry_events);
+		++cb_ptr->cb_count;
+		complete(&cb_ptr->cb_completion);
+		spin_unlock_irqrestore(&cb_ptr->lock, flags);
+		return -EAGAIN;
+	} else {
+		rx_buf = kmalloc(size, GFP_KERNEL);
+		*pkt_priv = (void *)0x1234;
+		*buffer = rx_buf;
+		return 0;
+	}
+	return 0;
+}
+
+/**
+ * Verify get_rx_buffer callback retry.
+ *
+ * @buf  Buffer for status message
+ * @max  Size of buffer
+ *
+ * @returns Number of bytes written to @buf
+ */
+static int smux_ut_local_get_rx_buff_retry(char *buf, int max)
+{
+	static struct smux_mock_callback cb_data;
+	static int cb_initialized;
+	int i = 0;
+	int failed = 0;
+	char try_two[] = "try 2";
+	int ret;
+	unsigned long start_j;
+	struct mock_get_rx_buff_event *event;
+	struct mock_read_event *read_event;
+	int try;
+
+	i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
+	pr_err("%s", buf);
+
+	if (!cb_initialized)
+		mock_cb_data_init(&cb_data);
+
+	mock_cb_data_reset(&cb_data);
+	smux_byte_loopback = SMUX_TEST_LCID;
+	while (!failed) {
+		/* open port for loopback */
+		ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
+				SMUX_CH_OPTION_LOCAL_LOOPBACK,
+				0);
+		UT_ASSERT_INT(ret, ==, 0);
+
+		ret = msm_smux_open(SMUX_TEST_LCID, &cb_data,
+				smux_mock_cb, get_rx_buffer_mock);
+		UT_ASSERT_INT(ret, ==, 0);
+		UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ), >, 0);
+		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		UT_ASSERT_INT(cb_data.event_connected, ==, 1);
+		mock_cb_data_reset(&cb_data);
+
+		/*
+		 * Force get_rx_buffer failure for a single RX packet
+		 *
+		 * The get_rx_buffer calls should follow an exponential
+		 * back-off with a maximum timeout of 1024 ms after which we
+		 * will get a failure notification.
+		 *
+		 * Try   Post Delay (ms)
+		 *  0      -
+		 *  1      1
+		 *  2      2
+		 *  3      4
+		 *  4      8
+		 *  5     16
+		 *  6     32
+		 *  7     64
+		 *  8    128
+		 *  9    256
+		 * 10    512
+		 * 11   1024
+		 * 12   Fail
+		 *
+		 * All times are limited by the precision of the timer
+		 * framework, so ranges are used in the test
+		 * verification.
+		 */
+		get_rx_buffer_mock_fail = 1;
+		start_j = jiffies;
+		ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
+					test_array, sizeof(test_array));
+		UT_ASSERT_INT(ret, ==, 0);
+		ret = msm_smux_write(SMUX_TEST_LCID, (void *)2,
+					try_two, sizeof(try_two));
+		UT_ASSERT_INT(ret, ==, 0);
+
+		/* wait for RX failure event */
+		while (cb_data.event_read_failed == 0) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, 2*HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		if (failed)
+			break;
+
+		/* verify retry attempts */
+		UT_ASSERT_INT(cb_data.get_rx_buff_retry_count, ==, 12);
+		event = list_first_entry(&cb_data.get_rx_buff_retry_events,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				0, 0 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				1, 1 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				2, 2 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				4, 4 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				8, 8 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				16, 16 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				32 - 20, 32 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				64 - 20, 64 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				128 - 20, 128 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				256 - 20, 256 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				512 - 20, 512 + 20);
+		start_j = event->jiffies;
+
+		event = list_first_entry(&event->list,
+				struct mock_get_rx_buff_event, list);
+		pr_err("%s: event->jiffies = %d (ms)\n", __func__,
+				jiffies_to_msecs(event->jiffies - start_j));
+		UT_ASSERT_INT_IN_RANGE(
+				jiffies_to_msecs(event->jiffies - start_j),
+				1024 - 20, 1024 + 20);
+		mock_cb_data_reset(&cb_data);
+
+		/* verify 2nd pending RX packet goes through */
+		get_rx_buffer_mock_fail = 0;
+		INIT_COMPLETION(cb_data.cb_completion);
+		if (cb_data.event_read_done == 0)
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+		UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
+		UT_ASSERT_INT(list_empty(&cb_data.read_events), ==, 0);
+		read_event = list_first_entry(&cb_data.read_events,
+				struct mock_read_event, list);
+		UT_ASSERT_PTR(read_event->meta.pkt_priv, ==, (void *)0x1234);
+		UT_ASSERT_PTR(read_event->meta.buffer, !=, NULL);
+		UT_ASSERT_INT(0, ==, memcmp(read_event->meta.buffer, try_two,
+				sizeof(try_two)));
+		mock_cb_data_reset(&cb_data);
+
+		/* Test maximum retry queue size */
+		get_rx_buffer_mock_fail = 1;
+		for (try = 0; try < (SMUX_RX_RETRY_MAX_PKTS + 1); ++try) {
+			mock_cb_data_reset(&cb_data);
+			ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
+						test_array, sizeof(test_array));
+			UT_ASSERT_INT(ret, ==, 0);
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+		}
+
+		/* should have 32 successful rx packets and 1 failed */
+		while (cb_data.event_read_failed == 0) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, 2*HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		if (failed)
+			break;
+
+		get_rx_buffer_mock_fail = 0;
+		while (cb_data.event_read_done < SMUX_RX_RETRY_MAX_PKTS) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, 2*HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		if (failed)
+			break;
+
+		UT_ASSERT_INT(1, ==, cb_data.event_read_failed);
+		UT_ASSERT_INT(SMUX_RX_RETRY_MAX_PKTS, ==,
+				cb_data.event_read_done);
+		mock_cb_data_reset(&cb_data);
+
+		/* close port */
+		ret = msm_smux_close(SMUX_TEST_LCID);
+		UT_ASSERT_INT(ret, ==, 0);
+		UT_ASSERT_INT(
+			(int)wait_for_completion_timeout(
+				&cb_data.cb_completion, HZ),
+			>, 0);
+		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
+		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		break;
+	}
+
+	if (!failed) {
+		i += scnprintf(buf + i, max - i, "\tOK\n");
+	} else {
+		pr_err("%s: Failed\n", __func__);
+		i += scnprintf(buf + i, max - i, "\tFailed\n");
+		i += mock_cb_data_print(&cb_data, buf + i, max - i);
+		msm_smux_close(SMUX_TEST_LCID);
+	}
+	smux_byte_loopback = 0;
+	mock_cb_data_reset(&cb_data);
+	return i;
+}
+
 static char debug_buffer[DEBUG_BUFMAX];
 
 static ssize_t debug_read(struct file *file, char __user *buf,
@@ -1214,6 +1629,8 @@
 	debug_create("ut_local_wm", 0444, dent, smux_ut_local_wm);
 	debug_create("ut_local_smuxld_receive_buf", 0444, dent,
 			smux_ut_local_smuxld_receive_buf);
+	debug_create("ut_local_get_rx_buff_retry", 0444, dent,
+			smux_ut_local_get_rx_buff_retry);
 
 	return 0;
 }
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 4e6091e..81ce143 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -26,6 +26,9 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/msm_hsusb.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/rpm-regulator.h>
 
 #include "core.h"
 #include "gadget.h"
@@ -95,6 +98,49 @@
 	u8 ep_num_mapping[DBM_MAX_EPS];
 	const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
 	struct list_head req_complete_list;
+	struct regulator	*hsusb_3p3;
+	struct regulator	*hsusb_1p8;
+	struct regulator	*hsusb_vddcx;
+	struct regulator	*ssusb_1p8;
+	struct regulator	*ssusb_vddcx;
+	enum usb_vdd_type	ss_vdd_type;
+	enum usb_vdd_type	hs_vdd_type;
+};
+
+#define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
+#define USB_HSPHY_3P3_VOL_MAX		3300000 /* uV */
+#define USB_HSPHY_3P3_HPM_LOAD		16000	/* uA */
+
+#define USB_HSPHY_1P8_VOL_MIN		1800000 /* uV */
+#define USB_HSPHY_1P8_VOL_MAX		1800000 /* uV */
+#define USB_HSPHY_1P8_HPM_LOAD		19000	/* uA */
+
+#define USB_SSPHY_1P8_VOL_MIN		1800000 /* uV */
+#define USB_SSPHY_1P8_VOL_MAX		1800000 /* uV */
+#define USB_SSPHY_1P8_HPM_LOAD		23000	/* uA */
+
+#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 */
+
+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,
+			[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 struct dwc3_msm *context;
@@ -750,6 +796,213 @@
 }
 EXPORT_SYMBOL(msm_ep_unconfig);
 
+/* HSPHY */
+static int dwc3_hsusb_config_vddcx(int high)
+{
+	int min_vol, ret;
+	struct dwc3_msm *dwc = context;
+	enum usb_vdd_type vdd_type = context->hs_vdd_type;
+	int max_vol = vdd_val[vdd_type][VDD_MAX];
+
+	min_vol = vdd_val[vdd_type][high ? VDD_MIN : VDD_NONE];
+	ret = regulator_set_voltage(dwc->hsusb_vddcx, min_vol, max_vol);
+	if (ret) {
+		dev_err(dwc->dev, "unable to set voltage for HSUSB_VDDCX\n");
+		return ret;
+	}
+
+	dev_dbg(dwc->dev, "%s: min_vol:%d max_vol:%d\n", __func__,
+							min_vol, max_vol);
+
+	return ret;
+}
+
+static int dwc3_hsusb_ldo_init(int init)
+{
+	int rc = 0;
+	struct dwc3_msm *dwc = context;
+
+	if (!init) {
+		regulator_set_voltage(dwc->hsusb_1p8, 0, USB_HSPHY_1P8_VOL_MAX);
+		regulator_set_voltage(dwc->hsusb_3p3, 0, USB_HSPHY_3P3_VOL_MAX);
+		return 0;
+	}
+
+	dwc->hsusb_3p3 = devm_regulator_get(dwc->dev, "HSUSB_3p3");
+	if (IS_ERR(dwc->hsusb_3p3)) {
+		dev_err(dwc->dev, "unable to get hsusb 3p3\n");
+		return PTR_ERR(dwc->hsusb_3p3);
+	}
+
+	rc = regulator_set_voltage(dwc->hsusb_3p3,
+			USB_HSPHY_3P3_VOL_MIN, USB_HSPHY_3P3_VOL_MAX);
+	if (rc) {
+		dev_err(dwc->dev, "unable to set voltage for hsusb 3p3\n");
+		return rc;
+	}
+	dwc->hsusb_1p8 = devm_regulator_get(dwc->dev, "HSUSB_1p8");
+	if (IS_ERR(dwc->hsusb_1p8)) {
+		dev_err(dwc->dev, "unable to get hsusb 1p8\n");
+		rc = PTR_ERR(dwc->hsusb_1p8);
+		goto devote_3p3;
+	}
+	rc = regulator_set_voltage(dwc->hsusb_1p8,
+			USB_HSPHY_1P8_VOL_MIN, USB_HSPHY_1P8_VOL_MAX);
+	if (rc) {
+		dev_err(dwc->dev, "unable to set voltage for hsusb 1p8\n");
+		goto devote_3p3;
+	}
+
+	return 0;
+
+devote_3p3:
+	regulator_set_voltage(dwc->hsusb_3p3, 0, USB_HSPHY_3P3_VOL_MAX);
+
+	return rc;
+}
+
+static int dwc3_hsusb_ldo_enable(int on)
+{
+	int rc = 0;
+	struct dwc3_msm *dwc = context;
+
+	dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+
+	if (!on)
+		goto disable_regulators;
+
+
+	rc = regulator_set_optimum_mode(dwc->hsusb_1p8, USB_HSPHY_1P8_HPM_LOAD);
+	if (rc < 0) {
+		dev_err(dwc->dev, "Unable to set HPM of regulator HSUSB_1p8\n");
+		return rc;
+	}
+
+	rc = regulator_enable(dwc->hsusb_1p8);
+	if (rc) {
+		dev_err(dwc->dev, "Unable to enable HSUSB_1p8\n");
+		goto put_1p8_lpm;
+	}
+
+	rc = regulator_set_optimum_mode(dwc->hsusb_3p3,	USB_HSPHY_3P3_HPM_LOAD);
+	if (rc < 0) {
+		dev_err(dwc->dev, "Unable to set HPM of regulator HSUSB_3p3\n");
+		goto disable_1p8;
+	}
+
+	rc = regulator_enable(dwc->hsusb_3p3);
+	if (rc) {
+		dev_err(dwc->dev, "Unable to enable HSUSB_3p3\n");
+		goto put_3p3_lpm;
+	}
+
+	return 0;
+
+disable_regulators:
+	rc = regulator_disable(dwc->hsusb_3p3);
+	if (rc)
+		dev_err(dwc->dev, "Unable to disable HSUSB_3p3\n");
+
+put_3p3_lpm:
+	rc = regulator_set_optimum_mode(dwc->hsusb_3p3, 0);
+	if (rc < 0)
+		dev_err(dwc->dev, "Unable to set LPM of regulator HSUSB_3p3\n");
+
+disable_1p8:
+	rc = regulator_disable(dwc->hsusb_1p8);
+	if (rc)
+		dev_err(dwc->dev, "Unable to disable HSUSB_1p8\n");
+
+put_1p8_lpm:
+	rc = regulator_set_optimum_mode(dwc->hsusb_1p8, 0);
+	if (rc < 0)
+		dev_err(dwc->dev, "Unable to set LPM of regulator HSUSB_1p8\n");
+
+	return rc < 0 ? rc : 0;
+}
+
+/* SSPHY */
+static int dwc3_ssusb_config_vddcx(int high)
+{
+	int min_vol, ret;
+	struct dwc3_msm *dwc = context;
+	enum usb_vdd_type vdd_type = context->ss_vdd_type;
+	int max_vol = vdd_val[vdd_type][VDD_MAX];
+
+	min_vol = vdd_val[vdd_type][high ? VDD_MIN : VDD_NONE];
+	ret = regulator_set_voltage(dwc->ssusb_vddcx, min_vol, max_vol);
+	if (ret) {
+		dev_err(dwc->dev, "unable to set voltage for SSUSB_VDDCX\n");
+		return ret;
+	}
+
+	dev_dbg(dwc->dev, "%s: min_vol:%d max_vol:%d\n", __func__,
+							min_vol, max_vol);
+	return ret;
+}
+
+/* 3.3v supply not needed for SS PHY */
+static int dwc3_ssusb_ldo_init(int init)
+{
+	int rc = 0;
+	struct dwc3_msm *dwc = context;
+
+	if (!init) {
+		regulator_set_voltage(dwc->ssusb_1p8, 0, USB_SSPHY_1P8_VOL_MAX);
+		return 0;
+	}
+
+	dwc->ssusb_1p8 = devm_regulator_get(dwc->dev, "SSUSB_1p8");
+	if (IS_ERR(dwc->ssusb_1p8)) {
+		dev_err(dwc->dev, "unable to get ssusb 1p8\n");
+		return PTR_ERR(dwc->ssusb_1p8);
+	}
+	rc = regulator_set_voltage(dwc->ssusb_1p8,
+			USB_SSPHY_1P8_VOL_MIN, USB_SSPHY_1P8_VOL_MAX);
+	if (rc)
+		dev_err(dwc->dev, "unable to set voltage for ssusb 1p8\n");
+
+	return rc;
+}
+
+static int dwc3_ssusb_ldo_enable(int on)
+{
+	int rc = 0;
+	struct dwc3_msm *dwc = context;
+
+	dev_dbg(context->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+
+	if (!on)
+		goto disable_regulators;
+
+
+	rc = regulator_set_optimum_mode(dwc->ssusb_1p8, USB_SSPHY_1P8_HPM_LOAD);
+	if (rc < 0) {
+		dev_err(dwc->dev, "Unable to set HPM of SSUSB_1p8\n");
+		return rc;
+	}
+
+	rc = regulator_enable(dwc->ssusb_1p8);
+	if (rc) {
+		dev_err(dwc->dev, "Unable to enable SSUSB_1p8\n");
+		goto put_1p8_lpm;
+	}
+
+	return 0;
+
+disable_regulators:
+	rc = regulator_disable(dwc->ssusb_1p8);
+	if (rc)
+		dev_err(dwc->dev, "Unable to disable SSUSB_1p8\n");
+
+put_1p8_lpm:
+	rc = regulator_set_optimum_mode(dwc->ssusb_1p8, 0);
+	if (rc < 0)
+		dev_err(dwc->dev, "Unable to set LPM of SSUSB_1p8\n");
+
+	return rc < 0 ? rc : 0;
+}
+
 static int __devinit dwc3_msm_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
@@ -766,26 +1019,107 @@
 
 	platform_set_drvdata(pdev, msm);
 	context = msm;
+	msm->dev = &pdev->dev;
 
 	INIT_LIST_HEAD(&msm->req_complete_list);
 
+	/* SS PHY */
+	msm->ss_vdd_type = VDDCX_CORNER;
+	msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
+	if (IS_ERR(msm->ssusb_vddcx)) {
+		msm->ssusb_vddcx = devm_regulator_get(&pdev->dev,
+							"SSUSB_VDDCX");
+		if (IS_ERR(msm->ssusb_vddcx)) {
+			dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
+			return PTR_ERR(msm->ssusb_vddcx);
+		}
+		msm->ss_vdd_type = VDDCX;
+		dev_dbg(&pdev->dev, "ss_vdd_type: VDDCX\n");
+	}
+
+	ret = dwc3_ssusb_config_vddcx(1);
+	if (ret) {
+		dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
+		return ret;
+	}
+
+	ret = regulator_enable(context->ssusb_vddcx);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable the ssusb vddcx\n");
+		goto unconfig_ss_vddcx;
+	}
+
+	ret = dwc3_ssusb_ldo_init(1);
+	if (ret) {
+		dev_err(&pdev->dev, "ssusb vreg configuration failed\n");
+		goto disable_ss_vddcx;
+	}
+
+	ret = dwc3_ssusb_ldo_enable(1);
+	if (ret) {
+		dev_err(&pdev->dev, "ssusb vreg enable failed\n");
+		goto free_ss_ldo_init;
+	}
+
+	/* HS PHY */
+	msm->hs_vdd_type = VDDCX_CORNER;
+	msm->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
+	if (IS_ERR(msm->hsusb_vddcx)) {
+		msm->hsusb_vddcx = devm_regulator_get(&pdev->dev,
+							"HSUSB_VDDCX");
+		if (IS_ERR(msm->hsusb_vddcx)) {
+			dev_err(&pdev->dev, "unable to get hsusb vddcx\n");
+			ret = PTR_ERR(msm->ssusb_vddcx);
+			goto disable_ss_ldo;
+		}
+		msm->hs_vdd_type = VDDCX;
+		dev_dbg(&pdev->dev, "hs_vdd_type: VDDCX\n");
+	}
+
+	ret = dwc3_hsusb_config_vddcx(1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+		goto disable_ss_ldo;
+	}
+
+	ret = regulator_enable(context->hsusb_vddcx);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
+		goto unconfig_hs_vddcx;
+	}
+
+	ret = dwc3_hsusb_ldo_init(1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+		goto disable_hs_vddcx;
+	}
+
+	ret = dwc3_hsusb_ldo_enable(1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+		goto free_hs_ldo_init;
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "missing memory base resource\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto disable_hs_ldo;
 	}
 
 	msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
 		resource_size(res));
 	if (!msm->base) {
 		dev_err(&pdev->dev, "ioremap failed\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto disable_hs_ldo;
 	}
 
 	dwc3 = platform_device_alloc("dwc3-msm", -1);
 	if (!dwc3) {
 		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
-		return -ENOMEM;
+		ret = -ENODEV;
+		goto disable_hs_ldo;
 	}
 
 	dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
@@ -794,7 +1128,6 @@
 	dwc3->dev.dma_mask = pdev->dev.dma_mask;
 	dwc3->dev.dma_parms = pdev->dev.dma_parms;
 	msm->resource_size = resource_size(res);
-	msm->dev = &pdev->dev;
 	msm->dwc3 = dwc3;
 
 	if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
@@ -810,20 +1143,20 @@
 			"max: %d, dbm_num_eps: %d\n",
 			DBM_MAX_EPS, msm->dbm_num_eps);
 		ret = -ENODEV;
-		goto err1;
+		goto put_pdev;
 	}
 
 	ret = platform_device_add_resources(dwc3, pdev->resource,
 		pdev->num_resources);
 	if (ret) {
 		dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
-		goto err1;
+		goto put_pdev;
 	}
 
 	ret = platform_device_add(dwc3);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register dwc3 device\n");
-		goto err1;
+		goto put_pdev;
 	}
 
 	/* Reset the DBM */
@@ -831,8 +1164,24 @@
 
 	return 0;
 
-err1:
+put_pdev:
 	platform_device_put(dwc3);
+disable_hs_ldo:
+	dwc3_hsusb_ldo_enable(0);
+free_hs_ldo_init:
+	dwc3_hsusb_ldo_init(0);
+disable_hs_vddcx:
+	regulator_disable(context->hsusb_vddcx);
+unconfig_hs_vddcx:
+	dwc3_hsusb_config_vddcx(0);
+disable_ss_ldo:
+	dwc3_ssusb_ldo_enable(0);
+free_ss_ldo_init:
+	dwc3_ssusb_ldo_init(0);
+disable_ss_vddcx:
+	regulator_disable(context->ssusb_vddcx);
+unconfig_ss_vddcx:
+	dwc3_ssusb_config_vddcx(0);
 
 	return ret;
 }
@@ -843,6 +1192,15 @@
 
 	platform_device_unregister(msm->dwc3);
 
+	dwc3_hsusb_ldo_enable(0);
+	dwc3_hsusb_ldo_init(0);
+	regulator_disable(msm->hsusb_vddcx);
+	dwc3_hsusb_config_vddcx(0);
+	dwc3_ssusb_ldo_enable(0);
+	dwc3_ssusb_ldo_init(0);
+	regulator_disable(msm->ssusb_vddcx);
+	dwc3_ssusb_config_vddcx(0);
+
 	return 0;
 }
 
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 6bd0577..5ed16cc 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -690,6 +690,13 @@
 
 skip_phy_resume:
 
+	if (!(readl_relaxed(USB_USBCMD) & CMD_RUN) &&
+			(readl_relaxed(USB_PORTSC) & PORT_SUSPEND)) {
+		writel_relaxed(readl_relaxed(USB_USBCMD) | CMD_RUN ,
+				USB_USBCMD);
+		dbg_log_event(NULL, "Set RS", readl_relaxed(USB_USBCMD));
+	}
+
 	usb_hcd_resume_root_hub(hcd);
 
 	atomic_set(&mehci->in_lpm, 0);
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index bf8e5f4..6ee3204 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -479,7 +479,7 @@
 	result = usb_autopm_get_interface(dev->intf);
 	if (result < 0) {
 		dev_err(&dev->udev->dev, "%s: resume failure\n", __func__);
-		goto error;
+		goto pm_error;
 	}
 
 	txurb = usb_alloc_urb(0, GFP_KERNEL);
@@ -536,7 +536,7 @@
 error:
 	dev->txurb_drp_cnt++;
 	usb_autopm_put_interface(dev->intf);
-
+pm_error:
 	return result;
 }
 EXPORT_SYMBOL(data_bridge_write);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 59f01f6..61fbac0 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -838,10 +838,14 @@
 	clk_disable_unprepare(motg->core_clk);
 
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
-	ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
-	if (ret)
-		dev_err(phy->dev, "%s failed to devote for "
-			"TCXO D0 buffer%d\n", __func__, ret);
+	if (!host_bus_suspend) {
+		ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
+		if (ret)
+			dev_err(phy->dev, "%s failed to devote for "
+				"TCXO D0 buffer%d\n", __func__, ret);
+		else
+			motg->lpm_flags |= XO_SHUTDOWN;
+	}
 
 	if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
 			!host_bus_suspend && !dcp) {
@@ -886,10 +890,13 @@
 	wake_lock(&motg->wlock);
 
 	/* Vote for TCXO when waking up the phy */
-	ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
-	if (ret)
-		dev_err(phy->dev, "%s failed to vote for "
-			"TCXO D0 buffer%d\n", __func__, ret);
+	if (motg->lpm_flags & XO_SHUTDOWN) {
+		ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
+		if (ret)
+			dev_err(phy->dev, "%s failed to vote for "
+				"TCXO D0 buffer%d\n", __func__, ret);
+		motg->lpm_flags &= ~XO_SHUTDOWN;
+	}
 
 	clk_prepare_enable(motg->core_clk);
 
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index b8d1df8..7777154 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -297,6 +297,11 @@
 	select FB_MSM_LVDS
 	default n
 
+config FB_MSM_LVDS_FRC_FHD
+	bool
+	select FB_MSM_LVDS
+	default n
+
 config FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
 	bool
 	select FB_MSM_MIPI_DSI_TOSHIBA
@@ -490,6 +495,15 @@
         ---help---
           Support for LVDS Chimei WXGA(1366x768) panel
 
+config FB_MSM_LVDS_FRC_FHD_PANEL
+	bool "LVDS FRC FHD Panel"
+	select FB_MSM_LVDS_FRC_FHD
+	---help---
+	  Support for LVDS Frc FHD(1920x1080) panel
+	  FRC(Frame Rate Converter) uses LVDS as input
+	  interface. It is treated as a HDMI panel with
+	  1920x1080 resolution.
+
 config FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
 	depends on FB_MSM_LCDC_HW
 	bool "MDDI Panel Auto Detect + LCDC Prism WVGA"
@@ -568,6 +582,7 @@
 config FB_MSM_LVDS_MIPI_PANEL_DETECT
 	bool "LVDS + MIPI Panel Auto Detect"
 	select FB_MSM_LVDS_CHIMEI_WXGA
+	select FB_MSM_LVDS_FRC_FHD
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index b2ecb08..e4a0948 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -165,6 +165,7 @@
 obj-$(CONFIG_FB_MSM_HDMI_ADV7520_PANEL) += adv7520.o
 obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
 obj-$(CONFIG_FB_MSM_LVDS_CHIMEI_WXGA) += lvds_chimei_wxga.o
+obj-$(CONFIG_FB_MSM_LVDS_FRC_FHD) += lvds_frc_fhd.o
 obj-$(CONFIG_FB_MSM_HDMI_MSM_PANEL) += hdmi_msm.o
 obj-$(CONFIG_FB_MSM_EXT_INTERFACE_COMMON) += external_common.o
 obj-$(CONFIG_FB_MSM_LCDC_TRULY_HVGA_IPS3P2335) += lcdc_truly_ips3p2335.o
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
index 6323423..f5d8201 100644
--- a/drivers/video/msm/lvds.c
+++ b/drivers/video/msm/lvds.c
@@ -33,6 +33,9 @@
 
 #include "msm_fb.h"
 #include "mdp4.h"
+
+#define LVDS_PIXEL_MAP_PATTERN_2	2
+
 static int lvds_probe(struct platform_device *pdev);
 static int lvds_remove(struct platform_device *pdev);
 
@@ -65,14 +68,39 @@
 	usleep(1000);
 
 	/* LVDS PHY PLL configuration */
-	MDP_OUTP(MDP_BASE + 0xc3004, 0x62);
-	MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
-	MDP_OUTP(MDP_BASE + 0xc300c, 0xc4);
-	MDP_OUTP(MDP_BASE + 0xc3014, 0x10);
-	MDP_OUTP(MDP_BASE + 0xc3018, 0x05);
-	MDP_OUTP(MDP_BASE + 0xc301c, 0x62);
-	MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
-	MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
+	if (mfd->panel_info.clk_rate == 74250000) {
+		MDP_OUTP(MDP_BASE + 0xc3000, 0x08);
+		MDP_OUTP(MDP_BASE + 0xc3004, 0x4c);
+		MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
+		MDP_OUTP(MDP_BASE + 0xc300c, 0xc3);
+		MDP_OUTP(MDP_BASE + 0xc3014, 0x10);
+		MDP_OUTP(MDP_BASE + 0xc3018, 0x04);
+		MDP_OUTP(MDP_BASE + 0xc301c, 0x62);
+		MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
+		MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
+		MDP_OUTP(MDP_BASE + 0xc3028, 0x07);
+		MDP_OUTP(MDP_BASE + 0xc302c, 0x00);
+		MDP_OUTP(MDP_BASE + 0xc3030, 0x1c);
+		MDP_OUTP(MDP_BASE + 0xc3034, 0x01);
+		MDP_OUTP(MDP_BASE + 0xc3038, 0x00);
+		MDP_OUTP(MDP_BASE + 0xc3040, 0xC0);
+		MDP_OUTP(MDP_BASE + 0xc3044, 0x00);
+		MDP_OUTP(MDP_BASE + 0xc3048, 0x30);
+		MDP_OUTP(MDP_BASE + 0xc304c, 0x00);
+
+		MDP_OUTP(MDP_BASE + 0xc3000, 0x11);
+		MDP_OUTP(MDP_BASE + 0xc3064, 0x05);
+		MDP_OUTP(MDP_BASE + 0xc3050, 0x20);
+	} else {
+		MDP_OUTP(MDP_BASE + 0xc3004, 0x62);
+		MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
+		MDP_OUTP(MDP_BASE + 0xc300c, 0xc4);
+		MDP_OUTP(MDP_BASE + 0xc3014, 0x10);
+		MDP_OUTP(MDP_BASE + 0xc3018, 0x05);
+		MDP_OUTP(MDP_BASE + 0xc301c, 0x62);
+		MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
+		MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
+	}
 
 	MDP_OUTP(MDP_BASE + 0xc3000, 0x01);
 	/* Wait until LVDS PLL is locked and ready */
@@ -99,22 +127,42 @@
 		if (lvds_pdata &&
 		    lvds_pdata->lvds_pixel_remap &&
 		    lvds_pdata->lvds_pixel_remap()) {
-			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
-			MDP_OUTP(MDP_BASE +  0xc2014, 0x05080001);
-			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
-			MDP_OUTP(MDP_BASE +  0xc2018, 0x00020304);
-			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
-			MDP_OUTP(MDP_BASE +  0xc201c, 0x1011090a);
-			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
-			MDP_OUTP(MDP_BASE +  0xc2020, 0x000b0c0d);
-			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
-			MDP_OUTP(MDP_BASE +  0xc2024, 0x191a1213);
-			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
-			MDP_OUTP(MDP_BASE +  0xc2028, 0x00141518);
-			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
-			MDP_OUTP(MDP_BASE +  0xc202c, 0x171b0607);
-			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
-			MDP_OUTP(MDP_BASE +  0xc2030, 0x000e0f16);
+			if (lvds_pdata->lvds_pixel_remap() ==
+				LVDS_PIXEL_MAP_PATTERN_2) {
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+				MDP_OUTP(MDP_BASE +  0xc2014, 0x070A1B1B);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+				MDP_OUTP(MDP_BASE +  0xc2018, 0x00040506);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+				MDP_OUTP(MDP_BASE +  0xc201c, 0x12131B1B);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+				MDP_OUTP(MDP_BASE +  0xc2020, 0x000B0C0D);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+				MDP_OUTP(MDP_BASE +  0xc2024, 0x191A1B1B);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+				MDP_OUTP(MDP_BASE +  0xc2028, 0x00141518);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
+				MDP_OUTP(MDP_BASE +  0xc202c, 0x171B1B1B);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
+				MDP_OUTP(MDP_BASE +  0xc2030, 0x000e0f16);
+			} else {
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+				MDP_OUTP(MDP_BASE +  0xc2014, 0x05080001);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+				MDP_OUTP(MDP_BASE +  0xc2018, 0x00020304);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+				MDP_OUTP(MDP_BASE +  0xc201c, 0x1011090a);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+				MDP_OUTP(MDP_BASE +  0xc2020, 0x000b0c0d);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+				MDP_OUTP(MDP_BASE +  0xc2024, 0x191a1213);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+				MDP_OUTP(MDP_BASE +  0xc2028, 0x00141518);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
+				MDP_OUTP(MDP_BASE +  0xc202c, 0x171b0607);
+				/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
+				MDP_OUTP(MDP_BASE +  0xc2030, 0x000e0f16);
+			}
 		} else {
 			/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
 			MDP_OUTP(MDP_BASE +  0xc2014, 0x03040508);
@@ -135,7 +183,7 @@
 		}
 		if (mfd->panel_info.lvds.channel_mode ==
 			LVDS_DUAL_CHANNEL_MODE) {
-			lvds_intf = 0x0001ff80;
+			lvds_intf = 0x0003ff80;
 			lvds_phy_cfg0 = BIT(6) | BIT(7);
 			if (mfd->panel_info.lvds.channel_swap)
 				lvds_intf |= BIT(4);
@@ -159,7 +207,7 @@
 
 		if (mfd->panel_info.lvds.channel_mode ==
 			LVDS_DUAL_CHANNEL_MODE) {
-			lvds_intf = 0x00017788;
+			lvds_intf = 0x00037788;
 			lvds_phy_cfg0 = BIT(6) | BIT(7);
 			if (mfd->panel_info.lvds.channel_swap)
 				lvds_intf |= BIT(4);
diff --git a/drivers/video/msm/lvds_frc_fhd.c b/drivers/video/msm/lvds_frc_fhd.c
new file mode 100644
index 0000000..7739588
--- /dev/null
+++ b/drivers/video/msm/lvds_frc_fhd.c
@@ -0,0 +1,201 @@
+/* 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 <mach/gpio.h>
+#include "msm_fb.h"
+
+static struct lvds_panel_platform_data *frc_pdata;
+static struct platform_device *frc_fbpdev;
+static int gpio_update;		/* 268 */
+static int gpio_reset;	/* 269 */
+static int gpio_pwr;		/* 270 */
+
+static int lvds_frc_panel_on(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = gpio_request(gpio_pwr, "frc_pwr");
+	if (ret) {
+		pr_err("%s: gpio_pwr=%d, gpio_request failed\n",
+			__func__, gpio_pwr);
+		goto panel_on_exit;
+	}
+	ret = gpio_request(gpio_update, "frc_update");
+	if (ret) {
+		pr_err("%s: gpio_update=%d, gpio_request failed\n",
+			__func__, gpio_update);
+		goto panel_on_exit1;
+	}
+	ret = gpio_request(gpio_reset, "frc_reset");
+	if (ret) {
+		pr_err("%s: gpio_reset=%d, gpio_request failed\n",
+			__func__, gpio_reset);
+		goto panel_on_exit2;
+	}
+
+	gpio_direction_output(gpio_reset, 1);
+	gpio_direction_output(gpio_pwr, 0);
+	gpio_direction_output(gpio_update, 0);
+	usleep(1000);
+	gpio_direction_output(gpio_reset, 0);
+	usleep(1000);
+	gpio_direction_output(gpio_pwr, 1);
+	usleep(1000);
+	gpio_direction_output(gpio_update, 1);
+	usleep(1000);
+	gpio_direction_output(gpio_reset, 1);
+	usleep(1000);
+	gpio_free(gpio_reset);
+panel_on_exit2:
+	gpio_free(gpio_update);
+panel_on_exit1:
+	gpio_free(gpio_pwr);
+panel_on_exit:
+	return ret;
+}
+
+static int lvds_frc_panel_off(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = gpio_request(gpio_pwr, "frc_pwr");
+	if (ret) {
+		pr_err("%s: gpio_pwr=%d, gpio_request failed\n",
+			__func__, gpio_pwr);
+		goto panel_off_exit;
+	}
+	ret = gpio_request(gpio_update, "frc_update");
+	if (ret) {
+		pr_err("%s: gpio_update=%d, gpio_request failed\n",
+			__func__, gpio_update);
+		goto panel_off_exit1;
+	}
+	ret = gpio_request(gpio_reset, "frc_reset");
+	if (ret) {
+		pr_err("%s: gpio_reset=%d, gpio_request failed\n",
+			__func__, gpio_reset);
+		goto panel_off_exit2;
+	}
+	gpio_direction_output(gpio_reset, 0);
+	usleep(1000);
+	gpio_direction_output(gpio_update, 0);
+	usleep(1000);
+	gpio_direction_output(gpio_pwr, 0);
+	usleep(1000);
+	gpio_free(gpio_reset);
+panel_off_exit2:
+	gpio_free(gpio_update);
+panel_off_exit1:
+	gpio_free(gpio_pwr);
+panel_off_exit:
+	return ret;
+}
+
+static int __devinit lvds_frc_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	if (pdev->id == 0) {
+		frc_pdata = pdev->dev.platform_data;
+		if (frc_pdata != NULL) {
+			gpio_update = frc_pdata->gpio[0];
+			gpio_reset = frc_pdata->gpio[1];
+			gpio_pwr = frc_pdata->gpio[2];
+			pr_info("%s: power=%d update=%d reset=%d\n",
+				__func__, gpio_pwr, gpio_update, gpio_reset);
+		}
+		return 0;
+	}
+
+	frc_fbpdev = msm_fb_add_device(pdev);
+	if (!frc_fbpdev) {
+		dev_err(&pdev->dev, "failed to add msm_fb device\n");
+		rc = -ENODEV;
+		goto probe_exit;
+	}
+
+probe_exit:
+	return rc;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = lvds_frc_probe,
+	.driver = {
+		.name   = "lvds_frc_fhd",
+	},
+};
+
+static struct msm_fb_panel_data lvds_frc_panel_data = {
+	.on = lvds_frc_panel_on,
+	.off = lvds_frc_panel_off,
+};
+
+static struct platform_device this_device = {
+	.name   = "lvds_frc_fhd",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &lvds_frc_panel_data,
+	}
+};
+
+static int __init lvds_frc_fhd_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+	if (msm_fb_detect_client("lvds_frc_fhd"))
+		return 0;
+
+	ret = platform_driver_register(&this_driver);
+	if (ret)
+		return ret;
+
+	pinfo = &lvds_frc_panel_data.panel_info;
+	pinfo->xres = 1920;
+	pinfo->yres = 1080;
+	MSM_FB_SINGLE_MODE_PANEL(pinfo);
+	pinfo->type = LVDS_PANEL;
+	pinfo->pdest = DISPLAY_1;
+	pinfo->wait_cycle = 0;
+	pinfo->bpp = 24;
+	pinfo->fb_num = 2;
+	pinfo->clk_rate = 74250000;
+	pinfo->bl_max = 255;
+	pinfo->bl_min = 1;
+
+	/*
+	 * use hdmi 1080p60 setting, for dual channel mode,
+	 * horizontal length is half.
+	 */
+	pinfo->lcdc.h_back_porch = 148/2;
+	pinfo->lcdc.h_front_porch = 88/2;
+	pinfo->lcdc.h_pulse_width = 44/2;
+	pinfo->lcdc.v_back_porch = 36;
+	pinfo->lcdc.v_front_porch = 4;
+	pinfo->lcdc.v_pulse_width = 5;
+	pinfo->lcdc.underflow_clr = 0xff;
+	pinfo->lcdc.hsync_skew = 0;
+	pinfo->lvds.channel_mode = LVDS_DUAL_CHANNEL_MODE;
+	pinfo->lcdc.is_sync_active_high = TRUE;
+
+	/* Set border color, padding only for reducing active display region */
+	pinfo->lcdc.border_clr = 0x0;
+	pinfo->lcdc.xres_pad = 0;
+	pinfo->lcdc.yres_pad = 0;
+
+	ret = platform_device_register(&this_device);
+	if (ret)
+		platform_driver_unregister(&this_driver);
+
+	return ret;
+}
+
+module_init(lvds_frc_fhd_init);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 7fd2d91..ca5d2c6 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -93,7 +93,7 @@
 static struct delayed_work mdp_pipe_ctrl_worker;
 
 static boolean mdp_suspended = FALSE;
-static DEFINE_MUTEX(mdp_suspend_mutex);
+DEFINE_MUTEX(mdp_suspend_mutex);
 
 #ifdef CONFIG_FB_MSM_MDP40
 struct mdp_dma_data dma2_data;
@@ -1887,7 +1887,7 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
 	if (mdp_rev >= MDP_REV_41 && mfd->panel.type == MIPI_CMD_PANEL)
-		mdp_dsi_cmd_overlay_suspend();
+		mdp_dsi_cmd_overlay_suspend(mfd);
 	return ret;
 }
 
@@ -1897,7 +1897,6 @@
 
 #ifdef CONFIG_FB_MSM_MDP40
 	struct msm_fb_data_type *mfd;
-	mdp4_overlay_ctrl_db_reset();
 
 	mfd = platform_get_drvdata(pdev);
 
@@ -2575,17 +2574,6 @@
 	return rc;
 }
 
-unsigned int mdp_check_suspended(void)
-{
-	unsigned int ret;
-
-	mutex_lock(&mdp_suspend_mutex);
-	ret = mdp_suspended;
-	mutex_unlock(&mdp_suspend_mutex);
-
-	return ret;
-}
-
 void mdp_footswitch_ctrl(boolean on)
 {
 	mutex_lock(&mdp_suspend_mutex);
@@ -2652,7 +2640,6 @@
 #ifdef CONFIG_FB_MSM_DTV
 	mdp4_dtv_set_black_screen();
 #endif
-	mdp4_iommu_detach();
 	mdp_footswitch_ctrl(FALSE);
 }
 
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index b104b33..511edb6 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -801,7 +801,6 @@
 void mdp_histogram_handle_isr(struct mdp_hist_mgmt *mgmt);
 void __mdp_histogram_kickoff(struct mdp_hist_mgmt *mgmt);
 void __mdp_histogram_reset(struct mdp_hist_mgmt *mgmt);
-unsigned int mdp_check_suspended(void);
 void mdp_footswitch_ctrl(boolean on);
 
 #ifdef CONFIG_FB_MSM_MDP303
@@ -825,14 +824,10 @@
 #endif
 
 #ifndef CONFIG_FB_MSM_MDP40
-static inline void mdp_dsi_cmd_overlay_suspend(void)
+static inline void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
 {
 	/* empty */
 }
-static inline void mdp4_iommu_detach(void)
-{
-    /* empty */
-}
 #endif
 
 int mdp_ppp_v4l2_overlay_set(struct fb_info *info, struct mdp_overlay *req);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index a7161fe..16fede1 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -173,6 +173,7 @@
 	MDP4_MIXER_STAGE0,	/* zorder 0 */
 	MDP4_MIXER_STAGE1,	/* zorder 1 */
 	MDP4_MIXER_STAGE2,	/* zorder 2 */
+	MDP4_MIXER_STAGE3,	/* zorder 3 */
 	MDP4_MIXER_STAGE_MAX
 };
 
@@ -256,6 +257,19 @@
 	u8 mark_unmap;
 };
 
+struct blend_cfg {
+	u32 op;
+	u32 bg_alpha;
+	u32 fg_alpha;
+	u32 co3_sel;
+	u32 transp_low0;
+	u32 transp_low1;
+	u32 transp_high0;
+	u32 transp_high1;
+	int solidfill;
+	struct mdp4_overlay_pipe *solidfill_pipe;
+};
+
 struct mdp4_overlay_pipe {
 	uint32 pipe_used;
 	uint32 pipe_type;		/* rgb, video/graphic */
@@ -403,6 +417,7 @@
 void mdp4_intr_clear_set(ulong clear, ulong set);
 void mdp4_dma_p_cfg(void);
 unsigned is_mdp4_hw_reset(void);
+void mdp4_overlay_cfg_init(void);
 void mdp4_hw_init(void);
 void mdp4_isr_read(int);
 void mdp4_clear_lcdc(void);
@@ -417,6 +432,7 @@
 uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
 uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
 uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
+void mdp4_lcdc_base_swap(struct mdp4_overlay_pipe *pipe);
 void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
 #ifdef CONFIG_FB_MSM_DTV
 void mdp4_overlay_dtv_start(void);
@@ -489,6 +505,7 @@
 			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);
@@ -506,7 +523,7 @@
 int mdp4_overlay_dsi_state_get(void);
 void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
 void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
-void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_blend_setup(int mixer);
 struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage);
 void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
 void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
@@ -519,6 +536,7 @@
 int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
 int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
 int mdp4_overlay_unset(struct fb_info *info, int ndx);
+int mdp4_overlay_unset_mixer(int mixer);
 int mdp4_overlay_play_wait(struct fb_info *info,
 	struct msmfb_overlay_data *req);
 int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req);
@@ -533,7 +551,7 @@
 void mdp4_overlay0_done_lcdc(struct mdp_dma_data *dma);
 void mdp4_overlay0_done_mddi(struct mdp_dma_data *dma);
 void mdp4_dma_s_done_mddi(void);
-void mdp4_dma_p_done_mddi(void);
+void mdp4_dma_p_done_mddi(struct mdp_dma_data *dma);
 void mdp4_dma_p_done_dsi(struct mdp_dma_data *dma);
 void mdp4_dma_p_done_dsi_video(struct mdp_dma_data *dma);
 void mdp4_dma_p_done_lcdc(void);
@@ -557,10 +575,32 @@
 {
 	/* empty */
 }
+static inline void mdp4_mddi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd)
+{
+	/* empty */
+}
 static inline void mdp4_mddi_overlay_restore(void)
 {
 	/* empty */
 }
+static inline void mdp4_mddi_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+	/*empty*/
+}
+static inline void mdp4_mddi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+	/*empty*/
+}
+static inline void mdp4_mddi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+					struct msmfb_overlay_blt *req)
+{
+	/* empty */
+}
+static inline void mdp4_mddi_overlay_blt(struct msm_fb_data_type *mfd,
+					struct msmfb_overlay_blt *req)
+{
+	/* empty*/
+}
 #endif
 
 void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
@@ -590,6 +630,7 @@
 					struct msmfb_overlay_blt *req);
 int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
 					struct msmfb_overlay_blt *req);
+void mdp4_dsi_video_base_swap(struct mdp4_overlay_pipe *pipe);
 
 #ifdef CONFIG_FB_MSM_MDP40
 static inline void mdp3_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
@@ -598,6 +639,13 @@
 }
 #endif
 #else
+int mdp4_mddi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+					struct msmfb_overlay_blt *req);
+void mdp4_mddi_overlay_blt(struct msm_fb_data_type *mfd,
+					struct msmfb_overlay_blt *req);
+int mdp4_mddi_overlay_blt_start(struct msm_fb_data_type *mfd);
+int mdp4_mddi_overlay_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_mddi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd);
 static inline int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd)
 {
 	return -ENODEV;
@@ -630,6 +678,10 @@
 {
 	return -ENODEV;
 }
+static inline void mdp4_dsi_video_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+	/* empty */
+}
 #endif
 
 void mdp4_lcdc_overlay_blt(struct msm_fb_data_type *mfd,
@@ -640,9 +692,6 @@
 void mdp4_lcdc_overlay_blt_stop(struct msm_fb_data_type *mfd);
 void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd);
 void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd);
-
-int mdp4_mddi_overlay_blt_offset(int *off);
-void mdp4_mddi_overlay_blt(ulong addr);
 void mdp4_overlay_panel_mode(int mixer_num, uint32 mode);
 void mdp4_overlay_panel_mode_unset(int mixer_num, uint32 mode);
 int mdp4_overlay_mixer_play(int mixer_num);
@@ -664,7 +713,7 @@
 void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe);
 void mdp4_dsi_cmd_overlay_restore(void);
-void mdp_dsi_cmd_overlay_suspend(void);
+void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd);
 #else
 static inline void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
 {
@@ -688,7 +737,7 @@
 	/* empty */
 }
 #ifdef CONFIG_FB_MSM_MDP40
-static inline void mdp_dsi_cmd_overlay_suspend(void)
+static inline void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
 {
 	/* empty */
 }
@@ -701,6 +750,7 @@
 				struct mdp4_overlay_pipe *pipe);
 void mdp4_dsi_cmd_overlay_kickoff(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_base_swap(struct mdp4_overlay_pipe *pipe);
 
 void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d);
 int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req);
@@ -721,7 +771,7 @@
 void mdp4_overlay_dsi_video_wait4vsync(struct msm_fb_data_type *mfd);
 void mdp4_primary_vsync_dsi_video(void);
 uint32_t mdp4_ss_table_value(int8_t param, int8_t index);
-void mdp4_overlay_ctrl_db_reset(void);
+void mdp4_overlay_borderfill_stage_down(struct mdp4_overlay_pipe *pipe);
 
 int mdp4_overlay_writeback_on(struct platform_device *pdev);
 int mdp4_overlay_writeback_off(struct platform_device *pdev);
@@ -759,7 +809,6 @@
 int mdp4_igc_lut_config(struct mdp_igc_lut_data *cfg);
 void mdp4_iommu_unmap(struct mdp4_overlay_pipe *pipe);
 void mdp4_iommu_attach(void);
-void mdp4_iommu_detach(void);
 int mdp4_v4l2_overlay_set(struct fb_info *info, struct mdp_overlay *req,
 		struct mdp4_overlay_pipe **ppipe);
 void mdp4_v4l2_overlay_clear(struct mdp4_overlay_pipe *pipe);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 6d4e44b..2a15506 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -46,8 +46,12 @@
 struct mdp4_overlay_ctrl {
 	struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX];
 	struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
+	struct mdp4_overlay_pipe *baselayer[MDP4_MIXER_MAX];
+	struct blend_cfg blend[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
 	uint32 mixer_cfg[MDP4_MIXER_MAX];
+	uint32 flush[MDP4_MIXER_MAX];
 	uint32 cs_controller;
+	uint32 hw_version;
 	uint32 panel_3d;
 	uint32 panel_mode;
 	uint32 mixer0_played;
@@ -198,14 +202,6 @@
 	}
 }
 
-void mdp4_overlay_ctrl_db_reset(void)
-{
-	int i;
-
-	for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++)
-		ctrl->mixer_cfg[i] = 0;
-}
-
 int mdp4_overlay_mixer_play(int mixer_num)
 {
 	if (mixer_num == MDP4_MIXER2)
@@ -236,6 +232,20 @@
 	return ctrl->panel_mode;
 }
 
+void mdp4_overlay_cfg_init(void)
+{
+	if (ctrl->hw_version == 0) {
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		ctrl->hw_version = inpdw(MDP_BASE + 0x0); /* MDP_HW_VERSION */
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
+
+	if (ctrl->hw_version >= 0x0402030b) {
+		/* MDP_LAYERMIXER_IN_CFG_UPDATE_METHOD */
+		outpdw(MDP_BASE + 0x100fc, 0x01);
+	}
+}
+
 void mdp4_overlay_dmae_cfg(struct msm_fb_data_type *mfd, int atv)
 {
 	uint32	dmae_cfg_reg;
@@ -847,6 +857,8 @@
 	case MDP_YCRCB_H1V1:
 	case MDP_YCBCR_H1V1:
 		return OVERLAY_TYPE_VIDEO;
+	case MDP_RGB_BORDERFILL:
+		return OVERLAY_TYPE_BF;
 	default:
 		mdp4_stat.err_format++;
 		return -ERANGE;
@@ -1120,6 +1132,9 @@
 			pipe->element2 = C2_R_Cr;   /* R */
 		}
 		pipe->bpp = 3;  /* 3 bpp */
+	case MDP_RGB_BORDERFILL:
+		pipe->alpha_enable = 0;
+		pipe->alpha = 0;
 		break;
 	default:
 		/* not likely */
@@ -1441,13 +1456,13 @@
 		return -ENODEV;
 
 	cnt = 0;
-	ndx = 1; /* ndx 0 if not used */
-
+	ndx = MDP4_MIXER_STAGE_BASE;
 	for ( ; ndx < MDP4_MIXER_STAGE_MAX; ndx++) {
 		pipe = ctrl->stage[mixer_num][ndx];
 		if (pipe == NULL)
 			continue;
 		info->z_order = pipe->mixer_stage - MDP4_MIXER_STAGE0;
+		/* z_order == -1, means base layer */
 		info->ptype = pipe->pipe_type;
 		info->pnum = pipe->pipe_num;
 		info->pndx = pipe->pipe_ndx;
@@ -1458,331 +1473,458 @@
 	return cnt;
 }
 
-static void mdp4_overlay_bg_solidfill_clear(uint32 mixer_num)
-{
-	struct mdp4_overlay_pipe *bg_pipe;
-	unsigned char *rgb_base;
-	uint32 rgb_src_format;
-	int pnum;
-
-	bg_pipe = mdp4_overlay_stage_pipe(mixer_num,
-		MDP4_MIXER_STAGE_BASE);
-	if (bg_pipe && bg_pipe->pipe_type == OVERLAY_TYPE_BF) {
-		bg_pipe = mdp4_overlay_stage_pipe(mixer_num,
-				MDP4_MIXER_STAGE0);
-	}
-
-	if (bg_pipe && bg_pipe->pipe_type == OVERLAY_TYPE_RGB) {
-		rgb_src_format = mdp4_overlay_format(bg_pipe);
-		if (!(rgb_src_format & MDP4_FORMAT_SOLID_FILL)) {
-			pnum = bg_pipe->pipe_num - OVERLAY_PIPE_RGB1;
-			rgb_base = MDP_BASE + MDP4_RGB_BASE;
-			rgb_base += MDP4_RGB_OFF * pnum;
-			outpdw(rgb_base + 0x50, rgb_src_format);
-			outpdw(rgb_base + 0x0058, bg_pipe->op_mode);
-			mdp4_overlay_reg_flush(bg_pipe, 0);
-		}
-	}
-}
-
-void mdp4_mixer_pipe_cleanup(int mixer)
-{
-	struct mdp4_overlay_pipe *pipe;
-	int j;
-
-	for (j = MDP4_MIXER_STAGE_MAX - 1; j > MDP4_MIXER_STAGE_BASE; j--) {
-		pipe = ctrl->stage[mixer][j];
-		if (pipe == NULL)
-			continue;
-		pr_debug("%s(): pipe %u\n", __func__, pipe->pipe_ndx);
-		mdp4_mixer_stage_down(pipe);
-		mdp4_overlay_pipe_free(pipe);
-	}
-}
-
 static void mdp4_mixer_stage_commit(int mixer)
 {
 	struct mdp4_overlay_pipe *pipe;
-	int i, j, off;
-	u32 data = 0, stage, flush_bits = 0, pipe_cnt = 0, pull_mode = 0;
-	u32 cfg[MDP4_MIXER_MAX];
+	int i, num;
+	u32 data, stage;
+	int off;
+	unsigned long flags;
 
-	if (mixer == MDP4_MIXER0)
-		flush_bits |= 0x1;
-	else if (mixer == MDP4_MIXER1)
-		flush_bits |= 0x2;
+	data = 0;
+	for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+		pipe = ctrl->stage[mixer][i];
+		if (pipe == NULL)
+			continue;
+		pr_debug("%s: mixer=%d ndx=%d stage=%d\n", __func__,
+					mixer, pipe->pipe_ndx, i);
+		stage = pipe->mixer_stage;
+		if (mixer >= MDP4_MIXER1)
+			stage += 8;
+		stage <<= (4 * pipe->pipe_num);
+		data |= stage;
+	}
 
-	for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++) {
-		cfg[i] = 0;
-		for (j = MDP4_MIXER_STAGE_BASE; j < MDP4_MIXER_STAGE_MAX; j++) {
-			pipe = ctrl->stage[i][j];
-			if (pipe == NULL)
-				break;
-			stage = pipe->mixer_stage;
-			if (i >= MDP4_MIXER1)
-				stage += 8;
-			stage <<= (4 * pipe->pipe_num);
-			cfg[i] |= stage;
-			pipe_cnt++;
+	mdp4_mixer_blend_setup(mixer);
 
-			mdp4_mixer_blend_setup(pipe);
+	off = 0;
+	if (data != ctrl->mixer_cfg[mixer]) {
+		ctrl->mixer_cfg[mixer] = data;
+		if (mixer >= MDP4_MIXER2) {
+			/* MDP_LAYERMIXER2_IN_CFG */
+			off = 0x100f0;
+		} else {
+			/* mixer 0 or 1 */
+			num = mixer + 1;
+			num &= 0x01;
+			data |= ctrl->mixer_cfg[num];
+			off = 0x10100;
 		}
+		pr_debug("%s: mixer=%d data=%x flush=%x\n", __func__,
+				mixer, data, ctrl->flush[mixer]);
 	}
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	if (ctrl->mixer_cfg[mixer] != cfg[mixer]) {
-		if ((ctrl->mixer_cfg[MDP4_MIXER0] != cfg[MDP4_MIXER0]) ||
-		    (ctrl->mixer_cfg[MDP4_MIXER1] != cfg[MDP4_MIXER1])) {
-			off = 0x10100;
-			if (ctrl->mixer_cfg[MDP4_MIXER0] != cfg[MDP4_MIXER0]) {
-				flush_bits |= 0x1;
-				ctrl->mixer_cfg[MDP4_MIXER0] = cfg[MDP4_MIXER0];
+	local_irq_save(flags);
+	if (off)
+		outpdw(MDP_BASE + off, data);
 
-				if ((ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) ||
-				    (ctrl->panel_mode & MDP4_PANEL_LCDC))
-					pull_mode = 1;
-			}
-			if (ctrl->mixer_cfg[MDP4_MIXER1] != cfg[MDP4_MIXER1]) {
-				flush_bits |= 0x2;
-				ctrl->mixer_cfg[MDP4_MIXER1] = cfg[MDP4_MIXER1];
-
-				pull_mode = 1;
-			}
-
-			data = cfg[MDP4_MIXER0] | cfg[MDP4_MIXER1];
-
-			pr_debug("%s: mixer=%d data=%x flush=%x\n", __func__,
-			       mixer, data, flush_bits);
-
-			outpdw(MDP_BASE + off, data); /* LAYERMIXER_IN_CFG */
-			if (pull_mode) {
-				outpdw(MDP_BASE + 0x18000, flush_bits);
-			/* wait for vsync on both pull mode interfaces */
-				msleep(20);
-			}
-		}
-
-		if (ctrl->mixer_cfg[MDP4_MIXER2] != cfg[MDP4_MIXER2]) {
-			off = 0x100F0;
-			ctrl->mixer_cfg[MDP4_MIXER2] = cfg[MDP4_MIXER2];
-			data = cfg[MDP4_MIXER2];
-
-			pr_debug("%s: mixer=%d data=%x\n", __func__,
-			       mixer, data);
-
-			outpdw(MDP_BASE + off, data); /* LAYERMIXER_IN_CFG */
-		}
-	} else {
-		if (mixer == MDP4_MIXER0) {
-			if ((ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) ||
-			(ctrl->panel_mode & MDP4_PANEL_LCDC))
-				pull_mode = 1;
-		} else if (mixer == MDP4_MIXER1) {
-			pull_mode = 1;
-		}
-
-		if (pull_mode)
-			outpdw(MDP_BASE + 0x18000, flush_bits);
+	if (ctrl->flush[mixer]) {
+		outpdw(MDP_BASE + 0x18000, ctrl->flush[mixer]);
+		ctrl->flush[mixer] = 0;
 	}
+	local_irq_restore(flags);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	if (data && pipe_cnt == 1)
-		mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
 }
 
+
 void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
 {
-	struct mdp4_overlay_pipe *spipe;
-	int mixer;
+	struct mdp4_overlay_pipe *pp;
+	int i, mixer;
 
 	mixer = pipe->mixer_num;
 
-	spipe = ctrl->stage[mixer][pipe->mixer_stage];
-	if ((spipe != NULL) && (spipe->pipe_num != pipe->pipe_num)) {
-		mdp4_stat.err_stage++;
-		return;
+	for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+		pp = ctrl->stage[mixer][i];
+		if (pp == pipe) {
+			ctrl->stage[mixer][i] = NULL;
+			break;
+		}
 	}
 
 	ctrl->stage[mixer][pipe->mixer_stage] = pipe;	/* keep it */
 
-	if (!(pipe->flags & MDP_OV_PLAY_NOWAIT))
+	if (!(pipe->flags & MDP_OV_PLAY_NOWAIT)) {
+		pr_debug("%s: mixer=%d ndx=%d stage=%d flags=%x\n",
+			__func__, mixer, pipe->pipe_ndx,
+				pipe->mixer_stage, pipe->flags);
 		mdp4_mixer_stage_commit(mixer);
+	}
 }
 
 void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
 {
-	struct mdp4_overlay_pipe *spipe;
+	struct mdp4_overlay_pipe *pp;
+	int i, mixer;
 
-	spipe = ctrl->stage[pipe->mixer_num][pipe->mixer_stage];
-	if (spipe == NULL)	/* not running */
+	mixer = pipe->mixer_num;
+
+	for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+		pp = ctrl->stage[mixer][i];
+		if (pp == pipe)
+			ctrl->stage[mixer][i] = NULL;  /* clear it */
+	}
+
+	if (!(pipe->flags & MDP_OV_PLAY_NOWAIT)) {
+		pr_debug("%s: mixer=%d ndx=%d stage=%d flags=%x\n",
+			__func__, pipe->mixer_num, pipe->pipe_ndx,
+				pipe->mixer_stage, pipe->flags);
+		mdp4_mixer_stage_commit(pipe->mixer_num);
+	}
+}
+/*
+ * mixer0: rgb3: border color at register 0x15004, 0x15008
+ * mixer1:  vg3: border color at register 0x1D004, 0x1D008
+ * mixer2:  xxx: border color at register 0x8D004, 0x8D008
+ */
+void mdp4_overlay_borderfill_stage_up(struct mdp4_overlay_pipe *pipe)
+{
+	struct mdp4_overlay_pipe *bspipe;
+	int ptype, pnum, pndx, mixer;
+	int format, alpha_enable, alpha;
+
+	if (pipe->pipe_type != OVERLAY_TYPE_BF)
 		return;
 
-	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;	/* clear it */
+	mixer = pipe->mixer_num;
 
-	mdp4_mixer_stage_commit(pipe->mixer_num);
+	if (ctrl->baselayer[mixer])
+		return;
+
+	bspipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+
+	/* save original base layer */
+	ctrl->baselayer[mixer] = bspipe;
+
+	pipe->alpha = 0;	/* make sure bf pipe has alpha 0 */
+	ptype = pipe->pipe_type;
+	pnum = pipe->pipe_num;
+	pndx = pipe->pipe_ndx;
+	format = pipe->src_format;
+	alpha_enable = pipe->alpha_enable;
+	alpha = pipe->alpha;
+	*pipe = *bspipe;	/* keep base layer configuration */
+	pipe->pipe_type = ptype;
+	pipe->pipe_num = pnum;
+	pipe->pipe_ndx = pndx;
+	pipe->src_format = format;
+	pipe->alpha_enable = alpha_enable;
+	pipe->alpha = alpha;
+
+	/* free original base layer pipe to be sued as normal pipe */
+	bspipe->pipe_used = 0;
+
+	if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+		mdp4_dsi_video_base_swap(pipe);
+	else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+		mdp4_lcdc_base_swap(pipe);
+	else if (ctrl->panel_mode & MDP4_PANEL_DTV)
+		mdp4_dtv_base_swap(pipe);
+
+	mdp4_overlay_reg_flush(bspipe, 1);
+	/* borderfill pipe as base layer */
+	mdp4_mixer_stage_up(pipe);
 }
 
-void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
+void mdp4_overlay_borderfill_stage_down(struct mdp4_overlay_pipe *pipe)
 {
-	struct mdp4_overlay_pipe *bg_pipe;
-	unsigned char *overlay_base, *rgb_base;
-	uint32 c0, c1, c2, blend_op, constant_color = 0, rgb_src_format;
-	uint32 fg_color3_out, fg_alpha = 0, bg_alpha = 0;
-	int off, pnum;
+	struct mdp4_overlay_pipe *bspipe;
+	int ptype, pnum, pndx, mixer;
+	int format, alpha_enable, alpha;
 
-	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE)
+	if (pipe->pipe_type != OVERLAY_TYPE_BF)
 		return;
 
+	mixer = pipe->mixer_num;
+
+	/* retrieve original base layer */
+	bspipe = ctrl->baselayer[mixer];
+	if (bspipe == NULL) {
+		pr_err("%s: no base layer at mixer=%d\n",
+				__func__, mixer);
+		return;
+	}
+
+	ptype = bspipe->pipe_type;
+	pnum = bspipe->pipe_num;
+	pndx = bspipe->pipe_ndx;
+	format = bspipe->src_format;
+	alpha_enable = bspipe->alpha_enable;
+	alpha = bspipe->alpha;
+	*bspipe = *pipe;	/* restore base layer configuration */
+	bspipe->pipe_type = ptype;
+	bspipe->pipe_num = pnum;
+	bspipe->pipe_ndx = pndx;
+	bspipe->src_format = format;
+	bspipe->alpha_enable = alpha_enable;
+	bspipe->alpha = alpha;
+
+	bspipe->pipe_used++;	/* mark base layer pipe used */
+
+	ctrl->baselayer[mixer] = NULL;
+
+	/* free borderfill pipe */
+	pipe->pipe_used = 0;
+
+	mdp4_dsi_video_base_swap(bspipe);
+
+	/* free borderfill pipe */
+	mdp4_overlay_reg_flush(pipe, 1);
+	mdp4_mixer_stage_down(pipe);
+	mdp4_overlay_pipe_free(pipe);
+
+	/* stage up base layer */
+	mdp4_overlay_reg_flush(bspipe, 1);
+	/* restore original base layer */
+	mdp4_mixer_stage_up(bspipe);
+}
+
+
+static struct mdp4_overlay_pipe *mdp4_background_layer(int mixer,
+			struct mdp4_overlay_pipe *sp)
+{
+	struct mdp4_overlay_pipe *pp;
+	struct mdp4_overlay_pipe *kp;
+	int i;
+
+	kp = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+	for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+		pp = ctrl->stage[mixer][i];
+		if (pp == NULL)
+			continue;
+		if (pp == sp)
+			break;
+
+		if ((pp->dst_x <= sp->dst_x) &&
+			((pp->dst_x + pp->dst_w) >= (sp->dst_x + sp->dst_w))) {
+			if ((pp->dst_y <= sp->dst_y) &&
+				((pp->dst_y + pp->dst_h) >=
+					(sp->dst_y + sp->dst_h))) {
+				kp = pp;
+			}
+		}
+	}
+	return kp;
+}
+
+static void mdp4_overlay_bg_solidfill(struct blend_cfg *blend)
+{
+	struct mdp4_overlay_pipe *pipe;
+	char *base;
+	u32 op_mode, format;
+	int pnum, ptype;
+
+	pipe = blend->solidfill_pipe;
+	if (pipe == NULL)
+		return;
+
+	if (pipe->pipe_type == OVERLAY_TYPE_BF)
+		return;
+
+	ptype = mdp4_overlay_format2type(pipe->src_format);
+	if (ptype == OVERLAY_TYPE_RGB) {
+		pnum = pipe->pipe_num - OVERLAY_PIPE_RGB1;
+		base = MDP_BASE + MDP4_RGB_BASE;
+		base += MDP4_RGB_OFF * pnum;
+	} else {
+		pnum = pipe->pipe_num - OVERLAY_PIPE_VG1;
+		base = MDP_BASE + MDP4_VIDEO_BASE;
+		base += MDP4_VIDEO_OFF * pnum;
+	}
+
+	format = inpdw(base + 0x50);
+	if (blend->solidfill) {
+		format |= MDP4_FORMAT_SOLID_FILL;
+		/*
+		 * If solid fill is enabled, flip and scale
+		 * have to be disabled. otherwise, h/w
+		 * underruns.
+		 */
+		op_mode = inpdw(base + 0x0058);
+		op_mode &= ~(MDP4_OP_FLIP_LR + MDP4_OP_SCALEX_EN);
+		op_mode &= ~(MDP4_OP_FLIP_UD + MDP4_OP_SCALEY_EN);
+		outpdw(base + 0x0058, op_mode);
+		outpdw(base + 0x1008, 0);	/* black */
+	} else {
+		format &= ~MDP4_FORMAT_SOLID_FILL;
+		blend->solidfill_pipe = NULL;
+	}
+
+	outpdw(base + 0x50, format);
+
+	mdp4_overlay_reg_flush(pipe, 0);
+}
+
+/*
+ * D(i+1) = Ks * S + Kd * D(i)
+ */
+void mdp4_mixer_blend_setup(int mixer)
+{
+	struct mdp4_overlay_pipe *d_pipe;
+	struct mdp4_overlay_pipe *s_pipe;
+	struct blend_cfg *blend;
+	int i, off, ptype;
+	int d_alpha, s_alpha;
+	unsigned char *overlay_base;
+	uint32 c0, c1, c2;
+
+
+	d_pipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+	if (d_pipe == NULL) {
+		pr_err("%s: Error: no bg_pipe at mixer=%d\n", __func__, mixer);
+		return;
+	}
+
+	blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE0];
+	for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
+		blend->solidfill = 0;
+		blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
+				    MDP4_BLEND_BG_ALPHA_BG_CONST);
+		s_pipe = ctrl->stage[mixer][i];
+		if (s_pipe == NULL) {
+			blend++;
+			d_pipe = NULL;
+			d_alpha = 0;
+			continue;
+		}
+		d_pipe = mdp4_background_layer(mixer, s_pipe);
+		d_alpha = d_pipe->alpha_enable;
+		s_alpha = s_pipe->alpha_enable;
+		pr_debug("%s: stage=%d: bg: ndx=%d da=%d dalpha=%x "
+			"fg: ndx=%d sa=%d salpha=%x is_fg=%d\n",
+		 __func__, i-2, d_pipe->pipe_ndx, d_alpha, d_pipe->alpha,
+		s_pipe->pipe_ndx, s_alpha, s_pipe->alpha, s_pipe->is_fg);
+
+		/* base on fg's alpha */
+		blend->bg_alpha = 0x0ff - s_pipe->alpha;
+		blend->fg_alpha = s_pipe->alpha;
+		blend->co3_sel = 1; /* use fg alpha */
+
+		if (s_pipe->is_fg) {
+			if (s_pipe->alpha == 0xff) {
+				blend->solidfill = 1;
+				blend->solidfill_pipe = d_pipe;
+			}
+		} else if (s_alpha) {
+			blend->op = (MDP4_BLEND_BG_ALPHA_FG_PIXEL |
+				    MDP4_BLEND_BG_INV_ALPHA);
+		} else if (d_alpha) {
+			ptype = mdp4_overlay_format2type(s_pipe->src_format);
+			if (ptype == OVERLAY_TYPE_VIDEO) {
+				blend->op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
+				    MDP4_BLEND_FG_ALPHA_BG_PIXEL |
+				    MDP4_BLEND_FG_INV_ALPHA);
+				blend->co3_sel = 0; /* use bg alpha */
+			} else {
+				/* s_pipe is rgb without alpha */
+				blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
+					    MDP4_BLEND_BG_ALPHA_BG_CONST);
+				blend->bg_alpha = 0;
+			}
+		}
+
+		if (s_pipe->transp != MDP_TRANSP_NOP) {
+			if (s_pipe->is_fg) {
+				transp_color_key(s_pipe->src_format,
+						s_pipe->transp, &c0, &c1, &c2);
+				/* Fg blocked */
+				blend->op |= MDP4_BLEND_FG_TRANSP_EN;
+				/* lower limit */
+				blend->transp_low0 = (c1 << 16 | c0);
+				blend->transp_low1 = c2;
+				/* upper limit */
+				blend->transp_high0 = (c1 << 16 | c0);
+				blend->transp_high1 = c2;
+			} else {
+				transp_color_key(d_pipe->src_format,
+						s_pipe->transp, &c0, &c1, &c2);
+				/* Fg blocked */
+				blend->op |= MDP4_BLEND_BG_TRANSP_EN;
+				blend--; /* one stage back */
+				/* lower limit */
+				blend->transp_low0 = (c1 << 16 | c0);
+				blend->transp_low1 = c2;
+				/* upper limit */
+				blend->transp_high0 = (c1 << 16 | c0);
+				blend->transp_high1 = c2;
+				blend++; /* back to original stage */
+			}
+		}
+		blend++;
+	}
+
 	/* mixer numer, /dev/fb0, /dev/fb1, /dev/fb2 */
-	if (pipe->mixer_num == MDP4_MIXER2)
+	if (mixer == MDP4_MIXER2)
 		overlay_base = MDP_BASE + MDP4_OVERLAYPROC2_BASE;/* 0x88000 */
-	else if (pipe->mixer_num == MDP4_MIXER1)
+	else if (mixer == MDP4_MIXER1)
 		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
 	else
 		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
 
-	/* stage 0 to stage 2 */
-	off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
-
-	bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
-					  MDP4_MIXER_STAGE_BASE);
-	if (bg_pipe == NULL) {
-		pr_err("%s: Error: no bg_pipe\n", __func__);
-		return;
-	}
-
-	if (bg_pipe->pipe_type == OVERLAY_TYPE_BF &&
-	    pipe->mixer_stage > MDP4_MIXER_STAGE0) {
-		bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
-						  MDP4_MIXER_STAGE0);
-	}
-
-	if (pipe->alpha_enable) {
-		/* alpha channel is lost on VG pipe when downscaling */
-		if (pipe->pipe_type == OVERLAY_TYPE_VIDEO &&
-		    (pipe->dst_w < pipe->src_w || pipe->dst_h < pipe->src_h))
-			fg_alpha = 0;
-		else
-			fg_alpha = 1;
-	}
-
-	if (!fg_alpha && bg_pipe && bg_pipe->alpha_enable) {
-		struct mdp4_overlay_pipe *tmp;
-		int stage;
-
-		bg_alpha = 1;
-		/* check all bg layers are opaque to propagate bg alpha */
-		stage = bg_pipe->mixer_stage + 1;
-		for (; stage < pipe->mixer_stage; stage++) {
-			tmp = mdp4_overlay_stage_pipe(pipe->mixer_num, stage);
-			if (!tmp || tmp->alpha_enable || tmp->is_fg) {
-				bg_alpha = 0;
-				break;
-			}
-		}
-	}
-
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE_BASE];
+	/* lower limit */
+	outpdw(overlay_base + 0x180, blend->transp_low0);
+	outpdw(overlay_base + 0x184,  blend->transp_low1);
+	/* upper limit */
+	outpdw(overlay_base + 0x188, blend->transp_high0);
+	outpdw(overlay_base + 0x18c,  blend->transp_high1);
+	blend++; /* stage0 */
+	for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
+		off = 20 * i;
+		off = 0x20 * (i - MDP4_MIXER_STAGE0);
+		if (i == MDP4_MIXER_STAGE3)
+			off -= 4;
 
-	blend_op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
-		    MDP4_BLEND_BG_ALPHA_BG_CONST);
-	outpdw(overlay_base + off + 0x108, pipe->alpha);
-	outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
-	fg_color3_out = 1; /* keep fg alpha by default */
+		if (blend->solidfill_pipe)
+			mdp4_overlay_bg_solidfill(blend);
 
-	if (pipe->is_fg) {
-		if (pipe->alpha == 0xff &&
-			bg_pipe->pipe_type == OVERLAY_TYPE_RGB) {
-			u32 op_mode;
-			pnum = bg_pipe->pipe_num - OVERLAY_PIPE_RGB1;
-			rgb_base = MDP_BASE + MDP4_RGB_BASE;
-			rgb_base += MDP4_RGB_OFF * pnum;
-			rgb_src_format = inpdw(rgb_base + 0x50);
-			rgb_src_format |= MDP4_FORMAT_SOLID_FILL;
-			/*
-			 * If solid fill is enabled, flip and scale
-			 * have to be disabled. otherwise, h/w
-			 * underruns. Also flush the pipe inorder
-			 * to take solid fill into effect.
-			 */
-			op_mode = inpdw(rgb_base + 0x0058);
-			op_mode &= ~(MDP4_OP_FLIP_LR + MDP4_OP_SCALEX_EN);
-			op_mode &= ~(MDP4_OP_FLIP_UD + MDP4_OP_SCALEY_EN);
-			outpdw(rgb_base + 0x0058, op_mode);
-			outpdw(rgb_base + 0x50, rgb_src_format);
-			outpdw(rgb_base + 0x1008, constant_color);
-			mdp4_overlay_reg_flush(bg_pipe, 0);
-		}
-	} else if (fg_alpha) {
-		blend_op = (MDP4_BLEND_BG_ALPHA_FG_PIXEL |
-			    MDP4_BLEND_BG_INV_ALPHA);
-		fg_color3_out = 1; /* keep fg alpha */
-	} else if (bg_alpha) {
-		blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
-			    MDP4_BLEND_FG_ALPHA_BG_PIXEL |
-			    MDP4_BLEND_FG_INV_ALPHA);
-		fg_color3_out = 0; /* keep bg alpha */
-	}
-
-	if (pipe->transp != MDP_TRANSP_NOP) {
-		if (pipe->is_fg) {
-			transp_color_key(pipe->src_format, pipe->transp,
-					&c0, &c1, &c2);
-			/* Fg blocked */
-			blend_op |= MDP4_BLEND_FG_TRANSP_EN;
-			/* lower limit */
-			outpdw(overlay_base + off + 0x110,
-					(c1 << 16 | c0));/* low */
-			outpdw(overlay_base + off + 0x114, c2);/* low */
+		outpdw(overlay_base + off + 0x108, blend->fg_alpha);
+		outpdw(overlay_base + off + 0x10c, blend->bg_alpha);
+		outpdw(overlay_base + off + 0x104, blend->op);
+		outpdw(overlay_base + (off << 5) + 0x1004, blend->co3_sel);
+		outpdw(overlay_base + off + 0x110, blend->transp_low0);/* low */
+		outpdw(overlay_base + off + 0x114, blend->transp_low1);/* low */
 			/* upper limit */
-			outpdw(overlay_base + off + 0x118,
-					(c1 << 16 | c0));
-			outpdw(overlay_base + off + 0x11c, c2);
-		} else if (bg_pipe) {
-			transp_color_key(bg_pipe->src_format,
-				pipe->transp, &c0, &c1, &c2);
-			/* bg blocked */
-			blend_op |= MDP4_BLEND_BG_TRANSP_EN;
-			/* lower limit */
-			outpdw(overlay_base + 0x180,
-					(c1 << 16 | c0));/* low */
-			outpdw(overlay_base + 0x184, c2);/* low */
-			/* upper limit */
-			outpdw(overlay_base + 0x188,
-					(c1 << 16 | c0));/* high */
-			outpdw(overlay_base + 0x18c, c2);/* high */
-		}
+		outpdw(overlay_base + off + 0x118, blend->transp_high0);
+		outpdw(overlay_base + off + 0x11c, blend->transp_high1);
+		blend++;
 	}
-
-	outpdw(overlay_base + off + 0x104, blend_op);
-	outpdw(overlay_base + (off << 5) + 0x1004, fg_color3_out);
-
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
 void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
 {
-	struct mdp4_overlay_pipe *bg_pipe;
-	uint32 bits = 0;
+	int mixer;
+	uint32 *reg;
+
+	mixer = pipe->mixer_num;
+	reg = &ctrl->flush[mixer];
+	*reg |= (1 << (2 + pipe->pipe_num));
 
 	if (all) {
-		if (pipe->mixer_num == MDP4_MIXER1)
-			bits |= 0x02;
+		if (mixer == MDP4_MIXER0)
+			*reg |= 0x01;
 		else
-			bits |= 0x01;
+			*reg |= 0x02;
 	}
+}
 
-	if (pipe->pipe_num <= OVERLAY_PIPE_RGB2)
-		bits |= 1 << (2 + pipe->pipe_num);
-	if (pipe->is_fg && pipe->alpha == 0xFF) {
-		bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
-						  MDP4_MIXER_STAGE_BASE);
-		bits |= 1 << (2 + bg_pipe->pipe_num);
-	}
+void mdp4_overlay_flush_piggyback(int m0, int m1)
+{
+	u32 data;
 
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	outpdw(MDP_BASE + 0x18000, bits);	/* MDP_OVERLAY_REG_FLUSH */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	data = ctrl->flush[m0] | ctrl->flush[m1];
+	ctrl->flush[m0] = data;
+}
+
+void mdp4_overlay_reg_flush_reset(struct mdp4_overlay_pipe *pipe)
+{
+	int mixer;
+
+	mixer = pipe->mixer_num;
+	ctrl->flush[mixer] = 0;
 }
 
 struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage)
@@ -1810,6 +1952,11 @@
 	int i;
 	struct mdp4_overlay_pipe *pipe;
 
+	if (ptype == OVERLAY_TYPE_BF) {
+		if (!mdp4_overlay_borderfill_supported())
+			return NULL;
+	}
+
 	for (i = 0; i < OVERLAY_PIPE_MAX; i++) {
 		pipe = &ctrl->plist[i];
 		if ((pipe->pipe_used == 0) && ((pipe->pipe_type == ptype) ||
@@ -1951,7 +2098,7 @@
 		return -ERANGE;
 	}
 
-	if (req->z_order < 0 || req->z_order > 2) {
+	if (req->z_order < 0 || req->z_order > 3) {
 		pr_err("%s: z_order=%d out of range!\n", __func__,
 				req->z_order);
 		mdp4_stat.err_zorder++;
@@ -2076,12 +2223,12 @@
 	if (req->id == MSMFB_NEW_REQUEST) {  /* new request */
 		pipe->pipe_used++;
 		pipe->mixer_num = mixer;
-		pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
 		pr_debug("%s: zorder=%d pipe ndx=%d num=%d\n", __func__,
 			req->z_order, pipe->pipe_ndx, pipe->pipe_num);
 
 	}
 
+	pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
 	pipe->src_width = req->src.width & 0x1fff;	/* source img width */
 	pipe->src_height = req->src.height & 0x1fff;	/* source img height */
 	pipe->src_h = req->src_rect.h & 0x07ff;
@@ -2217,6 +2364,8 @@
 		mdp4_dsi_video_overlay_blt(mfd, req);
 	else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
 		mdp4_lcdc_overlay_blt(mfd, req);
+	else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
+		mdp4_mddi_overlay_blt(mfd, req);
 
 	mutex_unlock(&mfd->dma->ov_mutex);
 
@@ -2238,6 +2387,8 @@
 		ret = mdp4_dsi_video_overlay_blt_offset(mfd, req);
 	else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
 		ret = mdp4_lcdc_overlay_blt_offset(mfd, req);
+	else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
+		mdp4_mddi_overlay_blt_offset(mfd, req);
 
 	mutex_unlock(&mfd->dma->ov_mutex);
 
@@ -2331,7 +2482,14 @@
 
 void mdp4_update_perf_level(u32 perf_level)
 {
+	static int first = 1;
+
 	new_perf_level = perf_level;
+
+	if (first) {
+		first = 0;
+		mdp4_set_perf_level();
+	}
 }
 
 void mdp4_set_perf_level(void)
@@ -2365,6 +2523,8 @@
 			mdp4_dsi_video_blt_start(mfd);
 		else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
 			mdp4_dsi_overlay_blt_start(mfd);
+		else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
+			mdp4_mddi_overlay_blt_start(mfd);
 	} else {
 		if (mfd->panel_info.type == LCDC_PANEL ||
 		    mfd->panel_info.type == LVDS_PANEL)
@@ -2373,6 +2533,8 @@
 			mdp4_dsi_video_blt_stop(mfd);
 		else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
 			mdp4_dsi_overlay_blt_stop(mfd);
+		else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
+			mdp4_mddi_overlay_blt_stop(mfd);
 	}
 	mfd->ov0_blt_state = mfd->use_ov0_blt;
 }
@@ -2413,6 +2575,12 @@
 			use_blt = 1;
 	}
 
+	if (mfd->panel_info.type == MDDI_PANEL) {
+		if ((req->src_rect.h/2) >= req->dst_rect.h ||
+			(req->src_rect.w/2) >= req->dst_rect.w)
+				use_blt = 1;
+	}
+
 	if (mfd->mdp_rev == MDP_REV_41) {
 		/*
 		* writeback (blt) mode to provide work around for
@@ -2539,6 +2707,7 @@
 					mdp4_set_perf_level();
 			} else if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
 				mdp4_mddi_dma_busy_wait(mfd);
+				mdp4_mddi_blt_dmap_busy_wait(mfd);
 				mdp4_set_perf_level();
 			}
 		} else {
@@ -2553,6 +2722,24 @@
 	return 0;
 }
 
+int mdp4_overlay_unset_mixer(int mixer)
+{
+	struct mdp4_overlay_pipe *pipe;
+	int i, cnt = 0;
+
+	for (i = MDP4_MIXER_STAGE3; i >= MDP4_MIXER_STAGE_BASE; i--) {
+		pipe = ctrl->stage[mixer][i];
+		if (pipe == NULL)
+			continue;
+		pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+		mdp4_mixer_stage_down(pipe);
+		mdp4_overlay_pipe_free(pipe);
+		cnt++;
+	}
+
+	return cnt;
+}
+
 int mdp4_overlay_unset(struct fb_info *info, int ndx)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -2573,6 +2760,12 @@
 		return -ENODEV;
 	}
 
+	if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+		mdp4_overlay_borderfill_stage_down(pipe);
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return 0;
+	}
+
 	if (pipe->mixer_num == MDP4_MIXER2)
 		ctrl->mixer2_played = 0;
 	else if (pipe->mixer_num == MDP4_MIXER1)
@@ -2589,21 +2782,17 @@
 #else
 		if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
 			if (mfd->panel_power_on)
-				mdp4_mddi_dma_busy_wait(mfd);
+				mdp4_mddi_blt_dmap_busy_wait(mfd);
 		}
 #endif
 	}
 
-	if (mfd->mdp_rev >= MDP_REV_41 &&
-		mdp4_overlay_is_rgb_type(pipe->src_format) &&
-		!mfd->use_ov0_blt && (pipe->mixer_num == MDP4_MIXER0 ||
-		hdmi_prim_display)) {
-			ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
-	} else {
-		if (pipe->is_fg &&
-			!mdp4_overlay_is_rgb_type(pipe->src_format)) {
-			mdp4_overlay_bg_solidfill_clear(pipe->mixer_num);
-			pipe->is_fg = 0;
+	{
+		mdp4_overlay_reg_flush(pipe, 1);
+
+		if (mfd->use_ov0_blt || pipe->mixer_num == MDP4_MIXER1) {
+			/* unstage pipe forcedly */
+			pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
 		}
 
 		mdp4_mixer_stage_down(pipe);
@@ -2764,6 +2953,12 @@
 	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
 		return -EINTR;
 
+	if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+		mdp4_overlay_borderfill_stage_up(pipe);
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return 0;
+	}
+
 	img = &req->data;
 	get_img(img, info, pipe, 0, &start, &len, &srcp0_file,
 		&ps0_need, &srcp0_ihdl);
@@ -2778,6 +2973,10 @@
 	pipe->srcp0_addr = addr;
 	pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
 
+
+	pr_debug("%s: mixer=%d ndx=%x addr=%x flags=%x\n", __func__,
+		pipe->mixer_num, pipe->pipe_ndx, (int)addr, pipe->flags);
+
 	if ((req->version_key & VERSION_KEY_MASK) == 0xF9E8D700)
 		overlay_version = (req->version_key & ~VERSION_KEY_MASK);
 
@@ -2874,6 +3073,7 @@
 	if (mfd->use_ov1_blt)
 		mdp4_overlay1_update_blt_mode(mfd);
 
+
 	if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
 		mdp4_overlay_vg_setup(pipe);	/* video/graphic pipe */
 	} else {
@@ -2886,11 +3086,7 @@
 		mdp4_overlay_rgb_setup(pipe);	/* rgb pipe */
 	}
 
-	if ((ctrl->panel_mode & MDP4_PANEL_DTV) ||
-		(ctrl->panel_mode & MDP4_PANEL_LCDC) ||
-		(ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO))
-		mdp4_overlay_reg_flush(pipe, 0);
-
+	mdp4_overlay_reg_flush(pipe, 1);
 	mdp4_mixer_stage_up(pipe);
 
 	if (pipe->mixer_num == MDP4_MIXER2) {
@@ -2905,6 +3101,9 @@
 		ctrl->mixer1_played++;
 		/* enternal interface */
 		if (ctrl->panel_mode & MDP4_PANEL_DTV) {
+			if (pipe->flags & MDP_OV_PLAY_NOWAIT)
+				mdp4_overlay_flush_piggyback(MDP4_MIXER0,
+							MDP4_MIXER1);
 			mdp4_overlay_dtv_start();
 			mdp4_overlay_dtv_ov_done_push(mfd, pipe);
 			if (!mfd->use_ov1_blt)
@@ -2933,6 +3132,7 @@
 		}
 #endif
 		else {
+			mdp4_overlay_reg_flush_reset(pipe);
 			/* mddi & mipi dsi cmd mode */
 			if (pipe->flags & MDP_OV_PLAY_NOWAIT) {
 				mdp4_stat.overlay_play[pipe->mixer_num]++;
@@ -3002,7 +3202,6 @@
 	},
 };
 
-static int iommu_enabled;
 static int mdp_iommu_fault_handler(struct iommu_domain *domain,
 	struct device *dev, unsigned long iova, int flags)
 {
@@ -3012,10 +3211,11 @@
 
 void mdp4_iommu_attach(void)
 {
+	static int done;
 	struct iommu_domain *domain;
 	int i;
 
-	if (!iommu_enabled) {
+	if (!done) {
 		for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
 			int domain_idx;
 			struct device *ctx = msm_iommu_get_ctx(
@@ -3040,38 +3240,7 @@
 				continue;
 			}
 		}
-		pr_debug("Attached MDP IOMMU device\n");
-		iommu_enabled = 1;
-	}
-}
-
-void mdp4_iommu_detach(void)
-{
-	struct iommu_domain *domain;
-	int i;
-
-	if (!mdp_check_suspended() || mdp4_extn_disp)
-		return;
-
-	if (iommu_enabled) {
-		for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
-			int domain_idx;
-			struct device *ctx = msm_iommu_get_ctx(
-				msm_iommu_ctx_names[i].name);
-
-			if (!ctx)
-				continue;
-
-			domain_idx = msm_iommu_ctx_names[i].domain;
-
-			domain = msm_get_iommu_domain(domain_idx);
-			if (!domain)
-				continue;
-
-			iommu_detach_device(domain,	ctx);
-		}
-		pr_debug("Detached MDP IOMMU device\n");
-		iommu_enabled = 0;
+		done = 1;
 	}
 }
 
@@ -3092,7 +3261,7 @@
 		return err;
 	}
 
-	mdp4_mixer_blend_setup(pipe);
+	mdp4_mixer_blend_setup(pipe->mixer_num);
 	*ppipe = pipe;
 
 	return 0;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index a5b4b3e..7ba4e75 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -114,6 +114,11 @@
 	}
 }
 
+void mdp4_dsi_cmd_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+	dsi_pipe = pipe;
+}
+
 void mdp4_overlay_update_dsi_cmd(struct msm_fb_data_type *mfd)
 {
 	MDPIBUF *iBuf = &mfd->ibuf;
@@ -162,6 +167,14 @@
 	} else {
 		pipe = dsi_pipe;
 	}
+
+	if (pipe->pipe_used == 0 ||
+			pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+		pr_err("%s: NOT baselayer\n", __func__);
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return;
+	}
+
 	/*
 	 * configure dsi stream id
 	 * dma_p = 0, dma_s = 1
@@ -207,6 +220,8 @@
 
 	mdp4_overlay_rgb_setup(pipe);
 
+	mdp4_overlay_reg_flush(pipe, 1);
+
 	mdp4_mixer_stage_up(pipe);
 
 	mdp4_overlayproc_cfg(pipe);
@@ -240,6 +255,12 @@
 	dsi_pipe->src_width_3d = r3d->width;
 
 	pipe = dsi_pipe;
+	if (pipe->pipe_used == 0 ||
+			pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+		pr_err("%s: NOT baselayer\n", __func__);
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return;
+	}
 
 	if (pipe->is_3d)
 		mdp4_overlay_panel_3d(pipe->mixer_num, MDP4_3D_SIDE_BY_SIDE);
@@ -282,6 +303,8 @@
 
 	mdp4_overlay_rgb_setup(pipe);
 
+	mdp4_overlay_reg_flush(pipe, 1);
+
 	mdp4_mixer_stage_up(pipe);
 
 	mdp4_overlayproc_cfg(pipe);
@@ -651,12 +674,22 @@
 	mdp4_stat.kickoff_ov0++;
 }
 
-void mdp_dsi_cmd_overlay_suspend(void)
+void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
 {
 	/* dis-engage rgb0 from mixer0 */
 	if (dsi_pipe) {
-		mdp4_mixer_stage_down(dsi_pipe);
-		mdp4_iommu_unmap(dsi_pipe);
+		if (mfd->ref_cnt == 0) {
+			/* adb stop */
+			if (dsi_pipe->pipe_type == OVERLAY_TYPE_BF)
+				mdp4_overlay_borderfill_stage_down(dsi_pipe);
+
+			/* dsi_pipe == rgb1 */
+			mdp4_overlay_unset_mixer(dsi_pipe->mixer_num);
+			dsi_pipe = NULL;
+		} else {
+			mdp4_mixer_stage_down(dsi_pipe);
+			mdp4_iommu_unmap(dsi_pipe);
+		}
 	}
 }
 
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index fb71cc1..05c6fe8 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -69,6 +69,11 @@
 static void mdp4_overlay_dsi_video_wait4event(struct msm_fb_data_type *mfd,
 						int intr_done);
 
+void mdp4_dsi_video_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+	dsi_pipe = pipe;
+}
+
 int mdp4_dsi_video_on(struct platform_device *pdev)
 {
 	int dsi_width;
@@ -118,8 +123,6 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
-	mdp4_overlay_ctrl_db_reset();
-
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
@@ -192,8 +195,9 @@
 
 	mdp4_overlay_dmap_xy(pipe);	/* dma_p */
 	mdp4_overlay_dmap_cfg(mfd, 1);
-
 	mdp4_overlay_rgb_setup(pipe);
+	mdp4_overlay_reg_flush(pipe, 1);
+	mdp4_mixer_stage_up(pipe);
 
 	mdp4_overlayproc_cfg(pipe);
 
@@ -291,10 +295,12 @@
 int mdp4_dsi_video_off(struct platform_device *pdev)
 {
 	int ret = 0;
+	struct msm_fb_data_type *mfd;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	mdp4_mixer_pipe_cleanup(dsi_pipe->mixer_num);
 	MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
 	dsi_video_enabled = 0;
 	/* MDP cmd block disable */
@@ -308,8 +314,18 @@
 
 	/* dis-engage rgb0 from mixer0 */
 	if (dsi_pipe) {
-		mdp4_mixer_stage_down(dsi_pipe);
-		mdp4_iommu_unmap(dsi_pipe);
+		if (mfd->ref_cnt == 0) {
+			/* adb stop */
+			if (dsi_pipe->pipe_type == OVERLAY_TYPE_BF)
+				mdp4_overlay_borderfill_stage_down(dsi_pipe);
+
+			/* dsi_pipe == rgb1 */
+			mdp4_overlay_unset_mixer(dsi_pipe->mixer_num);
+			dsi_pipe = NULL;
+		} else {
+			mdp4_mixer_stage_down(dsi_pipe);
+			mdp4_iommu_unmap(dsi_pipe);
+		}
 	}
 
 	return ret;
@@ -384,7 +400,6 @@
 	mdp4_overlay_dmap_cfg(mfd, 1);
 
 	mdp4_overlay_reg_flush(pipe, 1);
-
 	mdp4_mixer_stage_up(pipe);
 
 	mb();
@@ -632,7 +647,6 @@
 
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
-
 	/*
 	 * may need mutex here to sync with whom dsiable
 	 * timing generator
@@ -693,6 +707,12 @@
 	mutex_lock(&mfd->dma->ov_mutex);
 
 	pipe = dsi_pipe;
+	if (pipe->pipe_used == 0 ||
+			pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+		pr_err("%s: NOT baselayer\n", __func__);
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return;
+	}
 
 	if (mfd->display_iova)
 		pipe->srcp0_addr = mfd->display_iova + buf_offset;
@@ -700,7 +720,7 @@
 		pipe->srcp0_addr = (uint32)(buf + buf_offset);
 
 	mdp4_overlay_rgb_setup(pipe);
-	mdp4_overlay_reg_flush(pipe, 0);
+	mdp4_overlay_reg_flush(pipe, 1);
 	mdp4_mixer_stage_up(pipe);
 	mdp4_overlay_dsi_video_start();
 	mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index dd96439..aa1795f 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -56,6 +56,12 @@
 static struct mdp4_overlay_pipe *dtv_pipe;
 static DECLARE_COMPLETION(dtv_comp);
 
+void mdp4_dtv_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+	if (hdmi_prim_display)
+		dtv_pipe = pipe;
+}
+
 static int mdp4_dtv_start(struct msm_fb_data_type *mfd)
 {
 	int dtv_width;
@@ -208,7 +214,6 @@
 
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	mdp4_mixer_pipe_cleanup(dtv_pipe->mixer_num);
 	msleep(20);
 	MDP_OUTP(MDP_BASE + DTV_BASE, 0);
 	dtv_enabled = 0;
@@ -262,19 +267,24 @@
 
 	if (dtv_pipe != NULL) {
 		mdp4_dtv_stop(mfd);
+		if (hdmi_prim_display && mfd->ref_cnt == 0) {
+			/* adb stop */
+			if (dtv_pipe->pipe_type == OVERLAY_TYPE_BF)
+				mdp4_overlay_borderfill_stage_down(dtv_pipe);
 
-		/* delay to make sure the last frame finishes */
-		msleep(20);
-
-		mdp4_mixer_stage_down(dtv_pipe);
-		mdp4_overlay_pipe_free(dtv_pipe);
-		mdp4_iommu_unmap(dtv_pipe);
-		dtv_pipe = NULL;
+			/* dtv_pipe == rgb1 */
+			mdp4_overlay_unset_mixer(dtv_pipe->mixer_num);
+			dtv_pipe = NULL;
+		} else {
+			mdp4_mixer_stage_down(dtv_pipe);
+			mdp4_overlay_pipe_free(dtv_pipe);
+			mdp4_iommu_unmap(dtv_pipe);
+			dtv_pipe = NULL;
+		}
 	}
 	mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV);
 
 	ret = panel_next_off(pdev);
-	mdp4_iommu_detach();
 	mdp_footswitch_ctrl(FALSE);
 
 	dev_info(&pdev->dev, "mdp4_overlay_dtv: off");
@@ -610,7 +620,8 @@
 	*/
 	temp_src_format = inpdw(rgb_base + 0x0050);
 	MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
-	mdp4_overlay_reg_flush(dtv_pipe, 0);
+	mdp4_overlay_reg_flush(dtv_pipe, 1);
+	mdp4_mixer_stage_up(dtv_pipe);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
@@ -696,11 +707,19 @@
 	}
 	mutex_lock(&mfd->dma->ov_mutex);
 	pipe = dtv_pipe;
+
+	if (hdmi_prim_display && (pipe->pipe_used == 0 ||
+			pipe->mixer_stage != MDP4_MIXER_STAGE_BASE)) {
+		pr_err("%s: NOT baselayer\n", __func__);
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return;
+	}
+
 	if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
 		pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
 		mdp4_overlay_rgb_setup(pipe);
 	}
-	mdp4_overlay_reg_flush(pipe, 0);
+	mdp4_overlay_reg_flush(pipe, 1);
 	mdp4_mixer_stage_up(pipe);
 	mdp4_overlay_dtv_start();
 	mdp4_overlay_dtv_ov_done_push(mfd, pipe);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index a1fecb6..8410592 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -46,6 +46,11 @@
 static struct mdp4_overlay_pipe *lcdc_pipe;
 static struct completion lcdc_comp;
 
+void mdp4_lcdc_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+	lcdc_pipe = pipe;
+}
+
 int mdp_lcdc_on(struct platform_device *pdev)
 {
 	int lcdc_width;
@@ -95,8 +100,6 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
-	mdp4_overlay_ctrl_db_reset();
-
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
@@ -155,6 +158,8 @@
 	mdp4_overlay_dmap_cfg(mfd, 1);
 
 	mdp4_overlay_rgb_setup(pipe);
+	mdp4_overlay_reg_flush(pipe, 1);
+	mdp4_mixer_stage_up(pipe);
 
 	mdp4_overlayproc_cfg(pipe);
 
@@ -176,7 +181,12 @@
 	lcdc_bpp = mfd->panel_info.bpp;
 
 	hsync_period =
-	    hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+	    hsync_pulse_width + h_back_porch + h_front_porch;
+	if ((mfd->panel_info.type == LVDS_PANEL) &&
+		(mfd->panel_info.lvds.channel_mode == LVDS_DUAL_CHANNEL_MODE))
+		hsync_period += lcdc_width / 2;
+	else
+		hsync_period += lcdc_width;
 	hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
 	hsync_start_x = hsync_pulse_width + h_back_porch;
 	hsync_end_x = hsync_period - h_front_porch - 1;
@@ -211,8 +221,13 @@
 
 
 #ifdef CONFIG_FB_MSM_MDP40
-	hsync_polarity = 1;
-	vsync_polarity = 1;
+	if (mfd->panel_info.lcdc.is_sync_active_high) {
+		hsync_polarity = 0;
+		vsync_polarity = 0;
+	} else {
+		hsync_polarity = 1;
+		vsync_polarity = 1;
+	}
 	lcdc_underflow_clr |= 0x80000000;	/* enable recovery */
 #else
 	hsync_polarity = 0;
@@ -263,7 +278,6 @@
 
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	mdp4_mixer_pipe_cleanup(lcdc_pipe->mixer_num);
 	MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
 	lcdc_enabled = 0;
 	/* MDP cmd block disable */
@@ -280,8 +294,18 @@
 
 	/* dis-engage rgb0 from mixer0 */
 	if (lcdc_pipe) {
-		mdp4_mixer_stage_down(lcdc_pipe);
-		mdp4_iommu_unmap(lcdc_pipe);
+		if (mfd->ref_cnt == 0) {
+			/* adb stop */
+			if (lcdc_pipe->pipe_type == OVERLAY_TYPE_BF)
+				mdp4_overlay_borderfill_stage_down(lcdc_pipe);
+
+			/* lcdc_pipe == rgb1 */
+			mdp4_overlay_unset_mixer(lcdc_pipe->mixer_num);
+			lcdc_pipe = NULL;
+		} else {
+			mdp4_mixer_stage_down(lcdc_pipe);
+			mdp4_iommu_unmap(lcdc_pipe);
+		}
 	}
 
 #ifdef CONFIG_MSM_BUS_SCALING
@@ -494,7 +518,7 @@
 	}
 }
 /*
- * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile
+ * make sure the WRITEBACK_SIZE defined at boardfile
  * has enough space h * w * 3 * 2
  */
 static void mdp4_lcdc_do_blt(struct msm_fb_data_type *mfd, int enable)
@@ -585,6 +609,12 @@
 	mutex_lock(&mfd->dma->ov_mutex);
 
 	pipe = lcdc_pipe;
+	if (pipe->pipe_used == 0 ||
+			pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+		pr_err("%s: NOT baselayer\n", __func__);
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return;
+	}
 
 	if (mfd->display_iova)
 		pipe->srcp0_addr = mfd->display_iova + buf_offset;
@@ -592,7 +622,7 @@
 		pipe->srcp0_addr = (uint32)(buf + buf_offset);
 
 	mdp4_overlay_rgb_setup(pipe);
-	mdp4_overlay_reg_flush(pipe, 0);
+	mdp4_overlay_reg_flush(pipe, 1);
 	mdp4_mixer_stage_up(pipe);
 	mdp4_overlay_lcdc_start();
 	mdp4_overlay_lcdc_vsync_push(mfd, pipe);
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index 5aa5965..82864918 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -124,7 +124,6 @@
 			printk(KERN_INFO "%s: format2type failed\n", __func__);
 
 		mddi_pipe = pipe; /* keep it */
-		mddi_pipe->blt_end = 1;	/* mark as end */
 		mddi_ld_param = 0;
 		mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
 
@@ -163,6 +162,8 @@
 			 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
 
 		MDP_OUTP(MDP_BASE + 0x00098, 0x01);
+		mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
+		pipe->blt_addr = 0;
 	} else {
 		pipe = mddi_pipe;
 	}
@@ -246,59 +247,82 @@
 
 	/* MDP cmd block disable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
 }
 
-int mdp4_mddi_overlay_blt_offset(int *off)
-{
-	if (mdp_hw_revision < MDP4_REVISION_V2_1) { /* need dmas dmap switch */
-		if (mddi_pipe->blt_end ||
-			(mdp4_overlay_mixer_play(mddi_pipe->mixer_num) == 0)) {
-			*off = -1;
-			return -EINVAL;
-		}
-	} else {
-		/* no dmas dmap switch */
-		if (mddi_pipe->blt_end) {
-			*off = -1;
-			return -EINVAL;
-		}
-	}
-
-	if (mddi_pipe->blt_cnt & 0x01)
-		*off = mddi_pipe->src_height * mddi_pipe->src_width * 3;
-	else
-		*off = 0;
-
-	return 0;
-}
-
-void mdp4_mddi_overlay_blt(ulong addr)
+int mdp4_mddi_overlay_blt_start(struct msm_fb_data_type *mfd)
 {
 	unsigned long flag;
 
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	if (addr) {
-		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		mdp_intr_mask |= INTR_DMA_P_DONE;
-		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-		mddi_pipe->blt_cnt = 0;
-		mddi_pipe->blt_end = 0;
-		mddi_pipe->blt_addr = addr;
-	} else {
-		mddi_pipe->blt_end = 1;	/* mark as end */
+	pr_debug("%s: blt_end=%d blt_addr=%x pid=%d\n",
+	__func__, mddi_pipe->blt_end, (int)mddi_pipe->blt_addr, current->pid);
+
+	mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+	if (mfd->ov0_wb_buf->phys_addr == 0) {
+		pr_info("%s: no blt_base assigned\n", __func__);
+		return -EBUSY;
 	}
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	if (mddi_pipe->blt_addr == 0) {
+		mdp4_mddi_dma_busy_wait(mfd);
+		spin_lock_irqsave(&mdp_spin_lock, flag);
+		mddi_pipe->blt_end = 0;
+		mddi_pipe->blt_cnt = 0;
+		mddi_pipe->ov_cnt = 0;
+		mddi_pipe->dmap_cnt = 0;
+		mddi_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr;
+		mdp4_stat.blt_mddi++;
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
+	return 0;
+}
+
+	return -EBUSY;
+}
+
+int mdp4_mddi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+	unsigned long flag;
+
+	pr_debug("%s: blt_end=%d blt_addr=%x\n",
+		 __func__, mddi_pipe->blt_end, (int)mddi_pipe->blt_addr);
+
+	if ((mddi_pipe->blt_end == 0) && mddi_pipe->blt_addr) {
+		spin_lock_irqsave(&mdp_spin_lock, flag);
+		mddi_pipe->blt_end = 1;	/* mark as end */
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
+		return 0;
+	}
+
+	return -EBUSY;
+}
+
+int mdp4_mddi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+					struct msmfb_overlay_blt *req)
+{
+	req->offset = 0;
+	req->width = mddi_pipe->src_width;
+	req->height = mddi_pipe->src_height;
+	req->bpp = mddi_pipe->bpp;
+
+	return sizeof(*req);
+}
+
+void mdp4_mddi_overlay_blt(struct msm_fb_data_type *mfd,
+					struct msmfb_overlay_blt *req)
+{
+	if (req->enable)
+		mdp4_mddi_overlay_blt_start(mfd);
+	else if (req->enable == 0)
+		mdp4_mddi_overlay_blt_stop(mfd);
+
 }
 
 void mdp4_blt_xy_update(struct mdp4_overlay_pipe *pipe)
 {
-	uint32 off, addr;
+	uint32 off, addr, addr2;
 	int bpp;
 	char *overlay_base;
 
-
 	if (pipe->blt_addr == 0)
 		return;
 
@@ -317,29 +341,62 @@
 	/* dmap */
 	MDP_OUTP(MDP_BASE + 0x90008, addr);
 
+	off = 0;
+	if (pipe->ov_cnt & 0x01)
+		off = pipe->src_height * pipe->src_width * bpp;
+	addr2 = pipe->blt_addr + off;
 	/* overlay 0 */
 	overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
-	outpdw(overlay_base + 0x000c, addr);
-	outpdw(overlay_base + 0x001c, addr);
+	outpdw(overlay_base + 0x000c, addr2);
+	outpdw(overlay_base + 0x001c, addr2);
 }
 
 /*
  * mdp4_dmap_done_mddi: called from isr
  */
-void mdp4_dma_p_done_mddi(void)
+void mdp4_dma_p_done_mddi(struct mdp_dma_data *dma)
 {
-	if (mddi_pipe->blt_end) {
-		mddi_pipe->blt_addr = 0;
-		mdp_intr_mask &= ~INTR_DMA_P_DONE;
-		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-		mdp4_overlayproc_cfg(mddi_pipe);
-		mdp4_overlay_dmap_xy(mddi_pipe);
+	int diff;
+
+	mddi_pipe->dmap_cnt++;
+	diff = mddi_pipe->ov_cnt - mddi_pipe->dmap_cnt;
+	pr_debug("%s: ov_cnt=%d dmap_cnt=%d\n",
+			__func__, mddi_pipe->ov_cnt, mddi_pipe->dmap_cnt);
+
+	if (diff <= 0) {
+		spin_lock(&mdp_spin_lock);
+		dma->dmap_busy = FALSE;
+		complete(&dma->dmap_comp);
+		spin_unlock(&mdp_spin_lock);
+
+		if (mddi_pipe->blt_end) {
+			mddi_pipe->blt_end = 0;
+			mddi_pipe->blt_addr = 0;
+			pr_debug("%s: END, ov_cnt=%d dmap_cnt=%d\n", __func__,
+				mddi_pipe->ov_cnt, mddi_pipe->dmap_cnt);
+			mdp_intr_mask &= ~INTR_DMA_P_DONE;
+			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+		}
+
+		mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+		mdp_disable_irq_nosync(MDP_DMA2_TERM);  /* disable intr */
+		return;
 	}
 
-	/*
-	 * single buffer, no need to increase
-	 * mdd_pipe->dmap_cnt here
-	 */
+	spin_lock(&mdp_spin_lock);
+	dma->busy = FALSE;
+	spin_unlock(&mdp_spin_lock);
+	complete(&dma->comp);
+	if (busy_wait_cnt)
+		busy_wait_cnt--;
+
+	pr_debug("%s: kickoff dmap\n", __func__);
+
+	mdp4_blt_xy_update(mddi_pipe);
+	/* kick off dmap */
+	outpdw(MDP_BASE + 0x000c, 0x0);
+	mdp4_stat.kickoff_dmap++;
+	mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
 }
 
 /*
@@ -347,37 +404,60 @@
  */
 void mdp4_overlay0_done_mddi(struct mdp_dma_data *dma)
 {
-	mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+	int diff;
 
+	if (mddi_pipe->blt_addr == 0) {
+		mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+		spin_lock(&mdp_spin_lock);
+		dma->busy = FALSE;
+		spin_unlock(&mdp_spin_lock);
+		complete(&dma->comp);
+
+		if (busy_wait_cnt)
+			busy_wait_cnt--;
+		mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+
+		return;
+	}
+
+	/* blt enabled */
+	if (mddi_pipe->blt_end == 0)
+		mddi_pipe->ov_cnt++;
+
+	pr_debug("%s: ov_cnt=%d dmap_cnt=%d\n",
+			__func__, mddi_pipe->ov_cnt, mddi_pipe->dmap_cnt);
+
+	if (mddi_pipe->blt_cnt == 0) {
+		/* first kickoff since blt enabled */
+		mdp_intr_mask |= INTR_DMA_P_DONE;
+		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	}
+
+	mddi_pipe->blt_cnt++;
+
+	diff = mddi_pipe->ov_cnt - mddi_pipe->dmap_cnt;
+	if (diff >= 2) {
+		mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+		return;
+	}
+
+	spin_lock(&mdp_spin_lock);
 	dma->busy = FALSE;
+	dma->dmap_busy = TRUE;
+	spin_unlock(&mdp_spin_lock);
 	complete(&dma->comp);
-	mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK,
-			MDP_BLOCK_POWER_OFF, TRUE);
 
 	if (busy_wait_cnt)
 		busy_wait_cnt--;
 
-	pr_debug("%s: ISR-done\n", __func__);
+	pr_debug("%s: kickoff dmap\n", __func__);
 
-	if (mddi_pipe->blt_addr) {
-		if (mddi_pipe->blt_cnt == 0) {
-			mdp4_overlayproc_cfg(mddi_pipe);
-			mdp4_overlay_dmap_xy(mddi_pipe);
-			mddi_pipe->ov_cnt = 0;
-			mddi_pipe->dmap_cnt = 0;
-			/* BLT start from next frame */
-		} else {
-			mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON,
-						FALSE);
-			mdp4_blt_xy_update(mddi_pipe);
-			outpdw(MDP_BASE + 0x000c, 0x0); /* start DMAP */
-		}
-		mddi_pipe->blt_cnt++;
-		mddi_pipe->ov_cnt++;
-	}
-
-
-
+	mdp4_blt_xy_update(mddi_pipe);
+	mdp_enable_irq(MDP_DMA2_TERM);	/* enable intr */
+	/* kick off dmap */
+	outpdw(MDP_BASE + 0x000c, 0x0);
+	mdp4_stat.kickoff_dmap++;
+	mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
 }
 
 void mdp4_mddi_overlay_restore(void)
@@ -392,6 +472,9 @@
 	if (mddi_mfd && mddi_pipe) {
 		mdp4_mddi_dma_busy_wait(mddi_mfd);
 		mdp4_overlay_update_lcd(mddi_mfd);
+
+		if (mddi_pipe->blt_addr)
+			mdp4_mddi_blt_dmap_busy_wait(mddi_mfd);
 		mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
 		mddi_mfd->dma_update_flag = 1;
 	}
@@ -399,9 +482,27 @@
 		mdp4_mddi_overlay_dmas_restore();
 }
 
+void mdp4_mddi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd)
+{
+	unsigned long flag;
+	int need_wait = 0;
+
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	if (mfd->dma->dmap_busy == TRUE) {
+		INIT_COMPLETION(mfd->dma->dmap_comp);
+		need_wait++;
+	}
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	if (need_wait) {
+		/* wait until DMA finishes the current job */
+		wait_for_completion(&mfd->dma->dmap_comp);
+	}
+}
+
 /*
  * mdp4_mddi_cmd_dma_busy_wait: check mddi link activity
- * dsi link is a shared resource and it can only be used
+ * mddi link is a shared resource and it can only be used
  * while it is in idle state.
  * ov_mutex need to be acquired before call this function.
  */
@@ -432,7 +533,24 @@
 void mdp4_mddi_kickoff_video(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe)
 {
-	pr_debug("%s: pid=%d\n", __func__, current->pid);
+	/*
+	 * a video kickoff may happen before UI kickoff after
+	 * blt enabled. mdp4_overlay_update_lcd() need
+	 * to be called before kickoff.
+	 * vice versa for blt disabled.
+	 */
+	if (mddi_pipe->blt_addr && mddi_pipe->blt_cnt == 0)
+		mdp4_overlay_update_lcd(mfd); /* first time */
+	else if (mddi_pipe->blt_addr == 0  && mddi_pipe->blt_cnt) {
+		mdp4_overlay_update_lcd(mfd); /* last time */
+		mddi_pipe->blt_cnt = 0;
+	}
+
+	pr_debug("%s: blt_addr=%d blt_cnt=%d\n",
+		__func__, (int)mddi_pipe->blt_addr, mddi_pipe->blt_cnt);
+
+	if (mddi_pipe->blt_addr)
+		mdp4_mddi_blt_dmap_busy_wait(mddi_mfd);
 	mdp4_mddi_overlay_kickoff(mfd, pipe);
 }
 
@@ -447,11 +565,16 @@
 void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe)
 {
+	unsigned long flag;
 	/* change mdp clk while mdp is idle` */
 	mdp4_set_perf_level();
 
 	mdp_enable_irq(MDP_OVERLAY0_TERM);
+	spin_lock_irqsave(&mdp_spin_lock, flag);
 	mfd->dma->busy = TRUE;
+	if (mddi_pipe->blt_addr)
+		mfd->dma->dmap_busy = TRUE;
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	/* start OVERLAY pipe */
 	mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
 	mdp4_stat.kickoff_ov0++;
@@ -533,7 +656,10 @@
 	mdp4_set_perf_level();
 
 	mdp_enable_irq(MDP_DMA_S_TERM);
-	mfd->dma->busy = TRUE;
+
+	if (mddi_pipe->blt_addr == 0)
+		mfd->dma->busy = TRUE;
+
 	mfd->ibuf_flushed = TRUE;
 	/* start dma_s pipe */
 	mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
@@ -561,6 +687,10 @@
 
 	if (mfd && mfd->panel_power_on) {
 		mdp4_mddi_dma_busy_wait(mfd);
+
+		if (mddi_pipe && mddi_pipe->blt_addr)
+			mdp4_mddi_blt_dmap_busy_wait(mfd);
+
 		mdp4_overlay_update_lcd(mfd);
 
 		if (mdp_hw_revision < MDP4_REVISION_V2_1) {
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index b2657cf..f192b12 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -314,6 +314,8 @@
 	clk_rate = mdp_get_core_clk();
 	mdp4_fetch_cfg(clk_rate);
 
+	mdp4_overlay_cfg_init();
+
 	/* Mark hardware as initialized. Only revisions > v2.1 have a register
 	 * for tracking core reset status. */
 	if (mdp_hw_revision > MDP4_REVISION_V2_1)
@@ -378,6 +380,7 @@
 	outpdw(MDP_INTR_CLEAR, isr);
 
 	if (isr & INTR_PRIMARY_INTF_UDERRUN) {
+		pr_debug("%s: UNDERRUN -- primary\n", __func__);
 		mdp4_stat.intr_underrun_p++;
 		/* When underun occurs mdp clear the histogram registers
 		that are set before in hw_init so restore them back so
@@ -395,8 +398,10 @@
 		}
 	}
 
-	if (isr & INTR_EXTERNAL_INTF_UDERRUN)
+	if (isr & INTR_EXTERNAL_INTF_UDERRUN) {
+		pr_debug("%s: UNDERRUN -- external\n", __func__);
 		mdp4_stat.intr_underrun_e++;
+	}
 
 	isr &= mask;
 
@@ -522,7 +527,7 @@
 		}
 #else
 		else { /* MDDI */
-			mdp4_dma_p_done_mddi();
+			mdp4_dma_p_done_mddi(dma);
 			mdp_pipe_ctrl(MDP_DMA2_BLOCK,
 				MDP_BLOCK_POWER_OFF, TRUE);
 			complete(&dma->comp);
diff --git a/drivers/video/msm/mdp_debugfs.c b/drivers/video/msm/mdp_debugfs.c
index 7defd82..4a0ea4c 100644
--- a/drivers/video/msm/mdp_debugfs.c
+++ b/drivers/video/msm/mdp_debugfs.c
@@ -437,38 +437,38 @@
 	len = snprintf(bp, dlen, "frame_push:\n");
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "rgb1:  %08lu\t\t",
+	len = snprintf(bp, dlen, "rgb1:   %08lu\t",
 		       mdp4_stat.pipe[OVERLAY_PIPE_RGB1]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "rgb2:  %08lu\n",
+	len = snprintf(bp, dlen, "rgb2:   %08lu\n",
 		       mdp4_stat.pipe[OVERLAY_PIPE_RGB2]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "vg1:   %08lu\t\t",
+	len = snprintf(bp, dlen, "vg1 :   %08lu\t",
 		       mdp4_stat.pipe[OVERLAY_PIPE_VG1]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "vg2:   %08lu\n",
+	len = snprintf(bp, dlen, "vg2 :   %08lu\n",
 		       mdp4_stat.pipe[OVERLAY_PIPE_VG2]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_mixer: %08lu\t", mdp4_stat.err_mixer);
+	len = snprintf(bp, dlen, "err_mixer : %08lu\t", mdp4_stat.err_mixer);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_size : %08lu\n", mdp4_stat.err_size);
+	len = snprintf(bp, dlen, "err_size  : %08lu\n", mdp4_stat.err_size);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_scale: %08lu\t", mdp4_stat.err_scale);
+	len = snprintf(bp, dlen, "err_scale : %08lu\t", mdp4_stat.err_scale);
 	bp += len;
 	dlen -= len;
 	len = snprintf(bp, dlen, "err_format: %08lu\n", mdp4_stat.err_format);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_play:  %08lu\t", mdp4_stat.err_play);
+	len = snprintf(bp, dlen, "err_play  : %08lu\t", mdp4_stat.err_play);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_stage: %08lu\n", mdp4_stat.err_stage);
+	len = snprintf(bp, dlen, "err_stage : %08lu\n", mdp4_stat.err_stage);
 	bp += len;
 	dlen -= len;
 	len = snprintf(bp, dlen, "err_underflow: %08lu\n\n",
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index d271b85..418528e 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -2403,7 +2403,10 @@
 			   uint32 width,
 			   uint32 height, int bpp, MDPIBUF *iBuf, int layer)
 {
-	*src0 += (x + y * width) * bpp;
+	if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO && layer == 0)
+		*src0 += (x + y * ALIGN(width, 32)) * bpp;
+	else
+		*src0 += (x + y * width) * bpp;
 
 	/* if it's dest/bg buffer, we need to adjust it for rotation */
 	if (layer != 0)
@@ -2414,9 +2417,14 @@
 		 * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
 		 * we need to shift x direction same as y dir for offsite
 		 */
-		*src1 +=
-		    ((x / h_slice) * h_slice +
-		     ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
+		if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO
+							&& layer == 0)
+			*src1 += ((x / h_slice) * h_slice + ((y == 0) ? 0 :
+			(((y + 1) / v_slice - 1) * (ALIGN(width/2, 32) * 2))))
+									* bpp;
+		else
+			*src1 += ((x / h_slice) * h_slice +
+			((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
 
 		/* if it's dest/bg buffer, we need to adjust it for rotation */
 		if (layer != 0)
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 3ed305b..c9642c3 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1316,7 +1316,7 @@
 					GEN_POOL,
 					fbi->fix.smem_len,
 					SZ_4K,
-					1,
+					0,
 					&(mfd->display_iova));
 
 	msm_iommu_map_contig_buffer(fbi->fix.smem_start,
@@ -1324,7 +1324,7 @@
 					GEN_POOL,
 					fbi->fix.smem_len,
 					SZ_4K,
-					1,
+					0,
 					&(mfd->rotator_iova));
 
 	if (!bf_supported || mfd->index == 0)
diff --git a/drivers/video/msm/msm_fb_panel.h b/drivers/video/msm/msm_fb_panel.h
index 8ccc21c..a2c3db1 100644
--- a/drivers/video/msm/msm_fb_panel.h
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -82,6 +82,7 @@
 	uint32 xres_pad;
 	/* Pad height */
 	uint32 yres_pad;
+	boolean is_sync_active_high;
 };
 
 struct mddi_panel_info {
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 81b1436..d5b195d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -473,8 +473,7 @@
 	u32 vcd_status = VCD_S_SUCCESS;
 	struct vcd_transc *transc;
 	transc = (struct vcd_transc *)(ddl->client_data);
-	DDL_MSG_LOW("%s: transc = 0x%x, in_use = %u",
-		__func__, (u32)ddl->client_data, transc->in_use);
+	DDL_MSG_LOW("%s: transc = 0x%x", __func__, (u32)ddl->client_data);
 	if (encoder->slice_delivery_info.enable) {
 		return ddl_encode_frame_batch(ddl_handle,
 					input_frame,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index ac1ff24..3c082e4 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -228,6 +228,7 @@
 			[DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH];
 	u32 num_output_frames;
 	u32 out_frm_next_frmindex;
+	u32  first_output_frame_tag;
 };
 struct ddl_encoder_data{
 	struct ddl_codec_data_hdr   hdr;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index 50c3696..8a33512 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -30,6 +30,9 @@
 #define DDL_MAX_FRAME_WIDTH   1920
 #define DDL_MAX_FRAME_HEIGHT  1088
 
+#define DDL_MAX_VC1_FRAME_WIDTH		(DDL_MAX_FRAME_WIDTH)
+#define DDL_MAX_VC1_FRAME_HEIGHT	(1280)
+
 #define MAX_DPB_SIZE_L4PT0_MBS    DDL_KILO_BYTE(32)
 #define MAX_FRAME_SIZE_L4PT0_MBS  DDL_KILO_BYTE(8)
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index e2c0a2a..58d1f23 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -312,6 +312,20 @@
 					return process_further;
 				}
 			break;
+		case VCD_CODEC_VC1:
+		case VCD_CODEC_VC1_RCV:
+			if ((seq_hdr_info.img_size_x >
+					DDL_MAX_VC1_FRAME_WIDTH) ||
+				(seq_hdr_info.img_size_y >
+					DDL_MAX_VC1_FRAME_HEIGHT)) {
+				DDL_MSG_ERROR("Unsupported VC1 clip: "
+					"Resolution X=%d and Y=%d",
+					seq_hdr_info.img_size_x,
+					seq_hdr_info.img_size_y);
+					ddl_client_fatal_cb(ddl);
+					return process_further;
+			}
+			break;
 		default:
 			break;
 		}
@@ -1703,6 +1717,13 @@
 	(void)ddl_get_encoded_frame(output_frame,
 		encoder->codec.codec, encoder->enc_frame_info.enc_frame
 								);
+	if (!IS_ERR_OR_NULL(output_frame->buff_ion_handle)) {
+		msm_ion_do_cache_op(ddl_context->video_ion_client,
+			output_frame->buff_ion_handle,
+			(unsigned long *) output_frame->virtual,
+			(unsigned long) output_frame->alloc_len,
+			ION_IOC_INV_CACHES);
+	}
 	ddl_process_encoder_metadata(ddl);
 	ddl_vidc_encode_dynamic_property(ddl, false);
 	ddl->input_frame.frm_trans_end = false;
@@ -1774,6 +1795,27 @@
 		vidc_sm_get_frame_tags(&ddl->shared_mem
 			[ddl->command_channel],
 			&output_frame->ip_frm_tag, &bottom_frame_tag);
+
+		if (start_bfr_idx == 0) {
+			encoder->batch_frame.first_output_frame_tag =
+				output_frame->ip_frm_tag;
+			DDL_MSG_LOW("%s: first_output_frame_tag[0x%x]",
+				__func__, output_frame->ip_frm_tag);
+			if (!output_frame->ip_frm_tag) {
+				DDL_MSG_ERROR("%s: first_output_frame_tag "\
+					"is zero", __func__);
+			}
+		}
+		if (output_frame->ip_frm_tag !=
+			encoder->batch_frame.first_output_frame_tag) {
+			DDL_MSG_ERROR("%s: output_frame->ip_frm_tag[0x%x] is "\
+				"not equal to the first_output_frame_tag[0x%x]\n",
+				__func__, output_frame->ip_frm_tag,
+				encoder->batch_frame.first_output_frame_tag);
+			output_frame->ip_frm_tag =
+				encoder->batch_frame.first_output_frame_tag;
+		}
+
 		ddl_get_encoded_frame(output_frame,
 				encoder->codec.codec,
 				encoder->enc_frame_info.enc_frame);
@@ -1856,6 +1898,27 @@
 		vidc_sm_get_frame_tags(&ddl->shared_mem
 			[ddl->command_channel],
 			&output_frame->ip_frm_tag, &bottom_frame_tag);
+
+		if (start_bfr_idx == 0) {
+			encoder->batch_frame.first_output_frame_tag =
+				output_frame->ip_frm_tag;
+			DDL_MSG_LOW("%s: first_output_frame_tag[0x%x]",
+				__func__, output_frame->ip_frm_tag);
+			if (!output_frame->ip_frm_tag) {
+				DDL_MSG_ERROR("%s: first_output_frame_tag "\
+					"is zero", __func__);
+			}
+		}
+		if (output_frame->ip_frm_tag !=
+			encoder->batch_frame.first_output_frame_tag) {
+			DDL_MSG_ERROR("%s: output_frame->ip_frm_tag[0x%x] is "\
+				"not equal to the first_output_frame_tag[0x%x]\n",
+				__func__, output_frame->ip_frm_tag,
+				encoder->batch_frame.first_output_frame_tag);
+			output_frame->ip_frm_tag =
+				encoder->batch_frame.first_output_frame_tag;
+		}
+
 		ddl_get_encoded_frame(output_frame,
 				encoder->codec.codec,
 				encoder->enc_frame_info.enc_frame);
@@ -1925,6 +1988,10 @@
 				&ddl->shared_mem[ddl->command_channel],
 				&output_frame->ip_frm_tag,
 				&bottom_frame_tag);
+		if (!output_frame->ip_frm_tag) {
+			DDL_MSG_ERROR("%s: output frame tag is zero",
+				__func__);
+		}
 		ddl_get_encoded_frame(
 				output_frame,
 				encoder->codec.codec,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index 878db62..839a9c1 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -207,7 +207,7 @@
 #define VIDC_SM_MPEG4_ASPECT_RATIO_INFO_SHFT         0x0
 #define VIDC_SM_EXTENDED_PAR_ADDR                    0x00cc
 #define VIDC_SM_EXTENDED_PAR_WIDTH_BMSK              0xffff0000
-#define VIDC_SM_EXTENDED_PAR_WIDTH_SHFT              0xf
+#define VIDC_SM_EXTENDED_PAR_WIDTH_SHFT              16
 #define VIDC_SM_EXTENDED_PAR_HEIGHT_BMSK             0x0000ffff
 #define VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT             0x0
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index d0cf4e8..14e1331 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -867,6 +867,7 @@
 	DDL_MEMSET(encoder->batch_frame.slice_batch_in.align_virtual_addr, 0,
 		sizeof(struct vidc_1080p_enc_slice_batch_in_param));
 	encoder->batch_frame.out_frm_next_frmindex = 0;
+	encoder->batch_frame.first_output_frame_tag = 0;
 	bitstream_size = encoder->batch_frame.output_frame[0].vcd_frm.alloc_len;
 	encoder->output_buf_req.sz = bitstream_size;
 	y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
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 d90b8ca..5b22b21 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
@@ -28,8 +28,8 @@
 #define PIL_FW_BASE_ADDR 0x9fe00000
 #define PIL_FW_SIZE 0x200000
 
-static unsigned int vidc_clk_table[3] = {
-	48000000, 133330000, 200000000
+static unsigned int vidc_clk_table[4] = {
+	48000000, 133330000, 200000000, 228570000,
 };
 static unsigned int restrk_mmu_subsystem[] =	{
 		MSM_SUBSYSTEM_VIDEO, MSM_SUBSYSTEM_VIDEO_FWARE};
@@ -544,17 +544,27 @@
 			enc_perf_level += cctxt_itr->reqd_perf_lvl;
 		cctxt_itr = cctxt_itr->next;
 	}
+
 	if (!enc_perf_level)
 		client_type = 1;
 	if (perf_level <= RESTRK_1080P_VGA_PERF_LEVEL)
 		bus_clk_index = 0;
 	else if (perf_level <= RESTRK_1080P_720P_PERF_LEVEL)
 		bus_clk_index = 1;
-	else
+	else if (perf_level <= RESTRK_1080P_MAX_PERF_LEVEL)
 		bus_clk_index = 2;
+	else
+		bus_clk_index = 3;
 
 	if (dev_ctxt->reqd_perf_lvl + dev_ctxt->curr_perf_lvl == 0)
 		bus_clk_index = 2;
+	else if (resource_context.vidc_platform_data->disable_turbo
+						&& bus_clk_index == 3) {
+		VCDRES_MSG_ERROR("Warning: Turbo mode not supported "
+				" falling back to 1080p bus\n");
+		bus_clk_index = 2;
+	}
+
 	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);
@@ -575,6 +585,13 @@
 		return false;
 	}
 	VCDRES_MSG_LOW("%s(), req_perf_lvl = %d", __func__, req_perf_lvl);
+
+	if (resource_context.vidc_platform_data->disable_turbo
+			&& req_perf_lvl > RESTRK_1080P_MAX_PERF_LEVEL) {
+		VCDRES_MSG_ERROR("%s(): Turbo not supported! dev_ctxt(%p)\n",
+			__func__, dev_ctxt);
+	}
+
 #ifdef CONFIG_MSM_BUS_SCALING
 	if (!res_trk_update_bus_perf_level(dev_ctxt, req_perf_lvl) < 0) {
 		VCDRES_MSG_ERROR("%s(): update buf perf level failed\n",
@@ -592,10 +609,22 @@
 	} else if (req_perf_lvl <= RESTRK_1080P_720P_PERF_LEVEL) {
 		vidc_freq = vidc_clk_table[1];
 		*pn_set_perf_lvl = RESTRK_1080P_720P_PERF_LEVEL;
+	} else if (req_perf_lvl <= RESTRK_1080P_MAX_PERF_LEVEL) {
+		vidc_freq = vidc_clk_table[2];
+		*pn_set_perf_lvl = RESTRK_1080P_MAX_PERF_LEVEL;
 	} else {
+		vidc_freq = vidc_clk_table[3];
+		*pn_set_perf_lvl = RESTRK_1080P_TURBO_PERF_LEVEL;
+	}
+
+	if (resource_context.vidc_platform_data->disable_turbo &&
+		*pn_set_perf_lvl == RESTRK_1080P_TURBO_PERF_LEVEL) {
+		VCDRES_MSG_ERROR("Warning: Turbo mode not supported "
+				" falling back to 1080p clocks\n");
 		vidc_freq = vidc_clk_table[2];
 		*pn_set_perf_lvl = RESTRK_1080P_MAX_PERF_LEVEL;
 	}
+
 	resource_context.perf_level = *pn_set_perf_lvl;
 	VCDRES_MSG_MED("VIDC: vidc_freq = %u, req_perf_lvl = %u\n",
 		vidc_freq, req_perf_lvl);
@@ -969,6 +998,9 @@
 	case VCD_PERF_LEVEL2:
 		res_trk_perf_level = RESTRK_1080P_MAX_PERF_LEVEL;
 		break;
+	case VCD_PERF_LEVEL_TURBO:
+		res_trk_perf_level = RESTRK_1080P_TURBO_PERF_LEVEL;
+		break;
 	default:
 		VCD_MSG_ERROR("Invalid perf level: %d\n", perf_level);
 		res_trk_perf_level = -EINVAL;
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 bf8607d..d5e656b 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
@@ -28,6 +28,7 @@
 
 #define RESTRK_1080P_MIN_PERF_LEVEL RESTRK_1080P_VGA_PERF_LEVEL
 #define RESTRK_1080P_MAX_PERF_LEVEL RESTRK_1080P_1080P_PERF_LEVEL
+#define RESTRK_1080P_TURBO_PERF_LEVEL (RESTRK_1080P_MAX_PERF_LEVEL + 1)
 
 struct res_trk_context {
 	struct device *device;
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 1b77b67..67917b9 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -252,6 +252,8 @@
 		/* Timestamp pass-through from input frame */
 		venc_msg->venc_msg_info.buf.timestamp =
 			vcd_frame_data->time_stamp;
+		venc_msg->venc_msg_info.buf.sz =
+			vcd_frame_data->alloc_len;
 
 		/* Decoded picture width and height */
 		venc_msg->venc_msg_info.msgdata_size =
@@ -269,7 +271,7 @@
 			msm_ion_do_cache_op(client_ctx->user_ion_client,
 				buff_handle,
 				(unsigned long *) kernel_vaddr,
-				(unsigned long)venc_msg->venc_msg_info.buf.len,
+				(unsigned long)venc_msg->venc_msg_info.buf.sz,
 				ION_IOC_CLEAN_INV_CACHES);
 		}
 	}
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index bbbe0cf..43e8d5e 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -1723,6 +1723,7 @@
 	struct file *file;
 	s32 buffer_index = -1;
 	u32 vcd_status = VCD_ERR_FAIL;
+	struct ion_handle *buff_handle = NULL;
 
 	struct vcd_frame_data vcd_frame;
 
@@ -1738,9 +1739,13 @@
 
 		memset((void *)&vcd_frame, 0,
 					 sizeof(struct vcd_frame_data));
+		vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
+				pmem_fd, kernel_vaddr, buffer_index,
+				&buff_handle);
 		vcd_frame.virtual = (u8 *) kernel_vaddr;
 		vcd_frame.frm_clnt_data = (u32) output_frame_info->clientdata;
 		vcd_frame.alloc_len = output_frame_info->sz;
+		vcd_frame.buff_ion_handle = buff_handle;
 
 		vcd_status = vcd_fill_output_buffer(client_ctx->vcd_handle,
 								&vcd_frame);
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 6ca4dbe..b71212c 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -2067,8 +2067,8 @@
 		rc = VCD_ERR_CLIENT_FATAL;
 
 	if (VCD_FAILED(rc)) {
-		VCD_MSG_FATAL(
-			"vcd_validate_io_done_pyld: invalid transaction");
+		VCD_MSG_FATAL("vcd_validate_io_done_pyld: "\
+			"invalid transaction 0x%x", (u32)transc);
 	} else if (!frame->vcd_frm.virtual &&
 		status != VCD_ERR_INTRLCD_FIELD_DROP)
 		rc = VCD_ERR_BAD_POINTER;
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index ec9f187..4358a92 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -977,7 +977,7 @@
 	struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
 			.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
 	struct timespec time;
-	unsigned int saved_nlink;
+	unsigned int saved_nlink = 0;
 
 	/*
 	 * Budget request settings: deletion direntry, new direntry, removing
diff --git a/include/linux/mfd/pm8xxx/mpp.h b/include/linux/mfd/pm8xxx/mpp.h
index 802948b..2a934e5 100644
--- a/include/linux/mfd/pm8xxx/mpp.h
+++ b/include/linux/mfd/pm8xxx/mpp.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
@@ -168,7 +168,7 @@
 #define	PM8921_MPP_DIG_LEVEL_VPH	7
 
 /* Digital Input/Output: level [PM8821] */
-#define	PM8821_MPP_DIG_LEVEL_1P8	1
+#define	PM8821_MPP_DIG_LEVEL_1P8	0
 #define	PM8821_MPP_DIG_LEVEL_VPH	7
 
 /* Digital Input/Output: level [PM8018] */
diff --git a/include/linux/mfd/pm8xxx/pm8821-irq.h b/include/linux/mfd/pm8xxx/pm8821-irq.h
new file mode 100644
index 0000000..af985e6
--- /dev/null
+++ b/include/linux/mfd/pm8xxx/pm8821-irq.h
@@ -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.
+ */
+/*
+ * Qualcomm PMIC irq 8821 driver header file
+ *
+ */
+
+#ifndef __MFD_PM8821_IRQ_H
+#define __MFD_PM8821_IRQ_H
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/mfd/pm8xxx/irq.h>
+
+#ifdef CONFIG_MFD_PM8821_IRQ
+int pm8821_get_irq_stat(struct pm_irq_chip *chip, int irq);
+struct pm_irq_chip *pm8821_irq_init(struct device *dev,
+				const struct pm8xxx_irq_platform_data *pdata);
+int pm8821_irq_exit(struct pm_irq_chip *chip);
+#else
+static inline int pm8821_get_irq_stat(struct pm_irq_chip *chip, int irq)
+{
+	return -ENXIO;
+}
+static inline struct pm_irq_chip *pm8821_irq_init(const struct device *dev,
+				const struct pm8xxx_irq_platform_data *pdata)
+{
+	return ERR_PTR(-ENXIO);
+}
+static inline int pm8821_irq_exit(struct pm_irq_chip *chip)
+{
+	return -ENXIO;
+}
+#endif /* CONFIG_MFD_PM8821_IRQ */
+#endif /* __MFD_PM8821_IRQ_H */
diff --git a/include/linux/mfd/pm8xxx/pm8821.h b/include/linux/mfd/pm8xxx/pm8821.h
index 850e8c1..7ed7617 100644
--- a/include/linux/mfd/pm8xxx/pm8821.h
+++ b/include/linux/mfd/pm8xxx/pm8821.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,14 +19,19 @@
 #define __MFD_PM8821_H
 
 #include <linux/device.h>
-#include <linux/mfd/pm8xxx/irq.h>
+#include <linux/mfd/pm8xxx/pm8821-irq.h>
 #include <linux/mfd/pm8xxx/mpp.h>
 
-#define PM8821_NR_IRQS		(64)
+#define PM8821_NR_IRQS		(112)
 #define PM8821_NR_MPPS		(4)
 
-#define PM8821_MPP_BLOCK_START	(16)
-#define PM8821_IRQ_BLOCK_BIT(block, bit) ((block) * 8 + (bit))
+#define PM8821_MPP_BLOCK_START	(4)
+
+/*
+ * Block 0 does not exist in PM8821 IRQ SSBI address space,
+ * IRQ0 is assigned to bit0 of block1
+ */
+#define PM8821_IRQ_BLOCK_BIT(block, bit) ((block-1) * 8 + (bit))
 
 /* MPPs [1,N] */
 #define PM8821_MPP_IRQ(base, mpp)	((base) + \
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/card.h b/include/linux/mmc/card.h
index 3f6d994..19ca831 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -61,6 +61,10 @@
 	unsigned int		generic_cmd6_time;	/* Units: 10ms */
 	unsigned int            power_off_longtime;     /* Units: ms */
 	unsigned int		hs_max_dtr;
+#define MMC_HIGH_26_MAX_DTR	26000000
+#define MMC_HIGH_52_MAX_DTR	52000000
+#define MMC_HIGH_DDR_MAX_DTR	52000000
+#define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
 	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 01f4991..b867c62 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -368,66 +368,6 @@
 #define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
 
-#define EXT_CSD_CARD_TYPE_SDR_200	(EXT_CSD_CARD_TYPE_SDR_1_8V | \
-					 EXT_CSD_CARD_TYPE_SDR_1_2V)
-
-#define EXT_CSD_CARD_TYPE_SDR_ALL	(EXT_CSD_CARD_TYPE_SDR_200 | \
-					 EXT_CSD_CARD_TYPE_52 | \
-					 EXT_CSD_CARD_TYPE_26)
-
-#define	EXT_CSD_CARD_TYPE_SDR_1_2V_ALL	(EXT_CSD_CARD_TYPE_SDR_1_2V | \
-					 EXT_CSD_CARD_TYPE_52 | \
-					 EXT_CSD_CARD_TYPE_26)
-
-#define	EXT_CSD_CARD_TYPE_SDR_1_8V_ALL	(EXT_CSD_CARD_TYPE_SDR_1_8V | \
-					 EXT_CSD_CARD_TYPE_52 | \
-					 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V	(EXT_CSD_CARD_TYPE_SDR_1_2V | \
-						 EXT_CSD_CARD_TYPE_DDR_1_8V | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V	(EXT_CSD_CARD_TYPE_SDR_1_8V | \
-						 EXT_CSD_CARD_TYPE_DDR_1_8V | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V	(EXT_CSD_CARD_TYPE_SDR_1_2V | \
-						 EXT_CSD_CARD_TYPE_DDR_1_2V | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V	(EXT_CSD_CARD_TYPE_SDR_1_8V | \
-						 EXT_CSD_CARD_TYPE_DDR_1_2V | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52	(EXT_CSD_CARD_TYPE_SDR_1_2V | \
-						 EXT_CSD_CARD_TYPE_DDR_52 | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52	(EXT_CSD_CARD_TYPE_SDR_1_8V | \
-						 EXT_CSD_CARD_TYPE_DDR_52 | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V	(EXT_CSD_CARD_TYPE_SDR_200 | \
-						 EXT_CSD_CARD_TYPE_DDR_1_8V | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V	(EXT_CSD_CARD_TYPE_SDR_200 | \
-						 EXT_CSD_CARD_TYPE_DDR_1_2V | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52	(EXT_CSD_CARD_TYPE_SDR_200 | \
-						 EXT_CSD_CARD_TYPE_DDR_52 | \
-						 EXT_CSD_CARD_TYPE_52 | \
-						 EXT_CSD_CARD_TYPE_26)
-
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
 #define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */
diff --git a/include/linux/msm_ipc.h b/include/linux/msm_ipc.h
index 82f76a6..44fa8eb 100644
--- a/include/linux/msm_ipc.h
+++ b/include/linux/msm_ipc.h
@@ -62,12 +62,19 @@
 #define IPC_ROUTER_IOCTL_BIND_CONTROL_PORT \
 	_IOR(IPC_ROUTER_IOCTL_MAGIC, 4, unsigned int)
 
+struct msm_ipc_server_info {
+	uint32_t node_id;
+	uint32_t port_id;
+	uint32_t service;
+	uint32_t instance;
+};
+
 struct server_lookup_args {
 	struct msm_ipc_port_name port_name;
 	int num_entries_in_array;
 	int num_entries_found;
 	uint32_t lookup_mask;
-	struct msm_ipc_port_addr port_addr[0];
+	struct msm_ipc_server_info srv_info[0];
 };
 
 #endif
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index a0af4b5..f757fae 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -99,6 +99,7 @@
 	MDP_YCRCB_H1V1,   /* YCrCb interleave */
 	MDP_YCBCR_H1V1,   /* YCbCr interleave */
 	MDP_IMGTYPE_LIMIT,
+	MDP_RGB_BORDERFILL,	/* border fill pipe */
 	MDP_BGR_565 = MDP_IMGTYPE2_START,      /* BGR 565 planer */
 	MDP_FB_FORMAT,    /* framebuffer format */
 	MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index e2a0392..f8329dd 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -335,6 +335,7 @@
 	unsigned long lpm_flags;
 #define PHY_PWR_COLLAPSED		BIT(0)
 #define PHY_RETENTIONED			BIT(1)
+#define XO_SHUTDOWN			BIT(2)
 	int reset_counter;
 	unsigned long b_last_se0_sess;
 	unsigned long tmouts;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index c148b75..f6f3c1e 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -401,6 +401,7 @@
 #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
 #define V4L2_PIX_FMT_DIVX_311  v4l2_fourcc('D', 'I', 'V', '3') /* DIVX311     */
 #define V4L2_PIX_FMT_DIVX      v4l2_fourcc('D', 'I', 'V', 'X') /* DIVX        */
+#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* ON2 VP8 stream */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -1274,6 +1275,8 @@
 
 /* last CID + 1 */
 #define V4L2_CID_LASTP1                         (V4L2_CID_BASE+42)
+#define V4L2_CID_SPECIAL_EFFECT			(V4L2_CID_BASE+43)
+/* Minimum number of buffer neede by the device */
 
 /*  MPEG-class control IDs defined by V4L2 */
 #define V4L2_CID_MPEG_BASE 			(V4L2_CTRL_CLASS_MPEG | 0x900)
@@ -1641,6 +1644,10 @@
 #define V4L2_CID_MPEG_QCOM_BASE	(V4L2_CTRL_CLASS_MPEG | 0x2100)
 
 #define V4L2_CID_MPEG_QCOM_SET_PERF_LEVEL (V4L2_CID_MPEG_QCOM_BASE + 0)
+enum v3l2_mpeg_qcom_perf_level {
+	V4L2_CID_MPEG_QCOM_PERF_LEVEL_PERFORMANCE		= 0,
+	V4L2_CID_MPEG_QCOM_PERF_LEVEL_TURBO			= 1,
+};
 
 #define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY		(V4L2_CID_MPEG_MFC51_BASE+0)
 #define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE	(V4L2_CID_MPEG_MFC51_BASE+1)
diff --git a/include/media/Kbuild b/include/media/Kbuild
index 03951ce..2a21336 100644
--- a/include/media/Kbuild
+++ b/include/media/Kbuild
@@ -5,3 +5,4 @@
 header-y += msm_isp.h
 header-y += msm_gemini.h
 header-y += msm_gestures.h
+header-y += msm_mercury.h
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index cd00800..37d2343 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -99,6 +99,7 @@
 	VCD_PERF_LEVEL0,
 	VCD_PERF_LEVEL1,
 	VCD_PERF_LEVEL2,
+	VCD_PERF_LEVEL_TURBO,
 };
 
 #define VCD_METADATA_DATANONE       0x001
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 8222b67..271079e 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -916,6 +916,21 @@
 	MSM_V4L2_SATURATION_L10,
 };
 
+enum msm_v4l2_contrast_level {
+	MSM_V4L2_CONTRAST_L0,
+	MSM_V4L2_CONTRAST_L1,
+	MSM_V4L2_CONTRAST_L2,
+	MSM_V4L2_CONTRAST_L3,
+	MSM_V4L2_CONTRAST_L4,
+	MSM_V4L2_CONTRAST_L5,
+	MSM_V4L2_CONTRAST_L6,
+	MSM_V4L2_CONTRAST_L7,
+	MSM_V4L2_CONTRAST_L8,
+	MSM_V4L2_CONTRAST_L9,
+	MSM_V4L2_CONTRAST_L10,
+};
+
+
 enum msm_v4l2_exposure_level {
 	MSM_V4L2_EXPOSURE_N2,
 	MSM_V4L2_EXPOSURE_N1,
@@ -951,16 +966,29 @@
 };
 
 enum msm_v4l2_wb_mode {
-	MSM_V4L2_WB_MIN_MINUS_1,
-	MSM_V4L2_WB_AUTO = 1,
+	MSM_V4L2_WB_OFF,
+	MSM_V4L2_WB_AUTO ,
 	MSM_V4L2_WB_CUSTOM,
 	MSM_V4L2_WB_INCANDESCENT,
 	MSM_V4L2_WB_FLUORESCENT,
 	MSM_V4L2_WB_DAYLIGHT,
 	MSM_V4L2_WB_CLOUDY_DAYLIGHT,
-	MSM_V4L2_WB_TWILIGHT,
-	MSM_V4L2_WB_SHADE,
-	MSM_V4L2_WB_OFF,
+};
+
+enum msm_v4l2_special_effect {
+	MSM_V4L2_EFFECT_OFF,
+	MSM_V4L2_EFFECT_MONO,
+	MSM_V4L2_EFFECT_NEGATIVE,
+	MSM_V4L2_EFFECT_SOLARIZE,
+	MSM_V4L2_EFFECT_SEPIA,
+	MSM_V4L2_EFFECT_POSTERAIZE,
+	MSM_V4L2_EFFECT_WHITEBOARD,
+	MSM_V4L2_EFFECT_BLACKBOARD,
+	MSM_V4L2_EFFECT_AQUA,
+	MSM_V4L2_EFFECT_EMBOSS,
+	MSM_V4L2_EFFECT_SKETCH,
+	MSM_V4L2_EFFECT_NEON,
+	MSM_V4L2_EFFECT_MAX,
 };
 
 enum msm_v4l2_power_line_frequency {
@@ -1422,25 +1450,33 @@
 #define QCAMERA_VNODE_GROUP_ID 2
 
 #define MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_camera_v4l2_ioctl_t *)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_camera_v4l2_ioctl_t)
 
 #define MSM_CAM_V4L2_IOCTL_GET_CONFIG_INFO \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct msm_camera_v4l2_ioctl_t *)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct msm_camera_v4l2_ioctl_t)
 
 #define MSM_CAM_V4L2_IOCTL_GET_MCTL_INFO \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct msm_camera_v4l2_ioctl_t *)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct msm_camera_v4l2_ioctl_t)
 
 #define MSM_CAM_V4L2_IOCTL_CTRL_CMD_DONE \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct msm_camera_v4l2_ioctl_t *)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct msm_camera_v4l2_ioctl_t)
 
 #define MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t *)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t)
 
 #define MSM_CAM_IOCTL_SEND_EVENT \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_event)
 
+#define MSM_CAM_V4L2_IOCTL_CFG_VPE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_vpe_cfg_cmd)
+
+#define MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_camera_v4l2_ioctl_t)
+
 struct msm_camera_v4l2_ioctl_t {
+	uint32_t id;
 	void __user *ioctl_ptr;
+	uint32_t len;
 };
 
 #endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/media/msm_mercury.h b/include/media/msm_mercury.h
new file mode 100644
index 0000000..1d14724
--- /dev/null
+++ b/include/media/msm_mercury.h
@@ -0,0 +1,119 @@
+#ifndef __LINUX_MSM_MERCURY_H
+#define __LINUX_MSM_MERCURY_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define MSM_MERCURY_HW_VERSION_REG  0x0004/* this offset does not exist in HW*/
+
+#define OUTPUT_H2V1  0
+#define OUTPUT_H2V2  1
+#define OUTPUT_BYTE  6
+
+#define MSM_MERCURY_MODE_REALTIME_ENCODE 0
+#define MSM_MERCURY_MODE_OFFLINE_ENCODE 1
+#define MSM_MERCURY_MODE_REALTIME_ROTATION 2
+#define MSM_MERCURY_MODE_OFFLINE_ROTATION 3
+
+#define MSM_MERCURY_EVT_RESET       1
+#define MSM_MERCURY_EVT_FRAMEDONE	2
+#define MSM_MERCURY_EVT_ERR         3
+#define MSM_MERCURY_EVT_UNBLOCK     4
+
+#define MSM_MERCURY_HW_CMD_TYPE_READ      0
+#define MSM_MERCURY_HW_CMD_TYPE_WRITE     1
+#define MSM_MERCURY_HW_CMD_TYPE_WRITE_OR  2
+#define MSM_MERCURY_HW_CMD_TYPE_UWAIT     3
+#define MSM_MERCURY_HW_CMD_TYPE_MWAIT     4
+#define MSM_MERCURY_HW_CMD_TYPE_MDELAY    5
+#define MSM_MERCURY_HW_CMD_TYPE_UDELAY    6
+
+#define MSM_MCR_IOCTL_MAGIC 'g'
+
+#define MSM_MCR_IOCTL_GET_HW_VERSION \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 1, struct msm_mercury_hw_cmd *)
+
+#define MSM_MCR_IOCTL_RESET \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 2, struct msm_mercury_ctrl_cmd *)
+
+#define MSM_MCR_IOCTL_STOP \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 3, struct msm_mercury_hw_cmds *)
+
+#define MSM_MCR_IOCTL_START \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 4, struct msm_mercury_hw_cmds *)
+
+#define MSM_MCR_IOCTL_INPUT_BUF_CFG \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 5, struct msm_mercury_buf *)
+
+#define MSM_MCR_IOCTL_INPUT_GET \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 6, struct msm_mercury_buf *)
+
+#define MSM_MCR_IOCTL_INPUT_GET_UNBLOCK \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 7, int)
+
+#define MSM_MCR_IOCTL_OUTPUT_BUF_CFG \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 8, struct msm_mercury_buf *)
+
+#define MSM_MCR_IOCTL_OUTPUT_GET \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 9, struct msm_mercury_buf *)
+
+#define MSM_MCR_IOCTL_OUTPUT_GET_UNBLOCK \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 10, int)
+
+#define MSM_MCR_IOCTL_EVT_GET \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 11, struct msm_mercury_ctrl_cmd *)
+
+#define MSM_MCR_IOCTL_EVT_GET_UNBLOCK \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 12, int)
+
+#define MSM_MCR_IOCTL_HW_CMD \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 13, struct msm_mercury_hw_cmd *)
+
+#define MSM_MCR_IOCTL_HW_CMDS \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 14, struct msm_mercury_hw_cmds *)
+
+#define MSM_MCR_IOCTL_TEST_DUMP_REGION \
+	_IOW(MSM_MCR_IOCTL_MAGIC, 15, unsigned long)
+
+struct msm_mercury_ctrl_cmd {
+	uint32_t type;
+	uint32_t len;
+	void     *value;
+};
+
+struct msm_mercury_buf {
+	uint32_t type;
+	int      fd;
+	void     *vaddr;
+	uint32_t y_off;
+	uint32_t y_len;
+	uint32_t framedone_len;
+	uint32_t cbcr_off;
+	uint32_t cbcr_len;
+	uint32_t num_of_mcu_rows;
+	uint32_t offset;
+};
+
+struct msm_mercury_hw_cmd {
+
+	uint32_t type:4;
+	/* n microseconds of timeout for WAIT */
+	/* n microseconds of time for DELAY */
+	/* repeat n times for READ/WRITE */
+	/* max is 0xFFF, 4095 */
+	uint32_t n:12;
+	uint32_t offset:16;
+	uint32_t mask;
+	union {
+		/* for single READ/WRITE/WAIT, n = 1 */
+		uint32_t data;
+		uint32_t *pdata;/* for multiple READ/WRITE/WAIT, n > 1 */
+	};
+};
+
+struct msm_mercury_hw_cmds {
+	uint32_t m;	/* number of elements in the hw_cmd array */
+	struct msm_mercury_hw_cmd hw_cmd[1];
+};
+
+#endif /* __LINUX_MSM_MERCURY_H */
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 96795a3..ec8d73e 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -59,6 +59,9 @@
 #define INT_FM_TX 0x3005		/* index = 29 */
 #define RT_PROXY_PORT_001_RX	0x2000    /* index = 30 */
 #define RT_PROXY_PORT_001_TX	0x2001    /* index = 31 */
+#define SECONDARY_PCM_RX 12			/* index = 32 */
+#define SECONDARY_PCM_TX 13			/* index = 33 */
+
 
 #define AFE_PORT_INVALID 0xFFFF
 #define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index 8cdcc18..f93af1f 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -68,6 +68,8 @@
 	IDX_INT_FM_TX = 29,
 	IDX_RT_PROXY_PORT_001_RX = 30,
 	IDX_RT_PROXY_PORT_001_TX = 31,
+	IDX_SECONDARY_PCM_RX = 32,
+	IDX_SECONDARY_PCM_TX = 33,
 	AFE_MAX_PORTS
 };
 
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 54a9187..ee90797 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -81,7 +81,8 @@
 #define SESSION_MAX	0x08
 
 #define SOFT_PAUSE_PERIOD       30   /* ramp up/down for 30ms    */
-#define SOFT_PAUSE_STEP         2000 /* Step value 2ms or 2000us */
+#define SOFT_PAUSE_STEP_LINEAR  0    /* Step value 0ms or 0us */
+#define SOFT_PAUSE_STEP         2000 /* Step value 2000ms or 2000us */
 enum {
 	SOFT_PAUSE_CURVE_LINEAR = 0,
 	SOFT_PAUSE_CURVE_EXP,
@@ -89,7 +90,8 @@
 };
 
 #define SOFT_VOLUME_PERIOD       30   /* ramp up/down for 30ms    */
-#define SOFT_VOLUME_STEP         2000 /* Step value 2ms or 2000us */
+#define SOFT_VOLUME_STEP_LINEAR  0    /* Step value 0ms or 0us */
+#define SOFT_VOLUME_STEP         2000 /* Step value 2000ms or 2000us */
 enum {
 	SOFT_VOLUME_CURVE_LINEAR = 0,
 	SOFT_VOLUME_CURVE_EXP,
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 77a6dd9..deb67f5 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1634,7 +1634,8 @@
 			 $exec_file =~ /^Kconfig$/) &&
 			$rawline =~ /^new (file )?mode\s([0-9]+)$/ &&
 			(oct($2) & 0111))  {
-			    ERROR("Source file has +x permissions: " .
+			    ERROR("EXECUTE_PERMISSIONS",
+				  "Source file has +x permissions: " .
 			    "$exec_file\n");
 		}
 		$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
@@ -1647,7 +1648,8 @@
 			if ($shorttext == IN_SHORTTEXT_BLANKLINE && $line=~/\S/) {
 				# the subject line was just processed,
 				# a blank line must be next
-				WARN("non-blank line after summary line\n" . $herecurr);
+				WARN("NONBLANK_AFTER_SUMMARY",
+				     "non-blank line after summary line\n" . $herecurr);
 				$shorttext = IN_SHORTTEXT;
 				# this non-blank line may or may not be commit text -
 				# a warning has been generated so assume it is commit
@@ -1658,7 +1660,8 @@
 			if ($shorttext == IN_SHORTTEXT) {
 				if ($line=~/^---/ || $line=~/^diff.*/) {
 					if ($commit_text_present == 0) {
-						WARN("please add commit text explaining " .
+						WARN("NO_COMMIT_TEXT",
+						     "please add commit text explaining " .
 						     "*why* the change is needed\n" .
 						     $herecurr);
 					}
@@ -1668,7 +1671,8 @@
 					 && $line !~ /^:([0-7]{6}\s){2}
 						      ([[:xdigit:]]+\.*
 						       \s){2}\w+\s\w+/xms) {
-					WARN("commit text line over " .
+					WARN("LONG_COMMIT_TEXT",
+					     "commit text line over " .
 					     SHORTTEXT_LIMIT .
 					     " characters\n" . $herecurr);
 				} elsif ($line=~/^\s*change-id:/i ||
@@ -1678,7 +1682,8 @@
 					# this is a tag, there must be commit
 					# text by now
 					if ($commit_text_present == 0) {
-						WARN("please add commit text explaining " .
+						WARN("NO_COMMIT_TEXT",
+						     "please add commit text explaining " .
 						     "*why* the change is needed\n" .
 						     $herecurr);
 						# prevent duplicate warnings
@@ -1699,7 +1704,8 @@
 					$shorttext = IN_SHORTTEXT;
 					# Check for Subject line followed by a blank line.
 					if (length($line) != 0) {
-						WARN("non-blank line after " .
+						WARN("NONBLANK_AFTER_SUMMARY",
+						     "non-blank line after " .
 						     "summary line\n" .
 						     $sublinenr . $here .
 						     "\n" . $subjectline .
@@ -1721,7 +1727,8 @@
 				$sublinenr = "#$linenr & ";
 # Check for Subject line less than line limit
 				if (length($1) > SHORTTEXT_LIMIT) {
-					WARN("summary line over " .
+					WARN("LONG_SUMMARY_LINE",
+					     "summary line over " .
 					     SHORTTEXT_LIMIT .
 					     " characters\n" . $herecurr);
 				}
@@ -1732,7 +1739,8 @@
 				$shorttext = IN_SHORTTEXT_BLANKLINE;
 				$shorttext_exspc = 4;
 				if (length($1) > SHORTTEXT_LIMIT) {
-					WARN("summary line over " .
+					WARN("LONG_SUMMARY_LINE",
+					     "summary line over " .
 					     SHORTTEXT_LIMIT .
 					     " characters\n" . $herecurr);
 				}
@@ -1797,13 +1805,14 @@
 				}
 			}
 			if ($line =~ /^\s*signed-off-by:.*(quicinc|qualcomm)\.com/i) {
-				WARN("invalid Signed-off-by identity\n" . $line );
+				WARN("BAD_SIGN_OFF",
+				     "invalid Signed-off-by identity\n" . $line );
 			}
 		}
 
 #check the patch for invalid author credentials
 		if ($line =~ /^From:.*(quicinc|qualcomm)\.com/) {
-			WARN("invalid author identity\n" . $line );
+			WARN("BAD_AUTHOR", "invalid author identity\n" . $line );
 		}
 
 # Check for wrappage within a valid hunk of the file
@@ -3291,19 +3300,20 @@
 
 # sys_open/read/write/close are not allowed in the kernel
 		if ($line =~ /\b(sys_(?:open|read|write|close))\b/) {
-			ERROR("$1 is inappropriate in kernel code.\n" .
+			ERROR("FILE_OPS", "$1 is inappropriate in kernel code.\n" .
 			      $herecurr);
 		}
 
 # filp_open is a backdoor for sys_open
 		if ($line =~ /\b(filp_open)\b/) {
-			ERROR("$1 is inappropriate in kernel code.\n" .
+			ERROR("FILE_OPS", "$1 is inappropriate in kernel code.\n" .
 			      $herecurr);
 		}
 
 # read[bwl] & write[bwl] use too many barriers, use the _relaxed variants
 		if ($line =~ /\b((?:read|write)[bwl])\b/) {
-			ERROR("Use of $1 is deprecated: use $1_relaxed\n\t" .
+			ERROR("NON_RELAXED_IO",
+			      "Use of $1 is deprecated: use $1_relaxed\n\t" .
 			      "with appropriate memory barriers instead.\n" .
 			      $herecurr);
 		}
@@ -3313,7 +3323,8 @@
 			my ($all, $pref, $suf) = ($1, $2, $3);
 			$pref =~ s/in/read/;
 			$pref =~ s/out/write/;
-			ERROR("Use of $all is deprecated: use " .
+			ERROR("NON_RELAXED_IO",
+			      "Use of $all is deprecated: use " .
 			      "__raw_$pref$suf\n\t" .
 			      "with appropriate memory barriers instead.\n" .
 			      $herecurr);
@@ -3321,7 +3332,8 @@
 
 # dsb is too ARMish, and should usually be mb.
 		if ($line =~ /\bdsb\b/) {
-			WARN("Use of dsb is discouranged: prefer mb.\n" .
+			WARN("ARM_BARRIER",
+			     "Use of dsb is discouranged: prefer mb.\n" .
 			     $herecurr);
 		}
 
@@ -3329,12 +3341,13 @@
 	if ($realfile =~ /\/mach-msm\/board-[0-9]+/ &&
 	    $realfile !~ /camera/ && $realfile !~ /gpiomux/ &&
 	    $line =~ /\s*struct msm_gpiomux_config\s*/ ) {
-		WARN("Non gpiomux board file cannot have a gpiomux config declarations. Please declare gpiomux configs in board-*-gpiomux.c file.\n" . $herecurr);
+		WARN("GPIOMUX_IN_BOARD",
+		     "Non gpiomux board file cannot have a gpiomux config declarations. Please declare gpiomux configs in board-*-gpiomux.c file.\n" . $herecurr);
 	}
 
 # MSM - check if vreg_xxx function are used
 	if ($line =~ /\b(vreg_(get|put|set_level|enable|disable))\b/) {
-		WARN("Use of $1 API is deprecated: " .
+		WARN("DEPRECATED_VREG_APIS", "Use of $1 API is deprecated: " .
 			"use regulator APIs\n" . $herecurr);
 	}
 
@@ -3354,7 +3367,8 @@
 		);
 		foreach my $k (keys %str_fns) {
 			if ($line =~ /\b$k\b/) {
-				ERROR("Use of $k is deprecated: " .
+				ERROR("UNBOUNDED_STRING_FNS",
+				      "Use of $k is deprecated: " .
 				      "use $str_fns{$k} instead.\n" .
 				      $herecurr);
 			}
@@ -3362,13 +3376,15 @@
 
 # warn about #if 0
 		if ($line =~ /^.\s*\#\s*if\s+0\b/) {
-			WARN("if this code is redundant consider removing it\n"
+			WARN("IF_0",
+			     "if this code is redundant consider removing it\n"
 				.  $herecurr);
 		}
 
 # warn about #if 1
 		if ($line =~ /^.\s*\#\s*if\s+1\b/) {
-			WARN("if this code is required consider removing"
+			WARN("IF_1",
+			     "if this code is required consider removing"
 				. " #if 1\n" .  $herecurr);
 		}
 
@@ -3408,7 +3424,8 @@
 
 # check the patch for use of mdelay
 		if ($line =~ /\bmdelay\s*\(/) {
-			WARN("use of mdelay() found: msleep() is the preferred API.\n" . $line );
+			WARN("MDELAY",
+			     "use of mdelay() found: msleep() is the preferred API.\n" . $line );
 		}
 
 # warn about #ifdefs in C files
@@ -3598,7 +3615,8 @@
 
 # check for return codes on error paths
 		if ($line =~ /\breturn\s+-\d+/) {
-			ERROR("illegal return value, please use an error code\n" . $herecurr);
+			ERROR("NO_ERROR_CODE",
+			      "illegal return value, please use an error code\n" . $herecurr);
 		}
 
 # check for gcc specific __FUNCTION__
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index 3732160..583a5ce 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -40,8 +40,9 @@
 # force LANG to be set to en_US.UTF-8 to get consistent warnings.
 
 allowed_warnings = set([
-    "return_address.c:62",
+    "alignment.c:327",
     "mmu.c:602",
+    "return_address.c:62",
  ])
 
 # Capture the name of the object file, can find it.
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 c5dbdae..94bdd27 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -257,6 +257,23 @@
 struct sitar_priv *debug_sitar_priv;
 #endif
 
+static int sitar_get_anc_slot(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	ucontrol->value.integer.value[0] = sitar->anc_slot;
+	return 0;
+}
+
+static int sitar_put_anc_slot(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	sitar->anc_slot = ucontrol->value.integer.value[0];
+	return 0;
+}
 
 static int sitar_pa_gain_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
@@ -536,6 +553,9 @@
 	SOC_SINGLE("MICBIAS1 CAPLESS Switch", SITAR_A_MICB_1_CTL, 4, 1, 1),
 	SOC_SINGLE("MICBIAS2 CAPLESS Switch", SITAR_A_MICB_2_CTL, 4, 1, 1),
 
+	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, sitar_get_anc_slot,
+				   sitar_put_anc_slot),
+
 	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
 
 	SOC_SINGLE("TX1 HPF Switch", SITAR_A_CDC_TX1_MUX_CTL, 3, 1, 0),
@@ -633,11 +653,11 @@
 };
 
 static const char *dec1_mux_text[] = {
-	"ZERO", "DMIC1", "ADC1", "ADC2", "ADC3", "MBADC", "DMIC4", "ANCFB1",
+	"ZERO", "DMIC1", "ADC1", "ADC2", "ADC3", "MBADC", "DMIC4", "ANC1_FB",
 };
 
 static const char *dec2_mux_text[] = {
-	"ZERO", "DMIC2", "ADC1", "ADC2", "ADC3", "MBADC", "DMIC3", "ANCFB2",
+	"ZERO", "DMIC2", "ADC1", "ADC2", "ADC3", "MBADC", "DMIC3", "ANC2_FB",
 };
 
 static const char *dec3_mux_text[] = {
@@ -648,6 +668,15 @@
 	"ZERO", "DMIC4", "ADC1", "ADC2", "ADC3", "DMIC3", "DMIC2", "DMIC1"
 };
 
+static const char const *anc_mux_text[] = {
+	"ZERO", "ADC1", "ADC2", "ADC3", "RSVD1", "RSVD2", "RSVD3",
+	"MBADC", "RSVD4", "DMIC1", "DMIC2",	"DMIC3", "DMIC4"
+};
+
+static const char const *anc1_fb_mux_text[] = {
+	"ZERO", "EAR_HPH_L", "EAR_LINE_1",
+};
+
 static const char *iir1_inp1_text[] = {
 	"ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "ZERO", "ZERO", "ZERO",
 	"ZERO", "ZERO", "ZERO", "RX1", "RX2", "RX3", "RX4", "RX5",
@@ -710,6 +739,15 @@
 static const struct soc_enum dec4_mux_enum =
 	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B2_CTL, 3, 8, dec4_mux_text);
 
+static const struct soc_enum anc1_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_ANC_B1_CTL, 0, 13, anc_mux_text);
+
+static const struct soc_enum anc2_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_ANC_B1_CTL, 4, 13, anc_mux_text);
+
+static const struct soc_enum anc1_fb_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
+
 static const struct soc_enum iir1_inp1_mux_enum =
 	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_EQ1_B1_CTL, 0, 16, iir1_inp1_text);
 
@@ -773,6 +811,15 @@
 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", SITAR_A_RX_EAR_EN, 5, 1, 0),
 };
@@ -803,27 +850,39 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 	u16 adc_reg;
+	u8 init_bit_shift;
 
 	pr_debug("%s %d\n", __func__, event);
 
 	if (w->reg == SITAR_A_TX_1_2_EN)
 		adc_reg = SITAR_A_TX_1_2_TEST_CTL;
+	else if (w->reg == SITAR_A_TX_3_EN)
+		adc_reg = SITAR_A_TX_3_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:
 		sitar_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 << w->shift,
-			1 << w->shift);
-		usleep_range(1000, 1000);
-		snd_soc_update_bits(codec, adc_reg, 1 << w->shift, 0x00);
-		usleep_range(1000, 1000);
-		snd_soc_update_bits(codec, adc_reg, 0x08, 0x08);
+
+		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		sitar_codec_enable_adc_block(codec, 0);
@@ -949,6 +1008,115 @@
 	return 0;
 }
 
+static int sitar_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 sitar_priv *sitar = 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:
+
+		/* Use the same firmware file as that of WCD9310,
+		 * since the register sequences are same for
+		 * WCD9310 and WCD9304
+		 */
+		filename = "wcd9310/wcd9310_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 (sitar->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 < SITAR_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 * SITAR_PACKED_REG_SIZE
+				> anc_size_remaining) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -ENOMEM;
+			}
+
+			if (sitar->anc_slot == i)
+				break;
+
+			anc_size_remaining -= (anc_writes_size *
+				SITAR_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++) {
+			SITAR_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);
+
+		/* For Sitar, it is required to enable both Feed-forward
+		 * and Feed back clocks to enable ANC
+		 */
+		snd_soc_write(codec, SITAR_A_CDC_CLK_ANC_CLK_EN_CTL, 0x0F);
+
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_write(codec, SITAR_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+		snd_soc_write(codec, SITAR_A_CDC_CLK_ANC_CLK_EN_CTL, 0x00);
+		break;
+	}
+	return 0;
+}
+
+
 static void sitar_codec_start_hs_polling(struct snd_soc_codec *codec)
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
@@ -1708,6 +1876,15 @@
 	SND_SOC_DAPM_MUX_E("DEC4 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
 		&dec4_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
 
+	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
+	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
+
+	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
+		sitar_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_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
 	SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, 0, 0, &sb_tx2_mux),
 	SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, 0, 0, &sb_tx3_mux),
@@ -1774,6 +1951,10 @@
 	{"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
 	{"LINEOUT1 DAC", NULL, "DAC2 MUX"},
 
+	{"ANC1 FB MUX", "EAR_HPH_L", "RX2 MIX1"},
+	{"ANC1 FB MUX", "EAR_LINE_1", "RX3 MIX1"},
+	{"ANC", NULL, "ANC1 FB MUX"},
+
 
 	/* Headset (RX MIX1 and RX MIX2) */
 	{"HEADPHONE", NULL, "HPHL"},
@@ -1805,6 +1986,21 @@
 	{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
 	{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
 
+	/* ANC */
+	{"ANC", NULL, "ANC1 MUX"},
+	{"ANC", NULL, "ANC2 MUX"},
+	{"ANC1 MUX", "ADC1", "ADC1"},
+	{"ANC1 MUX", "ADC2", "ADC2"},
+	{"ANC1 MUX", "ADC3", "ADC3"},
+	{"ANC2 MUX", "ADC1", "ADC1"},
+	{"ANC2 MUX", "ADC2", "ADC2"},
+	{"ANC2 MUX", "ADC3", "ADC3"},
+
+	{"ANC", NULL, "CDC_CONN"},
+
+	{"RX2 MIX1", NULL, "ANC"},
+	{"RX3 MIX1", NULL, "ANC"},
+
 	/* SLIMBUS Connections */
 
 	/* Slimbus port 5 is non functional in Sitar 1.0 */
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 4b4dae1..9dcfc1c 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -5265,16 +5265,37 @@
 	wcd9xxx_unlock_sleep(core);
 }
 
+static u16 tabla_get_cfilt_reg(struct snd_soc_codec *codec, u8 cfilt)
+{
+	u16 reg;
+
+	switch (cfilt) {
+	case TABLA_CFILT1_SEL:
+		reg = TABLA_A_MICB_CFILT_1_CTL;
+		break;
+	case TABLA_CFILT2_SEL:
+		reg = TABLA_A_MICB_CFILT_2_CTL;
+		break;
+	case TABLA_CFILT3_SEL:
+		reg = TABLA_A_MICB_CFILT_3_CTL;
+		break;
+	default:
+		BUG();
+	}
+	return reg;
+}
+
 void tabla_mbhc_cal(struct snd_soc_codec *codec)
 {
 	struct tabla_priv *tabla;
 	struct tabla_mbhc_btn_detect_cfg *btn_det;
-	u8 cfilt_mode, bg_mode;
+	u8 cfilt_mode, micbias2_cfilt_mode, bg_mode;
 	u8 ncic, nmeas, navg;
 	u32 mclk_rate;
 	u32 dce_wait, sta_wait;
 	u8 *n_cic;
 	void *calibration;
+	u16 bias2_ctl;
 
 	tabla = snd_soc_codec_get_drvdata(codec);
 	calibration = tabla->mbhc_cfg.calibration;
@@ -5303,7 +5324,16 @@
 	 * Need to restore defaults once calculation is done.
 	 */
 	cfilt_mode = snd_soc_read(codec, tabla->mbhc_bias_regs.cfilt_ctl);
-	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
+	micbias2_cfilt_mode =
+	    snd_soc_read(codec, tabla_get_cfilt_reg(codec,
+					tabla->pdata->micbias.bias2_cfilt_sel));
+	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
+			    TABLA_CFILT_FAST_MODE);
+	snd_soc_update_bits(codec,
+			    tabla_get_cfilt_reg(codec,
+					 tabla->pdata->micbias.bias2_cfilt_sel),
+			    0x40, TABLA_CFILT_FAST_MODE);
+
 	bg_mode = snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02,
 				      0x02);
 
@@ -5317,6 +5347,12 @@
 	snd_soc_write(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x78);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
 
+	/* MICBIAS2 routing for calibration */
+	bias2_ctl = snd_soc_read(codec, TABLA_A_MICB_2_CTL);
+	snd_soc_update_bits(codec, TABLA_A_MICB_1_MBHC, 0x03, TABLA_MICBIAS2);
+	snd_soc_write(codec, TABLA_A_MICB_2_CTL,
+		      snd_soc_read(codec, tabla->mbhc_bias_regs.ctl_reg));
+
 	/* DCE measurement for 0 volts */
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
@@ -5354,7 +5390,15 @@
 	tabla->mbhc_data.sta_mb = tabla_codec_read_sta_result(codec);
 
 	/* Restore default settings. */
+	snd_soc_write(codec, TABLA_A_MICB_2_CTL, bias2_ctl);
+	snd_soc_update_bits(codec, TABLA_A_MICB_1_MBHC, 0x03,
+			    tabla->mbhc_cfg.micbias);
+
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
+	snd_soc_update_bits(codec,
+			    tabla_get_cfilt_reg(codec,
+				   tabla->pdata->micbias.bias2_cfilt_sel), 0x40,
+			    micbias2_cfilt_mode);
 	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
 			    cfilt_mode);
 	snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02, bg_mode);
@@ -5538,6 +5582,10 @@
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
 
 	snd_soc_update_bits(codec, TABLA_A_MBHC_SCALING_MUX_2, 0xF0, 0xF0);
+
+	/* override mbhc's micbias */
+	snd_soc_update_bits(codec, TABLA_A_MICB_1_MBHC, 0x03,
+			    tabla->mbhc_cfg.micbias);
 }
 
 static bool tabla_mbhc_fw_validate(const struct firmware *fw)
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/apq8064.c b/sound/soc/msm/apq8064.c
index 353ffd6..a7fd38b 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -46,6 +46,8 @@
 #define BOTTOM_SPK_AMP_NEG	0x2
 #define TOP_SPK_AMP_POS		0x4
 #define TOP_SPK_AMP_NEG		0x8
+#define TOP_SPK_AMP		0x10
+
 
 #define GPIO_AUX_PCM_DOUT 43
 #define GPIO_AUX_PCM_DIN 44
@@ -65,7 +67,8 @@
 	SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
 	SLIM_3_RX_1 = 151, /* External echo-cancellation ref */
 	SLIM_3_RX_2 = 152, /* External echo-cancellation ref */
-	SLIM_3_TX_1 = 147, /* HDMI RX */
+	SLIM_3_TX_1 = 153, /* HDMI RX */
+	SLIM_3_TX_2 = 154, /* HDMI RX */
 	SLIM_4_TX_1 = 148, /* In-call recording RX */
 	SLIM_4_TX_2 = 149, /* In-call recording RX */
 	SLIM_4_RX_1 = 150, /* In-call music delivery TX */
@@ -123,6 +126,8 @@
 	.gpio_level_insert = 1,
 };
 
+static struct mutex cdc_mclk_mutex;
+
 static void msm_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
 {
 	int ret = 0;
@@ -201,10 +206,14 @@
 			usleep_range(4000, 4000);
 		}
 
-	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
+	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG | TOP_SPK_AMP)) {
 
-		if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
-			(msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
+		pr_debug("%s():top_spk_amp_state = 0x%x spk_event = 0x%x\n",
+			__func__, msm_ext_top_spk_pamp, spk);
+
+		if (((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
+			(msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) ||
+				(msm_ext_top_spk_pamp & TOP_SPK_AMP)) {
 
 			pr_debug("%s() External Top Speaker Ampl already"
 				"turned on. spk = 0x%08x\n", __func__, spk);
@@ -213,8 +222,9 @@
 
 		msm_ext_top_spk_pamp |= spk;
 
-		if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
-			(msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
+		if (((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
+			(msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) ||
+				(msm_ext_top_spk_pamp & TOP_SPK_AMP)) {
 
 			msm_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
 			pr_debug("%s: sleeping 4 ms after turning on "
@@ -245,17 +255,31 @@
 
 		usleep_range(4000, 4000);
 
-	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
+	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG | TOP_SPK_AMP)) {
+
+		pr_debug("%s: top_spk_amp_state = 0x%x spk_event = 0x%x\n",
+				__func__, msm_ext_top_spk_pamp, spk);
 
 		if (!msm_ext_top_spk_pamp)
 			return;
 
+		if ((spk & TOP_SPK_AMP_POS) || (spk & TOP_SPK_AMP_NEG)) {
+
+			msm_ext_top_spk_pamp &= (~(TOP_SPK_AMP_POS |
+							TOP_SPK_AMP_NEG));
+		} else if (spk & TOP_SPK_AMP) {
+			msm_ext_top_spk_pamp &=  ~TOP_SPK_AMP;
+		}
+
+		if (msm_ext_top_spk_pamp)
+			return;
+
 		gpio_direction_output(top_spk_pamp_gpio, 0);
 		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 ext Top Spek Ampl is off\n",
+				__func__);
 
 		usleep_range(4000, 4000);
 	} else  {
@@ -320,6 +344,8 @@
 			msm_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
 		else if  (!strncmp(w->name, "Ext Spk Top Neg", 15))
 			msm_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
+		else if  (!strncmp(w->name, "Ext Spk Top", 12))
+			msm_ext_spk_power_amp_on(TOP_SPK_AMP);
 		else {
 			pr_err("%s() Invalid Speaker Widget = %s\n",
 					__func__, w->name);
@@ -335,6 +361,8 @@
 			msm_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
 		else if  (!strncmp(w->name, "Ext Spk Top Neg", 15))
 			msm_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
+		else if  (!strncmp(w->name, "Ext Spk Top", 12))
+			msm_ext_spk_power_amp_off(TOP_SPK_AMP);
 		else {
 			pr_err("%s() Invalid Speaker Widget = %s\n",
 					__func__, w->name);
@@ -347,35 +375,42 @@
 static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
 				    bool dapm)
 {
+	int r = 0;
 	pr_debug("%s: enable = %d\n", __func__, enable);
+
+	mutex_lock(&cdc_mclk_mutex);
 	if (enable) {
 		clk_users++;
 		pr_debug("%s: clk_users = %d\n", __func__, clk_users);
-		if (clk_users != 1)
-			return 0;
-
-		if (codec_clk) {
-			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
-			clk_prepare_enable(codec_clk);
-			tabla_mclk_enable(codec, 1, dapm);
-		} else {
-			pr_err("%s: Error setting Tabla MCLK\n", __func__);
-			clk_users--;
-			return -EINVAL;
+		if (clk_users == 1) {
+			if (codec_clk) {
+				clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
+				clk_prepare_enable(codec_clk);
+				tabla_mclk_enable(codec, 1, dapm);
+			} else {
+				pr_err("%s: Error setting Tabla MCLK\n",
+				       __func__);
+				clk_users--;
+				r = -EINVAL;
+			}
 		}
 	} else {
-		pr_debug("%s: clk_users = %d\n", __func__, clk_users);
-		if (clk_users == 0)
-			return 0;
-		clk_users--;
-		if (!clk_users) {
-			pr_debug("%s: disabling MCLK. clk_users = %d\n",
+		if (clk_users > 0) {
+			clk_users--;
+			pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+			if (clk_users == 0) {
+				pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
-			tabla_mclk_enable(codec, 0, dapm);
-			clk_disable_unprepare(codec_clk);
+				tabla_mclk_enable(codec, 0, dapm);
+				clk_disable_unprepare(codec_clk);
+			}
+		} else {
+			pr_err("%s: Error releasing Tabla MCLK\n", __func__);
+			r = -EINVAL;
 		}
 	}
-	return 0;
+	mutex_unlock(&cdc_mclk_mutex);
+	return r;
 }
 
 static int msm_mclk_event(struct snd_soc_dapm_widget *w,
@@ -434,6 +469,7 @@
 
 	SND_SOC_DAPM_SPK("Ext Spk Top Pos", msm_spkramp_event),
 	SND_SOC_DAPM_SPK("Ext Spk Top Neg", msm_spkramp_event),
+	SND_SOC_DAPM_SPK("Ext Spk Top", msm_spkramp_event),
 
 	/************ Analog MICs ************/
 	/**
@@ -468,6 +504,7 @@
 
 	{"Ext Spk Top Pos", NULL, "LINEOUT2"},
 	{"Ext Spk Top Neg", NULL, "LINEOUT4"},
+	{"Ext Spk Top", NULL, "LINEOUT5"},
 
 	/************   Analog MIC Paths  ************/
 
@@ -814,7 +851,7 @@
 	int ret = 0;
 	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
 	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
-	unsigned int user_set_tx_ch = 0;
+	unsigned int num_tx_ch = 0;
 
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -844,19 +881,17 @@
 	} else {
 
 		if (codec_dai->id  == 2)
-			user_set_tx_ch =  msm_slim_0_tx_ch;
-		else if (codec_dai->id  == 4)
-			user_set_tx_ch =  params_channels(params);
+			num_tx_ch =  msm_slim_0_tx_ch;
 		else if (codec_dai->id == 5) {
 			/* DAI 5 is used for external EC reference from codec.
 			 * Since Rx is fed as reference for EC, the config of
 			 * this DAI is based on that of the Rx path.
 			 */
-			user_set_tx_ch =  msm_slim_0_rx_ch;
+			num_tx_ch =  msm_slim_0_rx_ch;
 		}
 
 		pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
-			codec_dai->name, codec_dai->id, user_set_tx_ch);
+			codec_dai->name, codec_dai->id, num_tx_ch);
 
 		ret = snd_soc_dai_get_channel_map(codec_dai,
 				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
@@ -866,13 +901,13 @@
 		}
 
 		ret = snd_soc_dai_set_channel_map(cpu_dai,
-				user_set_tx_ch, tx_ch, 0 , 0);
+				num_tx_ch, tx_ch, 0 , 0);
 		if (ret < 0) {
 			pr_err("%s: failed to set cpu chan map\n", __func__);
 			goto end;
 		}
 		ret = snd_soc_dai_set_channel_map(codec_dai,
-				user_set_tx_ch, tx_ch, 0, 0);
+				num_tx_ch, tx_ch, 0, 0);
 		if (ret < 0) {
 			pr_err("%s: failed to set codec channel map\n",
 								__func__);
@@ -892,6 +927,77 @@
 	return 0;
 }
 
+static int msm_slimbus_2_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+	unsigned int num_tx_ch = 0;
+	unsigned int num_rx_ch = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+		num_rx_ch =  params_channels(params);
+
+		pr_debug("%s: %s rx_dai_id = %d  num_ch = %d\n", __func__,
+			codec_dai->name, codec_dai->id, num_rx_ch);
+
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+				num_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+				num_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+	} else {
+
+		num_tx_ch =  params_channels(params);
+
+		pr_debug("%s: %s  tx_dai_id = %d  num_ch = %d\n", __func__,
+			codec_dai->name, codec_dai->id, num_tx_ch);
+
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+				num_tx_ch, tx_ch, 0 , 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai,
+				num_tx_ch, tx_ch, 0, 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+	}
+end:
+	return ret;
+}
+
 static int msm_slimbus_1_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
@@ -935,6 +1041,7 @@
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret = 0;
 	unsigned int rx_ch[2] = {SLIM_3_RX_1, SLIM_3_RX_2};
+	unsigned int tx_ch[2] = {SLIM_3_TX_1, SLIM_3_TX_2};
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		pr_debug("%s: slim_3_rx_ch %d, sch %d %d\n",
@@ -950,7 +1057,16 @@
 			goto end;
 		}
 	} else {
-		pr_err("%s: SLIMBUS_3_TX not defined for this DAI\n", __func__);
+		pr_debug("%s: MDM RX -> SLIMBUS_3_TX -> APQ HDMI ch: %d, %d\n",
+			__func__, tx_ch[0], tx_ch[1]);
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 2, tx_ch, 0, 0);
+		if (ret < 0) {
+			pr_err("%s: Erorr %d setting SLIM_3 TX channel map\n",
+				__func__, ret);
+
+			goto end;
+		}
 	}
 
 end:
@@ -1147,6 +1263,22 @@
 	return 0;
 }
 
+static int msm_slim_3_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = 2;
+
+	return 0;
+}
+
 static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_hw_params *params)
 {
@@ -1263,8 +1395,12 @@
 }
 static int msm_startup(struct snd_pcm_substream *substream)
 {
-	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
-		 substream->name, substream->stream);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	pr_debug("%s(): dai_link_str_name = %s cpu_dai = %s codec_dai = %s\n",
+		__func__, rtd->dai_link->stream_name,
+		rtd->dai_link->cpu_dai_name,
+		 rtd->dai_link->codec_dai_name);
 	return 0;
 }
 
@@ -1290,8 +1426,11 @@
 
 static void msm_shutdown(struct snd_pcm_substream *substream)
 {
-	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
-		 substream->name, substream->stream);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	pr_debug("%s(): dai_link_str_name = %s cpu_dai = %s codec_dai = %s\n",
+		__func__, rtd->dai_link->stream_name,
+		rtd->dai_link->cpu_dai_name, rtd->dai_link->codec_dai_name);
 }
 
 static struct snd_soc_ops msm_be_ops = {
@@ -1323,6 +1462,13 @@
 	.shutdown = msm_shutdown,
 };
 
+static struct snd_soc_ops msm_slimbus_2_be_ops = {
+	.startup = msm_startup,
+	.hw_params = msm_slimbus_2_hw_params,
+	.shutdown = msm_shutdown,
+};
+
+
 /* Digital audio interface glue - connects codec <---> CPU */
 static struct snd_soc_dai_link msm_dai[] = {
 	/* FrontEnd DAI Links */
@@ -1679,18 +1825,30 @@
 		.be_hw_params_fixup =  msm_btsco_be_hw_params_fixup,
 		.ops = &msm_slimbus_1_be_ops,
 	},
+	/* Ultrasound TX Back End DAI Link */
 	{
-		.name = "SLIMBUS_2 Hostless",
-		.stream_name = "SLIMBUS_2 Hostless",
+		.name = "SLIMBUS_2 Hostless Capture",
+		.stream_name = "SLIMBUS_2 Hostless Capture",
 		.cpu_dai_name = "msm-dai-q6.16389",
 		.platform_name = "msm-pcm-hostless",
 		.codec_name = "tabla_codec",
 		.codec_dai_name = "tabla_tx2",
 		.ignore_suspend = 1,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ops = &msm_be_ops,
+		.ops = &msm_slimbus_2_be_ops,
 	},
-
+	/* Ultrasound RX Back End DAI Link */
+	{
+		.name = "SLIMBUS_2 Hostless Playback",
+		.stream_name = "SLIMBUS_2 Hostless Playback",
+		.cpu_dai_name = "msm-dai-q6.16388",
+		.platform_name = "msm-pcm-hostless",
+		.codec_name = "tabla_codec",
+		.codec_dai_name = "tabla_rx3",
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ops = &msm_slimbus_2_be_ops,
+	},
 	/* Incall Music Back End DAI Link */
 	{
 		.name = LPASS_BE_SLIMBUS_4_RX,
@@ -1748,6 +1906,18 @@
 		.ops = &msm_slimbus_3_be_ops,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
 	},
+	{
+		.name = LPASS_BE_SLIMBUS_3_TX,
+		.stream_name = "Slimbus3 Capture",
+		.cpu_dai_name = "msm-dai-q6.16391",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+		.be_hw_params_fixup = msm_slim_3_tx_be_hw_params_fixup,
+		.ops = &msm_slimbus_3_be_ops,
+	},
 };
 
 struct snd_soc_card snd_soc_card_msm = {
@@ -1847,6 +2017,7 @@
 	} else
 		msm_headset_gpios_configured = 1;
 
+	mutex_init(&cdc_mclk_mutex);
 	return ret;
 
 }
@@ -1863,6 +2034,7 @@
 	if (mbhc_cfg.gpio)
 		gpio_free(mbhc_cfg.gpio);
 	kfree(mbhc_cfg.calibration);
+	mutex_destroy(&cdc_mclk_mutex);
 }
 module_exit(msm_audio_exit);
 
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index 41a9c48..363635f 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -47,10 +47,15 @@
 #define TOP_SPK_AMP_POS		0x4
 #define TOP_SPK_AMP_NEG		0x8
 
-#define GPIO_AUX_PCM_DOUT 63
-#define GPIO_AUX_PCM_DIN 64
-#define GPIO_AUX_PCM_SYNC 65
-#define GPIO_AUX_PCM_CLK 66
+#define GPIO_AUX_PCM_DOUT 23
+#define GPIO_AUX_PCM_DIN 22
+#define GPIO_AUX_PCM_SYNC 21
+#define GPIO_AUX_PCM_CLK 20
+
+#define GPIO_SEC_AUX_PCM_DOUT 28
+#define GPIO_SEC_AUX_PCM_DIN 27
+#define GPIO_SEC_AUX_PCM_SYNC 26
+#define GPIO_SEC_AUX_PCM_CLK 25
 
 #define TABLA_EXT_CLK_RATE 12288000
 
@@ -144,6 +149,9 @@
 #define LPA_IF_REG_BASE (LPA_IF_BASE + 0x00000000)
 #define LPASS_SIF_MUX_ADDR  (SIF_MUX_REG_BASE + 0x00004000)
 #define LPAIF_SPARE_ADDR (LPA_IF_REG_BASE + 0x00000070)
+#define SEC_PCM_PORT_SLC_ADDR 0x00802074
+/* bits 2:0 should be updated with 100 to select SDC2 */
+#define SEC_PCM_PORT_SLC_VALUE 0x4
 /* SIF & SPARE MUX Values */
 #define MSM_SIF_FUNC_PCM              0
 #define MSM_SIF_FUNC_I2S_MIC        1
@@ -168,6 +176,7 @@
 static int msm9615_i2s_rx_ch = 1;
 static int msm9615_i2s_tx_ch = 1;
 static int msm9615_i2s_spk_control;
+
 /* SIF mux bit mask & shift */
 #define LPASS_SIF_MUX_CTL_PRI_MUX_SEL_BMSK                   0x30000
 #define LPASS_SIF_MUX_CTL_PRI_MUX_SEL_SHFT                      0x10
@@ -182,6 +191,8 @@
 static u32 spare_shadow;
 static u32 sif_shadow;
 
+static atomic_t msm9615_auxpcm_ref;
+static atomic_t msm9615_sec_auxpcm_ref;
 
 struct msm_i2s_mux_ctl {
 	const u8 sifconfig;
@@ -240,6 +251,10 @@
 
 static u32 top_spk_pamp_gpio  = PM8018_GPIO_PM_TO_SYS(3);
 static u32 bottom_spk_pamp_gpio = PM8018_GPIO_PM_TO_SYS(5);
+
+void *sif_virt_addr;
+void *secpcm_portslc_virt_addr;
+
 static int mdm9615_spk_control;
 static int mdm9615_ext_bottom_spk_pamp;
 static int mdm9615_ext_top_spk_pamp;
@@ -1601,6 +1616,63 @@
 	return 0;
 }
 
+static int mdm9615_sec_aux_pcm_get_gpios(void)
+{
+	int ret = 0;
+
+	pr_debug("%s\n", __func__);
+
+	ret = gpio_request(GPIO_SEC_AUX_PCM_DOUT, "SEC_AUX PCM DOUT");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): SEC_AUX PCM DOUT",
+		       __func__, GPIO_SEC_AUX_PCM_DOUT);
+		goto fail_dout;
+	}
+
+	ret = gpio_request(GPIO_SEC_AUX_PCM_DIN, "SEC_AUX PCM DIN");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): SEC_AUX PCM DIN",
+		       __func__, GPIO_SEC_AUX_PCM_DIN);
+		goto fail_din;
+	}
+
+	ret = gpio_request(GPIO_SEC_AUX_PCM_SYNC, "SEC_AUX PCM SYNC");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): SEC_AUX PCM SYNC",
+		       __func__, GPIO_SEC_AUX_PCM_SYNC);
+		goto fail_sync;
+	}
+
+	ret = gpio_request(GPIO_SEC_AUX_PCM_CLK, "SEC_AUX PCM CLK");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): SEC_AUX PCM CLK",
+		       __func__, GPIO_SEC_AUX_PCM_CLK);
+		goto fail_clk;
+	}
+
+	return 0;
+
+fail_clk:
+	gpio_free(GPIO_SEC_AUX_PCM_SYNC);
+fail_sync:
+	gpio_free(GPIO_SEC_AUX_PCM_DIN);
+fail_din:
+	gpio_free(GPIO_SEC_AUX_PCM_DOUT);
+fail_dout:
+
+	return ret;
+}
+
+static int mdm9615_sec_aux_pcm_free_gpios(void)
+{
+	gpio_free(GPIO_SEC_AUX_PCM_DIN);
+	gpio_free(GPIO_SEC_AUX_PCM_DOUT);
+	gpio_free(GPIO_SEC_AUX_PCM_SYNC);
+	gpio_free(GPIO_SEC_AUX_PCM_CLK);
+
+	return 0;
+}
+
 static int mdm9615_startup(struct snd_pcm_substream *substream)
 {
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
@@ -1608,15 +1680,37 @@
 	return 0;
 }
 
+void msm9615_config_sif_mux(u8 value)
+{
+	u32 sif_shadow  = 0x00000;
+
+	sif_shadow = (sif_shadow & LPASS_SIF_MUX_CTL_SEC_MUX_SEL_BMSK) |
+		     (value << LPASS_SIF_MUX_CTL_SEC_MUX_SEL_SHFT);
+	iowrite32(sif_shadow, sif_virt_addr);
+	/* Dont read SIF register. Device crashes. */
+	pr_debug("%s() SIF Reg = 0x%x\n", __func__, sif_shadow);
+}
+
+void msm9615_config_port_select(void)
+{
+	pr_debug("%s() port select defualt = 0x%x\n",
+		 __func__, ioread32(secpcm_portslc_virt_addr));
+	iowrite32(SEC_PCM_PORT_SLC_VALUE, secpcm_portslc_virt_addr);
+	pr_debug("%s() port select after updating = 0x%x\n",
+		 __func__, ioread32(secpcm_portslc_virt_addr));
+}
+
 static int mdm9615_auxpcm_startup(struct snd_pcm_substream *substream)
 {
 	int ret = 0;
 
 	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	ret = mdm9615_aux_pcm_get_gpios();
-	if (ret < 0) {
-		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
-		return -EINVAL;
+	if (atomic_inc_return(&msm9615_auxpcm_ref) == 1) {
+		ret = mdm9615_aux_pcm_get_gpios();
+		if (ret < 0) {
+			pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+			return -EINVAL;
+		}
 	}
 	return 0;
 }
@@ -1625,7 +1719,33 @@
 {
 
 	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	mdm9615_aux_pcm_free_gpios();
+	if (atomic_dec_return(&msm9615_auxpcm_ref) == 0)
+		mdm9615_aux_pcm_free_gpios();
+}
+
+static int mdm9615_sec_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+
+	pr_debug("%s(): substream = %s\n", __func__, substream->name);
+	if (atomic_inc_return(&msm9615_sec_auxpcm_ref) == 1) {
+		ret = mdm9615_sec_aux_pcm_get_gpios();
+		if (ret < 0) {
+			pr_err("%s: SEC Aux PCM GPIO request failed\n",
+			       __func__);
+			return -EINVAL;
+		}
+		msm9615_config_sif_mux(MSM_SIF_FUNC_PCM);
+		msm9615_config_port_select();
+	}
+	return 0;
+}
+
+static void mdm9615_sec_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s\n", __func__, substream->name);
+	if (atomic_dec_return(&msm9615_sec_auxpcm_ref) == 0)
+		mdm9615_sec_aux_pcm_free_gpios();
 }
 
 static void mdm9615_shutdown(struct snd_pcm_substream *substream)
@@ -1645,6 +1765,12 @@
 	.shutdown = mdm9615_auxpcm_shutdown,
 };
 
+static struct snd_soc_ops mdm9615_sec_auxpcm_be_ops = {
+	.startup = mdm9615_sec_auxpcm_startup,
+	.shutdown = mdm9615_sec_auxpcm_shutdown,
+};
+
+
 /* Digital audio interface glue - connects codec <---> CPU */
 static struct snd_soc_dai_link mdm9615_dai_common[] = {
 	/* FrontEnd DAI Links */
@@ -1823,8 +1949,34 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = mdm9615_auxpcm_be_params_fixup,
+		.ops = &mdm9615_auxpcm_be_ops,
 	},
 
+	/* SECONDARY AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_SEC_AUXPCM_RX,
+		.stream_name = "SEC AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6.12",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+		.be_hw_params_fixup = mdm9615_auxpcm_be_params_fixup,
+		.ops = &mdm9615_sec_auxpcm_be_ops,
+	},
+	{
+		.name = LPASS_BE_SEC_AUXPCM_TX,
+		.stream_name = "SEC AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6.13",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+		.be_hw_params_fixup = mdm9615_auxpcm_be_params_fixup,
+		.ops = &mdm9615_sec_auxpcm_be_ops,
+	},
 };
 
 static struct snd_soc_dai_link mdm9615_dai_i2s_tabla[] = {
@@ -2000,7 +2152,12 @@
 		snd_soc_card_mdm9615.dai_link = mdm9615_i2s_dai;
 		snd_soc_card_mdm9615.num_links =
 				ARRAY_SIZE(mdm9615_i2s_dai);
+	} else{
+		snd_soc_card_mdm9615.dai_link = mdm9615_dai_common;
+		snd_soc_card_mdm9615.num_links =
+				ARRAY_SIZE(mdm9615_dai_common);
 	}
+
 	platform_set_drvdata(mdm9615_snd_device, &snd_soc_card_mdm9615);
 	ret = platform_device_add(mdm9615_snd_device);
 	if (ret) {
@@ -2014,11 +2171,14 @@
 	} else
 		mdm9615_headset_gpios_configured = 1;
 
+	atomic_set(&msm9615_auxpcm_ref, 0);
+	atomic_set(&msm9615_sec_auxpcm_ref, 0);
 	msm9x15_i2s_ctl.sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
 	msm9x15_i2s_ctl.spare_virt_addr = ioremap(LPAIF_SPARE_ADDR, 4);
+	sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
+	secpcm_portslc_virt_addr = ioremap(SEC_PCM_PORT_SLC_ADDR, 4);
 
 	return ret;
-
 }
 module_init(mdm9615_audio_init);
 
@@ -2033,6 +2193,8 @@
 	kfree(mbhc_cfg.calibration);
 	iounmap(msm9x15_i2s_ctl.sif_virt_addr);
 	iounmap(msm9x15_i2s_ctl.spare_virt_addr);
+	iounmap(sif_virt_addr);
+	iounmap(secpcm_portslc_virt_addr);
 
 }
 module_exit(mdm9615_audio_exit);
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 0995300..9395e8f 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1110,10 +1110,10 @@
 		.be_id = MSM_FRONTEND_DAI_VOIP,
 	},
 	{
-		.name = "MSM8960 LPA",
-		.stream_name = "LPA",
+		.name = "MSM8960 Media3",
+		.stream_name = "MultiMedia3",
 		.cpu_dai_name	= "MultiMedia3",
-		.platform_name  = "msm-pcm-lpa",
+		.platform_name  = "msm-pcm-dsp",
 		.dynamic = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
 		.codec_dai_name = "snd-soc-dummy-dai",
@@ -1173,8 +1173,8 @@
 		.codec_name = "snd-soc-dummy",
 	},
 	{
-		.name = "MSM8960 Compr",
-		.stream_name = "COMPR",
+		.name = "MSM8960 Compr1",
+		.stream_name = "COMPR1",
 		.cpu_dai_name   = "MultiMedia4",
 		.platform_name  = "msm-compr-dsp",
 		.dynamic = 1,
@@ -1239,6 +1239,62 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 	},
+	{
+		.name = "MSM8960 Media5",
+		.stream_name = "MultiMedia5",
+		.cpu_dai_name	= "MultiMedia5",
+		.platform_name  = "msm-multi-ch-pcm-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE,
+					SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5
+	},
+	{
+		.name = "MSM8960 Media6",
+		.stream_name = "MultiMedia6",
+		.cpu_dai_name	= "MultiMedia6",
+		.platform_name  = "msm-multi-ch-pcm-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE,
+					SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA6
+	},
+	{
+		.name = "MSM8960 Compr2",
+		.stream_name = "COMPR2",
+		.cpu_dai_name   = "MultiMedia7",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE,
+					SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+	},
+	{
+		.name = "MSM8960 Compr3",
+		.stream_name = "COMPR3",
+		.cpu_dai_name   = "MultiMedia8",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE,
+					SND_SOC_DPCM_TRIGGER_BESPOKE},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* this dailink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index c8d3a71c..6e190b2 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -55,7 +55,7 @@
 					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 2,
+			.channels_max = 6,
 			.rate_min =     8000,
 			.rate_max =	48000,
 		},
@@ -157,7 +157,7 @@
 					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 2,
+			.channels_max = 6,
 			.rate_min =	8000,
 			.rate_max = 48000,
 		},
@@ -172,13 +172,69 @@
 					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 2,
+			.channels_max = 6,
 			.rate_min =	8000,
 			.rate_max = 48000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia4",
 	},
+	{
+		.playback = {
+			.stream_name = "MultiMedia5 Playback",
+			.rates = (SNDRV_PCM_RATE_8000_48000 |
+					SNDRV_PCM_RATE_KNOT),
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 6,
+			.rate_min =	8000,
+			.rate_max = 48000,
+		},
+		.ops = &msm_fe_Multimedia_dai_ops,
+		.name = "MultiMedia5",
+	},
+	{
+		.playback = {
+			.stream_name = "MultiMedia6 Playback",
+			.rates = (SNDRV_PCM_RATE_8000_48000 |
+					SNDRV_PCM_RATE_KNOT),
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 6,
+			.rate_min =	8000,
+			.rate_max = 48000,
+		},
+		.ops = &msm_fe_Multimedia_dai_ops,
+		.name = "MultiMedia6",
+	},
+	{
+		.playback = {
+			.stream_name = "MultiMedia7 Playback",
+			.rates = (SNDRV_PCM_RATE_8000_48000 |
+					SNDRV_PCM_RATE_KNOT),
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 6,
+			.rate_min =	8000,
+			.rate_max = 48000,
+		},
+		.ops = &msm_fe_Multimedia_dai_ops,
+		.name = "MultiMedia7",
+	},
+	{
+		.playback = {
+			.stream_name = "MultiMedia8 Playback",
+			.rates = (SNDRV_PCM_RATE_8000_48000 |
+					SNDRV_PCM_RATE_KNOT),
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 6,
+			.rate_min =	8000,
+			.rate_max = 48000,
+		},
+		.ops = &msm_fe_Multimedia_dai_ops,
+		.name = "MultiMedia8",
+	},
 	/* FE DAIs created for hostless operation purpose */
 	{
 		.playback = {
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 284320d..b3e5120 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -48,9 +48,11 @@
 };
 
 static struct clk *pcm_clk;
+static struct clk *sec_pcm_clk;
 static DEFINE_MUTEX(aux_pcm_mutex);
 static int aux_pcm_count;
 static struct msm_dai_auxpcm_pdata *auxpcm_plat_data;
+static struct msm_dai_auxpcm_pdata *sec_auxpcm_plat_data;
 
 static int msm_dai_q6_mi2s_format_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
@@ -558,6 +560,48 @@
 	return 0;
 }
 
+static int msm_dai_q6_sec_auxpcm_hw_params(
+				struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	struct msm_dai_auxpcm_pdata *auxpcm_pdata =
+			(struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
+
+	pr_debug("%s\n", __func__);
+	if (params_channels(params) != 1) {
+		dev_err(dai->dev, "SEC AUX PCM supports only mono stream\n");
+		return -EINVAL;
+	}
+	dai_data->channels = params_channels(params);
+
+	dai_data->rate = params_rate(params);
+	switch (dai_data->rate) {
+	case 8000:
+		dai_data->port_config.pcm.mode = auxpcm_pdata->mode_8k.mode;
+		dai_data->port_config.pcm.sync = auxpcm_pdata->mode_8k.sync;
+		dai_data->port_config.pcm.frame = auxpcm_pdata->mode_8k.frame;
+		dai_data->port_config.pcm.quant = auxpcm_pdata->mode_8k.quant;
+		dai_data->port_config.pcm.slot = auxpcm_pdata->mode_8k.slot;
+		dai_data->port_config.pcm.data = auxpcm_pdata->mode_8k.data;
+		break;
+	case 16000:
+		dai_data->port_config.pcm.mode = auxpcm_pdata->mode_16k.mode;
+		dai_data->port_config.pcm.sync = auxpcm_pdata->mode_16k.sync;
+		dai_data->port_config.pcm.frame = auxpcm_pdata->mode_16k.frame;
+		dai_data->port_config.pcm.quant = auxpcm_pdata->mode_16k.quant;
+		dai_data->port_config.pcm.slot = auxpcm_pdata->mode_16k.slot;
+		dai_data->port_config.pcm.data = auxpcm_pdata->mode_16k.data;
+		break;
+	default:
+		dev_err(dai->dev, "AUX PCM supports only 8kHz and 16kHz sampling rate\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int msm_dai_q6_afe_rtproxy_hw_params(struct snd_pcm_hw_params *params,
 				struct snd_soc_dai *dai)
 {
@@ -606,6 +650,7 @@
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_RX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_3_TX:
 	case SLIMBUS_4_RX:
 	case SLIMBUS_4_TX:
 		rc = msm_dai_q6_slim_bus_hw_params(params, dai,
@@ -682,6 +727,52 @@
 	mutex_unlock(&aux_pcm_mutex);
 }
 
+static void msm_dai_q6_sec_auxpcm_shutdown(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	int rc = 0;
+
+	pr_debug("%s\n", __func__);
+	mutex_lock(&aux_pcm_mutex);
+
+	if (aux_pcm_count == 0) {
+		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just"
+				" return\n", __func__, dai->id);
+		mutex_unlock(&aux_pcm_mutex);
+		return;
+	}
+
+	aux_pcm_count--;
+
+	if (aux_pcm_count > 0) {
+		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
+			__func__, dai->id, aux_pcm_count);
+		mutex_unlock(&aux_pcm_mutex);
+		return;
+	} else if (aux_pcm_count < 0) {
+		dev_err(dai->dev, "%s(): ERROR: dai->id %d"
+			" aux_pcm_count = %d < 0\n",
+			__func__, dai->id, aux_pcm_count);
+		aux_pcm_count = 0;
+		mutex_unlock(&aux_pcm_mutex);
+		return;
+	}
+
+	pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
+			dai->id, aux_pcm_count);
+
+	clk_disable_unprepare(sec_pcm_clk);
+	rc = afe_close(SECONDARY_PCM_RX); /* can block */
+	if (IS_ERR_VALUE(rc))
+		dev_err(dai->dev, "fail to close PCM_RX  AFE port\n");
+
+	rc = afe_close(SECONDARY_PCM_TX);
+	if (IS_ERR_VALUE(rc))
+		dev_err(dai->dev, "fail to close AUX PCM TX port\n");
+
+	mutex_unlock(&aux_pcm_mutex);
+}
+
 static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
 				struct snd_soc_dai *dai)
 {
@@ -768,7 +859,7 @@
 	if (dai_data->rate == 8000) {
 		pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
 	} else if (dai_data->rate == 16000) {
-		pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
+		pcm_clk_rate = auxpcm_pdata->mode_16k.pcm_clk_rate;
 	} else {
 		dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
 			  dai_data->rate);
@@ -789,6 +880,88 @@
 	return rc;
 }
 
+static int msm_dai_q6_sec_auxpcm_prepare(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	int rc = 0;
+	struct msm_dai_auxpcm_pdata *auxpcm_pdata =
+			(struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
+	unsigned long pcm_clk_rate;
+
+	pr_info("%s\n", __func__);
+
+	mutex_lock(&aux_pcm_mutex);
+
+	if (aux_pcm_count == 2) {
+		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just"
+			" return.\n", __func__, dai->id);
+		mutex_unlock(&aux_pcm_mutex);
+		return 0;
+	} else if (aux_pcm_count > 2) {
+		dev_err(dai->dev, "%s(): ERROR: dai->id %d"
+			" aux_pcm_count = %d > 2\n",
+			__func__, dai->id, aux_pcm_count);
+		mutex_unlock(&aux_pcm_mutex);
+		return 0;
+	}
+
+	aux_pcm_count++;
+	if (aux_pcm_count == 2)  {
+		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after "
+			" increment\n", __func__, dai->id, aux_pcm_count);
+		mutex_unlock(&aux_pcm_mutex);
+		return 0;
+	}
+
+	pr_debug("%s:dai->id:%d  aux_pcm_count = %d. opening afe\n",
+			__func__, dai->id, aux_pcm_count);
+
+	rc = afe_q6_interface_prepare();
+	if (IS_ERR_VALUE(rc))
+		dev_err(dai->dev, "fail to open AFE APR\n");
+
+	/*
+	 * For AUX PCM Interface the below sequence of clk
+	 * settings and afe_open is a strict requirement.
+	 *
+	 * Also using afe_open instead of afe_port_start_nowait
+	 * to make sure the port is open before deasserting the
+	 * clock line. This is required because pcm register is
+	 * not written before clock deassert. Hence the hw does
+	 * not get updated with new setting if the below clock
+	 * assert/deasset and afe_open sequence is not followed.
+	 */
+
+	clk_reset(sec_pcm_clk, CLK_RESET_ASSERT);
+
+	afe_open(SECONDARY_PCM_RX, &dai_data->port_config, dai_data->rate);
+
+	afe_open(SECONDARY_PCM_TX, &dai_data->port_config, dai_data->rate);
+	if (dai_data->rate == 8000) {
+		pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
+	} else if (dai_data->rate == 16000) {
+		pcm_clk_rate = auxpcm_pdata->mode_16k.pcm_clk_rate;
+	} else {
+		dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
+			  dai_data->rate);
+		return -EINVAL;
+	}
+
+	rc = clk_set_rate(sec_pcm_clk, pcm_clk_rate);
+	if (rc < 0) {
+		pr_err("%s: clk_set_rate failed\n", __func__);
+		return rc;
+	}
+
+	clk_prepare_enable(sec_pcm_clk);
+	clk_reset(sec_pcm_clk, CLK_RESET_DEASSERT);
+
+	mutex_unlock(&aux_pcm_mutex);
+
+	return rc;
+}
+
 static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
@@ -940,6 +1113,55 @@
 	return rc;
 }
 
+static int msm_dai_q6_dai_sec_auxpcm_probe(struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_dai_data *dai_data;
+	int rc = 0;
+	struct msm_dai_auxpcm_pdata *auxpcm_pdata =
+			(struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
+
+	pr_info("%s\n", __func__);
+
+	mutex_lock(&aux_pcm_mutex);
+
+	if (!sec_auxpcm_plat_data)
+		sec_auxpcm_plat_data = auxpcm_pdata;
+	else if (sec_auxpcm_plat_data != auxpcm_pdata) {
+		dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
+				" same platform data sec_auxpcm_plat_data\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * The clk name for AUX PCM operation is passed as platform
+	 * data to the cpu driver, since cpu drive is unaware of any
+	 * boarc specific configuration.
+	 */
+	if (!sec_pcm_clk) {
+
+		sec_pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
+		if (IS_ERR(sec_pcm_clk)) {
+			pr_err("%s: could not get sec_pcm_clk\n", __func__);
+			sec_pcm_clk = NULL;
+			return -ENODEV;
+		}
+	}
+
+	mutex_unlock(&aux_pcm_mutex);
+
+	dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
+
+	if (!dai_data) {
+		dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
+		dai->id);
+		rc = -ENOMEM;
+	} else
+		dev_set_drvdata(dai->dev, dai_data);
+
+	pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
+	return rc;
+}
+
 static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
 {
 	struct msm_dai_q6_dai_data *dai_data;
@@ -989,6 +1211,56 @@
 	return 0;
 }
 
+static int msm_dai_q6_dai_sec_auxpcm_remove(struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_dai_data *dai_data;
+	int rc;
+
+	pr_debug("%s\n", __func__);
+	dai_data = dev_get_drvdata(dai->dev);
+
+	mutex_lock(&aux_pcm_mutex);
+
+	if (aux_pcm_count == 0) {
+		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
+				" up and return\n", __func__, dai->id);
+		goto done;
+	}
+
+	aux_pcm_count--;
+
+	if (aux_pcm_count > 0) {
+		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
+			__func__, dai->id, aux_pcm_count);
+		goto done;
+	} else if (aux_pcm_count < 0) {
+		dev_err(dai->dev, "%s(): ERROR: dai->id %d"
+			" aux_pcm_count = %d < 0\n",
+			__func__, dai->id, aux_pcm_count);
+		goto done;
+	}
+
+	dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
+			"closing afe\n",
+		__func__, dai->id, aux_pcm_count);
+
+	rc = afe_close(SECONDARY_PCM_RX); /* can block */
+	if (IS_ERR_VALUE(rc))
+		dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
+
+	rc = afe_close(SECONDARY_PCM_TX);
+	if (IS_ERR_VALUE(rc))
+		dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
+
+done:
+	kfree(dai_data);
+	snd_soc_unregister_dai(dai->dev);
+
+	mutex_unlock(&aux_pcm_mutex);
+
+	return 0;
+}
+
 static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
 {
 	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
@@ -1164,6 +1436,7 @@
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_3_TX:
 	case SLIMBUS_4_TX:
 		/* channel number to be between 128 and 255. For RX port
 		 * use channel numbers from 138 to 144, for TX port
@@ -1217,6 +1490,13 @@
 	.shutdown	= msm_dai_q6_auxpcm_shutdown,
 };
 
+static struct snd_soc_dai_ops msm_dai_q6_sec_auxpcm_ops = {
+	.prepare	= msm_dai_q6_sec_auxpcm_prepare,
+	.trigger	= msm_dai_q6_auxpcm_trigger,
+	.hw_params	= msm_dai_q6_sec_auxpcm_hw_params,
+	.shutdown	= msm_dai_q6_sec_auxpcm_shutdown,
+};
+
 static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
@@ -1352,7 +1632,7 @@
 };
 
 static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
-	.playback = {
+	.capture = {
 		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		.channels_min = 1,
@@ -1381,7 +1661,7 @@
 };
 
 static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
-	.playback = {
+	.capture = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
 		SNDRV_PCM_RATE_16000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
@@ -1423,6 +1703,34 @@
 	.remove = msm_dai_q6_dai_auxpcm_remove,
 };
 
+static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_rx_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 1,
+		.rate_max = 16000,
+		.rate_min = 8000,
+	},
+	.ops = &msm_dai_q6_sec_auxpcm_ops,
+	.probe = msm_dai_q6_dai_sec_auxpcm_probe,
+	.remove = msm_dai_q6_dai_sec_auxpcm_remove,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_tx_dai = {
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 1,
+		.rate_max = 16000,
+		.rate_min = 8000,
+	},
+	.ops = &msm_dai_q6_sec_auxpcm_ops,
+	.probe = msm_dai_q6_dai_sec_auxpcm_probe,
+	.remove = msm_dai_q6_dai_sec_auxpcm_remove,
+};
+
 /* Channel min and max are initialized base on platform data */
 static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai = {
 	.playback = {
@@ -1543,6 +1851,14 @@
 				&msm_dai_q6_aux_pcm_tx_dai);
 		break;
 
+	case SECONDARY_PCM_RX:
+		rc = snd_soc_register_dai(&pdev->dev,
+				&msm_dai_q6_sec_aux_pcm_rx_dai);
+		break;
+	case SECONDARY_PCM_TX:
+		rc = snd_soc_register_dai(&pdev->dev,
+				&msm_dai_q6_sec_aux_pcm_tx_dai);
+		break;
 	case SLIMBUS_0_RX:
 	case SLIMBUS_4_RX:
 		rc = snd_soc_register_dai(&pdev->dev,
@@ -1550,6 +1866,7 @@
 		break;
 	case SLIMBUS_0_TX:
 	case SLIMBUS_4_TX:
+	case SLIMBUS_3_TX:
 		rc = snd_soc_register_dai(&pdev->dev,
 				&msm_dai_q6_slimbus_tx_dai);
 		break;
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index c65a7d2..3cab34f 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -109,8 +109,11 @@
 			break;
 		} else
 			atomic_set(&prtd->pending_buffer, 0);
-		if (runtime->status->hw_ptr >= runtime->control->appl_ptr)
-			break;
+		if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
+			memset((void *)buf[0].phys +
+				(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);
 
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 7a269ca..4219ab6 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -172,9 +172,12 @@
 	{ SLIMBUS_4_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_4_TX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_3_RX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_3_TX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
+	{ SECONDARY_PCM_RX, 0, 0, 0, 0, 0},
+	{ SECONDARY_PCM_TX, 0, 0, 0, 0, 0},
 };
 
 
@@ -188,6 +191,15 @@
 	{INVALID_SESSION, INVALID_SESSION},
 	/* MULTIMEDIA4 */
 	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA5 */
+	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA6 */
+	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA7*/
+	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA8 */
+	{INVALID_SESSION, INVALID_SESSION},
+
 };
 
 static uint8_t is_be_dai_extproc(int be_dai)
@@ -1027,6 +1039,18 @@
 	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
@@ -1042,6 +1066,18 @@
 	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -1057,6 +1093,18 @@
 	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = {
@@ -1072,6 +1120,18 @@
 	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
@@ -1087,6 +1147,18 @@
 	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 	/* incall music delivery mixer */
 static const struct snd_kcontrol_new incall_music_delivery_mixer_controls[] = {
@@ -1167,6 +1239,15 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
 	SOC_SINGLE_EXT("PRI_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1180,6 +1261,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_AUXPCM_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+		msm_routing_put_audio_mixer),
 	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
@@ -1302,6 +1386,18 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new sec_aux_pcm_rx_voice_mixer_controls[] = {
+	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	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),
+};
+
 static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1351,6 +1447,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX_Voice", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voice", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_volte_mixer_controls[] = {
@@ -1369,6 +1468,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
@@ -1390,6 +1492,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX_Voip", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voip", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
@@ -1408,6 +1513,9 @@
 	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("SLIM_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX,
+	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+	msm_routing_put_voice_stub_mixer),
 };
 
 static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
@@ -1465,6 +1573,9 @@
 	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("SLIM_3_TX", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_BACKEND_DAI_SLIMBUS_3_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_port_mixer_controls[] = {
@@ -1753,6 +1864,10 @@
 	SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
@@ -1817,6 +1932,10 @@
 
 	SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("SEC_AUX_PCM_RX", "SEC AUX PCM Playback",
+			     0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SEC_AUX_PCM_TX", "SEC AUX PCM Capture",
+			    0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("VOICE_STUB_UL", "VOICE_STUB Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("STUB_RX", "Stub Playback", 0, 0, 0, 0),
@@ -1825,6 +1944,7 @@
 	SND_SOC_DAPM_AIF_IN("SLIMBUS_1_TX", "Slimbus1 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("STUB_1_TX", "Stub1 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SLIMBUS_3_TX", "Slimbus3 Capture", 0, 0, 0, 0),
 
 	/* Switch Definitions */
 	SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
@@ -1848,6 +1968,8 @@
 	mmul2_mixer_controls, ARRAY_SIZE(mmul2_mixer_controls)),
 	SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+	sec_auxpcm_rx_mixer_controls, ARRAY_SIZE(sec_auxpcm_rx_mixer_controls)),
 	/* incall */
 	SND_SOC_DAPM_MIXER("Incall_Music Audio Mixer", SND_SOC_NOPM, 0, 0,
 			incall_music_delivery_mixer_controls,
@@ -1879,6 +2001,10 @@
 				SND_SOC_NOPM, 0, 0,
 				aux_pcm_rx_voice_mixer_controls,
 				ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX_Voice Mixer",
+			   SND_SOC_NOPM, 0, 0,
+			   sec_aux_pcm_rx_voice_mixer_controls,
+			   ARRAY_SIZE(sec_aux_pcm_rx_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("HDMI_RX_Voice Mixer",
 				SND_SOC_NOPM, 0, 0,
 				hdmi_rx_voice_mixer_controls,
@@ -1948,24 +2074,40 @@
 	{"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"PRI_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"PRI_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"PRI_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"PRI_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"PRI_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
 
 	{"SEC_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"SEC_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"SEC_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"SEC_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"SEC_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"SEC_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"SEC_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"SEC_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
 
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
 
 	{"HDMI Mixer", "MultiMedia1", "MM_DL1"},
 	{"HDMI Mixer", "MultiMedia2", "MM_DL2"},
 	{"HDMI Mixer", "MultiMedia3", "MM_DL3"},
 	{"HDMI Mixer", "MultiMedia4", "MM_DL4"},
+	{"HDMI Mixer", "MultiMedia5", "MM_DL5"},
+	{"HDMI Mixer", "MultiMedia6", "MM_DL6"},
+	{"HDMI Mixer", "MultiMedia7", "MM_DL7"},
+	{"HDMI Mixer", "MultiMedia8", "MM_DL8"},
 	{"HDMI", NULL, "HDMI Mixer"},
 
 		/* incall */
@@ -1990,6 +2132,7 @@
 	{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+	{"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
 
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -2023,6 +2166,10 @@
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX Audio Mixer"},
+
 	{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
@@ -2053,6 +2200,11 @@
 	{"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", "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", "Voip", "VOIP_DL"},
@@ -2065,12 +2217,14 @@
 	{"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
 	{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
 	{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
+	{"Voice_Tx Mixer", "SEC_AUX_PCM_TX_Voice", "SEC_AUX_PCM_TX"},
 	{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
 	{"VoLTE_Tx Mixer", "PRI_TX_VoLTE", "PRI_I2S_TX"},
 	{"VoLTE_Tx Mixer", "SLIM_0_TX_VoLTE", "SLIMBUS_0_TX"},
 	{"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
 	{"VoLTE_Tx Mixer", "AFE_PCM_TX_VoLTE", "PCM_TX"},
 	{"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"},
 	{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
 	{"Voip_Tx Mixer", "MI2S_TX_Voip", "MI2S_TX"},
@@ -2078,6 +2232,7 @@
 	{"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
 	{"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
 	{"Voip_Tx Mixer", "AUX_PCM_TX_Voip", "AUX_PCM_TX"},
+	{"Voip_Tx Mixer", "SEC_AUX_PCM_TX_Voip", "SEC_AUX_PCM_TX"},
 
 	{"VOIP_UL", NULL, "Voip_Tx Mixer"},
 	{"SLIMBUS_DL_HL", "Switch", "SLIM0_DL_HL"},
@@ -2108,6 +2263,7 @@
 	{"Voice Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"Voice Stub Tx Mixer", "STUB_1_TX_HL", "STUB_1_TX"},
 	{"Voice Stub Tx Mixer", "MI2S_TX", "MI2S_TX"},
+	{"Voice Stub Tx Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"},
 	{"VOICE_STUB_UL", NULL, "Voice Stub Tx Mixer"},
 
 	{"STUB_RX Mixer", "Voice Stub", "VOICE_STUB_DL"},
@@ -2117,6 +2273,7 @@
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 	{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 	{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
+	{"HDMI_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 
 	{"SLIMBUS_3_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 	{"SLIMBUS_3_RX", NULL, "SLIMBUS_3_RX_Voice Mixer"},
@@ -2131,6 +2288,7 @@
 
 
 	{"HDMI_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
+	{"HDMI_RX Port Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"},
 	{"HDMI", NULL, "HDMI_RX Port Mixer"},
 
 	{"SEC_I2S_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index ff073ce..d1230ad 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -26,6 +26,8 @@
 #define LPASS_BE_AFE_PCM_TX "RT_PROXY_DAI_002_TX"
 #define LPASS_BE_AUXPCM_RX "AUX_PCM_RX"
 #define LPASS_BE_AUXPCM_TX "AUX_PCM_TX"
+#define LPASS_BE_SEC_AUXPCM_RX "SEC_AUX_PCM_RX"
+#define LPASS_BE_SEC_AUXPCM_TX "SEC_AUX_PCM_TX"
 #define LPASS_BE_VOICE_PLAYBACK_TX "VOICE_PLAYBACK_TX"
 #define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX"
 #define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX"
@@ -39,6 +41,7 @@
 #define LPASS_BE_SLIMBUS_1_TX "SLIMBUS_1_TX"
 #define LPASS_BE_STUB_1_TX "STUB_1_TX"
 #define LPASS_BE_SLIMBUS_3_RX "SLIMBUS_3_RX"
+#define LPASS_BE_SLIMBUS_3_TX "SLIMBUS_3_TX"
 #define LPASS_BE_SLIMBUS_4_RX "SLIMBUS_4_RX"
 #define LPASS_BE_SLIMBUS_4_TX "SLIMBUS_4_TX"
 
@@ -53,6 +56,10 @@
 	MSM_FRONTEND_DAI_MULTIMEDIA2,
 	MSM_FRONTEND_DAI_MULTIMEDIA3,
 	MSM_FRONTEND_DAI_MULTIMEDIA4,
+	MSM_FRONTEND_DAI_MULTIMEDIA5,
+	MSM_FRONTEND_DAI_MULTIMEDIA6,
+	MSM_FRONTEND_DAI_MULTIMEDIA7,
+	MSM_FRONTEND_DAI_MULTIMEDIA8,
 	MSM_FRONTEND_DAI_CS_VOICE,
 	MSM_FRONTEND_DAI_VOIP,
 	MSM_FRONTEND_DAI_AFE_RX,
@@ -62,8 +69,8 @@
 	MSM_FRONTEND_DAI_MAX,
 };
 
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA4 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA4
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA8 + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA8
 
 enum {
 	MSM_BACKEND_DAI_PRI_I2S_RX = 0,
@@ -90,9 +97,12 @@
 	MSM_BACKEND_DAI_SLIMBUS_4_RX,
 	MSM_BACKEND_DAI_SLIMBUS_4_TX,
 	MSM_BACKEND_DAI_SLIMBUS_3_RX,
+	MSM_BACKEND_DAI_SLIMBUS_3_TX,
 	MSM_BACKEND_DAI_EXTPROC_RX,
 	MSM_BACKEND_DAI_EXTPROC_TX,
 	MSM_BACKEND_DAI_EXTPROC_EC_TX,
+	MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_BACKEND_DAI_SEC_AUXPCM_TX,
 	MSM_BACKEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 0f91665..20ac6e1 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -311,11 +311,11 @@
 	{"MIC BIAS2 Internal1", NULL, "Headset Mic"},
 
 	/* Microphone path */
-	{"AMIC1", NULL, "MIC BIAS2 Internal1"},
-	{"MIC BIAS2 Internal1", NULL, "ANCLeft Headset Mic"},
+	{"AMIC1", NULL, "MIC BIAS2 External"},
+	{"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
 
-	{"AMIC3", NULL, "MIC BIAS2 Internal1"},
-	{"MIC BIAS2 Internal1", NULL, "ANCRight Headset Mic"},
+	{"AMIC3", NULL, "MIC BIAS2 External"},
+	{"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
 
 	{"HEADPHONE", NULL, "LDO_H"},
 
@@ -514,7 +514,7 @@
 #undef S
 #define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
 	S(v_no_mic, 30);
-	S(v_hs_max, 1550);
+	S(v_hs_max, 1650);
 #undef S
 #define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
 	S(c[0], 62);
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index bb5d817..98cfa6d 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -47,6 +47,7 @@
 #define BOTTOM_SPK_AMP_NEG	0x2
 #define TOP_SPK_AMP_POS		0x4
 #define TOP_SPK_AMP_NEG		0x8
+#define TOP_SPK_AMP		0x10
 
 #define GPIO_AUX_PCM_DOUT 63
 #define GPIO_AUX_PCM_DIN 64
@@ -191,10 +192,14 @@
 			usleep_range(4000, 4000);
 		}
 
-	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
+	} else if  (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG | TOP_SPK_AMP)) {
 
-		if ((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
-			(msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
+		pr_debug("%s: top_spk_amp_state = 0x%x spk_event = 0x%x\n",
+			__func__, msm8960_ext_top_spk_pamp, spk);
+
+		if (((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
+			(msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) ||
+				(msm8960_ext_top_spk_pamp & TOP_SPK_AMP)) {
 
 			pr_debug("%s() External Top Speaker Ampl already"
 				"turned on. spk = 0x%08x\n", __func__, spk);
@@ -203,8 +208,9 @@
 
 		msm8960_ext_top_spk_pamp |= spk;
 
-		if ((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
-			(msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
+		if (((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
+			(msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) ||
+				(msm8960_ext_top_spk_pamp & TOP_SPK_AMP)) {
 
 			msm8960_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
 			pr_debug("%s: sleeping 4 ms after turning on "
@@ -235,17 +241,31 @@
 
 		usleep_range(4000, 4000);
 
-	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
+	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG | TOP_SPK_AMP)) {
+
+		pr_debug("%s: top_spk_amp_state = 0x%x spk_event = 0x%x\n",
+				__func__, msm8960_ext_top_spk_pamp, spk);
 
 		if (!msm8960_ext_top_spk_pamp)
 			return;
 
+		if ((spk & TOP_SPK_AMP_POS) || (spk & TOP_SPK_AMP_NEG)) {
+
+			msm8960_ext_top_spk_pamp &= (~(TOP_SPK_AMP_POS |
+							TOP_SPK_AMP_NEG));
+		} else if (spk & TOP_SPK_AMP) {
+			msm8960_ext_top_spk_pamp &=  ~TOP_SPK_AMP;
+		}
+
+		if (msm8960_ext_top_spk_pamp)
+			return;
+
 		gpio_direction_output(top_spk_pamp_gpio, 0);
 		gpio_free(top_spk_pamp_gpio);
 		msm8960_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 ext Top Spek Ampl is off\n",
+				__func__);
 
 		usleep_range(4000, 4000);
 	} else  {
@@ -313,6 +333,8 @@
 			msm8960_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
 		else if  (!strncmp(w->name, "Ext Spk Top Neg", 15))
 			msm8960_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
+		else if  (!strncmp(w->name, "Ext Spk Top", 12))
+			msm8960_ext_spk_power_amp_on(TOP_SPK_AMP);
 		else {
 			pr_err("%s() Invalid Speaker Widget = %s\n",
 					__func__, w->name);
@@ -328,6 +350,8 @@
 			msm8960_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
 		else if  (!strncmp(w->name, "Ext Spk Top Neg", 15))
 			msm8960_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
+		else if  (!strncmp(w->name, "Ext Spk Top", 12))
+			msm8960_ext_spk_power_amp_off(TOP_SPK_AMP);
 		else {
 			pr_err("%s() Invalid Speaker Widget = %s\n",
 					__func__, w->name);
@@ -411,6 +435,7 @@
 
 	SND_SOC_DAPM_SPK("Ext Spk Top Pos", msm8960_spkramp_event),
 	SND_SOC_DAPM_SPK("Ext Spk Top Neg", msm8960_spkramp_event),
+	SND_SOC_DAPM_SPK("Ext Spk Top", msm8960_spkramp_event),
 
 	SND_SOC_DAPM_MIC("Handset Mic", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
@@ -438,6 +463,7 @@
 
 	{"Ext Spk Top Pos", NULL, "LINEOUT2"},
 	{"Ext Spk Top Neg", NULL, "LINEOUT4"},
+	{"Ext Spk Top", NULL, "LINEOUT5"},
 
 	/* Microphone path */
 	{"AMIC1", NULL, "MIC BIAS1 Internal1"},
@@ -725,8 +751,6 @@
 	int ret = 0;
 	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
 	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
-	unsigned int user_set_tx_ch = 0;
-
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 
@@ -754,13 +778,8 @@
 		}
 	} else {
 
-		if (codec_dai->id  == 2)
-			user_set_tx_ch =  msm8960_slim_0_tx_ch;
-		else if (codec_dai->id  == 4)
-			user_set_tx_ch =  params_channels(params);
-
-		pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
-			codec_dai->name, codec_dai->id, user_set_tx_ch);
+		pr_debug("%s: %s  tx_dai_id = %d  num_ch = %d\n", __func__,
+			codec_dai->name, codec_dai->id, msm8960_slim_0_tx_ch);
 
 		ret = snd_soc_dai_get_channel_map(codec_dai,
 				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
@@ -769,20 +788,88 @@
 			goto end;
 		}
 		ret = snd_soc_dai_set_channel_map(cpu_dai,
-				user_set_tx_ch, tx_ch, 0 , 0);
+				msm8960_slim_0_tx_ch, tx_ch, 0 , 0);
 		if (ret < 0) {
 			pr_err("%s: failed to set cpu chan map\n", __func__);
 			goto end;
 		}
 		ret = snd_soc_dai_set_channel_map(codec_dai,
-				user_set_tx_ch, tx_ch, 0, 0);
+				msm8960_slim_0_tx_ch, tx_ch, 0, 0);
 		if (ret < 0) {
 			pr_err("%s: failed to set codec channel map\n",
 								__func__);
 			goto end;
 		}
+	}
+end:
+	return ret;
+}
 
+static int msm8960_slimbus_2_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+	unsigned int num_tx_ch = 0;
+	unsigned int num_rx_ch = 0;
 
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+		num_rx_ch =  params_channels(params);
+
+		pr_debug("%s: %s rx_dai_id = %d  num_ch = %d\n", __func__,
+			codec_dai->name, codec_dai->id, num_rx_ch);
+
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+				num_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+				num_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+	} else {
+		num_tx_ch =  params_channels(params);
+
+		pr_debug("%s: %s  tx_dai_id = %d  num_ch = %d\n", __func__,
+			codec_dai->name, codec_dai->id, num_tx_ch);
+
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+				num_tx_ch, tx_ch, 0 , 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai,
+				num_tx_ch, tx_ch, 0, 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
 	}
 end:
 	return ret;
@@ -1011,8 +1098,11 @@
 }
 static int msm8960_startup(struct snd_pcm_substream *substream)
 {
-	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
-		 substream->name, substream->stream);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	pr_debug("%s(): dai_link_str_name = %s cpu_dai = %s codec_dai = %s\n",
+		__func__, rtd->dai_link->stream_name,
+		rtd->dai_link->cpu_dai_name, rtd->dai_link->codec_dai_name);
 	return 0;
 }
 
@@ -1038,8 +1128,11 @@
 
 static void msm8960_shutdown(struct snd_pcm_substream *substream)
 {
-	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
-		 substream->name, substream->stream);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	pr_debug("%s(): dai_link str_name = %s cpu_dai = %s codec_dai = %s\n",
+		__func__, rtd->dai_link->stream_name,
+		rtd->dai_link->cpu_dai_name, rtd->dai_link->codec_dai_name);
 }
 
 static struct snd_soc_ops msm8960_be_ops = {
@@ -1053,6 +1146,12 @@
 	.shutdown = msm8960_auxpcm_shutdown,
 };
 
+static struct snd_soc_ops msm8960_slimbus_2_be_ops = {
+	.startup = msm8960_startup,
+	.hw_params = msm8960_slimbus_2_hw_params,
+	.shutdown = msm8960_shutdown,
+};
+
 /* Digital audio interface glue - connects codec <---> CPU */
 static struct snd_soc_dai_link msm8960_dai_common[] = {
 	/* FrontEnd DAI Links */
@@ -1396,16 +1495,29 @@
 		.be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8960_be_ops,
 	},
+	/* Ultrasound TX Back End DAI Link */
 	{
-		.name = "SLIMBUS_2 Hostless",
-		.stream_name = "SLIMBUS_2 Hostless",
+		.name = "SLIMBUS_2 Hostless Capture",
+		.stream_name = "SLIMBUS_2 Hostless Capture",
 		.cpu_dai_name = "msm-dai-q6.16389",
 		.platform_name = "msm-pcm-hostless",
 		.codec_name = "tabla1x_codec",
 		.codec_dai_name = "tabla_tx2",
 		.ignore_suspend = 1,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ops = &msm8960_be_ops,
+		.ops = &msm8960_slimbus_2_be_ops,
+	},
+	/* Ultrasound RX Back End DAI Link */
+	{
+		.name = "SLIMBUS_2 Hostless Playback",
+		.stream_name = "SLIMBUS_2 Hostless Playback",
+		.cpu_dai_name = "msm-dai-q6.16388",
+		.platform_name = "msm-pcm-hostless",
+		.codec_name = "tabla1x_codec",
+		.codec_dai_name = "tabla_rx3",
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ops = &msm8960_slimbus_2_be_ops,
 	},
 };
 
@@ -1438,16 +1550,29 @@
 		.be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8960_be_ops,
 	},
+	/* Ultrasound TX Back End DAI Link */
 	{
-		.name = "SLIMBUS_2 Hostless",
-		.stream_name = "SLIMBUS_2 Hostless",
+		.name = "SLIMBUS_2 Hostless Capture",
+		.stream_name = "SLIMBUS_2 Hostless Capture",
 		.cpu_dai_name = "msm-dai-q6.16389",
 		.platform_name = "msm-pcm-hostless",
 		.codec_name = "tabla_codec",
 		.codec_dai_name = "tabla_tx2",
 		.ignore_suspend = 1,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ops = &msm8960_be_ops,
+		.ops = &msm8960_slimbus_2_be_ops,
+	},
+	/* Ultrasound RX Back End DAI Link */
+	{
+		.name = "SLIMBUS_2 Hostless Playback",
+		.stream_name = "SLIMBUS_2 Hostless Playback",
+		.cpu_dai_name = "msm-dai-q6.16388",
+		.platform_name = "msm-pcm-hostless",
+		.codec_name = "tabla_codec",
+		.codec_dai_name = "tabla_rx3",
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ops = &msm8960_slimbus_2_be_ops,
 	},
 };
 
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 51ef359..7b16adb 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -142,6 +142,7 @@
 	switch (port_id) {
 	case PRIMARY_I2S_RX:
 	case PCM_RX:
+	case SECONDARY_PCM_RX:
 	case SECONDARY_I2S_RX:
 	case MI2S_RX:
 	case HDMI_RX:
@@ -160,6 +161,7 @@
 
 	case PRIMARY_I2S_TX:
 	case PCM_TX:
+	case SECONDARY_PCM_TX:
 	case SECONDARY_I2S_TX:
 	case MI2S_TX:
 	case DIGI_MIC_TX:
@@ -167,6 +169,7 @@
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_3_TX:
 	case INT_FM_TX:
 	case VOICE_RECORD_RX:
 	case INT_BT_SCO_TX:
@@ -192,6 +195,8 @@
 	case PRIMARY_I2S_TX:
 	case PCM_RX:
 	case PCM_TX:
+	case SECONDARY_PCM_RX:
+	case SECONDARY_PCM_TX:
 	case SECONDARY_I2S_RX:
 	case SECONDARY_I2S_TX:
 	case MI2S_RX:
@@ -210,6 +215,7 @@
 	case SLIMBUS_2_RX:
 	case SLIMBUS_2_TX:
 	case SLIMBUS_3_RX:
+	case SLIMBUS_3_TX:
 	case INT_BT_SCO_RX:
 	case INT_BT_SCO_TX:
 	case INT_BT_A2DP_RX:
@@ -259,6 +265,8 @@
 	case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
 	case PCM_RX: return IDX_PCM_RX;
 	case PCM_TX: return IDX_PCM_TX;
+	case SECONDARY_PCM_RX: return IDX_SECONDARY_PCM_RX;
+	case SECONDARY_PCM_TX: return IDX_SECONDARY_PCM_TX;
 	case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
 	case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
 	case MI2S_RX: return IDX_MI2S_RX;
@@ -277,6 +285,7 @@
 	case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
 	case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
 	case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
+	case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
 	case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
 	case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
@@ -313,6 +322,7 @@
 	case SLIMBUS_2_RX:
 	case SLIMBUS_2_TX:
 	case SLIMBUS_3_RX:
+	case SLIMBUS_3_TX:
 	case SLIMBUS_4_RX:
 	case SLIMBUS_4_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
@@ -323,6 +333,8 @@
 		break;
 	case PCM_RX:
 	case PCM_TX:
+	case SECONDARY_PCM_RX:
+	case SECONDARY_PCM_TX:
 	default:
 		ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
 		break;