Merge "Bluetooth: Handle error command status for AUTH_REQUESTED command" into msm-3.0
diff --git a/Documentation/devicetree/bindings/spmi/msm-spmi.txt b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
index fa91514..8fe415b 100644
--- a/Documentation/devicetree/bindings/spmi/msm-spmi.txt
+++ b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
@@ -25,8 +25,8 @@
 Second level
 
 Required properties :
- - spmi-dev-container: Used by the parser to understand that this is the second
-   level of the tree.
+ - spmi-slave-container: Used by the parser to understand that this is the
+   second level of the tree.
  - reg: <a b> where a is < 65536 and b is a size. Each device supports an
    arbitrary number of address ranges.
  - compatible : "qcom," prefixed string to match against the driver.
@@ -50,7 +50,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			reg = <0xd>;
-			spmi-dev-container;
+			spmi-slave-container;
 
 			coincell@2800 {
 				compatible = "qcom,qpnp-coincell";
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0a7fe5f..b46d7f1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -140,7 +140,7 @@
 	  Enable ticket locks, which help preserve fairness among
 	  contended locks and prevent livelock in multicore systems.
 	  Say 'y' if system stability is important.
-	default y if ARCH_MSM_SCORPIONMP
+	default y if ARCH_MSM_SCORPIONMP || ARCH_MSM_KRAITMP
 	depends on SMP
 
 config RWSEM_GENERIC_SPINLOCK
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 3d4b37d..c671d32 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -114,7 +114,6 @@
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 # CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_PMIC8058 is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index ebff2d2..80252d8 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -112,7 +112,6 @@
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 # CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_PMIC8058 is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 58aece2..0b89d45 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -37,6 +37,10 @@
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_NO_HZ=y
@@ -102,6 +106,8 @@
 # CONFIG_MFD_SUPPORT is not set
 CONFIG_ION=y
 CONFIG_ION_MSM=y
+CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_CI13XXX_MSM=y
@@ -168,13 +174,3 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-CONFIG_MSM_SMD=y
-CONFIG_MSM_SMD_PKG4=y
-CONFIG_MSM_SMD_PKT=y
-CONFIG_MSM_SMD_DEBUG=y
-CONFIG_MSM_SMD_TTY=y
-CONFIG_MSM_N_WAY_SMD=y
-CONFIG_MSM_N_WAY_SMSM=y
-CONFIG_MSM_SMD_LOGGING=y
-CONFIG_MSM_IPC_ROUTER=y
-CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 642d843..f4646dc 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -45,7 +45,6 @@
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM7X27A_AUDIO=y
 CONFIG_MSM_DMA_TEST=y
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_MSM_SLEEP_STATS_DEVICE=y
 CONFIG_BT_MSM_PINTEST=y
 CONFIG_MSM_RPC_VIBRATOR=y
@@ -235,6 +234,7 @@
 # CONFIG_MT9T013 is not set
 # CONFIG_MT9D112 is not set
 CONFIG_OV5640=y
+CONFIG_OV5647=y
 CONFIG_WEBCAM_OV7692_QRD=y
 CONFIG_WEBCAM_OV9726=y
 # CONFIG_MT9P012 is not set
@@ -330,9 +330,9 @@
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SHIRQ=y
-# CONFIG_SCHED_DEBUG is not set
 CONFIG_LOCKUP_DETECTOR=y
 CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_SLAB=y
 CONFIG_DEBUG_SLAB_LEAK=y
@@ -342,7 +342,6 @@
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_LIST=y
-CONFIG_LATENCYTOP=y
 CONFIG_DEBUG_PAGEALLOC=y
 # CONFIG_FTRACE is not set
 CONFIG_DYNAMIC_DEBUG=y
@@ -352,4 +351,3 @@
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRC_CCITT=y
-CONFIG_OV5647=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index e319f0d..5466498 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -40,7 +40,6 @@
 CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
 CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
 CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -223,7 +222,6 @@
 CONFIG_INPUT_EVBUG=m
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_KEYBOARD_PMIC8058 is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_MSM=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index b4babeb..1a70816 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -40,7 +40,6 @@
 CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
 CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
 CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
@@ -224,7 +223,6 @@
 CONFIG_INPUT_EVBUG=m
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_KEYBOARD_PMIC8058 is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_MSM=y
@@ -371,7 +369,6 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
 CONFIG_LOCKUP_DETECTOR=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_SCHED_DEBUG is not set
@@ -380,7 +377,6 @@
 CONFIG_DEBUG_SLAB=y
 CONFIG_DEBUG_SLAB_LEAK=y
 # CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_SPINLOCK=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_STACK_USAGE=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index b3a45d2..1365641 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -70,7 +70,6 @@
 CONFIG_MSM_RPM_STATS_LOG=y
 CONFIG_MSM_WATCHDOG=y
 CONFIG_MSM_DLOAD_MODE=y
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_MSM_ETM=y
 CONFIG_MSM_SLEEP_STATS=y
 CONFIG_MSM_GSBI9_UART=y
@@ -272,7 +271,6 @@
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_MATRIX=y
 CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_KEYBOARD_PMIC8058 is not set
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
@@ -299,7 +297,6 @@
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_SX150X=y
-# CONFIG_MPP_PMIC8901 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
 CONFIG_BATTERY_MSM8X60=y
@@ -324,9 +321,9 @@
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_USB_VIDEO_CLASS=y
+CONFIG_IMX074=y
 CONFIG_WEBCAM_OV9726=y
 CONFIG_MT9E013=y
-CONFIG_IMX074=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 1f511bb..fa4ba4e 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -271,7 +271,6 @@
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_MATRIX=y
 CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_KEYBOARD_PMIC8058 is not set
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
@@ -299,7 +298,6 @@
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_SX150X=y
-# CONFIG_MPP_PMIC8901 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
 CONFIG_BATTERY_MSM8X60=y
@@ -324,9 +322,9 @@
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_USB_VIDEO_CLASS=y
+CONFIG_IMX074=y
 CONFIG_WEBCAM_OV9726=y
 CONFIG_MT9E013=y
-CONFIG_IMX074=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index f54573d..e4456dc 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -227,7 +227,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_PMIC8XXX_VIBRATOR=y
-CONFIG_TZCOM=y
+CONFIG_QSEECOM=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
@@ -301,6 +301,7 @@
 CONFIG_MFD_PM8821_CORE=y
 CONFIG_MFD_PM8038_CORE=y
 CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_WCD9304_CODEC=y
 CONFIG_WCD9310_CODEC=y
 CONFIG_REGULATOR_PM8XXX=y
 CONFIG_REGULATOR_GPIO=y
@@ -310,15 +311,15 @@
 CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_MSM_CAMERA_V4L2=y
+CONFIG_IMX074=y
 CONFIG_MT9M114=y
+CONFIG_IMX074_ACT=y
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_OV2720=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
-CONFIG_IMX074=y
-CONFIG_IMX074_ACT=y
-CONFIG_OV2720=y
-CONFIG_S5K3L1YX=y
 CONFIG_MSM_GEMINI=y
+CONFIG_S5K3L1YX=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
@@ -335,9 +336,9 @@
 CONFIG_FB_MSM_OVERLAY=y
 CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
 CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y
+CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
 CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT=y
 CONFIG_FB_MSM_HDMI_MSM_PANEL=y
-CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_SOUND=y
@@ -351,7 +352,6 @@
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
 CONFIG_HID_MICROSOFT=y
-CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 2b56a11..406992a 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -229,7 +229,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_PMIC8XXX_VIBRATOR=y
-CONFIG_TZCOM=y
+CONFIG_QSEECOM=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
@@ -297,12 +297,11 @@
 CONFIG_SENSORS_PM8XXX_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
-CONFIG_THERMAL_PM8XXX=y
-CONFIG_THERMAL_MONITOR=y
 CONFIG_MFD_PM8921_CORE=y
 CONFIG_MFD_PM8821_CORE=y
 CONFIG_MFD_PM8038_CORE=y
 CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_WCD9304_CODEC=y
 CONFIG_WCD9310_CODEC=y
 CONFIG_REGULATOR_PM8XXX=y
 CONFIG_REGULATOR_GPIO=y
@@ -312,15 +311,15 @@
 CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_MSM_CAMERA_V4L2=y
+CONFIG_IMX074=y
 CONFIG_MT9M114=y
+CONFIG_IMX074_ACT=y
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_OV2720=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
-CONFIG_IMX074=y
-CONFIG_IMX074_ACT=y
-CONFIG_OV2720=y
-CONFIG_S5K3L1YX=y
 CONFIG_MSM_GEMINI=y
+CONFIG_S5K3L1YX=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
@@ -353,7 +352,6 @@
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
 CONFIG_HID_MICROSOFT=y
-CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 7ba17e6..d4552f8 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -70,6 +70,7 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 65c3f24..4e25f18 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -137,6 +137,11 @@
 	disable_irq
 	.endm
 
+	.macro	save_and_disable_irqs_notrace, oldcpsr
+	mrs	\oldcpsr, cpsr
+	disable_irq_notrace
+	.endm
+
 /*
  * Restore interrupt state previously stored in a register.  We don't
  * guarantee that this will preserve the flags.
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 0083033..de314ea 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -763,6 +763,7 @@
 			break;
 		case 0x0490:    /* 8960 sim */
 		case 0x04D0:    /* 8960 */
+		case 0x06F0:    /* 8064 */
 			armpmu = armv7_krait_pmu_init();
 			krait_l2_pmu_init();
 			break;
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 18fbcf6..a2c8827 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -477,6 +477,22 @@
 	help
 	  Support for the Qualcomm MSM8625 RUMI3 Emulation Platform.
 
+config MACH_MSM8625_SURF
+	depends on ARCH_MSM8625
+	depends on !MSM_STACKED_MEMORY
+	default y
+	bool "MSM8625 SURF"
+	help
+	  Support for the Qualcomm MSM8625 SURF.
+
+config MACH_MSM8625_EVB
+	depends on ARCH_MSM8625
+	depends on !MSM_STACKED_MEMORY
+	default y
+	bool "MSM8625 EVB"
+	help
+	  Support for the Qualcomm MSM8625 Reference Design.
+
 config MACH_MSM7X30_SURF
        depends on ARCH_MSM7X30
        depends on !MSM_STACKED_MEMORY
@@ -2082,6 +2098,7 @@
 config MSM_RTB_SEPARATE_CPUS
 	bool "Separate entries for each cpu"
 	depends on MSM_RTB
+	depends on SMP
 	help
 	  Under some circumstances, it may be beneficial to give dedicated space
 	  for each cpu to log accesses. Selecting this option will log each cpu
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 8347a25..1f3945e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -23,7 +23,7 @@
 obj-y += acpuclock.o
 obj-$(CONFIG_ARCH_MSM7X01A) += acpuclock-7201.o
 obj-$(CONFIG_ARCH_MSM7X25) += acpuclock-7201.o
-obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7201.o
+obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7201.o clock-pll.o
 obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
 obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o
 obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o
@@ -221,14 +221,18 @@
 obj-$(CONFIG_MACH_MSM7X27_SURF) += board-msm7x27.o devices-msm7x27.o
 obj-$(CONFIG_MACH_MSM7X27_FFA) += board-msm7x27.o devices-msm7x27.o
 obj-$(CONFIG_ARCH_MSM7X27A) += clock-pcom-lookup.o devices-msm7x27a.o
-obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7627A_QRD1) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7627A_QRD3) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7627A_EVB) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+board-7627a-all-objs += board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o
+board-7627a-all-objs += board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7627A_QRD1) += board-qrd7627a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7627A_QRD3) += board-qrd7627a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7627A_EVB) += board-qrd7627a.o board-7627a-all.o
 obj-$(CONFIG_ARCH_MSM8625) += devices-msm7x27a.o clock-pcom-lookup.o
 obj-$(CONFIG_MACH_MSM8625_RUMI3) += board-msm7x27a.o
+obj-$(CONFIG_MACH_MSM8625_SURF) +=  board-msm7x27a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM8625_EVB) +=  board-qrd7627a.o board-7627a-all.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o memory_topology.o
 obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o clock-7x30.o acpuclock-7x30.o
 obj-$(CONFIG_MACH_MSM7X25_SURF) += board-msm7x27.o devices-msm7x25.o
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 5a21407..781d896 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -27,7 +27,6 @@
 #include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/sort.h>
-#include <linux/remote_spinlock.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 #include <asm/mach-types.h>
@@ -39,17 +38,16 @@
 #define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
 #define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
 #define A11S_VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
-#define PLLn_MODE(n)	(MSM_CLK_CTL_BASE + 0x300 + 28 * (n))
-#define PLLn_L_VAL(n)	(MSM_CLK_CTL_BASE + 0x304 + 28 * (n))
 
-#define PLL4_MODE	(MSM_CLK_CTL_BASE + 0x374)
-#define PLL4_L_VAL	(MSM_CLK_CTL_BASE + 0x378)
 
 #define POWER_COLLAPSE_KHZ 19200
 
 /* Max CPU frequency allowed by hardware while in standby waiting for an irq. */
 #define MAX_WAIT_FOR_IRQ_KHZ 128000
 
+/**
+ * enum - For acpuclock PLL IDs
+ */
 enum {
 	ACPU_PLL_TCXO	= -1,
 	ACPU_PLL_0	= 0,
@@ -60,15 +58,16 @@
 	ACPU_PLL_END,
 };
 
-static const struct pll {
-	void __iomem *mod_reg;
-	const uint32_t l_val_mask;
-} soc_pll[ACPU_PLL_END] = {
-	[ACPU_PLL_0] = {PLLn_MODE(ACPU_PLL_0), 0x3f},
-	[ACPU_PLL_1] = {PLLn_MODE(ACPU_PLL_1), 0x3f},
-	[ACPU_PLL_2] = {PLLn_MODE(ACPU_PLL_2), 0x3f},
-	[ACPU_PLL_3] = {PLLn_MODE(ACPU_PLL_3), 0x3f},
-	[ACPU_PLL_4] = {PLL4_MODE, 0x3ff},
+struct acpu_clk_src {
+	struct clk *clk;
+	const char *name;
+};
+
+static struct acpu_clk_src pll_clk[ACPU_PLL_END] = {
+	[ACPU_PLL_0] = { .name = "pll0_clk" },
+	[ACPU_PLL_1] = { .name = "pll1_clk" },
+	[ACPU_PLL_2] = { .name = "pll2_clk" },
+	[ACPU_PLL_4] = { .name = "pll4_clk" },
 };
 
 struct clock_state {
@@ -78,24 +77,6 @@
 	struct clk			*ebi1_clk;
 };
 
-#define PLL_BASE	7
-
-struct shared_pll_control {
-	uint32_t	version;
-	struct {
-		/* Denotes if the PLL is ON. Technically, this can be read
-		 * directly from the PLL registers, but this feild is here,
-		 * so let's use it.
-		 */
-		uint32_t	on;
-		/* One bit for each processor core. The application processor
-		 * is allocated bit position 1. All other bits should be
-		 * considered as votes from other processors.
-		 */
-		uint32_t	votes;
-	} pll[PLL_BASE + ACPU_PLL_END];
-};
-
 struct clkctl_acpu_speed {
 	unsigned int	use_for_scaling;
 	unsigned int	a11clk_khz;
@@ -106,14 +87,11 @@
 	unsigned int	ahbclk_div;
 	int		vdd;
 	unsigned int	axiclk_khz;
-	unsigned long	lpj; /* loops_per_jiffy */
 	/* Pointers in acpu_freq_tbl[] for max up/down steppings. */
 	struct clkctl_acpu_speed *down[ACPU_PLL_END];
 	struct clkctl_acpu_speed *up[ACPU_PLL_END];
 };
 
-static remote_spinlock_t pll_lock;
-static struct shared_pll_control *pll_control;
 static struct clock_state drv_state = { 0 };
 static struct clkctl_acpu_speed *acpu_freq_tbl;
 
@@ -136,7 +114,7 @@
 	{ 0, 400000, ACPU_PLL_2, 2, 2, 133333, 2, 5, 160000 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 160000 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 7, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627 with CDMA capable modem */
@@ -150,7 +128,7 @@
 	{ 0, 400000, ACPU_PLL_2, 2, 2, 133333, 2, 5, 160000 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 160000 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 7, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627 with GSM capable modem - PLL2 @ 800 */
@@ -164,7 +142,7 @@
 	{ 0, 400000, ACPU_PLL_2, 2, 1, 133333, 2, 5, 160000 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 160000 },
 	{ 1, 800000, ACPU_PLL_2, 2, 0, 200000, 3, 7, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627 with CDMA capable modem - PLL2 @ 800 */
@@ -178,7 +156,7 @@
 	{ 0, 400000, ACPU_PLL_2, 2, 1, 133333, 2, 5, 160000 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 160000 },
 	{ 1, 800000, ACPU_PLL_2, 2, 0, 200000, 3, 7, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627a PLL2 @ 1200MHz with GSM capable modem */
@@ -193,7 +171,7 @@
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
 	{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627a PLL2 @ 1200MHz with CDMA capable modem */
@@ -208,7 +186,7 @@
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 120000 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
 	{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627aa PLL4 @ 1008MHz with GSM capable modem */
@@ -223,7 +201,7 @@
 	{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
 	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627aa PLL4 @ 1008MHz with CDMA capable modem */
@@ -238,7 +216,7 @@
 	{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
 	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7625a PLL2 @ 1200MHz with GSM capable modem */
@@ -252,7 +230,7 @@
 	{ 0, 400000, ACPU_PLL_2, 2, 2, 50000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627a PLL2 @ 1200MHz with GSM capable modem */
@@ -267,7 +245,7 @@
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
 	{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627a PLL2 @ 1200MHz with CDMA capable modem */
@@ -282,7 +260,7 @@
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 120000 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
 	{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627aa PLL4 @ 1008MHz with GSM capable modem */
@@ -297,7 +275,7 @@
 	{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
 	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7627aa PLL4 @ 1008MHz with CDMA capable modem */
@@ -312,7 +290,7 @@
 	{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
 	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
 /* 7625a PLL2 @ 1200MHz with GSM capable modem */
@@ -326,29 +304,19 @@
 	{ 0, 400000, ACPU_PLL_2, 2, 2, 50000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
 	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
-#define PLL_0_MHZ	0
-#define PLL_196_MHZ	10
-#define PLL_245_MHZ	12
-#define PLL_589_MHZ	30
-#define PLL_737_MHZ	38
-#define PLL_800_MHZ	41
-#define PLL_960_MHZ	50
-#define PLL_1008_MHZ	52
-#define PLL_1200_MHZ	62
-
 #define PLL_CONFIG(m0, m1, m2, m4) { \
-	PLL_##m0##_MHZ, PLL_##m1##_MHZ, PLL_##m2##_MHZ, PLL_##m4##_MHZ, \
+	m0, m1, m2, m4, \
 	pll0_##m0##_pll1_##m1##_pll2_##m2##_pll4_##m4 \
 }
 
 struct pll_freq_tbl_map {
-	unsigned int	pll0_l;
-	unsigned int	pll1_l;
-	unsigned int	pll2_l;
-	unsigned int	pll4_l;
+	unsigned int	pll0_rate;
+	unsigned int	pll1_rate;
+	unsigned int	pll2_rate;
+	unsigned int	pll4_rate;
 	struct clkctl_acpu_speed *tbl;
 };
 
@@ -405,59 +373,6 @@
 }
 #endif
 
-static void pll_enable(void __iomem *addr, unsigned on)
-{
-	if (on) {
-		writel_relaxed(2, addr);
-		mb();
-		udelay(5);
-		writel_relaxed(6, addr);
-		mb();
-		udelay(50);
-		writel_relaxed(7, addr);
-	} else {
-		writel_relaxed(0, addr);
-	}
-}
-
-static int pc_pll_request(unsigned id, unsigned on)
-{
-	int res = 0;
-	on = !!on;
-
-	if (on)
-		pr_debug("Enabling PLL %d\n", id);
-	else
-		pr_debug("Disabling PLL %d\n", id);
-
-	if (id >= ACPU_PLL_END)
-		return -EINVAL;
-
-	remote_spin_lock(&pll_lock);
-	if (on) {
-		pll_control->pll[PLL_BASE + id].votes |= 2;
-		if (!pll_control->pll[PLL_BASE + id].on) {
-			pll_enable(soc_pll[id].mod_reg, 1);
-			pll_control->pll[PLL_BASE + id].on = 1;
-		}
-	} else {
-		pll_control->pll[PLL_BASE + id].votes &= ~2;
-		if (pll_control->pll[PLL_BASE + id].on
-		    && !pll_control->pll[PLL_BASE + id].votes) {
-			pll_enable(soc_pll[id].mod_reg, 0);
-			pll_control->pll[PLL_BASE + id].on = 0;
-		}
-	}
-	remote_spin_unlock(&pll_lock);
-
-	if (on)
-		pr_debug("PLL enabled\n");
-	else
-		pr_debug("PLL disabled\n");
-
-	return res;
-}
-
 static int acpuclk_set_vdd_level(int vdd)
 {
 	uint32_t current_vdd;
@@ -576,7 +491,7 @@
 
 	if (reason == SETRATE_CPUFREQ) {
 		if (strt_s->pll != tgt_s->pll && tgt_s->pll != ACPU_PLL_TCXO) {
-			rc = pc_pll_request(tgt_s->pll, 1);
+			rc = clk_prepare_enable(pll_clk[tgt_s->pll].clk);
 			if (rc < 0) {
 				pr_err("PLL%d enable failed (%d)\n",
 					tgt_s->pll, rc);
@@ -651,7 +566,7 @@
 
 		if (cur_s->pll != ACPU_PLL_TCXO
 		    && !(plls_enabled & (1 << cur_s->pll))) {
-			rc = pc_pll_request(cur_s->pll, 1);
+			rc = clk_prepare_enable(pll_clk[cur_s->pll].clk);
 			if (rc < 0) {
 				pr_err("PLL%d enable failed (%d)\n",
 					cur_s->pll, rc);
@@ -662,8 +577,6 @@
 
 		acpuclk_set_div(cur_s);
 		drv_state.current_speed = cur_s;
-		/* Re-adjust lpj for the new clock speed. */
-		loops_per_jiffy = cur_s->lpj;
 		mb();
 		udelay(50);
 	}
@@ -684,12 +597,8 @@
 	if (tgt_s->pll != ACPU_PLL_TCXO)
 		plls_enabled &= ~(1 << tgt_s->pll);
 	for (pll = ACPU_PLL_0; pll < ACPU_PLL_END; pll++)
-		if (plls_enabled & (1 << pll)) {
-			res = pc_pll_request(pll, 0);
-			if (res < 0)
-				pr_warning("PLL%d disable failed (%d)\n",
-						pll, res);
-		}
+		if (plls_enabled & (1 << pll))
+			clk_disable_unprepare(pll_clk[pll].clk);
 
 	/* Nothing else to do for power collapse. */
 	if (reason == SETRATE_PC)
@@ -742,9 +651,10 @@
 	}
 
 	drv_state.current_speed = speed;
-	if (speed->pll != ACPU_PLL_TCXO)
-		if (pc_pll_request(speed->pll, 1))
+	if (speed->pll != ACPU_PLL_TCXO) {
+		if (clk_prepare_enable(pll_clk[speed->pll].clk))
 			pr_warning("Failed to vote for boot PLL\n");
+	}
 
 	/* Fix div2 to 2 for 7x27/5a(aa) targets */
 	if (!cpu_is_msm7x27()) {
@@ -777,64 +687,52 @@
 /*----------------------------------------------------------------------------
  * Clock driver initialization
  *---------------------------------------------------------------------------*/
-
-static void __init acpu_freq_tbl_fixup(void)
+#define MHZ 1000000
+static void __init select_freq_plan(void)
 {
-	unsigned long pll0_l, pll1_l, pll2_l, pll4_l;
-	struct pll_freq_tbl_map *lst;
+	unsigned long pll_mhz[ACPU_PLL_END];
+	struct pll_freq_tbl_map *t;
+	int i;
 
-	/* Wait for the PLLs to be initialized and then read their frequency.
-	 */
-	do {
-		pll0_l = readl_relaxed(PLLn_L_VAL(0)) &
-				soc_pll[ACPU_PLL_0].l_val_mask;
-		cpu_relax();
-		udelay(50);
-	} while (pll0_l == 0);
-	do {
-		pll1_l = readl_relaxed(PLLn_L_VAL(1)) &
-				soc_pll[ACPU_PLL_1].l_val_mask;
-		cpu_relax();
-		udelay(50);
-	} while (pll1_l == 0);
-	do {
-		pll2_l = readl_relaxed(PLLn_L_VAL(2)) &
-				soc_pll[ACPU_PLL_2].l_val_mask;
-		cpu_relax();
-		udelay(50);
-	} while (pll2_l == 0);
-
-	pr_info("L val: PLL0: %d, PLL1: %d, PLL2: %d\n",
-			(int)pll0_l, (int)pll1_l, (int)pll2_l);
-
-	if (!cpu_is_msm7x27() && !cpu_is_msm7x25a()) {
-		do {
-			pll4_l = readl_relaxed(PLL4_L_VAL) &
-				soc_pll[ACPU_PLL_4].l_val_mask;
-			cpu_relax();
-			udelay(50);
-		} while (pll4_l == 0);
-		pr_info("L val: PLL4: %d\n", (int)pll4_l);
-	} else {
-		pll4_l = 0;
+	/* Get PLL clocks */
+	for (i = 0; i < ACPU_PLL_END; i++) {
+		if (pll_clk[i].name) {
+			pll_clk[i].clk = clk_get_sys("acpu", pll_clk[i].name);
+			if (IS_ERR(pll_clk[i].clk)) {
+				pll_mhz[i] = 0;
+				continue;
+			}
+			/* Get PLL's Rate */
+			pll_mhz[i] = clk_get_rate(pll_clk[i].clk)/MHZ;
+		}
 	}
 
-	/* Fix the tables for 7x25a variant to not conflict with 7x27 ones */
+	/*
+	 * For the pll configuration used in acpuclock table e.g.
+	 * pll0_960_pll1_245_pll2_1200" is same for 7627 and
+	 * 7625a (as pll0,pll1,pll2) having same rates, but frequency
+	 * table is different for both targets.
+	 *
+	 * Hence below for loop will not be able to select correct
+	 * table based on PLL rates as rates are same. Hence we need
+	 * to add this cpu check for selecting the correct acpuclock table.
+	 */
 	if (cpu_is_msm7x25a()) {
-		if (pll1_l == PLL_245_MHZ) {
+		if (pll_mhz[ACPU_PLL_1] == 245) {
 			acpu_freq_tbl =
 				pll0_960_pll1_245_pll2_1200_25a;
-		} else if (pll1_l == PLL_737_MHZ) {
+		} else if (pll_mhz[ACPU_PLL_1] == 737) {
 			acpu_freq_tbl =
 				pll0_960_pll1_737_pll2_1200_25a;
 		}
 	} else {
 		/* Select the right table to use. */
-		for (lst = acpu_freq_tbl_list; lst->tbl != 0; lst++) {
-			if (lst->pll0_l == pll0_l && lst->pll1_l == pll1_l
-					&& lst->pll2_l == pll2_l
-					&& lst->pll4_l == pll4_l) {
-				acpu_freq_tbl = lst->tbl;
+		for (t = acpu_freq_tbl_list; t->tbl != 0; t++) {
+			if (t->pll0_rate == pll_mhz[ACPU_PLL_0]
+				&& t->pll1_rate == pll_mhz[ACPU_PLL_1]
+				&& t->pll2_rate == pll_mhz[ACPU_PLL_2]
+				&& t->pll4_rate == pll_mhz[ACPU_PLL_4]) {
+				acpu_freq_tbl = t->tbl;
 				break;
 			}
 		}
@@ -862,18 +760,6 @@
 	return found_khz;
 }
 
-/* Initalize the lpj field in the acpu_freq_tbl. */
-static void __init lpj_init(void)
-{
-	int i;
-	const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
-	for (i = 0; acpu_freq_tbl[i].a11clk_khz; i++) {
-		acpu_freq_tbl[i].lpj = cpufreq_scale(loops_per_jiffy,
-						base_clk->a11clk_khz,
-						acpu_freq_tbl[i].a11clk_khz);
-	}
-}
-
 static void __init precompute_stepping(void)
 {
 	int i, step_idx;
@@ -945,33 +831,6 @@
 	}
 }
 
-static void shared_pll_control_init(void)
-{
-#define PLL_REMOTE_SPINLOCK_ID "S:7"
-	unsigned smem_size;
-
-	remote_spin_lock_init(&pll_lock, PLL_REMOTE_SPINLOCK_ID);
-	pll_control = smem_get_entry(SMEM_CLKREGIM_SOURCES, &smem_size);
-
-	if (!pll_control) {
-		pr_err("Can't find shared PLL control data structure!\n");
-		BUG();
-	/* There might be more PLLs than what the application processor knows
-	 * about. But the index used for each PLL is guaranteed to remain the
-	 * same. */
-	} else if (smem_size < sizeof(struct shared_pll_control)) {
-			pr_err("Shared PLL control data"
-					"structure too small!\n");
-			BUG();
-	} else if (pll_control->version != 0xCCEE0001) {
-			pr_err("Shared PLL control version mismatch!\n");
-			BUG();
-	} else {
-		pr_info("Shared PLL control available.\n");
-		return;
-	}
-
-}
 
 static struct acpuclk_data acpuclk_7627_data = {
 	.set_rate = acpuclk_7627_set_rate,
@@ -988,13 +847,11 @@
 	BUG_ON(IS_ERR(drv_state.ebi1_clk));
 
 	mutex_init(&drv_state.lock);
-	shared_pll_control_init();
 	drv_state.max_speed_delta_khz = soc_data->max_speed_delta_khz;
-	acpu_freq_tbl_fixup();
+	select_freq_plan();
 	acpuclk_7627_data.wait_for_irq_khz = find_wait_for_irq_khz();
 	precompute_stepping();
 	acpuclk_hw_init();
-	lpj_init();
 	print_acpu_freq_tbl();
 	acpuclk_register(&acpuclk_7627_data);
 
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 99c3d78..8d35148 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -194,7 +194,7 @@
 			.hfpll_base      = MSM_HFPLL_BASE + 0x200,
 			.aux_clk_sel     = MSM_ACC0_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait0",     1150000 },
+			.vreg[VREG_CORE] = { "krait0",     1300000 },
 			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_L24 },
@@ -209,7 +209,7 @@
 			.hfpll_base      = MSM_HFPLL_BASE + 0x240,
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait1",     1150000 },
+			.vreg[VREG_CORE] = { "krait1",     1300000 },
 			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_L24 },
@@ -224,7 +224,7 @@
 			.hfpll_base      = MSM_HFPLL_BASE + 0x280,
 			.aux_clk_sel     = MSM_ACC2_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait2",     1150000 },
+			.vreg[VREG_CORE] = { "krait2",     1300000 },
 			.vreg[VREG_MEM]  = { "krait2_mem", 1150000,
 					     RPM_VREG_VOTER4,
 					     RPM_VREG_ID_PM8921_L24 },
@@ -239,7 +239,7 @@
 			.hfpll_base      = MSM_HFPLL_BASE + 0x2C0,
 			.aux_clk_sel     = MSM_ACC3_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait3",     1150000 },
+			.vreg[VREG_CORE] = { "krait3",     1300000 },
 			.vreg[VREG_MEM]  = { "krait3_mem", 1150000,
 					     RPM_VREG_VOTER5,
 					     RPM_VREG_ID_PM8921_L24 },
@@ -375,6 +375,7 @@
 	[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
 	[5] = BW_MBPS(3600), /* At least 450 MHz on bus. */
 	[6] = BW_MBPS(3936), /* At least 492 MHz on bus. */
+	[7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
 };
 
 static struct msm_bus_scale_pdata bus_client_pdata = {
@@ -546,47 +547,48 @@
 #define L2(x) (&l2_freq_tbl_8064[(x)])
 static struct l2_level l2_freq_tbl_8064[] = {
 	[0]  = { {STBY_KHZ, QSB,   0, 0, 0x00 }, 1050000, 1050000, 0 },
-	[1]  = { {  384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 0 },
-	[2]  = { {  432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
-	[3]  = { {  486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 1 },
-	[4]  = { {  540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 1 },
+	[1]  = { {  384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
+	[2]  = { {  432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
+	[3]  = { {  486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
+	[4]  = { {  540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
 	[5]  = { {  594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
-	[6]  = { {  648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 2 },
-	[7]  = { {  702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 2 },
-	[8]  = { {  756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 3 },
-	[9]  = { {  810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
-	[10] = { {  864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
-	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
-	[12] = { {  972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 3 },
-	[13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 3 },
-	[14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 4 },
-	[15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 4 },
-	[16] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 4 },
-	[17] = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 4 },
-	[18] = { { 1296000, HFPLL, 1, 0, 0x30 }, 1150000, 1150000, 4 },
-	[19] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 4 },
-	[20] = { { 1404000, HFPLL, 1, 0, 0x34 }, 1150000, 1150000, 4 },
-	[21] = { { 1458000, HFPLL, 1, 0, 0x36 }, 1150000, 1150000, 5 },
-	[22] = { { 1512000, HFPLL, 1, 0, 0x38 }, 1150000, 1150000, 5 },
-	[23] = { { 1566000, HFPLL, 1, 0, 0x3A }, 1150000, 1150000, 5 },
-	[24] = { { 1620000, HFPLL, 1, 0, 0x3C }, 1150000, 1150000, 5 },
-	[25] = { { 1674000, HFPLL, 1, 0, 0x3E }, 1150000, 1150000, 5 },
+	[6]  = { {  648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
+	[7]  = { {  702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
+	[8]  = { {  756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
+	[9]  = { {  810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
+	[10] = { {  864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
+	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 7 },
+	[12] = { {  972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 7 },
+	[13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 7 },
+	[14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 7 },
+	[15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 7 },
 };
 
 /* TODO: Update core voltages when data is available. */
 static struct acpu_level acpu_freq_tbl_8064[] = {
-	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),  1050000 },
-	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),  1050000 },
-	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(2),  1050000 },
-	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(3),  1050000 },
-	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(4),  1050000 },
-	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(5),  1050000 },
-	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),  1050000 },
-	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(7),  1050000 },
-	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(8),  1150000 },
-	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(9),  1150000 },
-	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(10), 1150000 },
-	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1150000 },
+	{ 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 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   975000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),  1000000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),  1000000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),  1025000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),  1025000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),  1075000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),  1075000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1100000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1100000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1125000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1125000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1237500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1250000 },
 	{ 0, { 0 } }
 };
 
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 5bef079..97f8722 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -556,8 +556,7 @@
 
 		if (!a2_pc_disabled) {
 			a2_pc_disabled = 1;
-			schedule_delayed_work(&ul_timeout_work,
-				msecs_to_jiffies(UL_TIMEOUT_DELAY));
+			ul_wakeup();
 		}
 
 		handle_bam_mux_cmd_open(rx_hdr);
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 486ebd3..f23bf2a 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -102,6 +102,13 @@
 
 static struct msm_gpiomux_config apq8064_cam_common_configs[] = {
 	{
+		.gpio = 1,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[2],
+			[GPIOMUX_SUSPENDED] = &cam_settings[0],
+		},
+	},
+	{
 		.gpio = 2,
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[12],
@@ -111,7 +118,7 @@
 	{
 		.gpio = 3,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[1],
+			[GPIOMUX_ACTIVE]    = &cam_settings[2],
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
 		},
 	},
@@ -173,6 +180,16 @@
 	},
 };
 
+
+#define VFE_CAMIF_TIMER1_GPIO 3
+#define VFE_CAMIF_TIMER2_GPIO 1
+
+static struct msm_camera_sensor_flash_src msm_flash_src = {
+	.flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
+	._fsrc.ext_driver_src.led_en = VFE_CAMIF_TIMER1_GPIO,
+	._fsrc.ext_driver_src.led_flash_en = VFE_CAMIF_TIMER2_GPIO,
+};
+
 static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
 };
 
@@ -419,7 +436,8 @@
 };
 
 static struct msm_camera_sensor_flash_data flash_imx074 = {
-	.flash_type	= MSM_CAMERA_FLASH_NONE,
+	.flash_type	= MSM_CAMERA_FLASH_LED,
+	.flash_src	= &msm_flash_src
 };
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
@@ -518,6 +536,9 @@
 	I2C_BOARD_INFO("ov2720", 0x6C),
 	.platform_data = &msm_camera_sensor_ov2720_data,
 	},
+	{
+	I2C_BOARD_INFO("sc628a", 0x6E),
+	},
 };
 
 struct msm_camera_board_info apq8064_camera_board_info = {
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 213215e..9fbb1c7 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -150,24 +150,23 @@
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
 	.pwrlevel = {
 		{
-			.gpu_freq = 192000000,
-			.bus_freq = 2,
-			.io_fraction = 100,
+			.gpu_freq = 400000000,
+			.bus_freq = 3,
+			.io_fraction = 0,
 		},
 		{
-			.gpu_freq = 192000000,
+			.gpu_freq = 320000000,
 			.bus_freq = 2,
-			.io_fraction = 100,
+			.io_fraction = 33,
 		},
 		{
 			.gpu_freq = 1920000000,
-			.bus_freq = 2,
+			.bus_freq = 1,
 			.io_fraction = 100,
 		},
 		{
-			.gpu_freq = 192000000,
-			.bus_freq = 2,
-			.io_fraction = 100,
+			.gpu_freq = 27000000,
+			.bus_freq = 0,
 		},
 	},
 	.init_level = 0,
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index bd5f703..05002a2 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -310,8 +310,8 @@
 static struct pm8xxx_irq_platform_data
 apq8064_pm8921_irq_pdata __devinitdata = {
 	.irq_base		= PM8921_IRQ_BASE,
-	.devirq			= PM8921_USR_IRQ_N,
-	.irq_trigger_flag	= IRQF_TRIGGER_HIGH,
+	.devirq			= MSM_GPIO_TO_INT(74),
+	.irq_trigger_flag	= IRQF_TRIGGER_LOW,
 	.dev_id			= 0,
 };
 
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 247b230..5a1957b 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -469,15 +469,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, 1150000);
+	SAW_VREG_INIT(S5, "8921_s5",	       950000, 1300000);
 struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6 =
-	SAW_VREG_INIT(S6, "8921_s6",	       950000, 1150000);
+	SAW_VREG_INIT(S6, "8921_s6",	       950000, 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, 1150000);
+	SAW_VREG_INIT(8821_S0, "8821_s0",       950000, 1300000);
 struct regulator_init_data msm8064_saw_regulator_pdata_8821_s1 =
-	SAW_VREG_INIT(8821_S1, "8821_s1",       950000, 1150000);
+	SAW_VREG_INIT(8821_S1, "8821_s1",       950000, 1300000);
 
 /* PM8921 regulator constraints */
 struct pm8xxx_regulator_platform_data
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 2f94a2e..9d4f0aa 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -16,8 +16,8 @@
 #include <linux/irq.h>
 #include <linux/i2c.h>
 #include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
 #include <linux/mfd/pm8xxx/misc.h>
 #include <linux/msm_ssbi.h>
 #include <linux/spi/spi.h>
@@ -54,10 +54,12 @@
 #include <linux/bootmem.h>
 #include <asm/setup.h>
 #include <mach/dma.h>
+#include <mach/msm_dsps.h>
 #include <mach/msm_bus_board.h>
 #include <mach/cpuidle.h>
 #include <mach/mdm2.h>
 #include <linux/msm_tsens.h>
+#include <mach/msm_xo.h>
 
 #include "msm_watchdog.h"
 #include "board-8064.h"
@@ -499,14 +501,14 @@
  * does not need to be as high as 2.85V. It is choosen for
  * microphone sensitivity purpose.
  */
-static struct tabla_pdata apq8064_tabla_platform_data = {
+static struct wcd9xxx_pdata apq8064_tabla_platform_data = {
 	.slimbus_slave_device = {
 		.name = "tabla-slave",
 		.e_addr = {0, 0, 0x10, 0, 0x17, 2},
 	},
 	.irq = MSM_GPIO_TO_INT(42),
 	.irq_base = TABLA_INTERRUPT_BASE,
-	.num_irqs = NR_TABLA_IRQS,
+	.num_irqs = NR_WCD9XXX_IRQS,
 	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
 	.micbias = {
 		.ldoh_v = TABLA_LDOH_2P85_V,
@@ -517,7 +519,45 @@
 		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
 		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
 		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
-	}
+	},
+	.regulator = {
+	{
+		.name = "CDC_VDD_CP",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_RX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_TX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+	},
+	{
+		.name = "VDDIO_CDC",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+	},
+	{
+		.name = "VDDD_CDC_D",
+		.min_uV = 1225000,
+		.max_uV = 1225000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_A_1P2V",
+		.min_uV = 1225000,
+		.max_uV = 1225000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+	},
+	},
 };
 
 static struct slim_device apq8064_slim_tabla = {
@@ -528,14 +568,14 @@
 	},
 };
 
-static struct tabla_pdata apq8064_tabla20_platform_data = {
+static struct wcd9xxx_pdata apq8064_tabla20_platform_data = {
 	.slimbus_slave_device = {
 		.name = "tabla-slave",
 		.e_addr = {0, 0, 0x60, 0, 0x17, 2},
 	},
 	.irq = MSM_GPIO_TO_INT(42),
 	.irq_base = TABLA_INTERRUPT_BASE,
-	.num_irqs = NR_TABLA_IRQS,
+	.num_irqs = NR_WCD9XXX_IRQS,
 	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
 	.micbias = {
 		.ldoh_v = TABLA_LDOH_2P85_V,
@@ -546,7 +586,45 @@
 		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
 		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
 		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
-	}
+	},
+	.regulator = {
+	{
+		.name = "CDC_VDD_CP",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_RX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_TX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+	},
+	{
+		.name = "VDDIO_CDC",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+	},
+	{
+		.name = "VDDD_CDC_D",
+		.min_uV = 1225000,
+		.max_uV = 1225000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_A_1P2V",
+		.min_uV = 1225000,
+		.max_uV = 1225000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+	},
+	},
 };
 
 static struct slim_device apq8064_slim_tabla20 = {
@@ -1770,6 +1848,18 @@
 	},
 };
 
+/* Sensors DSPS platform data */
+#define DSPS_PIL_GENERIC_NAME		"dsps"
+static void __init apq8064_init_dsps(void)
+{
+	struct msm_dsps_platform_data *pdata =
+		msm_dsps_device_8064.dev.platform_data;
+	pdata->pil_name = DSPS_PIL_GENERIC_NAME;
+	pdata->gpios = NULL;
+	pdata->gpios_num = 0;
+
+	platform_device_register(&msm_dsps_device_8064);
+}
 
 static void __init apq8064_clock_init(void)
 {
@@ -1863,6 +1953,8 @@
 	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
 	regulator_suppress_info_printing();
 	platform_device_register(&apq8064_device_rpm_regulator);
+	if (msm_xo_init())
+		pr_err("Failed to initialize XO votes\n");
 	apq8064_clock_init();
 	apq8064_init_gpiomux();
 	apq8064_i2c_init();
@@ -1891,6 +1983,7 @@
 	platform_device_register(&apq8064_slim_ctrl);
 	slim_register_board_info(apq8064_slim_devices,
 		ARRAY_SIZE(apq8064_slim_devices));
+	apq8064_init_dsps();
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
 	acpuclk_init(&acpuclk_8064_soc_data);
 	msm_spm_l2_init(msm_spm_l2_data);
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index dee1e98..e89bed4 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -122,8 +122,8 @@
 
 static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
 	{TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
-	{TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
-	{TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+	{TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+	{TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
 };
 
 /* SDC3 pad data */
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index ad71007..278c08c 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -42,6 +42,10 @@
 #include <linux/gpio_keys.h>
 #include <linux/memory.h>
 
+#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
@@ -68,12 +72,6 @@
 #include <mach/msm_xo.h>
 #include <mach/restart.h>
 
-#ifdef CONFIG_WCD9310_CODEC
-#include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/pdata.h>
-#endif
-
 #include <linux/ion.h>
 #include <mach/ion.h>
 #include <mach/mdm2.h>
@@ -518,9 +516,9 @@
 	msm8930_allocate_fb_region();
 }
 
-#ifdef CONFIG_WCD9310_CODEC
+#ifdef CONFIG_WCD9304_CODEC
 
-#define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
+#define SITAR_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
 
 /* Micbias setting is based on 8660 CDP/MTP/FLUID requirement
  * 4 micbiases are used to power various analog and digital
@@ -531,82 +529,77 @@
  * does not need to be as high as 2.85V. It is choosen for
  * microphone sensitivity purpose.
  */
-static struct tabla_pdata tabla_platform_data = {
-	.slimbus_slave_device = {
-		.name = "tabla-slave",
-		.e_addr = {0, 0, 0x10, 0, 0x17, 2},
+static struct wcd9xxx_pdata sitar_platform_data = {
+		.slimbus_slave_device = {
+		.name = "sitar-slave",
+		.e_addr = {0, 0, 0x00, 0, 0x17, 2},
 	},
 	.irq = MSM_GPIO_TO_INT(62),
-	.irq_base = TABLA_INTERRUPT_BASE,
-	.num_irqs = NR_TABLA_IRQS,
-
-/*TODO: Replace this with right PM8038 gpio */
-#ifndef MSM8930_PHASE_2
-	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
-#endif
+	.irq_base = SITAR_INTERRUPT_BASE,
+	.num_irqs = NR_WCD9XXX_IRQS,
+	.reset_gpio = 42,
 	.micbias = {
-		.ldoh_v = TABLA_LDOH_2P85_V,
+		.ldoh_v = SITAR_LDOH_2P85_V,
 		.cfilt1_mv = 1800,
 		.cfilt2_mv = 1800,
-		.cfilt3_mv = 1800,
-		.bias1_cfilt_sel = TABLA_CFILT1_SEL,
-		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
-		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
-		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
-	}
-};
-
-static struct slim_device msm_slim_tabla = {
-	.name = "tabla-slim",
-	.e_addr = {0, 1, 0x10, 0, 0x17, 2},
-	.dev = {
-		.platform_data = &tabla_platform_data,
+		.bias1_cfilt_sel = SITAR_CFILT1_SEL,
+		.bias2_cfilt_sel = SITAR_CFILT2_SEL,
+	},
+	.regulator = {
+	{
+		.name = "CDC_VDD_CP",
+		.min_uV = 2200000,
+		.max_uV = 2200000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_RX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_TX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+	},
+	{
+		.name = "VDDIO_CDC",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+	},
+	{
+		.name = "VDDD_CDC_D",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_A_1P2V",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+	},
 	},
 };
 
-static struct tabla_pdata tabla20_platform_data = {
-	.slimbus_slave_device = {
-		.name = "tabla-slave",
-		.e_addr = {0, 0, 0x60, 0, 0x17, 2},
-	},
-	.irq = MSM_GPIO_TO_INT(62),
-	.irq_base = TABLA_INTERRUPT_BASE,
-	.num_irqs = NR_TABLA_IRQS,
-
-/*TODO: Replace this with right PM8038 gpio */
-#ifndef MSM8930_PHASE_2
-	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
-#endif
-	.micbias = {
-		.ldoh_v = TABLA_LDOH_2P85_V,
-		.cfilt1_mv = 1800,
-		.cfilt2_mv = 1800,
-		.cfilt3_mv = 1800,
-		.bias1_cfilt_sel = TABLA_CFILT1_SEL,
-		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
-		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
-		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
-	}
-};
-
-static struct slim_device msm_slim_tabla20 = {
-	.name = "tabla2x-slim",
-	.e_addr = {0, 1, 0x60, 0, 0x17, 2},
+static struct slim_device msm_slim_sitar = {
+	.name = "sitar-slim",
+	.e_addr = {0, 1, 0x00, 0, 0x17, 2},
 	.dev = {
-		.platform_data = &tabla20_platform_data,
+	.platform_data = &sitar_platform_data,
 	},
 };
 #endif
 
+
 static struct slim_boardinfo msm_slim_devices[] = {
-#ifdef CONFIG_WCD9310_CODEC
+#ifdef CONFIG_WCD9304_CODEC
 	{
 		.bus_num = 1,
-		.slim_slave = &msm_slim_tabla,
-	},
-	{
-		.bus_num = 1,
-		.slim_slave = &msm_slim_tabla20,
+		.slim_slave = &msm_slim_sitar,
 	},
 #endif
 	/* add more slimbus slaves as needed */
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index 37a988a..4dba1be 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -670,6 +670,12 @@
 
 	mdp_ui_vectors[0].ab = 2000000000;
 	mdp_ui_vectors[0].ib = 2000000000;
+	mdp_vga_vectors[0].ab = 2000000000;
+	mdp_vga_vectors[0].ib = 2000000000;
+	mdp_720p_vectors[0].ab = 2000000000;
+	mdp_720p_vectors[0].ib = 2000000000;
+	mdp_1080p_vectors[0].ab = 2000000000;
+	mdp_1080p_vectors[0].ib = 2000000000;
 
 	mdp_pdata.mdp_core_clk_rate = 200000000;
 
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index e3646ed..4e18f89 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -564,6 +564,17 @@
 	.r_sense		= 10,
 };
 
+/**
+ * PM8XXX_PWM_DTEST_CHANNEL_NONE shall be used when no LPG
+ * channel should be in DTEST mode.
+ */
+
+#define PM8XXX_PWM_DTEST_CHANNEL_NONE   (-1)
+
+static struct pm8xxx_pwm_platform_data pm8xxx_pwm_pdata = {
+	.dtest_channel	= PM8XXX_PWM_DTEST_CHANNEL_NONE,
+};
+
 static struct pm8921_platform_data pm8921_platform_data __devinitdata = {
 	.irq_pdata		= &pm8xxx_irq_pdata,
 	.gpio_pdata		= &pm8xxx_gpio_pdata,
@@ -578,6 +589,7 @@
 	.adc_pdata		= &pm8xxx_adc_pdata,
 	.leds_pdata		= &pm8xxx_leds_pdata,
 	.ccadc_pdata		= &pm8xxx_ccadc_pdata,
+	.pwm_pdata		= &pm8xxx_pwm_pdata,
 };
 
 static struct msm_ssbi_platform_data msm8960_ssbi_pm8921_pdata __devinitdata = {
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index d98ae56..9c1a439 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -221,7 +221,6 @@
 };
 VREG_CONSUMERS(USB_OTG) = {
 	REGULATOR_SUPPLY("8921_usb_otg",	NULL),
-	REGULATOR_SUPPLY("vbus_otg",		"msm_otg"),
 };
 VREG_CONSUMERS(HDMI_MVS) = {
 	REGULATOR_SUPPLY("8921_hdmi_mvs",	NULL),
@@ -245,12 +244,12 @@
 };
 VREG_CONSUMERS(EXT_OTG_SW) = {
 	REGULATOR_SUPPLY("ext_otg_sw",		NULL),
+	REGULATOR_SUPPLY("vbus_otg",		"msm_otg"),
 };
 
 #define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
 			 _apply_uV, _pull_down, _always_on, _supply_regulator, \
-			 _system_uA, _enable_time, _reg_id, _ocp_enable, \
-			 _ocp_enable_time) \
+			 _system_uA, _enable_time, _reg_id) \
 	{ \
 		.init_data = { \
 			.constraints = { \
@@ -272,8 +271,6 @@
 		.pull_down_enable	= _pull_down, \
 		.system_uA		= _system_uA, \
 		.enable_time		= _enable_time, \
-		.ocp_enable		= _ocp_enable, \
-		.ocp_enable_time	= _ocp_enable_time, \
 	}
 
 #define PM8XXX_LDO(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
@@ -282,7 +279,7 @@
 		| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
 		REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
 		REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
-		_supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
+		_supply_regulator, _system_uA, _enable_time, _reg_id)
 
 #define PM8XXX_NLDO1200(_id, _name, _always_on, _pull_down, _min_uV, \
 		_max_uV, _enable_time, _supply_regulator, _system_uA, _reg_id) \
@@ -290,7 +287,7 @@
 		| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
 		REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
 		REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
-		_supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
+		_supply_regulator, _system_uA, _enable_time, _reg_id)
 
 #define PM8XXX_SMPS(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
 		_enable_time, _supply_regulator, _system_uA, _reg_id) \
@@ -298,32 +295,32 @@
 		| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
 		REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
 		REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
-		_supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
+		_supply_regulator, _system_uA, _enable_time, _reg_id)
 
 #define PM8XXX_FTSMPS(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
 		_enable_time, _supply_regulator, _system_uA, _reg_id) \
 	PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL, \
 		REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS \
 		| REGULATOR_CHANGE_MODE, 0, _pull_down, _always_on, \
-		_supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
+		_supply_regulator, _system_uA, _enable_time, _reg_id)
 
 #define PM8XXX_VS(_id, _name, _always_on, _pull_down, _enable_time, \
-		_ocp_enable, _ocp_enable_time, _supply_regulator, _reg_id) \
+		_supply_regulator, _reg_id) \
 	PM8XXX_VREG_INIT(_id, _name, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, \
 		_pull_down, _always_on, _supply_regulator, 0, _enable_time, \
-		_reg_id, _ocp_enable, _ocp_enable_time)
+		_reg_id)
 
 #define PM8XXX_VS300(_id, _name, _always_on, _pull_down, _enable_time, \
-		_ocp_enable, _ocp_enable_time, _supply_regulator, _reg_id) \
+		_supply_regulator, _reg_id) \
 	PM8XXX_VREG_INIT(_id, _name, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, \
 		_pull_down, _always_on, _supply_regulator, 0, _enable_time, \
-		_reg_id, _ocp_enable, _ocp_enable_time)
+		_reg_id)
 
 #define PM8XXX_NCP(_id, _name, _always_on, _min_uV, _max_uV, _enable_time, \
 		_supply_regulator, _reg_id) \
 	PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, 0, \
 		REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, 0, 0, \
-		_always_on, _supply_regulator, 0, _enable_time, _reg_id, 0, 0)
+		_always_on, _supply_regulator, 0, _enable_time, _reg_id)
 
 /* Pin control initialization */
 #define PM8XXX_PC(_id, _name, _always_on, _pin_fn, _pin_ctrl, \
@@ -472,7 +469,7 @@
 	GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
 		PM8921_GPIO_PM_TO_SYS(17), NULL),
 	GPIO_VREG(EXT_OTG_SW, "ext_otg_sw", "ext_otg_sw_en",
-		PM8921_GPIO_PM_TO_SYS(42), "ext_5v"),
+		PM8921_GPIO_PM_TO_SYS(42), "8921_usb_otg"),
 };
 
 /* SAW regulator constraints */
@@ -498,13 +495,9 @@
 	PM8XXX_LDO(L29,      "8921_l29", 0, 1, 2050000, 2100000, 200, "8921_s8",
 		0, 4),
 
-	/*
-	 *	     ID       name      always_on pd en_t ocp ocp_t supply
-	 *	reg_ID
-	 */
-	PM8XXX_VS300(USB_OTG,  "8921_usb_otg",  0, 0,   0, 1, 500, "ext_otg_sw",
-		5),
-	PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1,   0, 0,   0, "ext_5v", 6),
+	/*	     ID        name      always_on pd en_t supply    reg_ID */
+	PM8XXX_VS300(USB_OTG,  "8921_usb_otg",  0, 1, 0,   "ext_5v", 5),
+	PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0,   "ext_5v", 6),
 };
 
 static struct rpm_regulator_init_data
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index cb6674c..9a8b843 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -70,9 +70,8 @@
 #include <mach/restart.h>
 
 #ifdef CONFIG_WCD9310_CODEC
-#include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
 #endif
 
 #include <linux/ion.h>
@@ -664,14 +663,14 @@
  * does not need to be as high as 2.85V. It is choosen for
  * microphone sensitivity purpose.
  */
-static struct tabla_pdata tabla_platform_data = {
+static struct wcd9xxx_pdata tabla_platform_data = {
 	.slimbus_slave_device = {
 		.name = "tabla-slave",
 		.e_addr = {0, 0, 0x10, 0, 0x17, 2},
 	},
 	.irq = MSM_GPIO_TO_INT(62),
 	.irq_base = TABLA_INTERRUPT_BASE,
-	.num_irqs = NR_TABLA_IRQS,
+	.num_irqs = NR_WCD9XXX_IRQS,
 	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
 	.micbias = {
 		.ldoh_v = TABLA_LDOH_2P85_V,
@@ -682,7 +681,45 @@
 		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
 		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
 		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
-	}
+	},
+	.regulator = {
+	{
+		.name = "CDC_VDD_CP",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_RX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_TX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+	},
+	{
+		.name = "VDDIO_CDC",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+	},
+	{
+		.name = "VDDD_CDC_D",
+		.min_uV = 1225000,
+		.max_uV = 1225000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_A_1P2V",
+		.min_uV = 1225000,
+		.max_uV = 1225000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+	},
+	},
 };
 
 static struct slim_device msm_slim_tabla = {
@@ -693,14 +730,14 @@
 	},
 };
 
-static struct tabla_pdata tabla20_platform_data = {
+static struct wcd9xxx_pdata tabla20_platform_data = {
 	.slimbus_slave_device = {
 		.name = "tabla-slave",
 		.e_addr = {0, 0, 0x60, 0, 0x17, 2},
 	},
 	.irq = MSM_GPIO_TO_INT(62),
 	.irq_base = TABLA_INTERRUPT_BASE,
-	.num_irqs = NR_TABLA_IRQS,
+	.num_irqs = NR_WCD9XXX_IRQS,
 	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
 	.micbias = {
 		.ldoh_v = TABLA_LDOH_2P85_V,
@@ -711,7 +748,45 @@
 		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
 		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
 		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
-	}
+	},
+	.regulator = {
+	{
+		.name = "CDC_VDD_CP",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_RX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_TX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+	},
+	{
+		.name = "VDDIO_CDC",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+	},
+	{
+		.name = "VDDD_CDC_D",
+		.min_uV = 1225000,
+		.max_uV = 1225000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_A_1P2V",
+		.min_uV = 1225000,
+		.max_uV = 1225000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+	},
+	},
 };
 
 static struct slim_device msm_slim_tabla20 = {
@@ -1817,6 +1892,7 @@
 		.variant_id	= 0x2,
 		.version	= 0x10,
 		.build		= 0xAA,
+		.fw_name	= "atmel_8960_liquid_v2_1_AA.hex",
 	},
 	{
 		.config		= mxt1386e_config_data_v2_1,
@@ -2005,8 +2081,8 @@
 	&msm_device_saw_core0,
 	&msm_device_saw_core1,
 	&msm8960_device_ext_5v_vreg,
-	&msm8960_device_ext_otg_sw_vreg,
 	&msm8960_device_ssbi_pmic,
+	&msm8960_device_ext_otg_sw_vreg,
 	&msm8960_device_qup_spi_gsbi1,
 	&msm8960_device_qup_i2c_gsbi3,
 	&msm8960_device_qup_i2c_gsbi4,
@@ -2044,6 +2120,14 @@
 	&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],
+#else
+	&msm_device_tsif[0],
+#endif
+#endif
+
 #ifdef CONFIG_HW_RANDOM_MSM
 	&msm_device_rng,
 #endif
@@ -2266,62 +2350,62 @@
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
 		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
 		true,
-		100, 8000, 100000, 1,
+		100, 650, 801, 200,
 	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
 		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
 		true,
-		2000, 6000, 60100000, 3000,
+		2000, 200, 576000, 2000,
 	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 		MSM_RPMRS_LIMITS(ON, GDHS, MAX, ACTIVE),
 		false,
-		4200, 5000, 60350000, 3500,
+		8500, 51, 1122000, 8500,
 	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 		MSM_RPMRS_LIMITS(ON, HSFS_OPEN, MAX, ACTIVE),
 		false,
-		6300, 4500, 65350000, 4800,
+		9000, 51, 1130300, 9000,
 	},
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 		MSM_RPMRS_LIMITS(ON, HSFS_OPEN, ACTIVE, RET_HIGH),
 		false,
-		7000, 3500, 66600000, 5150,
+		10000, 51, 1130300, 10000,
 	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 		MSM_RPMRS_LIMITS(OFF, GDHS, MAX, ACTIVE),
 		false,
-		11700, 2500, 67850000, 5500,
+		12000, 14, 2205900, 12000,
 	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 		MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, MAX, ACTIVE),
 		false,
-		13800, 2000, 71850000, 6800,
+		18000, 12, 2364250, 18000,
 	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 		MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, ACTIVE, RET_HIGH),
 		false,
-		29700, 500, 75850000, 8800,
+		23500, 10, 2667000, 23500,
 	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 		MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, RET_HIGH, RET_LOW),
 		false,
-		29700, 0, 76350000, 9800,
+		29700, 5, 2867000, 30000,
 	},
 };
 
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index dc26d72..c30be16 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -37,6 +37,7 @@
 #endif
 #include <mach/msm_memtypes.h>
 #include <mach/msm_smd.h>
+#include <mach/qpnp-int.h>
 #include "clock.h"
 
 #define MSM_KERNEL_EBI1_MEM_SIZE	0x280000
@@ -361,6 +362,7 @@
 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, },
 	{}
 };
 
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index c70b30e..644c0855 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -32,7 +32,7 @@
 	{"bt", 21, 2900000, 3300000, 1, NULL}
 };
 
-struct platform_device msm_bt_power_device = {
+static struct platform_device msm_bt_power_device = {
 	.name = "bt_power",
 };
 
@@ -100,7 +100,7 @@
 {
 	if (machine_is_msm7627a_qrd1())
 		gpio_bt_sys_rest_en = 114;
-	if (machine_is_msm7627a_evb())
+	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
 		gpio_bt_sys_rest_en = 16;
 }
 
@@ -324,7 +324,8 @@
 	int pin, rc = 0;
 
 	if (mode == FM_I2S_ON) {
-		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf())
+		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
+				|| machine_is_msm8625_surf())
 			config_pcm_i2s_mode(0);
 		pr_err("%s mode = FM_I2S_ON", __func__);
 
@@ -367,7 +368,8 @@
 	int pin, rc = 0;
 
 	if (mode == BT_PCM_ON) {
-		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf())
+		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
+				|| machine_is_msm8625_surf())
 			config_pcm_i2s_mode(1);
 		pr_err("%s mode =BT_PCM_ON", __func__);
 		rc = switch_pcm_i2s_reg_mode(1);
@@ -940,9 +942,20 @@
 
 	gpio_bt_config();
 
-	i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
-			bahama_devices,
-			ARRAY_SIZE(bahama_devices));
+	rc = i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
+				bahama_devices,
+				ARRAY_SIZE(bahama_devices));
+	if (rc < 0) {
+		pr_err("%s: I2C Register failed\n", __func__);
+		return;
+	}
+
+	rc = platform_device_register(&msm_bt_power_device);
+	if (rc < 0) {
+		pr_err("%s: device register failed\n", __func__);
+		return;
+	}
+
 	dev = &msm_bt_power_device.dev;
 
 	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
@@ -964,6 +977,6 @@
 		regulator_put(bt_vregs[i].reg);
 		bt_vregs[i].reg = NULL;
 	}
-	return;
+	platform_device_unregister(&msm_bt_power_device);
 }
 #endif
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 06fbb7b..7b075cd 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -1041,7 +1041,7 @@
 
 	pr_debug("msm7627a_camera_init Entered\n");
 	/* LCD and camera power (VREG & LDO) init */
-	if (machine_is_msm7627a_evb())
+	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
 		lcd_camera_power_init();
 
 #ifndef CONFIG_MSM_CAMERA_V4L2
@@ -1049,7 +1049,7 @@
 		qrd1_camera_gpio_cfg();
 		platform_add_devices(camera_devices_qrd,
 				ARRAY_SIZE(camera_devices_qrd));
-	} else if (machine_is_msm7627a_evb()) {
+	} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
 		evb_camera_gpio_cfg();
 		platform_add_devices(camera_devices_evb,
 				ARRAY_SIZE(camera_devices_evb));
@@ -1059,7 +1059,8 @@
 		platform_add_devices(camera_devices_msm,
 				ARRAY_SIZE(camera_devices_msm));
 #endif
-	if (!machine_is_msm7627a_qrd1() || !machine_is_msm7627a_evb())
+	if (!machine_is_msm7627a_qrd1() || !machine_is_msm7627a_evb()
+					|| !machine_is_msm8625_evb())
 		register_i2c_devices();
 	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
 
@@ -1083,7 +1084,7 @@
 		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
 				i2c_camera_devices_qrd,
 				ARRAY_SIZE(i2c_camera_devices_qrd));
-	} else if (machine_is_msm7627a_evb()) {
+	} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
 		pr_debug("machine_is_msm7627a_evb i2c_register_board_info\n");
 		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
 				i2c_camera_devices_evb,
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 4e856b1..45bfaed 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -216,7 +216,8 @@
 {
 	int ret = -ENODEV;
 
-	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
+			machine_is_msm8625_surf()) {
 		if (!strncmp(name, "lcdc_toshiba_fwvga_pt", 21) ||
 				!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
 			ret = 0;
@@ -226,7 +227,7 @@
 	} else if (machine_is_msm7627a_qrd1()) {
 		if (!strncmp(name, "mipi_video_truly_wvga", 21))
 			ret = 0;
-	} else if (machine_is_msm7627a_evb()) {
+	} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
 		if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
 			ret = 0;
 	}
@@ -235,7 +236,8 @@
 	!defined(CONFIG_FB_MSM_MIPI_PANEL_AUTO_DETECT) && \
 	!defined(CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT)
 		if (machine_is_msm7x27a_surf() ||
-			machine_is_msm7625a_surf()) {
+			machine_is_msm7625a_surf() ||
+			machine_is_msm8625_surf()) {
 			if (!strncmp(name, LCDC_TOSHIBA_FWVGA_PANEL_NAME,
 				strnlen(LCDC_TOSHIBA_FWVGA_PANEL_NAME,
 					PANEL_NAME_MAX_LEN)))
@@ -427,7 +429,8 @@
 	gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
 
 	if (!rc) {
-		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
+				|| machine_is_msm8625_surf()) {
 			lcdc_reset_ptr = ioremap_nocache(LCDC_RESET_PHYS,
 				sizeof(uint32_t));
 
@@ -555,7 +558,7 @@
 
 	if (machine_is_msm7627a_qrd1())
 		rc = msm_fb_dsi_client_qrd1_reset();
-	else if (machine_is_msm7627a_evb())
+	else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
 		rc = msm_fb_dsi_client_qrd3_reset();
 	else
 		rc = msm_fb_dsi_client_msm_reset();
@@ -586,7 +589,8 @@
 			return rc;
 		}
 
-		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
+				|| machine_is_msm8625_surf()) {
 			rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, 1);
 			if (rc < 0) {
 				pr_err("failed to enable display pwr\n");
@@ -625,7 +629,8 @@
 
 		dsi_gpio_initialized = 1;
 	}
-	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
+			machine_is_msm8625_surf()) {
 		gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
 		gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
 	} else if (machine_is_msm7x27a_ffa() ||
@@ -649,7 +654,8 @@
 		gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
 
 		if (machine_is_msm7x27a_surf() ||
-				 machine_is_msm7625a_surf()) {
+				 machine_is_msm7625a_surf() ||
+				 machine_is_msm8625_surf()) {
 			lcdc_reset_cfg = readl_relaxed(lcdc_reset_ptr);
 			rmb();
 			lcdc_reset_cfg &= ~1;
@@ -817,7 +823,7 @@
 
 	if (machine_is_msm7627a_qrd1())
 		rc = mipi_dsi_panel_qrd1_power(on);
-	else if (machine_is_msm7627a_evb())
+	else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
 		rc = mipi_dsi_panel_qrd3_power(on);
 	else
 		rc = mipi_dsi_panel_msm_power(on);
@@ -840,7 +846,7 @@
 	if (machine_is_msm7627a_qrd1())
 		platform_add_devices(qrd_fb_devices,
 				ARRAY_SIZE(qrd_fb_devices));
-	else if (machine_is_msm7627a_evb())
+	else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
 		platform_add_devices(evb_fb_devices,
 				ARRAY_SIZE(evb_fb_devices));
 	else if (machine_is_msm7627a_qrd3())
@@ -850,7 +856,8 @@
 				ARRAY_SIZE(msm_fb_devices));
 
 	msm_fb_register_device("mdp", &mdp_pdata);
-	if (machine_is_msm7625a_surf() || machine_is_msm7x27a_surf())
+	if (machine_is_msm7625a_surf() || machine_is_msm7x27a_surf() ||
+			machine_is_msm8625_surf())
 		msm_fb_register_device("lcdc", &lcdc_pdata);
 #ifdef CONFIG_FB_MSM_MDP303
 	msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 88a519d..e4ee52e 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -19,6 +19,7 @@
 #include <mach/board.h>
 
 #include "devices.h"
+#include "pm.h"
 #include "board-msm7627a.h"
 
 #if (defined(CONFIG_MMC_MSM_SDC1_SUPPORT)\
@@ -149,7 +150,8 @@
 static int gpio_sdc1_hw_det = 85;
 static void gpio_sdc1_config(void)
 {
-	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb())
+	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
+					|| machine_is_msm8625_evb())
 		gpio_sdc1_hw_det = 42;
 }
 
@@ -250,7 +252,8 @@
 		status = gpio_direction_input(gpio_sdc1_hw_det);
 		if (!status) {
 			if (machine_is_msm7627a_qrd1() ||
-					machine_is_msm7627a_evb())
+					machine_is_msm7627a_evb() ||
+					machine_is_msm8625_evb())
 				status = !gpio_get_value(gpio_sdc1_hw_det);
 			else
 				status = gpio_get_value(gpio_sdc1_hw_det);
@@ -366,6 +369,8 @@
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 	if (mmc_regulator_init(3, "emmc", 3000000))
 		return;
+	sdc3_plat_data.swfi_latency = msm7627a_power_collapse_latency(
+			MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
 	msm_add_sdcc(3, &sdc3_plat_data);
 #endif
 	/* Micro-SD slot */
@@ -374,6 +379,8 @@
 	if (mmc_regulator_init(1, "mmc", 2850000))
 		return;
 	sdc1_plat_data.status_irq = MSM_GPIO_TO_INT(gpio_sdc1_hw_det);
+	sdc1_plat_data.swfi_latency = msm7627a_power_collapse_latency(
+			MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
 	msm_add_sdcc(1, &sdc1_plat_data);
 #endif
 	/* SDIO WLAN slot */
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index 6df7626..53d3c56 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -48,7 +48,8 @@
 int gpio_wlan_sys_rest_en = 134;
 static void gpio_wlan_config(void)
 {
-	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb())
+	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
+					|| machine_is_msm8625_evb())
 		gpio_wlan_sys_rest_en = 124;
 }
 
@@ -229,7 +230,8 @@
 	 * gpio_wlan_sys_rest_en is not from the GPIO expander for QRD7627a,
 	 * EVB1.0 and QRD8625,so the below step is required for those devices.
 	 */
-	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()) {
+	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
+					|| machine_is_msm8625_evb()) {
 		rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
 					GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
 					GPIO_CFG_2MA), GPIO_CFG_ENABLE);
@@ -302,7 +304,8 @@
 	 * gpio_wlan_sys_rest_en is not from the GPIO expander for QRD7627a,
 	 * EVB1.0 and QRD8625,so the below step is required for those devices.
 	 */
-	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()) {
+	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
+					|| machine_is_msm8625_evb()) {
 		rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
 					GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
 					GPIO_CFG_2MA), GPIO_CFG_ENABLE);
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index b0481a0..bde9b61 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -13,6 +13,7 @@
 #ifndef __ARCH_ARM_MACH_MSM_BOARD_7627A__
 #define __ARCH_ARM_MACH_MSM_BOARD_7627A__
 
+#include "pm.h"
 void __init msm7627a_init_mmc(void);
 
 void __init msm_msm7627a_allocate_memory_regions(void);
@@ -65,6 +66,7 @@
 	QRD_GPIO_CAM_GP_CAMIF_RESET,
 };
 
+#define ADSP_RPC_PROG           0x3000000a
 #if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
 
 #define FPGA_MSM_CNTRL_REG2 0x90008010
@@ -97,11 +99,9 @@
 	struct regulator *reg;
 };
 
-extern struct platform_device msm_bt_power_device;
-
 void __init msm7627a_bt_power_init(void);
 #endif
 
 void __init msm7627a_camera_init(void);
-
+u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode);
 #endif
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index d5d8edc..34ae4c8 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -92,6 +92,7 @@
 
 #define PMEM_KERNEL_EBI1_SIZE	0x1C000
 #endif
+#define ADSP_RPC_PROG           0x3000000a
 
 static struct resource smc91x_resources[] = {
 	[0] = {
@@ -1731,6 +1732,25 @@
 	}
 }
 
+static void msm_adsp_add_pdev(void)
+{
+	int rc = 0;
+	struct rpc_board_dev *rpc_adsp_pdev;
+
+	rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+	if (rpc_adsp_pdev == NULL) {
+		pr_err("%s: Memory Allocation failure\n", __func__);
+		return;
+	}
+	rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+	rpc_adsp_pdev->pdev = msm_adsp_device;
+	rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+	if (rc < 0) {
+		pr_err("%s: return val: %d\n",	__func__, rc);
+		kfree(rpc_adsp_pdev);
+	}
+}
+
 static void __init msm7x2x_init(void)
 {
 
@@ -1797,6 +1817,7 @@
 #ifdef CONFIG_MSM_CAMERA
 	config_camera_off_gpios(); /* might not be necessary */
 #endif
+	msm_adsp_add_pdev();
 	msm_device_i2c_init();
 	i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
 
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index a6b29dc..3ad4773 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -14,6 +14,7 @@
 #include <linux/gpio_event.h>
 #include <linux/memblock.h>
 #include <asm/mach-types.h>
+#include <linux/memblock.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 #include <mach/board.h>
@@ -93,7 +94,8 @@
 
 static void __init register_i2c_devices(void)
 {
-	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf())
+	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
+			machine_is_msm8625_surf())
 		sx150x_data[SX150X_CORE].io_open_drain_ena = 0xe0f0;
 
 	core_exp_i2c_info[0].platform_data =
@@ -153,10 +155,6 @@
 	.msm_i2c_config_gpio	= gsbi_qup_i2c_gpio_config,
 };
 
-static struct msm_i2c_platform_data msm8625_gsbi0_qup_i2c_pdata = {
-	.clk_freq		= 100000,
-};
-
 #ifdef CONFIG_ARCH_MSM7X27A
 #define MSM_PMEM_MDP_SIZE       0x2300000
 #define MSM7x25A_MSM_PMEM_MDP_SIZE       0x1500000
@@ -361,11 +359,97 @@
 	},
 };
 
+u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode mode)
+{
+	switch (mode) {
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+		return msm7x27a_pm_data
+		[MSM_PM_SLEEP_MODE_POWER_COLLAPSE].latency;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN:
+		return msm7x27a_pm_data
+		[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN].latency;
+	case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
+		return msm7x27a_pm_data
+		[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
+	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+		return msm7x27a_pm_data
+		[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
+	default:
+		return 0;
+	}
+}
+
 static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
 	.mode = MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS,
 	.p_addr = 0,
 };
 
+/* 8625 PM platform data */
+static struct msm_pm_platform_data msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+	/* CORE0 entries */
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 0,
+					.suspend_enabled = 0,
+					.latency = 16000,
+					.residency = 20000,
+	},
+
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 0,
+					.suspend_enabled = 0,
+					.latency = 12000,
+					.residency = 20000,
+	},
+
+	/* picked latency & redisdency values from 7x30 */
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 0,
+					.suspend_enabled = 0,
+					.latency = 500,
+					.residency = 6000,
+	},
+
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 1,
+					.suspend_enabled = 1,
+					.latency = 2,
+					.residency = 10,
+	},
+
+	/* picked latency & redisdency values from 7x30 */
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 0,
+					.suspend_enabled = 0,
+					.latency = 500,
+					.residency = 6000,
+	},
+
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 1,
+					.suspend_enabled = 1,
+					.latency = 2,
+					.residency = 10,
+	},
+
+};
+
+static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = {
+	.mode = MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR,
+	.v_addr = MSM_CFG_CTL_BASE,
+};
+
 static struct android_pmem_platform_data android_pmem_adsp_pdata = {
 	.name = "pmem_adsp",
 	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
@@ -697,37 +781,50 @@
 
 static struct platform_device *msm8625_rumi3_devices[] __initdata = {
 	&msm8625_device_dmov,
+	&msm8625_device_smd,
 	&msm8625_device_uart1,
-	&msm8625_device_qup_i2c_gsbi0,
+	&msm8625_gsbi0_qup_i2c_device,
 };
 
-static struct platform_device *surf_ffa_devices[] __initdata = {
+static struct platform_device *msm7627a_surf_ffa_devices[] __initdata = {
 	&msm_device_dmov,
 	&msm_device_smd,
 	&msm_device_uart1,
 	&msm_device_uart_dm1,
 	&msm_device_uart_dm2,
-	&msm_device_nand,
 	&msm_gsbi0_qup_i2c_device,
 	&msm_gsbi1_qup_i2c_device,
 	&msm_device_otg,
 	&msm_device_gadget_peripheral,
-	&fmem_device,
+	&smsc911x_device,
+	&msm_kgsl_3d0,
+};
+
+static struct platform_device *common_devices[] __initdata = {
 	&android_usb_device,
 	&android_pmem_device,
 	&android_pmem_adsp_device,
 	&android_pmem_audio_device,
+	&fmem_device,
+	&msm_device_nand,
 	&msm_device_snd,
 	&msm_device_adspdec,
-	&msm_batt_device,
-	&smsc911x_device,
-	&msm_kgsl_3d0,
-#ifdef CONFIG_BT
-	&msm_bt_power_device,
-#endif
 	&asoc_msm_pcm,
 	&asoc_msm_dai0,
 	&asoc_msm_dai1,
+	&msm_batt_device,
+};
+
+static struct platform_device *msm8625_surf_devices[] __initdata = {
+	&msm8625_device_dmov,
+	&msm8625_device_uart1,
+	&msm8625_device_uart_dm1,
+	&msm8625_device_uart_dm2,
+	&msm8625_gsbi0_qup_i2c_device,
+	&msm8625_gsbi1_qup_i2c_device,
+	&msm8625_device_smd,
+	&msm8625_device_otg,
+	&msm8625_device_gadget_peripheral,
 };
 
 static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
@@ -849,21 +946,25 @@
 
 static void __init msm8625_reserve(void)
 {
+	msm7x27a_reserve();
 	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+	msm_pm_8625_boot_pdata.p_addr = memblock_alloc(SZ_8, SZ_64K);
 }
 
-static void __init msm_device_i2c_init(void)
+static void __init msm7x27a_device_i2c_init(void)
 {
-	if (machine_is_msm8625_rumi3()) {
-		msm8625_device_qup_i2c_gsbi0.dev.platform_data =
-			&msm8625_gsbi0_qup_i2c_pdata;
-		return;
-	}
-
 	msm_gsbi0_qup_i2c_device.dev.platform_data = &msm_gsbi0_qup_i2c_pdata;
 	msm_gsbi1_qup_i2c_device.dev.platform_data = &msm_gsbi1_qup_i2c_pdata;
 }
 
+static void __init msm8625_device_i2c_init(void)
+{
+	msm8625_gsbi0_qup_i2c_device.dev.platform_data =
+		&msm_gsbi0_qup_i2c_pdata;
+	msm8625_gsbi1_qup_i2c_device.dev.platform_data =
+		&msm_gsbi1_qup_i2c_pdata;
+}
+
 #define MSM_EBI2_PHYS			0xa0d00000
 #define MSM_EBI2_XMEM_CS2_CFG1		0xa0d10030
 
@@ -878,7 +979,7 @@
 
 	ebi2_cfg = readl(ebi2_cfg_ptr);
 	if (machine_is_msm7x27a_rumi3() || machine_is_msm7x27a_surf() ||
-			machine_is_msm7625a_surf())
+		machine_is_msm7625a_surf() || machine_is_msm8625_surf())
 		ebi2_cfg |= (1 << 4); /* CS2 */
 
 	writel(ebi2_cfg, ebi2_cfg_ptr);
@@ -1115,6 +1216,29 @@
 	}
 };
 
+static void msm_adsp_add_pdev(void)
+{
+	int rc = 0;
+	struct rpc_board_dev *rpc_adsp_pdev;
+
+	rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+	if (rpc_adsp_pdev == NULL) {
+		pr_err("%s: Memory Allocation failure\n", __func__);
+		return;
+	}
+	rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+
+	if (cpu_is_msm8625())
+		rpc_adsp_pdev->pdev = msm8625_device_adsp;
+	else
+		rpc_adsp_pdev->pdev = msm_adsp_device;
+	rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+	if (rc < 0) {
+		pr_err("%s: return val: %d\n",	__func__, rc);
+		kfree(rpc_adsp_pdev);
+	}
+}
+
 static void __init msm7627a_rumi3_init(void)
 {
 	msm7x27a_init_ebi2();
@@ -1125,9 +1249,15 @@
 static void __init msm8625_rumi3_init(void)
 {
 	msm7x2x_misc_init();
-	msm_device_i2c_init();
+	msm_adsp_add_pdev();
+	msm8625_device_i2c_init();
 	platform_add_devices(msm8625_rumi3_devices,
 			ARRAY_SIZE(msm8625_rumi3_devices));
+
+	msm_pm_set_platform_data(msm8625_pm_data,
+			 ARRAY_SIZE(msm8625_pm_data));
+	BUG_ON(msm_pm_boot_init(&msm_pm_8625_boot_pdata));
+	msm8x25_spm_device_init();
 }
 
 #define LED_GPIO_PDM		96
@@ -1151,55 +1281,56 @@
 				__func__, rc);
 }
 
-static void __init msm7x2x_init(void)
+static void __init msm7x27a_add_footswitch_devices(void)
 {
-	msm7x2x_misc_init();
-
-	/* Initialize regulators first so that other devices can use them */
-	msm7x27a_init_regulators();
-
-	/* Common functions for SURF/FFA/RUMI3 */
-	msm_device_i2c_init();
-	msm7x27a_init_ebi2();
-	msm7x27a_cfg_uart2dm_serial();
-#ifdef CONFIG_SERIAL_MSM_HS
-	msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
-	msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata;
-#endif
-
-#ifdef CONFIG_USB_MSM_OTG_72K
-	msm_otg_pdata.swfi_latency =
-		msm7x27a_pm_data
-		[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
-	msm_device_otg.dev.platform_data = &msm_otg_pdata;
-#endif
-	msm_device_gadget_peripheral.dev.platform_data =
-		&msm_gadget_pdata;
-	msm7x27a_cfg_smsc911x();
 	platform_add_devices(msm_footswitch_devices,
 			msm_num_footswitch_devices);
-	platform_add_devices(surf_ffa_devices,
-			ARRAY_SIZE(surf_ffa_devices));
-	/* Ensure ar6000pm device is registered before MMC/SDC */
-	msm7x27a_init_ar6000pm();
-#ifdef CONFIG_MMC_MSM
-	msm7627a_init_mmc();
-#endif
-	msm_fb_add_devices();
-#ifdef CONFIG_USB_EHCI_MSM_72K
-	msm7x2x_init_host();
-#endif
+}
 
-	msm_pm_set_platform_data(msm7x27a_pm_data,
-				ARRAY_SIZE(msm7x27a_pm_data));
-	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+static void __init msm7x27a_add_platform_devices(void)
+{
+	if (machine_is_msm8625_surf()) {
+		platform_add_devices(msm8625_surf_devices,
+			ARRAY_SIZE(msm8625_surf_devices));
+	} else {
+		platform_add_devices(msm7627a_surf_ffa_devices,
+			ARRAY_SIZE(msm7627a_surf_ffa_devices));
+	}
 
-#if defined(CONFIG_I2C) && defined(CONFIG_GPIO_SX150X)
-	register_i2c_devices();
-#endif
-#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
-	msm7627a_bt_power_init();
-#endif
+	platform_add_devices(common_devices,
+			ARRAY_SIZE(common_devices));
+}
+
+static void __init msm7x27a_uartdm_config(void)
+{
+	msm7x27a_cfg_uart2dm_serial();
+	msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
+	if (cpu_is_msm8625())
+		msm8625_device_uart_dm1.dev.platform_data =
+			&msm_uart_dm1_pdata;
+	else
+		msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata;
+}
+
+static void __init msm7x27a_otg_gadget(void)
+{
+	msm_otg_pdata.swfi_latency =
+		msm7x27a_pm_data[
+		MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
+	if (cpu_is_msm8625()) {
+		msm8625_device_otg.dev.platform_data = &msm_otg_pdata;
+		msm8625_device_gadget_peripheral.dev.platform_data =
+			&msm_gadget_pdata;
+	} else {
+		msm_device_otg.dev.platform_data = &msm_otg_pdata;
+		msm_device_gadget_peripheral.dev.platform_data =
+			&msm_gadget_pdata;
+	}
+}
+
+static void __init msm7x27a_add_io_devices(void)
+{
+	/* touchscreen */
 	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
 		atmel_ts_pdata.min_x = 0;
 		atmel_ts_pdata.max_x = 480;
@@ -1208,16 +1339,15 @@
 	}
 
 	i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
-		atmel_ts_i2c_info,
-		ARRAY_SIZE(atmel_ts_i2c_info));
-
-#if defined(CONFIG_MSM_CAMERA)
-	msm7627a_camera_init();
-#endif
+				atmel_ts_i2c_info,
+				ARRAY_SIZE(atmel_ts_i2c_info));
+	/* keypad */
 	platform_device_register(&kp_pdev);
+
+	/* headset */
 	platform_device_register(&hs_pdev);
 
-	/* configure it as a pdm function*/
+	/* LED: configure it as a pdm function */
 	if (gpio_tlmm_config(GPIO_CFG(LED_GPIO_PDM, 3,
 				GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
 				GPIO_CFG_8MA), GPIO_CFG_ENABLE))
@@ -1226,10 +1356,50 @@
 	else
 		platform_device_register(&led_pdev);
 
-#ifdef CONFIG_MSM_RPC_VIBRATOR
+	/* Vibrator */
 	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
 		msm_init_pmic_vibrator();
-#endif
+}
+
+static void __init msm7x27a_pm_init(void)
+{
+	if (machine_is_msm8625_surf())
+		return;
+
+	msm_pm_set_platform_data(msm7x27a_pm_data,
+			ARRAY_SIZE(msm7x27a_pm_data));
+	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+}
+
+static void __init msm7x2x_init(void)
+{
+	msm7x2x_misc_init();
+
+	/* Initialize regulators first so that other devices can use them */
+	msm7x27a_init_regulators();
+	msm_adsp_add_pdev();
+	if (cpu_is_msm8625())
+		msm8625_device_i2c_init();
+	else
+		msm7x27a_device_i2c_init();
+	msm7x27a_init_ebi2();
+	msm7x27a_uartdm_config();
+
+	msm7x27a_otg_gadget();
+	msm7x27a_cfg_smsc911x();
+
+	msm7x27a_add_footswitch_devices();
+	msm7x27a_add_platform_devices();
+	/* Ensure ar6000pm device is registered before MMC/SDC */
+	msm7x27a_init_ar6000pm();
+	msm7627a_init_mmc();
+	msm_fb_add_devices();
+	msm7x2x_init_host();
+	msm7x27a_pm_init();
+	register_i2c_devices();
+	msm7627a_bt_power_init();
+	msm7627a_camera_init();
+	msm7x27a_add_io_devices();
 	/*7x25a kgsl initializations*/
 	msm7x25a_kgsl_3d0_init();
 }
@@ -1298,3 +1468,13 @@
 	.timer          = &msm_timer,
 	.handle_irq	= gic_handle_irq,
 MACHINE_END
+MACHINE_START(MSM8625_SURF, "QCT MSM8625 SURF")
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = msm8625_map_io,
+	.reserve        = msm8625_reserve,
+	.init_irq       = msm8625_init_irq,
+	.init_machine   = msm7x2x_init,
+	.timer          = &msm_timer,
+	.init_early     = msm7x2x_init_early,
+	.handle_irq	= gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 260c880..9f7104f 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -5236,7 +5236,8 @@
 	&msm_batt_device,
 	&msm_adc_device,
 	&msm_ebi0_thermal,
-	&msm_ebi1_thermal
+	&msm_ebi1_thermal,
+	&msm_adsp_device
 };
 
 static struct msm_gpio msm_i2c_gpios_hw[] = {
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 0427632..61443c3 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -28,9 +28,11 @@
 #include <linux/input/rmi_i2c.h>
 #include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/regulator/consumer.h>
+#include <linux/memblock.h>
 #include <asm/mach/mmc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 #include <mach/msm_hsusb.h>
@@ -659,7 +661,20 @@
 	.dev.platform_data  = &msm_psy_batt_data,
 };
 
-static struct platform_device *qrd_common_devices[] __initdata = {
+static struct platform_device *common_devices[] __initdata = {
+	&android_usb_device,
+	&android_pmem_device,
+	&android_pmem_adsp_device,
+	&android_pmem_audio_device,
+	&msm_batt_device,
+	&msm_device_adspdec,
+	&msm_device_snd,
+	&asoc_msm_pcm,
+	&asoc_msm_dai0,
+	&asoc_msm_dai1,
+};
+
+static struct platform_device *qrd7627a_devices[] __initdata = {
 	&msm_device_dmov,
 	&msm_device_smd,
 	&msm_device_uart1,
@@ -668,26 +683,23 @@
 	&msm_gsbi1_qup_i2c_device,
 	&msm_device_otg,
 	&msm_device_gadget_peripheral,
-	&android_usb_device,
-	&android_pmem_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
-	&msm_device_snd,
-	&msm_device_adspdec,
-	&msm_batt_device,
 	&msm_kgsl_3d0,
-#ifdef CONFIG_BT
-	&msm_bt_power_device,
-#endif
-	&asoc_msm_pcm,
-	&asoc_msm_dai0,
-	&asoc_msm_dai1,
 };
 
 static struct platform_device *qrd3_devices[] __initdata = {
 	&msm_device_nand,
 };
 
+static struct platform_device *msm8625_evb_devices[] __initdata = {
+	&msm8625_device_dmov,
+	&msm8625_device_smd,
+	&msm8625_gsbi0_qup_i2c_device,
+	&msm8625_gsbi1_qup_i2c_device,
+	&msm8625_device_uart1,
+	&msm8625_device_otg,
+	&msm8625_device_gadget_peripheral,
+};
+
 static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
 static int __init pmem_kernel_ebi1_size_setup(char *p)
 {
@@ -762,12 +774,49 @@
 	msm_reserve();
 }
 
-static void __init msm_device_i2c_init(void)
+static void __init msm8625_reserve(void)
+{
+	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+	msm7627a_reserve();
+}
+
+static void msmqrd_adsp_add_pdev(void)
+{
+	int rc = 0;
+	struct rpc_board_dev *rpc_adsp_pdev;
+
+	rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+	if (rpc_adsp_pdev == NULL) {
+		pr_err("%s: Memory Allocation failure\n", __func__);
+		return;
+	}
+	rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+
+	if (cpu_is_msm8625())
+		rpc_adsp_pdev->pdev = msm8625_device_adsp;
+	else
+		rpc_adsp_pdev->pdev = msm_adsp_device;
+	rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+	if (rc < 0) {
+		pr_err("%s: return val: %d\n",	__func__, rc);
+		kfree(rpc_adsp_pdev);
+	}
+}
+
+static void __init msm7627a_device_i2c_init(void)
 {
 	msm_gsbi0_qup_i2c_device.dev.platform_data = &msm_gsbi0_qup_i2c_pdata;
 	msm_gsbi1_qup_i2c_device.dev.platform_data = &msm_gsbi1_qup_i2c_pdata;
 }
 
+static void __init msm8625_device_i2c_init(void)
+{
+	msm8625_gsbi0_qup_i2c_device.dev.platform_data
+					= &msm_gsbi0_qup_i2c_pdata;
+	msm8625_gsbi1_qup_i2c_device.dev.platform_data
+					= &msm_gsbi1_qup_i2c_pdata;
+}
+
 static struct msm_handset_platform_data hs_platform_data = {
 	.hs_name = "7k_handset",
 	.pwr_key_delay_ms = 500, /* 0 will disable end key */
@@ -958,7 +1007,7 @@
 		i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
 					synaptic_i2c_clearpad3k,
 					ARRAY_SIZE(synaptic_i2c_clearpad3k));
-	} else if (machine_is_msm7627a_evb()) {
+	} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
 		rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_IRQ_GPIO, 0,
 				GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
 				GPIO_CFG_8MA), GPIO_CFG_ENABLE);
@@ -989,11 +1038,11 @@
 #endif
 
 	/* keypad */
-	if (machine_is_msm7627a_evb())
+	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
 		platform_device_register(&kp_pdev_8625);
 
 	/* leds */
-	if (machine_is_msm7627a_evb()) {
+	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
 		rc = gpio_tlmm_config(GPIO_CFG(LED_RED_GPIO_8625, 0,
 				GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
 				GPIO_CFG_16MA), GPIO_CFG_ENABLE);
@@ -1022,32 +1071,63 @@
 
 static void add_platform_devices(void)
 {
-	platform_add_devices(qrd_common_devices,
-			ARRAY_SIZE(qrd_common_devices));
-
-	if (machine_is_msm7627a_qrd3())
-		platform_add_devices(qrd3_devices,
-				ARRAY_SIZE(qrd3_devices));
+	if (machine_is_msm8625_evb())
+		platform_add_devices(msm8625_evb_devices,
+				ARRAY_SIZE(msm8625_evb_devices));
+	else {
+		platform_add_devices(qrd7627a_devices,
+				ARRAY_SIZE(qrd7627a_devices));
+		if (machine_is_msm7627a_qrd3())
+			platform_add_devices(qrd3_devices,
+					ARRAY_SIZE(qrd3_devices));
+	}
+	platform_add_devices(common_devices,
+			ARRAY_SIZE(common_devices));
 }
 
 #define UART1DM_RX_GPIO		45
+static void __init qrd7627a_uart1dm_config(void)
+{
+	msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
+	if (cpu_is_msm8625())
+		msm8625_device_uart_dm1.dev.platform_data =
+			&msm_uart_dm1_pdata;
+	else
+		msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata;
+}
+
+static void __init qrd7627a_otg_gadget(void)
+{
+	msm_otg_pdata.swfi_latency = msm7627a_pm_data
+		[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
+
+	if (cpu_is_msm8625()) {
+		msm8625_device_otg.dev.platform_data = &msm_otg_pdata;
+		msm8625_device_gadget_peripheral.dev.platform_data =
+					&msm_gadget_pdata;
+
+	} else {
+		msm_device_otg.dev.platform_data = &msm_otg_pdata;
+		msm_device_gadget_peripheral.dev.platform_data =
+					&msm_gadget_pdata;
+	}
+}
+
 static void __init msm_qrd_init(void)
 {
 	msm7x2x_misc_init();
 	msm7627a_init_regulators();
-	msm_device_i2c_init();
-#ifdef CONFIG_SERIAL_MSM_HS
-	msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
-	msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata;
-#endif
+	msmqrd_adsp_add_pdev();
 
-#ifdef CONFIG_USB_MSM_OTG_72K
-	msm_otg_pdata.swfi_latency = msm7627a_pm_data
-		[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
-	msm_device_otg.dev.platform_data = &msm_otg_pdata;
-#endif
-	msm_device_gadget_peripheral.dev.platform_data =
-		&msm_gadget_pdata;
+	if (cpu_is_msm8625())
+		msm8625_device_i2c_init();
+	else
+		msm7627a_device_i2c_init();
+
+	/* uart1dm*/
+	qrd7627a_uart1dm_config();
+	/*OTG gadget*/
+	qrd7627a_otg_gadget();
 
 	add_platform_devices();
 
@@ -1058,9 +1138,11 @@
 #ifdef CONFIG_USB_EHCI_MSM_72K
 	msm7627a_init_host();
 #endif
-	msm_pm_set_platform_data(msm7627a_pm_data,
+	if (!machine_is_msm8625_evb()) {
+		msm_pm_set_platform_data(msm7627a_pm_data,
 				ARRAY_SIZE(msm7627a_pm_data));
-	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+		BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+	}
 
 	msm_fb_add_devices();
 
@@ -1069,7 +1151,6 @@
 #endif
 
 	msm7627a_camera_init();
-
 	msm7627a_add_io_devices();
 }
 
@@ -1108,3 +1189,13 @@
 	.init_early	= qrd7627a_init_early,
 	.handle_irq	= vic_handle_irq,
 MACHINE_END
+MACHINE_START(MSM8625_EVB, "QRD MSM8625 EVB")
+	.boot_params	= PHYS_OFFSET + 0x100,
+	.map_io		= msm8625_map_io,
+	.reserve	= msm8625_reserve,
+	.init_irq	= msm8625_init_irq,
+	.init_machine	= msm_qrd_init,
+	.timer		= &msm_timer,
+	.init_early	= qrd7627a_init_early,
+	.handle_irq	= gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 5996388..0a3632e 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5045,7 +5045,7 @@
 	CLK_LOOKUP("tv_clk",		mdp_tv_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("hdmi_clk",		hdmi_tv_clk.c,		""),
 	CLK_LOOKUP("core_clk",		hdmi_app_clk.c,		""),
-	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		""),
+	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("core_clk",		vpe_clk.c,	"footswitch-8x60.9"),
 	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("core_clk",		vfe_clk.c,	"footswitch-8x60.8"),
@@ -5082,7 +5082,7 @@
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"footswitch-8x60.7"),
 	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
-	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		""),
+	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
 
 	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
diff --git a/arch/arm/mach-msm/clock-pcom-lookup.c b/arch/arm/mach-msm/clock-pcom-lookup.c
index 200cbfe..c20b7e4 100644
--- a/arch/arm/mach-msm/clock-pcom-lookup.c
+++ b/arch/arm/mach-msm/clock-pcom-lookup.c
@@ -11,9 +11,16 @@
  */
 
 #include "clock.h"
+#include "clock-pll.h"
 #include "clock-pcom.h"
 #include "clock-voter.h"
 
+#include <mach/msm_iomap.h>
+#include <mach/socinfo.h>
+
+#define PLLn_MODE(n)	(MSM_CLK_CTL_BASE + 0x300 + 28 * (n))
+#define PLL4_MODE	(MSM_CLK_CTL_BASE + 0x374)
+
 static DEFINE_CLK_PCOM(adm_clk,		ADM_CLK,	CLKFLAG_SKIP_AUTO_OFF);
 static DEFINE_CLK_PCOM(adsp_clk,	ADSP_CLK,	CLKFLAG_SKIP_AUTO_OFF);
 static DEFINE_CLK_PCOM(ahb_m_clk,	AHB_M_CLK,	CLKFLAG_SKIP_AUTO_OFF);
@@ -28,6 +35,46 @@
 static DEFINE_CLK_PCOM(csi1_p_clk,	CSI1_P_CLK,	CLKFLAG_SKIP_AUTO_OFF);
 static DEFINE_CLK_PCOM(csi1_vfe_clk,	CSI1_VFE_CLK,	CLKFLAG_SKIP_AUTO_OFF);
 
+static struct pll_shared_clk pll0_clk = {
+	.id = PLL_0,
+	.mode_reg = PLLn_MODE(0),
+	.c = {
+		.ops = &clk_pll_ops,
+		.dbg_name = "pll0_clk",
+		CLK_INIT(pll0_clk.c),
+	},
+};
+
+static struct pll_shared_clk pll1_clk = {
+	.id = PLL_1,
+	.mode_reg = PLLn_MODE(1),
+	.c = {
+		.ops = &clk_pll_ops,
+		.dbg_name = "pll1_clk",
+		CLK_INIT(pll1_clk.c),
+	},
+};
+
+static struct pll_shared_clk pll2_clk = {
+	.id = PLL_2,
+	.mode_reg = PLLn_MODE(2),
+	.c = {
+		.ops = &clk_pll_ops,
+		.dbg_name = "pll2_clk",
+		CLK_INIT(pll2_clk.c),
+	},
+};
+
+static struct pll_shared_clk pll4_clk = {
+	.id = PLL_4,
+	.mode_reg = PLL4_MODE,
+	.c = {
+		.ops = &clk_pll_ops,
+		.dbg_name = "pll4_clk",
+		CLK_INIT(pll4_clk.c),
+	},
+};
+
 static struct pcom_clk dsi_byte_clk = {
 	.id = P_DSI_BYTE_CLK,
 	.c = {
@@ -251,14 +298,20 @@
 	CLK_LOOKUP("core_clk",		ebi_usb_clk.c,	"msm_otg"),
 	CLK_LOOKUP("ebi1_vfe_clk",	ebi_vfe_clk.c,	NULL),
 	CLK_LOOKUP("mem_clk",		ebi_adm_clk.c,	"msm_dmov"),
+
+	CLK_LOOKUP("pll0_clk",		pll0_clk.c,	"acpu"),
+	CLK_LOOKUP("pll1_clk",		pll1_clk.c,	"acpu"),
+	CLK_LOOKUP("pll2_clk",		pll2_clk.c,	"acpu"),
 };
 
 struct clock_init_data msm7x27_clock_init_data __initdata = {
 	.table = msm_clocks_7x27,
 	.size = ARRAY_SIZE(msm_clocks_7x27),
+	.init = msm_shared_pll_control_init,
 };
 
-static struct clk_lookup msm_clocks_7x27a[] = {
+/* Clock table for common clocks between 7627a and 7625a */
+static struct clk_lookup msm_cmn_clk_7625a_7627a[] __initdata = {
 	CLK_LOOKUP("core_clk",		adm_clk.c,	"msm_dmov"),
 	CLK_LOOKUP("adsp_clk",		adsp_clk.c,	NULL),
 	CLK_LOOKUP("ahb_m_clk",		ahb_m_clk.c,	NULL),
@@ -340,11 +393,41 @@
 	CLK_LOOKUP("ebi1_mddi_clk",	ebi_mddi_clk.c,	NULL),
 	CLK_LOOKUP("ebi1_vfe_clk",	ebi_vfe_clk.c,	NULL),
 	CLK_LOOKUP("mem_clk",		ebi_adm_clk.c,	"msm_dmov"),
+
+	CLK_LOOKUP("pll0_clk",		pll0_clk.c,	"acpu"),
+	CLK_LOOKUP("pll1_clk",		pll1_clk.c,	"acpu"),
+	CLK_LOOKUP("pll2_clk",		pll2_clk.c,	"acpu"),
+
 };
 
+/* PLL 4 clock is available for 7627a target. */
+static struct clk_lookup msm_clk_7627a[] __initdata = {
+	CLK_LOOKUP("pll4_clk",		pll4_clk.c,	"acpu"),
+};
+
+static struct clk_lookup msm_clk_7627a_7625a[ARRAY_SIZE(msm_cmn_clk_7625a_7627a)
+					+ ARRAY_SIZE(msm_clk_7627a)];
+
+static void __init msm7627a_clock_init(void)
+{
+	int size = ARRAY_SIZE(msm_cmn_clk_7625a_7627a);
+
+	/* Intialize shared PLL control structure */
+	msm_shared_pll_control_init();
+
+	memcpy(&msm_clk_7627a_7625a, &msm_cmn_clk_7625a_7627a,
+					sizeof(msm_cmn_clk_7625a_7627a));
+	if (!cpu_is_msm7x25a()) {
+		memcpy(&msm_clk_7627a_7625a[size],
+				&msm_clk_7627a, sizeof(msm_clk_7627a));
+		size += ARRAY_SIZE(msm_clk_7627a);
+	}
+	msm7x27a_clock_init_data.size = size;
+}
+
 struct clock_init_data msm7x27a_clock_init_data __initdata = {
-	.table = msm_clocks_7x27a,
-	.size = ARRAY_SIZE(msm_clocks_7x27a),
+	.table = msm_clk_7627a_7625a,
+	.init = msm7627a_clock_init,
 };
 
 static struct clk_lookup msm_clocks_8x50[] = {
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
new file mode 100644
index 0000000..f6b2b45
--- /dev/null
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/remote_spinlock.h>
+
+#include <mach/socinfo.h>
+#include <mach/msm_iomap.h>
+
+#include "clock.h"
+#include "clock-pll.h"
+#include "smd_private.h"
+
+struct pll_rate {
+	unsigned int lvalue;
+	unsigned long rate;
+};
+
+static struct pll_rate pll_l_rate[] = {
+	{10, 196000000},
+	{12, 245760000},
+	{30, 589820000},
+	{38, 737280000},
+	{41, 800000000},
+	{50, 960000000},
+	{52, 1008000000},
+	{62, 1200000000},
+	{0, 0},
+};
+
+#define PLL_BASE	7
+
+struct shared_pll_control {
+	uint32_t	version;
+	struct {
+		/*
+		 * Denotes if the PLL is ON. Technically, this can be read
+		 * directly from the PLL registers, but this feild is here,
+		 * so let's use it.
+		 */
+		uint32_t	on;
+		/*
+		 * One bit for each processor core. The application processor
+		 * is allocated bit position 1. All other bits should be
+		 * considered as votes from other processors.
+		 */
+		uint32_t	votes;
+	} pll[PLL_BASE + PLL_END];
+};
+
+static remote_spinlock_t pll_lock;
+static struct shared_pll_control *pll_control;
+
+void __init msm_shared_pll_control_init(void)
+{
+#define PLL_REMOTE_SPINLOCK_ID "S:7"
+	unsigned smem_size;
+
+	remote_spin_lock_init(&pll_lock, PLL_REMOTE_SPINLOCK_ID);
+
+	pll_control = smem_get_entry(SMEM_CLKREGIM_SOURCES, &smem_size);
+	if (!pll_control) {
+		pr_err("Can't find shared PLL control data structure!\n");
+		BUG();
+	/*
+	 * There might be more PLLs than what the application processor knows
+	 * about. But the index used for each PLL is guaranteed to remain the
+	 * same.
+	 */
+	} else if (smem_size < sizeof(struct shared_pll_control)) {
+			pr_err("Shared PLL control data"
+					 "structure too small!\n");
+			BUG();
+	} else if (pll_control->version != 0xCCEE0001) {
+			pr_err("Shared PLL control version mismatch!\n");
+			BUG();
+	} else {
+		pr_info("Shared PLL control available.\n");
+		return;
+	}
+
+}
+
+static void pll_enable(void __iomem *addr, unsigned on)
+{
+	if (on) {
+		writel_relaxed(2, addr);
+		mb();
+		udelay(5);
+		writel_relaxed(6, addr);
+		mb();
+		udelay(50);
+		writel_relaxed(7, addr);
+	} else {
+		writel_relaxed(0, addr);
+	}
+}
+
+static int pll_clk_enable(struct clk *clk)
+{
+	struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+	unsigned int pll_id = pll->id;
+
+	remote_spin_lock(&pll_lock);
+
+	pll_control->pll[PLL_BASE + pll_id].votes |= BIT(1);
+	if (!pll_control->pll[PLL_BASE + pll_id].on) {
+		pll_enable(pll->mode_reg, 1);
+		pll_control->pll[PLL_BASE + pll_id].on = 1;
+	}
+
+	remote_spin_unlock(&pll_lock);
+	return 0;
+}
+
+static void pll_clk_disable(struct clk *clk)
+{
+	struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+	unsigned int pll_id = pll->id;
+
+	remote_spin_lock(&pll_lock);
+
+	pll_control->pll[PLL_BASE + pll_id].votes &= ~BIT(1);
+	if (pll_control->pll[PLL_BASE + pll_id].on
+	    && !pll_control->pll[PLL_BASE + pll_id].votes) {
+		pll_enable(pll->mode_reg, 0);
+		pll_control->pll[PLL_BASE + pll_id].on = 0;
+	}
+
+	remote_spin_unlock(&pll_lock);
+}
+
+static int pll_clk_is_enabled(struct clk *clk)
+{
+	struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+
+	return readl_relaxed(pll->mode_reg) & BIT(0);
+}
+
+static bool pll_clk_is_local(struct clk *clk)
+{
+	return true;
+}
+
+static int pll_clk_handoff(struct clk *clk)
+{
+	struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+	unsigned int pll_lval;
+	struct pll_rate *l;
+
+	/*
+	 * Wait for the PLLs to be initialized and then read their frequency.
+	 */
+	do {
+		pll_lval = readl_relaxed(pll->mode_reg + 4) & 0x3ff;
+		cpu_relax();
+		udelay(50);
+	} while (pll_lval == 0);
+
+	/* Convert PLL L values to PLL Output rate */
+	for (l = pll_l_rate; l->rate != 0; l++) {
+		if (l->lvalue == pll_lval) {
+			clk->rate = l->rate;
+			break;
+		}
+	}
+
+	if (!clk->rate) {
+		pr_crit("Unknown PLL's L value!\n");
+		BUG();
+	}
+
+	return 0;
+}
+
+struct clk_ops clk_pll_ops = {
+	.enable = pll_clk_enable,
+	.disable = pll_clk_disable,
+	.handoff = pll_clk_handoff,
+	.is_local = pll_clk_is_local,
+	.is_enabled = pll_clk_is_enabled,
+};
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
new file mode 100644
index 0000000..ae0ca17
--- /dev/null
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ */
+
+/**
+ * enum - For PLL IDs
+ */
+enum {
+	PLL_TCXO	= -1,
+	PLL_0	= 0,
+	PLL_1,
+	PLL_2,
+	PLL_3,
+	PLL_4,
+	PLL_END,
+};
+
+/**
+ * struct pll_shared_clk -  PLL shared with other processors without
+ * any HW voting
+ * @id: PLL ID
+ * @mode_reg: enable register
+ * @parent: clock source
+ * @c: clk
+ */
+struct pll_shared_clk {
+	unsigned int id;
+	void __iomem *const mode_reg;
+	struct clk c;
+};
+
+extern struct clk_ops clk_pll_ops;
+
+static inline struct pll_shared_clk *to_pll_shared_clk(struct clk *clk)
+{
+	return container_of(clk, struct pll_shared_clk, c);
+}
+
+/**
+ * msm_shared_pll_control_init() - Initialize shared pll control structure
+ */
+void msm_shared_pll_control_init(void);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index ca85a0a..630c128 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -23,11 +23,13 @@
 #include <mach/usbdiag.h>
 #include <mach/msm_sps.h>
 #include <mach/dma.h>
+#include <mach/msm_dsps.h>
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
 #include <mach/msm_bus_board.h>
 #include <mach/rpm.h>
 #include <mach/mdm2.h>
+#include <mach/msm_smd.h>
 #include <linux/ion.h>
 #include "clock.h"
 #include "devices.h"
@@ -1217,9 +1219,157 @@
 	.dev.platform_data = &msm_sps_pdata,
 };
 
+static struct resource smd_resource[] = {
+	{
+		.name   = "a9_m2a_0",
+		.start  = INT_A9_M2A_0,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "a9_m2a_5",
+		.start  = INT_A9_M2A_5,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "adsp_a11",
+		.start  = INT_ADSP_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "adsp_a11_smsm",
+		.start  = INT_ADSP_A11_SMSM,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "dsps_a11",
+		.start  = INT_DSPS_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "dsps_a11_smsm",
+		.start  = INT_DSPS_A11_SMSM,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "wcnss_a11",
+		.start  = INT_WCNSS_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "wcnss_a11_smsm",
+		.start  = INT_WCNSS_A11_SMSM,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+	{
+		.irq_config_id = SMD_MODEM,
+		.subsys_name = "gss",
+		.edge = SMD_APPS_MODEM,
+
+		.smd_int.irq_name = "a9_m2a_0",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos =  1 << 3,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "a9_m2a_5",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_smsm",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos =  1 << 4,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+	{
+		.irq_config_id = SMD_Q6,
+		.subsys_name = "q6",
+		.edge = SMD_APPS_QDSP,
+
+		.smd_int.irq_name = "adsp_a11",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos =  1 << 15,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "adsp_a11_smsm",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_smsm",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos =  1 << 14,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+	{
+		.irq_config_id = SMD_DSPS,
+		.subsys_name = "dsps",
+		.edge = SMD_APPS_DSPS,
+
+		.smd_int.irq_name = "dsps_a11",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos =  1,
+		.smd_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
+		.smd_int.out_offset = 0x4080,
+
+		.smsm_int.irq_name = "dsps_a11_smsm",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_smsm",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos =  1,
+		.smsm_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
+		.smsm_int.out_offset = 0x4094,
+	},
+	{
+		.irq_config_id = SMD_WCNSS,
+		.subsys_name = "wcnss",
+		.edge = SMD_APPS_WCNSS,
+
+		.smd_int.irq_name = "wcnss_a11",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos =  1 << 25,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "wcnss_a11_smsm",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_smsm",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos =  1 << 23,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+};
+
+static struct smd_platform smd_platform_data = {
+	.num_ss_configs = ARRAY_SIZE(smd_config_list),
+	.smd_ss_configs = smd_config_list,
+};
+
 struct platform_device msm_device_smd_apq8064 = {
 	.name		= "msm_smd",
 	.id		= -1,
+	.resource = smd_resource,
+	.num_resources = ARRAY_SIZE(smd_resource),
+	.dev = {
+		.platform_data = &smd_platform_data,
+	},
 };
 
 #ifdef CONFIG_HW_RANDOM_MSM
@@ -1752,6 +1902,53 @@
 	},
 };
 
+/* Sensors DSPS platform data */
+
+#define PPSS_REG_PHYS_BASE	0x12080000
+
+static struct dsps_clk_info dsps_clks[] = {};
+static struct dsps_regulator_info dsps_regs[] = {};
+
+/*
+ * Note: GPIOs field is	intialized in run-time at the function
+ * apq8064_init_dsps().
+ */
+
+struct msm_dsps_platform_data msm_dsps_pdata_8064 = {
+	.clks = dsps_clks,
+	.clks_num = ARRAY_SIZE(dsps_clks),
+	.gpios = NULL,
+	.gpios_num = 0,
+	.regs = dsps_regs,
+	.regs_num = ARRAY_SIZE(dsps_regs),
+	.dsps_pwr_ctl_en = 1,
+	.signature = DSPS_SIGNATURE,
+};
+
+static struct resource msm_dsps_resources[] = {
+	{
+		.start = PPSS_REG_PHYS_BASE,
+		.end   = PPSS_REG_PHYS_BASE + SZ_8K - 1,
+		.name  = "ppss_reg",
+		.flags = IORESOURCE_MEM,
+	},
+
+	{
+		.start = PPSS_WDOG_TIMER_IRQ,
+		.end   = PPSS_WDOG_TIMER_IRQ,
+		.name  = "ppss_wdog",
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_dsps_device_8064 = {
+	.name          = "msm_dsps",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(msm_dsps_resources),
+	.resource      = msm_dsps_resources,
+	.dev.platform_data = &msm_dsps_pdata_8064,
+};
+
 #ifdef CONFIG_MSM_MPM
 static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] __initdata = {
 	[1] = MSM_GPIO_TO_INT(26),
@@ -1891,4 +2088,3 @@
 	.num_resources	= ARRAY_SIZE(mdm_resources),
 	.resource	= mdm_resources,
 };
-
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 19a8db7..718cfb1 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -30,8 +30,10 @@
 #include <mach/rpm.h>
 #include <mach/msm_bus_board.h>
 #include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
+#include <mach/msm_tsif.h>
 #include "clock.h"
 #include "devices.h"
 #include "devices-msm8x60.h"
@@ -950,9 +952,158 @@
 	.id = -1,
 };
 
+static struct resource smd_resource[] = {
+	{
+		.name   = "a9_m2a_0",
+		.start  = INT_A9_M2A_0,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "a9_m2a_5",
+		.start  = INT_A9_M2A_5,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "adsp_a11",
+		.start  = INT_ADSP_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "adsp_a11_smsm",
+		.start  = INT_ADSP_A11_SMSM,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "dsps_a11",
+		.start  = INT_DSPS_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "dsps_a11_smsm",
+		.start  = INT_DSPS_A11_SMSM,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "wcnss_a11",
+		.start  = INT_WCNSS_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "wcnss_a11_smsm",
+		.start  = INT_WCNSS_A11_SMSM,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+	{
+		.irq_config_id = SMD_MODEM,
+		.subsys_name = "modem",
+		.edge = SMD_APPS_MODEM,
+
+		.smd_int.irq_name = "a9_m2a_0",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos =  1 << 3,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "a9_m2a_5",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_smsm",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos =  1 << 4,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+	{
+		.irq_config_id = SMD_Q6,
+		.subsys_name = "q6",
+		.edge = SMD_APPS_QDSP,
+
+		.smd_int.irq_name = "adsp_a11",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos =  1 << 15,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "adsp_a11_smsm",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_smsm",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos =  1 << 14,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+	{
+		.irq_config_id = SMD_DSPS,
+		.subsys_name = "dsps",
+		.edge = SMD_APPS_DSPS,
+
+		.smd_int.irq_name = "dsps_a11",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos =  1,
+		.smd_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
+		.smd_int.out_offset = 0x4080,
+
+		.smsm_int.irq_name = "dsps_a11_smsm",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_smsm",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos =  1,
+		.smsm_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
+		.smsm_int.out_offset = 0x4094,
+	},
+	{
+		.irq_config_id = SMD_WCNSS,
+		.subsys_name = "wcnss",
+		.edge = SMD_APPS_WCNSS,
+
+		.smd_int.irq_name = "wcnss_a11",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos =  1 << 25,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "wcnss_a11_smsm",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_smsm",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos =  1 << 23,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+};
+
+static struct smd_platform smd_platform_data = {
+	.num_ss_configs = ARRAY_SIZE(smd_config_list),
+	.smd_ss_configs = smd_config_list,
+};
+
+
 struct platform_device msm_device_smd = {
 	.name		= "msm_smd",
 	.id		= -1,
+	.resource = smd_resource,
+	.num_resources = ARRAY_SIZE(smd_resource),
+	.dev = {
+		.platform_data = &smd_platform_data,
+	},
 };
 
 struct platform_device msm_device_bam_dmux = {
@@ -1355,6 +1506,111 @@
 };
 #endif
 
+#define MSM_TSIF0_PHYS       (0x18200000)
+#define MSM_TSIF1_PHYS       (0x18201000)
+#define MSM_TSIF_SIZE        (0x200)
+
+#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 tsif0_gpios[] = {
+	{ .gpio_cfg = TSIF_0_CLK,  .label =  "tsif_clk", },
+	{ .gpio_cfg = TSIF_0_EN,   .label =  "tsif_en", },
+	{ .gpio_cfg = TSIF_0_DATA, .label =  "tsif_data", },
+	{ .gpio_cfg = TSIF_0_SYNC, .label =  "tsif_sync", },
+};
+
+static const struct msm_gpio tsif1_gpios[] = {
+	{ .gpio_cfg = TSIF_1_CLK,  .label =  "tsif_clk", },
+	{ .gpio_cfg = TSIF_1_EN,   .label =  "tsif_en", },
+	{ .gpio_cfg = TSIF_1_DATA, .label =  "tsif_data", },
+	{ .gpio_cfg = TSIF_1_SYNC, .label =  "tsif_sync", },
+};
+
+struct msm_tsif_platform_data tsif1_platform_data = {
+	.num_gpios = ARRAY_SIZE(tsif1_gpios),
+	.gpios = tsif1_gpios,
+	.tsif_pclk = "tsif_pclk",
+	.tsif_ref_clk = "tsif_ref_clk",
+};
+
+struct resource tsif1_resources[] = {
+	[0] = {
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF2_IRQ,
+		.end   = TSIF2_IRQ,
+	},
+	[1] = {
+		.flags = IORESOURCE_MEM,
+		.start = MSM_TSIF1_PHYS,
+		.end   = MSM_TSIF1_PHYS + MSM_TSIF_SIZE - 1,
+	},
+	[2] = {
+		.flags = IORESOURCE_DMA,
+		.start = DMOV_TSIF_CHAN,
+		.end   = DMOV_TSIF_CRCI,
+	},
+};
+
+struct msm_tsif_platform_data tsif0_platform_data = {
+	.num_gpios = ARRAY_SIZE(tsif0_gpios),
+	.gpios = tsif0_gpios,
+	.tsif_pclk = "tsif_pclk",
+	.tsif_ref_clk = "tsif_ref_clk",
+};
+struct resource tsif0_resources[] = {
+	[0] = {
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF1_IRQ,
+		.end   = TSIF1_IRQ,
+	},
+	[1] = {
+		.flags = IORESOURCE_MEM,
+		.start = MSM_TSIF0_PHYS,
+		.end   = MSM_TSIF0_PHYS + MSM_TSIF_SIZE - 1,
+	},
+	[2] = {
+		.flags = IORESOURCE_DMA,
+		.start = DMOV_TSIF_CHAN,
+		.end   = DMOV_TSIF_CRCI,
+	},
+};
+
+struct platform_device msm_device_tsif[2] = {
+	{
+		.name          = "msm_tsif",
+		.id            = 0,
+		.num_resources = ARRAY_SIZE(tsif0_resources),
+		.resource      = tsif0_resources,
+		.dev = {
+			.platform_data = &tsif0_platform_data
+		},
+	},
+	{
+		.name          = "msm_tsif",
+		.id            = 1,
+		.num_resources = ARRAY_SIZE(tsif1_resources),
+		.resource      = tsif1_resources,
+		.dev = {
+			.platform_data = &tsif1_platform_data
+		},
+	}
+};
+
 static struct resource resources_ssbi_pmic[] = {
 	{
 		.start  = MSM_PMIC1_SSBI_CMD_PHYS,
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index b895870..26f246d 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -76,6 +76,21 @@
 	.resource	= resources_uart2,
 };
 
+static struct resource resources_adsp[] = {
+	{
+		.start  = INT_ADSP_A9_A11,
+		.end    = INT_ADSP_A9_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_adsp_device = {
+	.name           = "msm_adsp",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(resources_adsp),
+	.resource       = resources_adsp,
+};
+
 #define MSM_UART1DM_PHYS      0xA0200000
 #define MSM_UART2DM_PHYS      0xA0300000
 static struct resource msm_uart1_dm_resources[] = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index c18b6b2..9a4696f 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -33,6 +33,7 @@
 #include "devices-msm7x2xa.h"
 #include "footswitch.h"
 #include "acpuclock.h"
+#include "spm.h"
 
 /* Address of GSBI blocks */
 #define MSM_GSBI0_PHYS		0xA1200000
@@ -210,6 +211,78 @@
 	.id	= -1,
 };
 
+static struct resource smd_8625_resource[] = {
+	{
+		.name   = "a9_m2a_0",
+		.start  = MSM8625_INT_A9_M2A_0,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "a9_m2a_5",
+		.start  = MSM8625_INT_A9_M2A_5,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct smd_subsystem_config smd_8625_config_list[] = {
+	{
+		.irq_config_id = SMD_MODEM,
+		.subsys_name = "modem",
+		.edge = SMD_APPS_MODEM,
+
+		.smd_int.irq_name = "a9_m2a_0",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+
+		.smd_int.out_bit_pos =  1,
+		.smd_int.out_base = (void __iomem *)MSM_CSR_BASE,
+		.smd_int.out_offset = 0x400 + (0) * 4,
+
+		.smsm_int.irq_name = "a9_m2a_5",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smsm_dev",
+		.smsm_int.dev_id = 0,
+
+		.smsm_int.out_bit_pos =  1,
+		.smsm_int.out_base = (void __iomem *)MSM_CSR_BASE,
+		.smsm_int.out_offset = 0x400 + (5) * 4,
+
+	}
+};
+
+static struct smd_platform smd_8625_platform_data = {
+	.num_ss_configs = ARRAY_SIZE(smd_8625_config_list),
+	.smd_ss_configs = smd_8625_config_list,
+};
+
+struct platform_device msm8625_device_smd = {
+	.name	= "msm_smd",
+	.id	= -1,
+	.resource = smd_8625_resource,
+	.num_resources = ARRAY_SIZE(smd_8625_resource),
+	.dev = {
+		.platform_data = &smd_8625_platform_data,
+	}
+};
+
+static struct resource resources_adsp[] = {
+	{
+		.start  = INT_ADSP_A9_A11,
+		.end    = INT_ADSP_A9_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_adsp_device = {
+	.name           = "msm_adsp",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(resources_adsp),
+	.resource       = resources_adsp,
+};
+
 static struct resource resources_uart1[] = {
 	{
 		.start	= INT_UART1,
@@ -569,6 +642,55 @@
 
 #endif
 
+/* Command sequence for simple WFI */
+static uint8_t spm_wfi_cmd_sequence[] __initdata = {
+	0x00, 0x40, 0x40, 0x03,
+	0x00, 0x40, 0x40, 0x0f,
+};
+
+/* Command sequence for GDFS, this won't send any interrupt to the modem */
+static uint8_t spm_pc_without_modem[] __initdata = {
+	0x20, 0x00, 0x30, 0x10,
+	0x40, 0x40, 0x03, 0x10,
+	0x00, 0x30, 0x2E, 0x40,
+	0x40, 0x0f,
+};
+
+static struct msm_spm_seq_entry msm_spm_seq_list[] __initdata = {
+	[0] = {
+		.mode = MSM_SPM_MODE_CLOCK_GATING,
+		.notify_rpm = false,
+		.cmd = spm_wfi_cmd_sequence,
+	},
+	[1] = {
+		.mode = MSM_SPM_MODE_POWER_COLLAPSE,
+		.notify_rpm = false,
+		.cmd = spm_pc_without_modem,
+	},
+};
+
+static struct msm_spm_platform_data msm_spm_data[] __initdata = {
+	[0] = {
+		.reg_base_addr = MSM_SAW0_BASE,
+		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x0,
+		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+		.num_modes = ARRAY_SIZE(msm_spm_seq_list),
+		.modes = msm_spm_seq_list,
+	},
+	[1] = {
+		.reg_base_addr = MSM_SAW1_BASE,
+		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x0,
+		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+		.num_modes = ARRAY_SIZE(msm_spm_seq_list),
+		.modes = msm_spm_seq_list,
+	},
+};
+
+void __init msm8x25_spm_device_init(void)
+{
+	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
+}
+
 #define MDP_BASE		0xAA200000
 #define MIPI_DSI_HW_BASE	0xA1100000
 
@@ -843,6 +965,21 @@
 	.resource	= msm8625_uart2dm_resources,
 };
 
+static struct resource msm8625_resources_adsp[] = {
+	{
+		.start  = MSM8625_INT_ADSP_A9_A11,
+		.end    = MSM8625_INT_ADSP_A9_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8625_device_adsp = {
+	.name           = "msm_adsp",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(msm8625_resources_adsp),
+	.resource       = msm8625_resources_adsp,
+};
+
 static struct resource msm8625_dmov_resource[] = {
 	{
 		.start	= MSM8625_INT_ADM_AARM,
@@ -887,7 +1024,7 @@
 };
 
 /* Use GSBI0 QUP for /dev/i2c-0 */
-struct platform_device msm8625_device_qup_i2c_gsbi0 = {
+struct platform_device msm8625_gsbi0_qup_i2c_device = {
 	.name		= "qup_i2c",
 	.id		= MSM_GSBI0_QUP_I2C_BUS_ID,
 	.num_resources	= ARRAY_SIZE(gsbi0_msm8625_qup_resources),
@@ -916,7 +1053,7 @@
 };
 
 /* Use GSBI1 QUP for /dev/i2c-1 */
-struct platform_device msm8625_device_qup_i2c_gsbi1 = {
+struct platform_device msm8625_gsbi1_qup_i2c_device = {
 	.name		= "qup_i2c",
 	.id		= MSM_GSBI1_QUP_I2C_BUS_ID,
 	.num_resources	= ARRAY_SIZE(gsbi1_qup_i2c_resources),
@@ -1401,7 +1538,7 @@
 	}
 
 	msm_clock_init(&msm7x27a_clock_init_data);
-	if (cpu_is_msm7x27aa())
+	if (cpu_is_msm7x27aa() || cpu_is_msm8625())
 		acpuclk_init(&acpuclk_7x27aa_soc_data);
 	else
 		acpuclk_init(&acpuclk_7x27a_soc_data);
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index c2383c6..3c81ccf 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -30,4 +30,5 @@
 void __init msm8625_init_irq(void);
 void __init msm8625_map_io(void);
 int  ar600x_wlan_power(bool on);
+void __init msm8x25_spm_device_init(void);
 #endif
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index e9b94f6..89c8aaf 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -74,6 +74,20 @@
 	.resource       = msm_ebi1_thermal_resources
 };
 
+static struct resource resources_adsp[] = {
+{
+	.start  = INT_ADSP_A9_A11,
+	.end    = INT_ADSP_A9_A11,
+	.flags  = IORESOURCE_IRQ,
+},
+};
+
+struct platform_device msm_adsp_device = {
+	.name           = "msm_adsp",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(resources_adsp),
+	.resource       = resources_adsp,
+};
 
 static struct resource resources_uart1[] = {
 	{
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 6da7b8f..7f2855d 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -38,6 +38,7 @@
 extern struct platform_device msm_ebi0_thermal;
 extern struct platform_device msm_ebi1_thermal;
 
+extern struct platform_device msm_adsp_device;
 extern struct platform_device msm_device_uart1;
 extern struct platform_device msm_device_uart2;
 extern struct platform_device msm_device_uart3;
@@ -127,8 +128,8 @@
 extern struct platform_device msm_gsbi9_qup_i2c_device;
 extern struct platform_device msm_gsbi12_qup_i2c_device;
 
-extern struct platform_device msm8625_device_qup_i2c_gsbi0;
-extern struct platform_device msm8625_device_qup_i2c_gsbi1;
+extern struct platform_device msm8625_gsbi0_qup_i2c_device;
+extern struct platform_device msm8625_gsbi1_qup_i2c_device;
 extern struct platform_device msm8625_device_uart_dm1;
 extern struct platform_device msm8625_device_uart_dm2;
 extern struct platform_device msm8625_device_sdc1;
@@ -139,6 +140,7 @@
 extern struct platform_device msm8625_device_hsusb_host;
 extern struct platform_device msm8625_device_otg;
 extern struct platform_device msm8625_kgsl_3d0;
+extern struct platform_device msm8625_device_adsp;
 
 extern struct platform_device msm_slim_ctrl;
 extern struct platform_device msm_device_sps;
@@ -147,6 +149,7 @@
 extern struct platform_device msm_device_bam_dmux;
 extern struct platform_device msm_device_smd;
 extern struct platform_device msm_device_smd_apq8064;
+extern struct platform_device msm8625_device_smd;
 extern struct platform_device msm_device_dmov;
 extern struct platform_device msm8960_device_dmov;
 extern struct platform_device apq8064_device_dmov;
@@ -320,3 +323,5 @@
 extern struct platform_device msm_bus_8064_cpss_fpb;
 
 extern struct platform_device mdm_8064_device;
+
+extern struct platform_device msm_dsps_device_8064;
diff --git a/arch/arm/mach-msm/idle.h b/arch/arm/mach-msm/idle.h
index 830e36b..6311b3c 100644
--- a/arch/arm/mach-msm/idle.h
+++ b/arch/arm/mach-msm/idle.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2009,2011 Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2007-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
@@ -28,6 +28,15 @@
 {
 	/* empty */
 }
+static inline void msm_pm_boot_entry(void)
+{
+	/* empty */
+}
+static inline void msm_pm_write_boot_vector(unsigned int cpu,
+						unsigned long address)
+{
+	/* empty */
+}
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/diag_bridge.h b/arch/arm/mach-msm/include/mach/diag_bridge.h
index a39ed25..b06f020 100644
--- a/arch/arm/mach-msm/include/mach/diag_bridge.h
+++ b/arch/arm/mach-msm/include/mach/diag_bridge.h
@@ -19,6 +19,8 @@
 			int buf_size, int actual);
 	void (*write_complete_cb)(void *ctxt, char *buf,
 			int buf_size, int actual);
+	int (*suspend)(void *ctxt);
+	void (*resume)(void *ctxt);
 };
 
 #if defined(CONFIG_USB_QCOM_DIAG_BRIDGE) \
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 3cb79b7..d170f5f 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -177,6 +177,9 @@
 #define DMOV_CE_OUT_CHAN       1
 #define DMOV_CE_OUT_CRCI       3
 
+#define DMOV_TSIF_CHAN         2
+#define DMOV_TSIF_CRCI         11
+
 #define DMOV_HSUART_GSBI6_TX_CHAN	7
 #define DMOV_HSUART_GSBI6_TX_CRCI	6
 
diff --git a/arch/arm/mach-msm/include/mach/irqs-copper.h b/arch/arm/mach-msm/include/mach/irqs-copper.h
index 821eaeb..c961804 100644
--- a/arch/arm/mach-msm/include/mach/irqs-copper.h
+++ b/arch/arm/mach-msm/include/mach/irqs-copper.h
@@ -36,7 +36,8 @@
 
 #define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
 #define NR_GPIO_IRQS 156
-#define NR_BOARD_IRQS 100
+#define NR_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
 #define NR_MSM_GPIOS NR_GPIO_IRQS
 
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 954b673..1ae7454 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -42,10 +42,11 @@
 #define NR_GPIO_IRQS 152
 #define NR_PM8921_IRQS 256
 #define NR_PM8821_IRQS 64
-#define NR_TABLA_IRQS 49
+#define NR_WCD9XXX_IRQS 49
+#define NR_TABLA_IRQS NR_WCD9XXX_IRQS
 #define NR_GPIO_EXPANDER_IRQS 8
 #define NR_BOARD_IRQS (NR_PM8921_IRQS + NR_PM8821_IRQS + \
-		NR_TABLA_IRQS + NR_GPIO_EXPANDER_IRQS)
+		NR_WCD9XXX_IRQS + NR_GPIO_EXPANDER_IRQS)
 #define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
 #define NR_MSM_GPIOS NR_GPIO_IRQS
 
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 4be6d9ea..8d3e640 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -236,6 +236,22 @@
  */
 int smd_write_end(smd_channel_t *ch);
 
+/*
+ * Returns a pointer to the subsystem name or NULL if no
+ * subsystem name is available.
+ *
+ * @type - Edge definition
+ */
+const char *smd_edge_to_subsystem(uint32_t type);
+
+/*
+ * Returns a pointer to the subsystem name given the
+ * remote processor ID.
+ *
+ * @pid     Remote processor ID
+ * @returns Pointer to subsystem name or NULL if not found
+ */
+const char *smd_pid_to_subsystem(uint32_t pid);
 #else
 
 static inline int smd_open(const char *name, smd_channel_t **ch, void *priv,
@@ -337,6 +353,16 @@
 {
 	return -ENODEV;
 }
+
+static inline const char *smd_edge_to_subsystem(uint32_t type)
+{
+	return NULL;
+}
+
+static inline const char *smd_pid_to_subsystem(uint32_t pid)
+{
+	return NULL;
+}
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_dev_ctl.h b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_dev_ctl.h
index 71f2bd9..20c6fc4 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_dev_ctl.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_dev_ctl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -96,6 +96,8 @@
 
 int msm_reset_all_device(void);
 
+int reset_device(void);
+
 int msm_clear_all_session(void);
 
 struct msm_snddev_info *audio_dev_ctrl_find_dev(u32 dev_id);
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 6aa944f..af4691a 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -22,6 +22,7 @@
 #define SCM_SVC_FUSE			0x8
 #define SCM_SVC_PWR			0x9
 #define SCM_SVC_CP			0xC
+#define SCM_SVC_DCVS			0xD
 #define SCM_SVC_TZSCHEDULER		0xFC
 
 #ifdef CONFIG_MSM_SCM
@@ -30,6 +31,8 @@
 
 extern s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1);
 extern s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2);
+extern s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3,
+		u32 arg4, u32 *ret1, u32 *ret2);
 
 #define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
 
@@ -54,6 +57,12 @@
 	return 0;
 }
 
+static inline s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2,
+		u32 arg3, u32 arg4, u32 *ret1, u32 *ret2)
+{
+	return 0;
+}
+
 static inline u32 scm_get_version(void)
 {
 	return 0;
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 8e74238..a643c68 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -419,6 +419,8 @@
 	MSM_CHIP_DEVICE(CLK_CTL, MSM8625),
 	MSM_CHIP_DEVICE(SAW0, MSM8625),
 	MSM_CHIP_DEVICE(SAW1, MSM8625),
+	MSM_CHIP_DEVICE(AD5, MSM7XXX),
+	MSM_CHIP_DEVICE(MDC, MSM7XXX),
 #if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
 	defined(CONFIG_DEBUG_MSM_UART3)
 	MSM_CHIP_DEVICE(DEBUG_UART, MSM7XXX),
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index 463d6c9..853888a 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -56,7 +56,7 @@
 
 static int msm_iommu_tex_class[4];
 
-DEFINE_SPINLOCK(msm_iommu_lock);
+DEFINE_MUTEX(msm_iommu_lock);
 
 struct msm_priv {
 	unsigned long *pgtable;
@@ -68,14 +68,14 @@
 {
 	int ret;
 
-	ret = clk_enable(drvdata->pclk);
+	ret = clk_prepare_enable(drvdata->pclk);
 	if (ret)
 		goto fail;
 
 	if (drvdata->clk) {
-		ret = clk_enable(drvdata->clk);
+		ret = clk_prepare_enable(drvdata->clk);
 		if (ret)
-			clk_disable(drvdata->pclk);
+			clk_disable_unprepare(drvdata->pclk);
 	}
 fail:
 	return ret;
@@ -84,8 +84,8 @@
 static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
 {
 	if (drvdata->clk)
-		clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
+		clk_disable_unprepare(drvdata->clk);
+	clk_disable_unprepare(drvdata->pclk);
 }
 
 static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
@@ -299,11 +299,10 @@
 static void msm_iommu_domain_destroy(struct iommu_domain *domain)
 {
 	struct msm_priv *priv;
-	unsigned long flags;
 	unsigned long *fl_table;
 	int i;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
+	mutex_lock(&msm_iommu_lock);
 	priv = domain->priv;
 	domain->priv = NULL;
 
@@ -320,7 +319,7 @@
 	}
 
 	kfree(priv);
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	mutex_unlock(&msm_iommu_lock);
 }
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -331,9 +330,8 @@
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	struct msm_iommu_ctx_drvdata *tmp_drvdata;
 	int ret = 0;
-	unsigned long flags;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
+	mutex_lock(&msm_iommu_lock);
 
 	priv = domain->priv;
 
@@ -373,7 +371,7 @@
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 
 fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	mutex_unlock(&msm_iommu_lock);
 	return ret;
 }
 
@@ -384,10 +382,9 @@
 	struct msm_iommu_ctx_dev *ctx_dev;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
+	mutex_lock(&msm_iommu_lock);
 	priv = domain->priv;
 
 	if (!priv || !dev)
@@ -412,7 +409,7 @@
 	list_del_init(&ctx_drvdata->attached_elm);
 
 fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	mutex_unlock(&msm_iommu_lock);
 }
 
 static int __get_pgprot(int prot, int len)
@@ -447,7 +444,6 @@
 			 phys_addr_t pa, int order, int prot)
 {
 	struct msm_priv *priv;
-	unsigned long flags;
 	unsigned long *fl_table;
 	unsigned long *fl_pte;
 	unsigned long fl_offset;
@@ -458,7 +454,7 @@
 	size_t len = 0x1000UL << order;
 	int ret = 0;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
+	mutex_lock(&msm_iommu_lock);
 
 	priv = domain->priv;
 	if (!priv) {
@@ -525,7 +521,7 @@
 
 		if (*fl_pte == 0) {
 			unsigned long *sl;
-			sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
+			sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
 							get_order(SZ_4K));
 
 			if (!sl) {
@@ -583,7 +579,7 @@
 
 	ret = __flush_iotlb_va(domain, va);
 fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	mutex_unlock(&msm_iommu_lock);
 	return ret;
 }
 
@@ -591,7 +587,6 @@
 			    int order)
 {
 	struct msm_priv *priv;
-	unsigned long flags;
 	unsigned long *fl_table;
 	unsigned long *fl_pte;
 	unsigned long fl_offset;
@@ -601,7 +596,7 @@
 	size_t len = 0x1000UL << order;
 	int i, ret = 0;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
+	mutex_lock(&msm_iommu_lock);
 
 	priv = domain->priv;
 
@@ -686,7 +681,7 @@
 
 	ret = __flush_iotlb_va(domain, va);
 fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	mutex_unlock(&msm_iommu_lock);
 	return ret;
 }
 
@@ -702,13 +697,12 @@
 	unsigned long fl_offset;
 	unsigned long *sl_table;
 	unsigned long sl_offset, sl_start;
-	unsigned long flags;
 	unsigned int chunk_offset = 0;
 	unsigned int chunk_pa;
 	int ret = 0;
 	struct msm_priv *priv;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
+	mutex_lock(&msm_iommu_lock);
 
 	BUG_ON(len & (SZ_4K - 1));
 
@@ -734,7 +728,7 @@
 		/* Set up a 2nd level page table if one doesn't exist */
 		if (*fl_pte == 0) {
 			sl_table = (unsigned long *)
-				 __get_free_pages(GFP_ATOMIC, get_order(SZ_4K));
+				 __get_free_pages(GFP_KERNEL, get_order(SZ_4K));
 
 			if (!sl_table) {
 				pr_debug("Could not allocate second level table\n");
@@ -782,7 +776,7 @@
 	}
 	__flush_iotlb(domain);
 fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	mutex_unlock(&msm_iommu_lock);
 	return ret;
 }
 
@@ -796,11 +790,10 @@
 	unsigned long fl_offset;
 	unsigned long *sl_table;
 	unsigned long sl_start, sl_end;
-	unsigned long flags;
 	int used, i;
 	struct msm_priv *priv;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
+	mutex_lock(&msm_iommu_lock);
 
 	BUG_ON(len & (SZ_4K - 1));
 
@@ -854,7 +847,7 @@
 	}
 
 	__flush_iotlb(domain);
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	mutex_unlock(&msm_iommu_lock);
 	return 0;
 }
 
@@ -865,12 +858,11 @@
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	unsigned int par;
-	unsigned long flags;
 	void __iomem *base;
 	phys_addr_t ret = 0;
 	int ctx;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
+	mutex_lock(&msm_iommu_lock);
 
 	priv = domain->priv;
 	if (list_empty(&priv->list_attached))
@@ -903,7 +895,7 @@
 
 	__disable_clocks(iommu_drvdata);
 fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	mutex_unlock(&msm_iommu_lock);
 	return ret;
 }
 
@@ -947,7 +939,7 @@
 	unsigned int fsr;
 	int i, ret;
 
-	spin_lock(&msm_iommu_lock);
+	mutex_lock(&msm_iommu_lock);
 
 	if (!drvdata) {
 		pr_err("Invalid device ID in context interrupt handler\n");
@@ -975,7 +967,7 @@
 	}
 	__disable_clocks(drvdata);
 fail:
-	spin_unlock(&msm_iommu_lock);
+	mutex_unlock(&msm_iommu_lock);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index 1982082..70e96b0 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -156,7 +156,7 @@
 		goto fail;
 	}
 
-	ret = clk_enable(iommu_pclk);
+	ret = clk_prepare_enable(iommu_pclk);
 	if (ret)
 		goto fail_enable;
 
@@ -168,7 +168,7 @@
 			clk_set_rate(iommu_clk, ret);
 		}
 
-		ret = clk_enable(iommu_clk);
+		ret = clk_prepare_enable(iommu_clk);
 		if (ret) {
 			clk_put(iommu_clk);
 			goto fail_pclk;
@@ -226,8 +226,8 @@
 		goto fail_io;
 	}
 
-	ret = request_irq(irq, msm_iommu_fault_handler, 0,
-			"msm_iommu_secure_irpt_handler", drvdata);
+	ret = request_threaded_irq(irq, NULL, msm_iommu_fault_handler,
+			IRQF_ONESHOT, "msm_iommu_secure_irpt_handler", drvdata);
 	if (ret) {
 		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
 		goto fail_io;
@@ -247,9 +247,9 @@
 	platform_set_drvdata(pdev, drvdata);
 
 	if (iommu_clk)
-		clk_disable(iommu_clk);
+		clk_disable_unprepare(iommu_clk);
 
-	clk_disable(iommu_pclk);
+	clk_disable_unprepare(iommu_pclk);
 
 	return 0;
 fail_io:
@@ -258,11 +258,11 @@
 	release_mem_region(r->start, len);
 fail_clk:
 	if (iommu_clk) {
-		clk_disable(iommu_clk);
+		clk_disable_unprepare(iommu_clk);
 		clk_put(iommu_clk);
 	}
 fail_pclk:
-	clk_disable(iommu_pclk);
+	clk_disable_unprepare(iommu_pclk);
 fail_enable:
 	clk_put(iommu_pclk);
 fail:
@@ -315,14 +315,14 @@
 	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
 	platform_set_drvdata(pdev, ctx_drvdata);
 
-	ret = clk_enable(drvdata->pclk);
+	ret = clk_prepare_enable(drvdata->pclk);
 	if (ret)
 		goto fail;
 
 	if (drvdata->clk) {
-		ret = clk_enable(drvdata->clk);
+		ret = clk_prepare_enable(drvdata->clk);
 		if (ret) {
-			clk_disable(drvdata->pclk);
+			clk_disable_unprepare(drvdata->pclk);
 			goto fail;
 		}
 	}
@@ -357,8 +357,8 @@
 	mb();
 
 	if (drvdata->clk)
-		clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
+		clk_disable_unprepare(drvdata->clk);
+	clk_disable_unprepare(drvdata->pclk);
 
 	dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
 	return 0;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index feabe04..56aba3e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -9,6 +9,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_config.c b/arch/arm/mach-msm/msm_bus/msm_bus_config.c
index 7d9d18f..28f3073 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_config.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_config.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
@@ -9,6 +9,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.c b/arch/arm/mach-msm/msm_bus/msm_bus_core.c
index 9fe05b7..4d73b03 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -9,6 +9,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 50afa81..e35130e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,22 +20,14 @@
 #include <mach/msm_bus_board.h>
 #include <mach/msm_bus.h>
 
-#if defined DEBUG
-
 #define MSM_BUS_DBG(msg, ...) \
-	printk(KERN_DEBUG "AXI: %s(): " msg, __func__, ## __VA_ARGS__)
-
-#else
-#define MSM_BUS_DBG(msg, ...) no_printk("AXI")
-#endif
-
+	pr_debug(msg, ## __VA_ARGS__)
 #define MSM_BUS_ERR(msg, ...) \
-	printk(KERN_ERR "AXI: %s(): " msg, __func__, ## __VA_ARGS__)
+	pr_err(msg, ## __VA_ARGS__)
 #define MSM_BUS_WARN(msg, ...) \
-	printk(KERN_WARNING "AXI: %s(): " msg, __func__, ## __VA_ARGS__)
+	pr_warn(msg, ## __VA_ARGS__)
 #define MSM_FAB_ERR(msg, ...) \
-	dev_err(&fabric->fabdev.dev, "AXI: %s(): " msg, __func__, ## \
-	__VA_ARGS__)
+	dev_err(&fabric->fabdev.dev, msg, ## __VA_ARGS__)
 
 enum msm_bus_dbg_op_type {
 	MSM_BUS_DBG_UNREGISTER = -2,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
index abd986b..e63df1b 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,9 @@
  * GNU General Public License for more details.
  *
  */
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 3b178b5..2c69914 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -10,6 +10,8 @@
  * GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/device.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c b/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c
index a8dc7c8..b13037e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_rpm.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
@@ -11,6 +11,8 @@
  *
  */
 
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -342,7 +344,7 @@
 		fab_pdata->nmasters) + 1);
 	ret = memcmp(cd1->arb, cd2->arb, n);
 	if (ret) {
-		MSM_BUS_DBG("Commit Data arb[%d] not equal\n", i);
+		MSM_BUS_DBG("Commit Data arb[%d] not equal\n", n);
 		return ret;
 	}
 
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 6e79dfe..3f56d1a 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -54,6 +54,7 @@
 	int nentries;
 	int size;
 	int enabled;
+	int initialized;
 	uint32_t filter;
 	int step_size;
 };
@@ -66,6 +67,7 @@
 
 struct msm_rtb_state msm_rtb = {
 	.filter = 1 << LOGK_LOGBUF,
+	.enabled = 1,
 };
 
 module_param_named(filter, msm_rtb.filter, uint, 0644);
@@ -73,7 +75,7 @@
 
 int msm_rtb_event_should_log(enum logk_event_type log_type)
 {
-	return msm_rtb.enabled &&
+	return msm_rtb.initialized && msm_rtb.enabled &&
 		((1 << log_type) & msm_rtb.filter);
 }
 EXPORT_SYMBOL(msm_rtb_event_should_log);
@@ -217,7 +219,7 @@
 #endif
 
 
-	msm_rtb.enabled = 1;
+	msm_rtb.initialized = 1;
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 74c64c1..f7d2bcb 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -237,13 +237,6 @@
 	unsigned long flags;
 	struct msm_xo_voter *xo_voter;
 
-	/*
-	 * TODO: Remove early return for 8064 once RPM XO voting support
-	 * is available.
-	 */
-	if (cpu_is_apq8064())
-		return NULL;
-
 	if (xo_id >= NUM_MSM_XO_IDS) {
 		ret = -EINVAL;
 		goto err;
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 534fc0e..3c46d0f 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -28,6 +28,8 @@
 #include "pm.h"
 
 #define MSM_CORE1_RESET		0xA8600590
+#define MSM_CORE1_STATUS_MSK	0x02800000
+
 /*
  * control for which core is the next to come out of the secondary
  * boot "holding pen"
@@ -60,6 +62,10 @@
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
+	pr_debug("CPU%u: Booted secondary processor\n", cpu);
+
+	WARN_ON(msm_platform_secondary_init(cpu));
+
 	/*
 	 * if any interrupts are already enabled for the primary
 	 * core (e.g. timer irq), then they will not have been enabled
@@ -80,20 +86,53 @@
 	spin_unlock(&boot_lock);
 }
 
+static int  __cpuinit msm8625_release_secondary(void)
+{
+	void __iomem *base_ptr;
+	int value = 0;
+	unsigned long timeout;
+
+	/*
+	 * loop to ensure that the GHS_STATUS_CORE1 bit in the
+	 * MPA5_STATUS_REG(0x3c) is set. The timeout for the while
+	 * loop can be set as 20us as of now
+	 */
+	timeout = jiffies + usecs_to_jiffies(20);
+	while (time_before(jiffies, timeout)) {
+		value = __raw_readl(MSM_CFG_CTL_BASE + 0x3c);
+		if ((value & MSM_CORE1_STATUS_MSK) ==
+				MSM_CORE1_STATUS_MSK)
+			break;
+			udelay(1);
+	}
+
+	if (!value) {
+		pr_err("Core 1 cannot be brought out of Reset!!!\n");
+		return -ENODEV;
+	}
+
+	base_ptr = ioremap_nocache(MSM_CORE1_RESET, SZ_4);
+	if (!base_ptr)
+		return -ENODEV;
+	/* Reset core 1 out of reset */
+	__raw_writel(0x0, base_ptr);
+	mb();
+
+	iounmap(base_ptr);
+
+	return 0;
+}
+
 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned long timeout;
-	void __iomem *base_ptr;
 
 	if (cold_boot_done == false) {
-		base_ptr = ioremap_nocache(MSM_CORE1_RESET, SZ_4);
-		if (!base_ptr)
+		if (msm8625_release_secondary()) {
+			pr_err("Failed to release secondary core\n");
 			return -ENODEV;
-		/* Reset core 1 out of reset */
-		__raw_writel(0x0, base_ptr);
-		mb();
+		}
 		cold_boot_done = true;
-		iounmap(base_ptr);
 	}
 
 	/*
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index ce09f9f..f4536f7 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -101,6 +101,7 @@
 int __init msm_pm_boot_init(struct msm_pm_boot_platform_data *pdata)
 {
 	int ret = 0;
+	unsigned long entry;
 
 	switch (pdata->mode) {
 	case MSM_PM_BOOT_CONFIG_TZ:
@@ -130,15 +131,44 @@
 		if (!pdata->p_addr || !pdata->v_addr)
 			return -ENODEV;
 
-		__raw_writel((pdata->p_addr | BOOT_REMAP_ENABLE),
-				pdata->v_addr);
-
 		ret = msm_pm_boot_reset_vector_init(__va(pdata->p_addr));
 
-		msm_pm_boot_before_pc
-			= msm_pm_config_rst_vector_before_pc;
-		msm_pm_boot_after_pc
-			= msm_pm_config_rst_vector_after_pc;
+		if (!cpu_is_msm8625()) {
+			__raw_writel((pdata->p_addr | BOOT_REMAP_ENABLE),
+					pdata->v_addr);
+
+			msm_pm_boot_before_pc
+				= msm_pm_config_rst_vector_before_pc;
+			msm_pm_boot_after_pc
+				= msm_pm_config_rst_vector_after_pc;
+		} else {
+			entry = virt_to_phys(msm_pm_boot_entry);
+
+			msm_pm_reset_vector[0] = 0xE51FF004; /* ldr pc, 4 */
+			msm_pm_reset_vector[1] = entry;
+
+			/* Here upper 16bits[16:31] used by CORE1
+			 * lower 16bits[0:15] used by CORE0
+			 */
+			entry = (pdata->p_addr) |
+					((pdata->p_addr & 0xFFFF0000) >> 16);
+
+			/* write 'entry' to boot remapper register */
+			__raw_writel(entry, (pdata->v_addr +
+						MPA5_BOOT_REMAP_ADDR));
+
+			/* Enable boot remapper for C0 [bit:25th] */
+			__raw_writel(readl_relaxed(pdata->v_addr +
+					MPA5_CFG_CTL_REG) | BIT(25),
+					pdata->v_addr + MPA5_CFG_CTL_REG);
+
+			/* Enable boot remapper for C1 [bit:26th] */
+			__raw_writel(readl_relaxed(pdata->v_addr +
+					MPA5_CFG_CTL_REG) | BIT(26),
+					pdata->v_addr + MPA5_CFG_CTL_REG);
+
+			msm_pm_boot_before_pc = msm_pm_write_boot_vector;
+		}
 		break;
 	default:
 		__WARN();
diff --git a/arch/arm/mach-msm/pm-boot.h b/arch/arm/mach-msm/pm-boot.h
index 185d542..30b67c21 100644
--- a/arch/arm/mach-msm/pm-boot.h
+++ b/arch/arm/mach-msm/pm-boot.h
@@ -13,6 +13,11 @@
 #ifndef _ARCH_ARM_MACH_MSM_PM_BOOT_H
 #define _ARCH_ARM_MACH_MSM_PM_BOOT_H
 
+/* 8x25 specific macros */
+#define MPA5_CFG_CTL_REG	0x30
+#define MPA5_BOOT_REMAP_ADDR	0x34
+/* end */
+
 enum {
 	MSM_PM_BOOT_CONFIG_TZ		     = 0,
 	MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS = 1,
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 7977d22..1396463 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -48,6 +48,7 @@
 #ifdef CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN
 #include <mach/msm_migrate_pages.h>
 #endif
+#include <mach/socinfo.h>
 
 #include "smd_private.h"
 #include "smd_rpcrouter.h"
@@ -68,13 +69,14 @@
  *****************************************************************************/
 
 enum {
-	MSM_PM_DEBUG_SUSPEND = 1U << 0,
-	MSM_PM_DEBUG_POWER_COLLAPSE = 1U << 1,
-	MSM_PM_DEBUG_STATE = 1U << 2,
-	MSM_PM_DEBUG_CLOCK = 1U << 3,
-	MSM_PM_DEBUG_RESET_VECTOR = 1U << 4,
-	MSM_PM_DEBUG_SMSM_STATE = 1U << 5,
-	MSM_PM_DEBUG_IDLE = 1U << 6,
+	MSM_PM_DEBUG_SUSPEND = BIT(0),
+	MSM_PM_DEBUG_POWER_COLLAPSE = BIT(1),
+	MSM_PM_DEBUG_STATE = BIT(2),
+	MSM_PM_DEBUG_CLOCK = BIT(3),
+	MSM_PM_DEBUG_RESET_VECTOR = BIT(4),
+	MSM_PM_DEBUG_SMSM_STATE = BIT(5),
+	MSM_PM_DEBUG_IDLE = BIT(6),
+	MSM_PM_DEBUG_HOTPLUG = BIT(7),
 };
 
 static int msm_pm_debug_mask;
@@ -142,7 +144,6 @@
 static char *msm_pm_sleep_mode_labels[MSM_PM_SLEEP_MODE_NR] = {
 	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND] = " ",
 	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = "power_collapse",
-	[MSM_PM_SLEEP_MODE_APPS_SLEEP] = "apps_sleep",
 	[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] =
 		"ramp_down_and_wfi",
 	[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = "wfi",
@@ -682,8 +683,6 @@
 	MSM_PM_STAT_IDLE_WFI,
 	MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
 	MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE,
-	MSM_PM_STAT_IDLE_SLEEP,
-	MSM_PM_STAT_IDLE_FAILED_SLEEP,
 	MSM_PM_STAT_IDLE_POWER_COLLAPSE,
 	MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE,
 	MSM_PM_STAT_SUSPEND,
@@ -1008,6 +1007,13 @@
 
 	memset(msm_pm_smem_data, 0, sizeof(*msm_pm_smem_data));
 
+	if (cpu_is_msm8625()) {
+		/* Program the SPM */
+		ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE,
+									false);
+		WARN_ON(ret);
+	}
+
 	msm_irq_enter_sleep1(true, from_idle, &msm_pm_smem_data->irq_mask);
 	msm_sirc_enter_sleep();
 	msm_gpio_enter_sleep(from_idle);
@@ -1210,6 +1216,13 @@
 	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): RUN");
 
 	smd_sleep_exit();
+
+	if (cpu_is_msm8625()) {
+		ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
+									false);
+		WARN_ON(ret);
+	}
+
 	return 0;
 
 power_collapse_early_exit:
@@ -1263,6 +1276,12 @@
 		smd_sleep_exit();
 
 power_collapse_bail:
+	if (cpu_is_msm8625()) {
+		ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
+									false);
+		WARN_ON(ret);
+	}
+
 	return ret;
 }
 
@@ -1272,10 +1291,11 @@
  * Return value:
  *      0: success
  */
-static int msm_pm_power_collapse_standalone(void)
+static int msm_pm_power_collapse_standalone(bool from_idle)
 {
 	int collapsed = 0;
 	int ret;
+	void *entry;
 
 	MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
 		KERN_INFO, "%s()\n", __func__);
@@ -1283,21 +1303,26 @@
 	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE, false);
 	WARN_ON(ret);
 
+	entry = (!smp_processor_id() || from_idle) ?
+			msm_pm_collapse_exit : msm_secondary_startup;
+
 	msm_pm_boot_config_before_pc(smp_processor_id(),
-			virt_to_phys(msm_pm_collapse_exit));
+						virt_to_phys(entry));
 
 #ifdef CONFIG_VFP
 	vfp_flush_context();
 #endif
 
 #ifdef CONFIG_CACHE_L2X0
-	l2x0_suspend();
+	if (!cpu_is_msm8625())
+		l2x0_suspend();
 #endif
 
 	collapsed = msm_pm_collapse();
 
 #ifdef CONFIG_CACHE_L2X0
-	l2x0_resume(collapsed);
+	if (!cpu_is_msm8625())
+		l2x0_resume(collapsed);
 #endif
 
 	msm_pm_boot_config_after_pc(smp_processor_id());
@@ -1321,18 +1346,6 @@
 }
 
 /*
- * Apps-sleep the Apps processor.  This function execute the handshake
- * protocol with Modem.
- *
- * Return value:
- *      -ENOSYS: function not implemented yet
- */
-static int msm_pm_apps_sleep(uint32_t sleep_delay, uint32_t sleep_limit)
-{
-	return -ENOSYS;
-}
-
-/*
  * Bring the Apps processor to SWFI.
  *
  * Return value:
@@ -1353,7 +1366,9 @@
 			return -EIO;
 	}
 
-	msm_pm_config_hw_before_swfi();
+	if (!cpu_is_msm8625())
+		msm_pm_config_hw_before_swfi();
+
 	msm_arch_idle();
 
 	if (ramp_acpu) {
@@ -1395,7 +1410,7 @@
 	int64_t t1;
 	static int64_t t2;
 	int exit_stat;
- #endif /* CONFIG_MSM_IDLE_STATS */
+ #endif
 
 	if (!atomic_read(&msm_pm_init_done))
 		return;
@@ -1412,19 +1427,19 @@
 
 	exit_stat = MSM_PM_STAT_IDLE_SPIN;
 	low_power = 0;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
 
 	for (i = 0; i < ARRAY_SIZE(allow); i++)
 		allow[i] = true;
 
-	if ((timer_expiration < msm_pm_idle_sleep_min_time) ||
+	if (num_online_cpus() > 1 ||
+		(timer_expiration < msm_pm_idle_sleep_min_time) ||
 #ifdef CONFIG_HAS_WAKELOCK
 		has_wake_lock(WAKE_LOCK_IDLE) ||
 #endif
 		!msm_irq_idle_sleep_allowed()) {
 		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false;
 		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false;
-		allow[MSM_PM_SLEEP_MODE_APPS_SLEEP] = false;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(allow); i++) {
@@ -1493,32 +1508,15 @@
 			exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
 			msm_pm_sleep_limit = sleep_limit;
 		}
-#endif /* CONFIG_MSM_IDLE_STATS */
-	} else if (allow[MSM_PM_SLEEP_MODE_APPS_SLEEP]) {
-		uint32_t sleep_delay;
-
-		sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
-			timer_expiration, MSM_PM_SLEEP_TICK_LIMIT);
-		if (sleep_delay == 0) /* 0 would mean infinite time */
-			sleep_delay = 1;
-
-		ret = msm_pm_apps_sleep(sleep_delay, sleep_limit);
-		low_power = 0;
-
-#ifdef CONFIG_MSM_IDLE_STATS
-		if (ret)
-			exit_stat = MSM_PM_STAT_IDLE_FAILED_SLEEP;
-		else
-			exit_stat = MSM_PM_STAT_IDLE_SLEEP;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
 	} else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
-		ret = msm_pm_power_collapse_standalone();
+		ret = msm_pm_power_collapse_standalone(true);
 		low_power = 0;
 #ifdef CONFIG_MSM_IDLE_STATS
 		exit_stat = ret ?
 			MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE :
 			MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
 	} else if (allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT]) {
 		ret = msm_pm_swfi(true);
 		if (ret)
@@ -1527,20 +1525,20 @@
 		low_power = 0;
 #ifdef CONFIG_MSM_IDLE_STATS
 		exit_stat = ret ? MSM_PM_STAT_IDLE_SPIN : MSM_PM_STAT_IDLE_WFI;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
 	} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
 		msm_pm_swfi(false);
 		low_power = 0;
 #ifdef CONFIG_MSM_IDLE_STATS
 		exit_stat = MSM_PM_STAT_IDLE_WFI;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
 	} else {
 		while (!msm_irq_pending())
 			udelay(1);
 		low_power = 0;
 #ifdef CONFIG_MSM_IDLE_STATS
 		exit_stat = MSM_PM_STAT_IDLE_SPIN;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
 	}
 
 	msm_timer_exit_idle(low_power);
@@ -1548,13 +1546,14 @@
 #ifdef CONFIG_MSM_IDLE_STATS
 	t2 = ktime_to_ns(ktime_get());
 	msm_pm_add_stat(exit_stat, t2 - t1);
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
 }
 
 /*
  * Suspend the Apps processor.
  *
  * Return value:
+ *	-EPERM: Suspend happened by a not permitted core
  *      -EAGAIN: modem reset occurred or early exit from suspend
  *      -EBUSY: modem not ready for our suspend
  *      -EINVAL: invalid sleep mode
@@ -1566,13 +1565,20 @@
 {
 	bool allow[MSM_PM_SLEEP_MODE_NR];
 	uint32_t sleep_limit = SLEEP_LIMIT_NONE;
-	int ret;
+	int ret = -EPERM;
 	int i;
-
 #ifdef CONFIG_MSM_IDLE_STATS
 	int64_t period = 0;
 	int64_t time = 0;
+#endif
 
+	/* Must executed by CORE0 */
+	if (smp_processor_id()) {
+		__WARN();
+		goto suspend_exit;
+	}
+
+#ifdef CONFIG_MSM_IDLE_STATS
 	time = msm_timer_get_sclk_time(&period);
 #endif
 
@@ -1589,8 +1595,6 @@
 			allow[i] = false;
 	}
 
-	ret = 0;
-
 	if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] ||
 		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN]) {
 #ifdef CONFIG_MSM_IDLE_STATS
@@ -1647,7 +1651,7 @@
 		msm_pm_add_stat(id, time);
 #endif
 	} else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
-		ret = msm_pm_power_collapse_standalone();
+		ret = msm_pm_power_collapse_standalone(false);
 	} else if (allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT]) {
 		ret = msm_pm_swfi(true);
 		if (ret)
@@ -1657,6 +1661,7 @@
 		msm_pm_swfi(false);
 	}
 
+suspend_exit:
 	MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND, KERN_INFO,
 		"%s(): return %d\n", __func__, ret);
 
@@ -1673,7 +1678,27 @@
  */
 void msm_pm_cpu_enter_lowpower(unsigned int cpu)
 {
-	return;
+	bool allow[MSM_PM_SLEEP_MODE_NR];
+	int i;
+
+	for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
+		struct msm_pm_platform_data *mode;
+
+		mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+		allow[i] = mode->suspend_supported && mode->suspend_enabled;
+	}
+
+	MSM_PM_DPRINTK(MSM_PM_DEBUG_HOTPLUG, KERN_INFO,
+		"CPU%u: %s: shutting down cpu\n", cpu, __func__);
+
+	if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
+		msm_pm_power_collapse_standalone(false);
+	} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
+		msm_pm_swfi(false);
+	} else {
+		MSM_PM_DPRINTK(MSM_PM_DEBUG_HOTPLUG, KERN_INFO,
+			"CPU%u: %s: shutting down failed!!!\n", cpu, __func__);
+	}
 }
 
 /******************************************************************************
@@ -1725,10 +1750,6 @@
 };
 
 
-/******************************************************************************
- *
- *****************************************************************************/
-
 /*
  * Initialize the power management subsystem.
  *
@@ -1837,15 +1858,6 @@
 			first_bucket_time =
 			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
 
-		stats[MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep";
-		stats[MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
-			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
-
-		stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].name =
-			"idle-failed-sleep";
-		stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
-			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
-
 		stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].name =
 			"idle-power-collapse";
 		stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index 1bf2a55..31a54b7 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -58,8 +58,6 @@
 #include <mach/msm_adsp.h>
 #include "adsp.h"
 
-#define INT_ADSP INT_ADSP_A9_A11
-
 static struct adsp_info adsp_info;
 static struct msm_rpc_endpoint *rpc_cb_server_client;
 static struct msm_adsp_module *adsp_modules;
@@ -1090,7 +1088,7 @@
 
 		mutex_lock(&adsp_open_lock);
 		if (adsp_open_count++ == 0) {
-			enable_irq(INT_ADSP);
+			enable_irq(adsp_info.int_adsp);
 			prevent_suspend();
 		}
 		mutex_unlock(&adsp_open_lock);
@@ -1148,7 +1146,7 @@
 			clk_disable(module->clk);
 		mutex_lock(&adsp_open_lock);
 		if (--adsp_open_count == 0) {
-			disable_irq(INT_ADSP);
+			disable_irq(adsp_info.int_adsp);
 			allow_suspend();
 			MM_DBG("disable interrupt\n");
 		}
@@ -1177,8 +1175,11 @@
 	unsigned count;
 	int rc, i;
 
-	if (pdev->id != (rpc_adsp_rtos_atom_vers & RPC_VERSION_MAJOR_MASK))
-		return -EINVAL;
+	adsp_info.int_adsp = platform_get_irq(pdev, 0);
+	if (adsp_info.int_adsp < 0) {
+		MM_ERR("no irq resource?\n");
+		return -ENODEV;
+	}
 
 	wake_lock_init(&adsp_wake_lock, WAKE_LOCK_SUSPEND, "adsp");
 	adsp_info.init_info_ptr = kzalloc(
@@ -1206,11 +1207,11 @@
 	spin_lock_init(&adsp_write_lock);
 	mutex_init(&adsp_info.lock);
 
-	rc = request_irq(INT_ADSP, adsp_irq_handler, IRQF_TRIGGER_RISING,
-			 "adsp", 0);
+	rc = request_irq(adsp_info.int_adsp, adsp_irq_handler,
+			IRQF_TRIGGER_RISING, "adsp", 0);
 	if (rc < 0)
 		goto fail_request_irq;
-	disable_irq(INT_ADSP);
+	disable_irq(adsp_info.int_adsp);
 
 	rpc_cb_server_client = msm_rpc_open();
 	if (IS_ERR(rpc_cb_server_client)) {
@@ -1262,8 +1263,8 @@
 	msm_rpc_close(rpc_cb_server_client);
 	rpc_cb_server_client = NULL;
 fail_rpc_open:
-	enable_irq(INT_ADSP);
-	free_irq(INT_ADSP, 0);
+	enable_irq(adsp_info.int_adsp);
+	free_irq(adsp_info.int_adsp, 0);
 fail_request_irq:
 	kfree(adsp_modules);
 	kfree(adsp_info.init_info_ptr);
@@ -1392,7 +1393,7 @@
 	},
 };
 
-static char msm_adsp_driver_name[] = "rs00000000";
+static const char msm_adsp_driver_name[] = "msm_adsp";
 
 #ifdef CONFIG_DEBUG_FS
 static const struct file_operations adsp_debug_fops = {
@@ -1431,9 +1432,6 @@
 	rpc_adsp_rtos_mtoa_vers_comp = 0x00030001;
 #endif
 
-	snprintf(msm_adsp_driver_name, sizeof(msm_adsp_driver_name),
-		"rs%08x",
-		rpc_adsp_rtos_atom_prog);
 	msm_adsp_driver.driver.name = msm_adsp_driver_name;
 	rc = platform_driver_register(&msm_adsp_driver);
 	MM_INFO("%s -- %d\n", msm_adsp_driver_name, rc);
diff --git a/arch/arm/mach-msm/qdsp5/adsp.h b/arch/arm/mach-msm/qdsp5/adsp.h
index 8e5a4f3..0f16111 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.h
+++ b/arch/arm/mach-msm/qdsp5/adsp.h
@@ -118,6 +118,9 @@
 	wait_queue_head_t	init_info_wait;
 	unsigned 		init_info_state;
 	struct mutex lock;
+
+	/* Interrupt value */
+	int int_adsp;
 };
 
 #define RPC_ADSP_RTOS_ATOM_NULL_PROC 0
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
index 7a962b2..2011c42 100644
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5/audio_mp3.c
  *
@@ -836,6 +836,7 @@
 
 	file->private_data = audio;
 	audio->opened = 1;
+	audio->stopped = 0;
 	rc = 0;
 done:
 	mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp.c b/arch/arm/mach-msm/qdsp5v2/adsp.c
index b7b56c8..acd9c4c 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp.c
@@ -2,7 +2,7 @@
  * Register/Interrupt access for userspace aDSP library.
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2009,2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009,2011-2012 Code Aurora Forum. All rights reserved.
  * Author: Iliyan Malchev <ibm@android.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -46,8 +46,6 @@
 static int wdump, rdump;
 #endif /* CONFIG_DEBUG_FS */
 
-#define INT_ADSP INT_ADSP_A9_A11
-
 static struct adsp_info adsp_info;
 static struct msm_adsp_module *adsp_modules;
 static int adsp_open_count;
@@ -889,7 +887,7 @@
 
 		mutex_lock(&adsp_open_lock);
 		if (adsp_open_count++ == 0)
-			enable_irq(INT_ADSP);
+			enable_irq(adsp_info.int_adsp);
 		mutex_unlock(&adsp_open_lock);
 		break;
 	case ADSP_STATE_ENABLING:
@@ -944,7 +942,7 @@
 		mutex_unlock(&module->lock);
 		mutex_lock(&adsp_open_lock);
 		if (--adsp_open_count == 0) {
-			disable_irq(INT_ADSP);
+			disable_irq(adsp_info.int_adsp);
 			MM_INFO("disable interrupt\n");
 		}
 		mutex_unlock(&adsp_open_lock);
@@ -959,6 +957,12 @@
 	unsigned count;
 	int rc, i;
 
+	adsp_info.int_adsp = platform_get_irq(pdev, 0);
+	if (adsp_info.int_adsp < 0) {
+		MM_ERR("no irq resource?\n");
+		return -ENODEV;
+	}
+
 	adsp_info.init_info_ptr = kzalloc(
 		(sizeof(struct adsp_rtos_mp_mtoa_init_info_type)), GFP_KERNEL);
 	if (!adsp_info.init_info_ptr)
@@ -996,11 +1000,11 @@
 	spin_lock_init(&adsp_cmd_lock);
 	spin_lock_init(&adsp_write_lock);
 
-	rc = request_irq(INT_ADSP, adsp_irq_handler,
+	rc = request_irq(adsp_info.int_adsp, adsp_irq_handler,
 			IRQF_TRIGGER_RISING, "adsp", 0);
 	if (rc < 0)
 		goto fail_request_irq;
-	disable_irq(INT_ADSP);
+	disable_irq(adsp_info.int_adsp);
 
 	for (i = 0; i < count; i++) {
 		struct msm_adsp_module *mod = adsp_modules + i;
@@ -1056,8 +1060,8 @@
 	daldevice_detach(adsp_info.handle);
 	adsp_info.handle = NULL;
 fail_dal_attach:
-	enable_irq(INT_ADSP);
-	free_irq(INT_ADSP, 0);
+	enable_irq(adsp_info.int_adsp);
+	free_irq(adsp_info.int_adsp, 0);
 fail_request_irq:
 	kfree(adsp_modules);
 	kfree(adsp_info.init_info_ptr);
@@ -1187,11 +1191,6 @@
 	},
 };
 
-struct platform_device msm_adsp_device = {
-	.name = "msm_adsp",
-	.id = -1,
-};
-
 static char msm_adsp_driver_name[] = "msm_adsp";
 
 #ifdef CONFIG_DEBUG_FS
@@ -1218,7 +1217,6 @@
 #endif /* CONFIG_DEBUG_FS */
 
 	msm_adsp_driver.driver.name = msm_adsp_driver_name;
-	rc = platform_device_register(&msm_adsp_device);
 	rc = platform_driver_register(&msm_adsp_driver);
 	MM_INFO("%s -- %d\n", msm_adsp_driver_name, rc);
 	return rc;
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp.h b/arch/arm/mach-msm/qdsp5v2/adsp.h
index 18f4046..5aceff9 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp.h
+++ b/arch/arm/mach-msm/qdsp5v2/adsp.h
@@ -229,6 +229,9 @@
 
 	void *handle;
 	void *cb_handle;
+
+	/* Interrupt value */
+	int int_adsp;
 };
 
 #define ADSP_STATE_DISABLED   0
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index ce5d084..9b03985 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -15,7 +15,7 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
-#include <linux/android_pmem.h>
+#include <linux/ion.h>
 #include <linux/mm.h>
 #include <mach/qdsp6v2/audio_acdb.h>
 
@@ -62,13 +62,13 @@
 	/* Sidetone Cal */
 	struct sidetone_atomic_cal	sidetone_cal;
 
-	/* PMEM information */
-	atomic_t			pmem_fd;
+	/* Allocation information */
+	struct ion_client		*ion_client;
+	struct ion_handle		*ion_handle;
+	atomic_t			map_handle;
 	atomic64_t			paddr;
 	atomic64_t			kvaddr;
-	atomic64_t			pmem_len;
-	struct file			*file;
-
+	atomic64_t			mem_len;
 };
 
 static struct acdb_data		acdb_data;
@@ -200,10 +200,10 @@
 {
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
-		pr_err("%s: offset %d is > pmem_len %ld\n",
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.pmem_len));
+			(long)atomic64_read(&acdb_data.mem_len));
 		goto done;
 	}
 
@@ -221,10 +221,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
-		pr_err("%s: offset %d is > pmem_len %ld\n",
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.pmem_len));
+			(long)atomic64_read(&acdb_data.mem_len));
 		goto done;
 	}
 	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
@@ -271,10 +271,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
-		pr_err("%s: offset %d is > pmem_len %ld\n",
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.pmem_len));
+			(long)atomic64_read(&acdb_data.mem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -321,10 +321,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
-		pr_err("%s: offset %d is > pmem_len %ld\n",
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.pmem_len));
+			(long)atomic64_read(&acdb_data.mem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -371,10 +371,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
-		pr_err("%s: offset %d is > pmem_len %ld\n",
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.pmem_len));
+			(long)atomic64_read(&acdb_data.mem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -432,10 +432,10 @@
 	atomic_set(&acdb_data.vocproc_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
 		if (cal_blocks[i].cal_offset >
-					atomic64_read(&acdb_data.pmem_len)) {
-			pr_err("%s: offset %d is > pmem_len %ld\n",
+					atomic64_read(&acdb_data.mem_len)) {
+			pr_err("%s: offset %d is > mem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				(long)atomic64_read(&acdb_data.pmem_len));
+				(long)atomic64_read(&acdb_data.mem_len));
 			atomic_set(&acdb_data.vocproc_cal[i].cal_size, 0);
 		} else {
 			atomic_add(cal_blocks[i].cal_size,
@@ -484,10 +484,10 @@
 	atomic_set(&acdb_data.vocstrm_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
 		if (cal_blocks[i].cal_offset >
-					atomic64_read(&acdb_data.pmem_len)) {
-			pr_err("%s: offset %d is > pmem_len %ld\n",
+					atomic64_read(&acdb_data.mem_len)) {
+			pr_err("%s: offset %d is > mem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				(long)atomic64_read(&acdb_data.pmem_len));
+				(long)atomic64_read(&acdb_data.mem_len));
 			atomic_set(&acdb_data.vocstrm_cal[i].cal_size, 0);
 		} else {
 			atomic_add(cal_blocks[i].cal_size,
@@ -536,10 +536,10 @@
 	atomic_set(&acdb_data.vocvol_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
 		if (cal_blocks[i].cal_offset >
-					atomic64_read(&acdb_data.pmem_len)) {
-			pr_err("%s: offset %d is > pmem_len %ld\n",
+					atomic64_read(&acdb_data.mem_len)) {
+			pr_err("%s: offset %d is > mem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				(long)atomic64_read(&acdb_data.pmem_len));
+				(long)atomic64_read(&acdb_data.mem_len));
 			atomic_set(&acdb_data.vocvol_cal[i].cal_size, 0);
 		} else {
 			atomic_add(cal_blocks[i].cal_size,
@@ -603,8 +603,9 @@
 	s32 result = 0;
 	pr_debug("%s\n", __func__);
 
-	if (atomic_read(&acdb_data.pmem_fd)) {
-		pr_debug("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
+	if (atomic64_read(&acdb_data.mem_len)) {
+		pr_debug("%s: ACDB opened but memory allocated, "
+			"using existing allocation!\n",
 			__func__);
 	}
 
@@ -612,46 +613,74 @@
 	return result;
 }
 
-static int deregister_pmem(void)
+static int deregister_memory(void)
 {
-	if (atomic_read(&acdb_data.pmem_fd)) {
+	if (atomic64_read(&acdb_data.mem_len)) {
 		mutex_lock(&acdb_data.acdb_mutex);
-		put_pmem_file(acdb_data.file);
+		ion_unmap_kernel(acdb_data.ion_client, acdb_data.ion_handle);
+		ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+		ion_client_destroy(acdb_data.ion_client);
 		mutex_unlock(&acdb_data.acdb_mutex);
-		atomic_set(&acdb_data.pmem_fd, 0);
+		atomic64_set(&acdb_data.mem_len, 0);
 	}
 	return 0;
 }
 
-static int register_pmem(void)
+static int register_memory(void)
 {
-	int result;
-	unsigned long paddr;
-	unsigned long kvaddr;
-	unsigned long pmem_len;
+	int			result;
+	unsigned long		paddr;
+	unsigned long		kvaddr;
+	unsigned long		mem_len;
 
 	mutex_lock(&acdb_data.acdb_mutex);
-	result = get_pmem_file(atomic_read(&acdb_data.pmem_fd),
-				&paddr, &kvaddr, &pmem_len,
-				&acdb_data.file);
-	mutex_unlock(&acdb_data.acdb_mutex);
-	if (result != 0) {
-		atomic_set(&acdb_data.pmem_fd, 0);
-		atomic64_set(&acdb_data.pmem_len, 0);
-		pr_err("%s: Could not register PMEM!!!\n", __func__);
-		goto done;
+	acdb_data.ion_client =
+		msm_ion_client_create(UINT_MAX, "audio_acdb_client");
+	if (IS_ERR_OR_NULL(acdb_data.ion_client)) {
+		pr_err("%s: Could not register ION client!!!\n", __func__);
+		goto err;
 	}
 
+	acdb_data.ion_handle = ion_import_fd(acdb_data.ion_client,
+		atomic_read(&acdb_data.map_handle));
+	if (IS_ERR_OR_NULL(acdb_data.ion_handle)) {
+		pr_err("%s: Could not import map handle!!!\n", __func__);
+		goto err_ion_client;
+	}
+
+	result = ion_phys(acdb_data.ion_client, acdb_data.ion_handle,
+				&paddr, (size_t *)&mem_len);
+	if (result != 0) {
+		pr_err("%s: Could not get phys addr!!!\n", __func__);
+		goto err_ion_handle;
+	}
+
+	kvaddr = (unsigned long)ion_map_kernel(acdb_data.ion_client,
+		acdb_data.ion_handle, 0);
+	if (IS_ERR_OR_NULL(&kvaddr)) {
+		pr_err("%s: Could not get kernel virt addr!!!\n", __func__);
+		goto err_ion_handle;
+	}
+	mutex_unlock(&acdb_data.acdb_mutex);
+
 	atomic64_set(&acdb_data.paddr, paddr);
 	atomic64_set(&acdb_data.kvaddr, kvaddr);
-	atomic64_set(&acdb_data.pmem_len, pmem_len);
-	pr_debug("AUDIO_REGISTER_PMEM done! paddr = 0x%lx, "
+	atomic64_set(&acdb_data.mem_len, mem_len);
+	pr_debug("%s done! paddr = 0x%lx, "
 		"kvaddr = 0x%lx, len = x%lx\n",
+		 __func__,
 		(long)atomic64_read(&acdb_data.paddr),
 		(long)atomic64_read(&acdb_data.kvaddr),
-		(long)atomic64_read(&acdb_data.pmem_len));
+		(long)atomic64_read(&acdb_data.mem_len));
 
-done:
+	return result;
+err_ion_handle:
+	ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+err_ion_client:
+	ion_client_destroy(acdb_data.ion_client);
+err:
+	atomic64_set(&acdb_data.mem_len, 0);
+	mutex_unlock(&acdb_data.acdb_mutex);
 	return result;
 }
 static long acdb_ioctl(struct file *f,
@@ -659,7 +688,7 @@
 {
 	int32_t			result = 0;
 	int32_t			size;
-	int32_t			pmem_fd;
+	int32_t			map_fd;
 	uint32_t		topology;
 	struct cal_block	data[MAX_NETWORKS];
 	pr_debug("%s\n", __func__);
@@ -667,23 +696,23 @@
 	switch (cmd) {
 	case AUDIO_REGISTER_PMEM:
 		pr_debug("AUDIO_REGISTER_PMEM\n");
-		if (atomic_read(&acdb_data.pmem_fd)) {
-			deregister_pmem();
-			pr_debug("Remove the existing PMEM\n");
+		if (atomic_read(&acdb_data.mem_len)) {
+			deregister_memory();
+			pr_debug("Remove the existing memory\n");
 		}
 
-		if (copy_from_user(&pmem_fd, (void *)arg, sizeof(pmem_fd))) {
-			pr_err("%s: fail to copy pmem handle!\n", __func__);
+		if (copy_from_user(&map_fd, (void *)arg, sizeof(map_fd))) {
+			pr_err("%s: fail to copy memory handle!\n", __func__);
 			result = -EFAULT;
 		} else {
-			atomic_set(&acdb_data.pmem_fd, pmem_fd);
-			result = register_pmem();
+			atomic_set(&acdb_data.map_handle, map_fd);
+			result = register_memory();
 		}
 		goto done;
 
 	case AUDIO_DEREGISTER_PMEM:
 		pr_debug("AUDIO_DEREGISTER_PMEM\n");
-		deregister_pmem();
+		deregister_memory();
 		goto done;
 	case AUDIO_SET_VOICE_RX_TOPOLOGY:
 		if (copy_from_user(&topology, (void *)arg,
@@ -835,8 +864,8 @@
 
 	pr_debug("%s\n", __func__);
 
-	if (atomic_read(&acdb_data.pmem_fd)) {
-		if (size <= atomic64_read(&acdb_data.pmem_len)) {
+	if (atomic64_read(&acdb_data.mem_len)) {
+		if (size <= atomic64_read(&acdb_data.mem_len)) {
 			vma->vm_page_prot = pgprot_noncached(
 						vma->vm_page_prot);
 			result = remap_pfn_range(vma,
@@ -845,11 +874,11 @@
 				size,
 				vma->vm_page_prot);
 		} else {
-			pr_err("%s: Not enough PMEM memory!\n", __func__);
+			pr_err("%s: Not enough memory!\n", __func__);
 			result = -ENOMEM;
 		}
 	} else {
-		pr_err("%s: PMEM is not allocated, yet!\n", __func__);
+		pr_err("%s: memory is not allocated, yet!\n", __func__);
 		result = -ENODEV;
 	}
 
@@ -869,7 +898,7 @@
 	if (atomic_read(&usage_count) >= 1)
 		result = -EBUSY;
 	else
-		result = deregister_pmem();
+		result = deregister_memory();
 
 	return result;
 }
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c b/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c
index 0a5acce..aaae776 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
+#include <linux/workqueue.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
 #include <mach/qdsp6v2/audio_dev_ctl.h>
@@ -31,6 +32,9 @@
 
 
 static DEFINE_MUTEX(session_lock);
+static struct workqueue_struct *msm_reset_device_work_queue;
+static void reset_device_work(struct work_struct *work);
+static DECLARE_WORK(msm_reset_device_work, reset_device_work);
 
 struct audio_dev_ctrl_state {
 	struct msm_snddev_info *devs[AUDIO_DEV_CTL_MAX_DEV];
@@ -119,6 +123,18 @@
 }
 EXPORT_SYMBOL(msm_reset_all_device);
 
+static void reset_device_work(struct work_struct *work)
+{
+	msm_reset_all_device();
+}
+
+int reset_device(void)
+{
+	queue_work(msm_reset_device_work_queue, &msm_reset_device_work);
+	return 0;
+}
+EXPORT_SYMBOL(reset_device);
+
 int msm_set_copp_id(int session_id, int copp_id)
 {
 	int rc = 0;
@@ -1686,7 +1702,9 @@
 	init_waitqueue_head(&audio_dev_ctrl.wait);
 
 	event.cb = NULL;
-
+	msm_reset_device_work_queue = create_workqueue("reset_device");
+	if (msm_reset_device_work_queue == NULL)
+		return -ENOMEM;
 	atomic_set(&audio_dev_ctrl.opened, 0);
 	audio_dev_ctrl.num_dev = 0;
 	audio_dev_ctrl.voice_tx_dev = NULL;
@@ -1704,6 +1722,7 @@
 
 static void __exit audio_dev_ctrl_exit(void)
 {
+	destroy_workqueue(msm_reset_device_work_queue);
 }
 module_init(audio_dev_ctrl_init);
 module_exit(audio_dev_ctrl_exit);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
index 3225d61..41a7387 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -28,8 +28,8 @@
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/earlysuspend.h>
+#include <linux/ion.h>
 #include <linux/list.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <asm/atomic.h>
 #include <asm/ioctls.h>
@@ -45,7 +45,7 @@
 #include <mach/debug_mm.h>
 #include <linux/fs.h>
 
-#define MAX_BUF 3
+#define MAX_BUF 4
 #define BUFSZ (524288)
 
 #define AUDDEC_DEC_PCM 0
@@ -88,10 +88,10 @@
 	int event_type;
 	union msm_audio_event_payload payload;
 };
-
-struct audlpa_pmem_region {
+struct audlpa_ion_region {
 	struct list_head list;
-	struct file *file;
+	struct ion_handle *handle;
+	struct ion_client *client;
 	int fd;
 	void *vaddr;
 	unsigned long paddr;
@@ -115,12 +115,13 @@
 
 static void audlpa_post_event(struct audio *audio, int type,
 	union msm_audio_event_payload payload);
-static unsigned long audlpa_pmem_fixup(struct audio *audio, void *addr,
+
+static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr,
 				unsigned long len, int ref_up);
+static void audlpa_unmap_ion_region(struct audio *audio);
 static void audlpa_async_send_data(struct audio *audio, unsigned needed,
 				uint32_t token);
 static int audlpa_pause(struct audio *audio);
-static void audlpa_unmap_pmem_region(struct audio *audio);
 static long pcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 static int audlpa_set_pcm_params(void *data);
 
@@ -422,7 +423,7 @@
 	    drv_evt->event_type == AUDIO_EVENT_READ_DONE)) {
 		pr_debug("%s: AUDIO_EVENT_WRITE_DONE completing\n", __func__);
 		mutex_lock(&audio->lock);
-		audlpa_pmem_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+		audlpa_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
 				  drv_evt->payload.aio_buf.buf_len, 0);
 		mutex_unlock(&audio->lock);
 	}
@@ -432,38 +433,41 @@
 	return rc;
 }
 
-static int audlpa_pmem_check(struct audio *audio,
-		void *vaddr, unsigned long len)
+static int audlpa_ion_check(struct audio *audio,
+			void *vaddr, unsigned long len)
 {
-	struct audlpa_pmem_region *region_elt;
-	struct audlpa_pmem_region t = { .vaddr = vaddr, .len = len };
+	struct audlpa_ion_region *region_elt;
+	struct audlpa_ion_region t = {.vaddr = vaddr, .len = len };
 
-	list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
+	list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
 		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
 		    OVERLAPS(region_elt, &t)) {
-			pr_err("%s: region (vaddr %p len %ld)"
-				" clashes with registered region"
-				" (vaddr %p paddr %p len %ld)\n",
-				__func__, vaddr, len,
-				region_elt->vaddr,
-				(void *)region_elt->paddr,
-				region_elt->len);
+			pr_err("%s[%p]:region (vaddr %p len %ld)"
+			" clashes with registered region"
+			" (vaddr %p paddr %p len %ld)\n",
+			__func__, audio, vaddr, len,
+			region_elt->vaddr,
+			(void *)region_elt->paddr, region_elt->len);
 			return -EINVAL;
 		}
 	}
 
 	return 0;
 }
-
-static int audlpa_pmem_add(struct audio *audio,
-	struct msm_audio_pmem_info *info)
+static int audlpa_ion_add(struct audio *audio,
+			struct msm_audio_ion_info *info)
 {
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct audlpa_pmem_region *region;
+	ion_phys_addr_t paddr;
+	size_t len;
+	unsigned long kvaddr;
+	struct audlpa_ion_region *region;
 	int rc = -EINVAL;
+	struct ion_handle *handle;
+	struct ion_client *client;
+	unsigned long ionflag;
+	void *temp_ptr;
 
-	pr_debug("%s:\n", __func__);
+	pr_debug("%s[%p]:\n", __func__, audio);
 	region = kmalloc(sizeof(*region), GFP_KERNEL);
 
 	if (!region) {
@@ -471,61 +475,105 @@
 		goto end;
 	}
 
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
-		kfree(region);
-		goto end;
+	client = msm_ion_client_create(UINT_MAX, "Audio_LPA_Client");
+	if (IS_ERR_OR_NULL(client)) {
+		pr_err("Unable to create ION client\n");
+		goto client_error;
 	}
 
-	rc = audlpa_pmem_check(audio, info->vaddr, len);
+	handle = ion_import_fd(client, info->fd);
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: could not get handle of the given fd\n", __func__);
+		goto import_error;
+	}
+
+	rc = ion_handle_get_flags(client, handle, &ionflag);
+	if (rc) {
+		pr_err("%s: could not get flags for the handle\n", __func__);
+		goto flag_error;
+	}
+
+	temp_ptr = ion_map_kernel(client, handle, ionflag);
+	if (IS_ERR_OR_NULL(temp_ptr)) {
+		pr_err("%s: could not get virtual address\n", __func__);
+		goto map_error;
+	}
+	kvaddr = (unsigned long) temp_ptr;
+
+	rc = ion_phys(client, handle, &paddr, &len);
+	if (rc) {
+		pr_err("%s: could not get physical address\n", __func__);
+		goto ion_error;
+	}
+
+	rc = audlpa_ion_check(audio, info->vaddr, len);
 	if (rc < 0) {
-		put_pmem_file(file);
-		kfree(region);
-		goto end;
+		pr_err("%s: audlpa_ion_check failed\n", __func__);
+		goto ion_error;
 	}
 
+	region->client = client;
+	region->handle = handle;
 	region->vaddr = info->vaddr;
 	region->fd = info->fd;
 	region->paddr = paddr;
 	region->kvaddr = kvaddr;
 	region->len = len;
-	region->file = file;
 	region->ref_cnt = 0;
-	pr_debug("%s: add region paddr %lx vaddr %p, len %lu\n", __func__,
-			 region->paddr, region->vaddr,
-			 region->len);
-	list_add_tail(&region->list, &audio->pmem_region_queue);
+	pr_debug("%s[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
+		__func__, audio,
+		region->paddr, region->vaddr, region->len, region->kvaddr);
+	list_add_tail(&region->list, &audio->ion_region_queue);
+
 	rc = q6asm_memory_map(audio->ac, (uint32_t)paddr, IN, (uint32_t)len, 1);
-	if (rc < 0)
-		pr_err("%s: memory map failed\n", __func__);
+	if (rc < 0) {
+		pr_err("%s[%p]: memory map failed\n", __func__, audio);
+		goto ion_error;
+	} else {
+		goto end;
+	}
+
+ion_error:
+	ion_unmap_kernel(client, handle);
+map_error:
+	ion_free(client, handle);
+flag_error:
+import_error:
+	ion_client_destroy(client);
+client_error:
+	kfree(region);
 end:
 	return rc;
 }
 
-static int audlpa_pmem_remove(struct audio *audio,
-	struct msm_audio_pmem_info *info)
+static int audlpa_ion_remove(struct audio *audio,
+			struct msm_audio_ion_info *info)
 {
-	struct audlpa_pmem_region *region;
+	struct audlpa_ion_region *region;
 	struct list_head *ptr, *next;
 	int rc = -EINVAL;
 
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audlpa_pmem_region, list);
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audlpa_ion_region, list);
 
-		if ((region != NULL) && (region->fd == info->fd) &&
-		    (region->vaddr == info->vaddr)) {
+		if (region != NULL && (region->fd == info->fd) &&
+			(region->vaddr == info->vaddr)) {
 			if (region->ref_cnt) {
-				pr_debug("%s: region %p in use ref_cnt %d\n",
-					__func__, region, region->ref_cnt);
+				pr_debug("%s[%p]:region %p in use ref_cnt %d\n",
+					__func__, audio, region,
+					region->ref_cnt);
 				break;
 			}
 			rc = q6asm_memory_unmap(audio->ac,
-						(uint32_t)region->paddr,
-						IN);
+				(uint32_t) region->paddr, IN);
 			if (rc < 0)
-				pr_err("%s: memory unmap failed\n", __func__);
+				pr_err("%s[%p]: memory unmap failed\n",
+					__func__, audio);
 
 			list_del(&region->list);
-			put_pmem_file(region->file);
+			ion_unmap_kernel(region->client, region->handle);
+			ion_free(region->client, region->handle);
+			ion_client_destroy(region->client);
 			kfree(region);
 			rc = 0;
 			break;
@@ -535,24 +583,21 @@
 	return rc;
 }
 
-static int audlpa_pmem_lookup_vaddr(struct audio *audio, void *addr,
-		     unsigned long len, struct audlpa_pmem_region **region)
+static int audlpa_ion_lookup_vaddr(struct audio *audio, void *addr,
+			unsigned long len, struct audlpa_ion_region **region)
 {
-	struct audlpa_pmem_region *region_elt;
-
+	struct audlpa_ion_region *region_elt;
 	int match_count = 0;
-
 	*region = NULL;
 
 	/* returns physical address or zero */
-	list_for_each_entry(region_elt, &audio->pmem_region_queue,
-		list) {
+	list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
 		if (addr >= region_elt->vaddr &&
-		    addr < region_elt->vaddr + region_elt->len &&
-		    addr + len <= region_elt->vaddr + region_elt->len) {
+			addr < region_elt->vaddr + region_elt->len &&
+			addr + len <= region_elt->vaddr + region_elt->len) {
 			/* offset since we could pass vaddr inside a registerd
-			 * pmem buffer
-			 */
+			* ion buffer
+			*/
 
 			match_count++;
 			if (!*region)
@@ -561,32 +606,33 @@
 	}
 
 	if (match_count > 1) {
-		pr_err("%s: multiple hits for vaddr %p, len %ld\n", __func__,
-			   addr, len);
-		list_for_each_entry(region_elt,
-		  &audio->pmem_region_queue, list) {
-			if (addr >= region_elt->vaddr &&
-			    addr < region_elt->vaddr + region_elt->len &&
-			    addr + len <= region_elt->vaddr + region_elt->len)
-				pr_err("%s: \t%p, %ld --> %p\n", __func__,
-					   region_elt->vaddr, region_elt->len,
-					   (void *)region_elt->paddr);
+		pr_err("%s[%p]:multiple hits for vaddr %p, len %ld\n",
+			 __func__, audio, addr, len);
+		list_for_each_entry(region_elt, &audio->ion_region_queue,
+					list) {
+		if (addr >= region_elt->vaddr &&
+			addr < region_elt->vaddr + region_elt->len &&
+			addr + len <= region_elt->vaddr + region_elt->len)
+			pr_err("\t%s[%p]:%p, %ld --> %p\n",
+				__func__, audio,
+					region_elt->vaddr,
+					region_elt->len,
+					(void *)region_elt->paddr);
 		}
 	}
-
 	return *region ? 0 : -1;
 }
-
-unsigned long audlpa_pmem_fixup(struct audio *audio, void *addr,
-		    unsigned long len, int ref_up)
+static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr,
+			unsigned long len, int ref_up)
 {
-	struct audlpa_pmem_region *region;
+	struct audlpa_ion_region *region;
 	unsigned long paddr;
 	int ret;
 
-	ret = audlpa_pmem_lookup_vaddr(audio, addr, len, &region);
+	ret = audlpa_ion_lookup_vaddr(audio, addr, len, &region);
 	if (ret) {
-		pr_err("%s: lookup (%p, %ld) failed\n", __func__, addr, len);
+		pr_err("%s[%p]:lookup (%p, %ld) failed\n",
+			__func__, audio, addr, len);
 		return 0;
 	}
 	if (ref_up)
@@ -613,7 +659,7 @@
 		return -EFAULT;
 	}
 
-	buf_node->paddr = audlpa_pmem_fixup(
+	buf_node->paddr = audlpa_ion_fixup(
 		audio, buf_node->buf.buf_addr,
 		buf_node->buf.buf_len, 1);
 	if (dir) {
@@ -669,6 +715,9 @@
 		break;
 	case ASM_SESSION_CMDRSP_GET_SESSION_TIME:
 		break;
+	case RESET_EVENTS:
+		reset_device();
+		break;
 	default:
 		break;
 	}
@@ -918,25 +967,26 @@
 		}
 		break;
 
-	case AUDIO_REGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			pr_debug("%s: AUDIO_REGISTER_PMEM\n", __func__);
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audlpa_pmem_add(audio, &info);
-			break;
-		}
+	case AUDIO_REGISTER_ION: {
+		struct msm_audio_ion_info info;
+		pr_debug("%s: AUDIO_REGISTER_ION\n", __func__);
+		if (copy_from_user(&info, (void *)arg, sizeof(info)))
+			rc = -EFAULT;
+		else
+			rc = audlpa_ion_add(audio, &info);
+		break;
+	}
 
-	case AUDIO_DEREGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			pr_debug("%s: AUDIO_DEREGISTER_PMEM\n", __func__);
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audlpa_pmem_remove(audio, &info);
-			break;
-		}
+	case AUDIO_DEREGISTER_ION: {
+		struct msm_audio_ion_info info;
+		pr_debug("%s: AUDIO_DEREGISTER_ION\n", __func__);
+		if (copy_from_user(&info, (void *)arg, sizeof(info)))
+			rc = -EFAULT;
+		else
+			rc = audlpa_ion_remove(audio, &info);
+		break;
+	}
+
 	case AUDIO_ASYNC_WRITE:
 		pr_debug("%s: AUDIO_ASYNC_WRITE\n", __func__);
 		if (audio->drv_status & ADRV_STATUS_FSYNC)
@@ -1035,34 +1085,37 @@
 	return audlpa_async_fsync(audio);
 }
 
-static void audlpa_reset_pmem_region(struct audio *audio)
+void audlpa_reset_ion_region(struct audio *audio)
 {
-	struct audlpa_pmem_region *region;
+	struct audlpa_ion_region *region;
 	struct list_head *ptr, *next;
 
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audlpa_pmem_region, list);
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audlpa_ion_region, list);
 		list_del(&region->list);
-		put_pmem_file(region->file);
+		ion_unmap_kernel(region->client, region->handle);
+		ion_free(region->client, region->handle);
+		ion_client_destroy(region->client);
 		kfree(region);
 	}
 
 	return;
 }
 
-static void audlpa_unmap_pmem_region(struct audio *audio)
+static void audlpa_unmap_ion_region(struct audio *audio)
 {
-	struct audlpa_pmem_region *region;
+	struct audlpa_ion_region *region;
 	struct list_head *ptr, *next;
 	int rc = -EINVAL;
 
-	pr_debug("%s:\n", __func__);
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audlpa_pmem_region, list);
-		pr_debug("%s: phy_address = 0x%lx\n", __func__, region->paddr);
+	pr_debug("%s[%p]:\n", __func__, audio);
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audlpa_ion_region, list);
+		pr_debug("%s[%p]: phy_address = 0x%lx\n",
+			__func__, audio, region->paddr);
 		if (region != NULL) {
 			rc = q6asm_memory_unmap(audio->ac,
-						(uint32_t)region->paddr, IN);
+					(uint32_t)region->paddr, IN);
 			if (rc < 0)
 				pr_err("%s: memory unmap failed\n", __func__);
 		}
@@ -1081,12 +1134,12 @@
 	if (audio->out_enabled)
 		audlpa_async_flush(audio);
 	audio->wflush = 0;
-	audlpa_unmap_pmem_region(audio);
+	audlpa_unmap_ion_region(audio);
 	audio_disable(audio);
 	msm_clear_session_id(audio->ac->session);
 	auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->ac->session);
 	q6asm_audio_client_free(audio->ac);
-	audlpa_reset_pmem_region(audio);
+	audlpa_reset_ion_region(audio);
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	unregister_early_suspend(&audio->suspend_ctl.node);
 #endif
@@ -1096,7 +1149,6 @@
 	audio->event_abort = 1;
 	wake_up(&audio->event_wait);
 	audlpa_reset_event_queue(audio);
-	pmem_kfree(audio->phys);
 	if (audio->stopped == 0)
 		audlpa_allow_sleep(audio);
 	wake_lock_destroy(&audio->wakelock);
@@ -1274,7 +1326,7 @@
 	spin_lock_init(&audio->dsp_lock);
 	init_waitqueue_head(&audio->write_wait);
 	INIT_LIST_HEAD(&audio->out_queue);
-	INIT_LIST_HEAD(&audio->pmem_region_queue);
+	INIT_LIST_HEAD(&audio->ion_region_queue);
 	INIT_LIST_HEAD(&audio->free_event_queue);
 	INIT_LIST_HEAD(&audio->event_queue);
 	init_waitqueue_head(&audio->wait);
@@ -1339,7 +1391,6 @@
 	return rc;
 err:
 	q6asm_audio_client_free(audio->ac);
-	pmem_kfree(audio->phys);
 	kfree(audio);
 	return rc;
 }
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_lpa.h b/arch/arm/mach-msm/qdsp6v2/audio_lpa.h
index ffc27ad..34b53f2 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_lpa.h
+++ b/arch/arm/mach-msm/qdsp6v2/audio_lpa.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -88,7 +88,7 @@
 
 	uint32_t device_events;
 
-	struct list_head pmem_region_queue; /* protected by lock */
+	struct list_head ion_region_queue; /* protected by lock */
 
 	int eq_enable;
 	int eq_needs_commit;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index c1b5e8b..d2557ca 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -1,6 +1,6 @@
 /* Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -129,23 +129,23 @@
 	}
 }
 
-static int audio_aio_pmem_lookup_vaddr(struct q6audio_aio *audio, void *addr,
+static int audio_aio_ion_lookup_vaddr(struct q6audio_aio *audio, void *addr,
 					unsigned long len,
-					struct audio_aio_pmem_region **region)
+					struct audio_aio_ion_region **region)
 {
-	struct audio_aio_pmem_region *region_elt;
+	struct audio_aio_ion_region *region_elt;
 
 	int match_count = 0;
 
 	*region = NULL;
 
 	/* returns physical address or zero */
-	list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
+	list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
 		if (addr >= region_elt->vaddr &&
 			addr < region_elt->vaddr + region_elt->len &&
 			addr + len <= region_elt->vaddr + region_elt->len) {
 			/* offset since we could pass vaddr inside a registerd
-			* pmem buffer
+			* ion buffer
 			*/
 
 			match_count++;
@@ -157,7 +157,7 @@
 	if (match_count > 1) {
 		pr_err("%s[%p]:multiple hits for vaddr %p, len %ld\n",
 			__func__, audio, addr, len);
-		list_for_each_entry(region_elt, &audio->pmem_region_queue,
+		list_for_each_entry(region_elt, &audio->ion_region_queue,
 					list) {
 			if (addr >= region_elt->vaddr &&
 			addr < region_elt->vaddr + region_elt->len &&
@@ -173,14 +173,14 @@
 	return *region ? 0 : -1;
 }
 
-static unsigned long audio_aio_pmem_fixup(struct q6audio_aio *audio, void *addr,
+static unsigned long audio_aio_ion_fixup(struct q6audio_aio *audio, void *addr,
 				unsigned long len, int ref_up, void **kvaddr)
 {
-	struct audio_aio_pmem_region *region;
+	struct audio_aio_ion_region *region;
 	unsigned long paddr;
 	int ret;
 
-	ret = audio_aio_pmem_lookup_vaddr(audio, addr, len, &region);
+	ret = audio_aio_ion_lookup_vaddr(audio, addr, len, &region);
 	if (ret) {
 		pr_err("%s[%p]:lookup (%p, %ld) failed\n",
 				__func__, audio, addr, len);
@@ -519,15 +519,17 @@
 	return rc;
 }
 
-void audio_aio_reset_pmem_region(struct q6audio_aio *audio)
+void audio_aio_reset_ion_region(struct q6audio_aio *audio)
 {
-	struct audio_aio_pmem_region *region;
+	struct audio_aio_ion_region *region;
 	struct list_head *ptr, *next;
 
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audio_aio_pmem_region, list);
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audio_aio_ion_region, list);
 		list_del(&region->list);
-		put_pmem_file(region->file);
+		ion_unmap_kernel(region->client, region->handle);
+		ion_free(region->client, region->handle);
+		ion_client_destroy(region->client);
 		kfree(region);
 	}
 
@@ -558,15 +560,15 @@
 	return;
 }
 
-static void audio_aio_unmap_pmem_region(struct q6audio_aio *audio)
+static void audio_aio_unmap_ion_region(struct q6audio_aio *audio)
 {
-	struct audio_aio_pmem_region *region;
+	struct audio_aio_ion_region *region;
 	struct list_head *ptr, *next;
 	int rc = -EINVAL;
 
 	pr_debug("%s[%p]:\n", __func__, audio);
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audio_aio_pmem_region, list);
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audio_aio_ion_region, list);
 		pr_debug("%s[%p]: phy_address = 0x%lx\n",
 				__func__, audio, region->paddr);
 		if (region != NULL) {
@@ -590,9 +592,9 @@
 	audio->wflush = 0;
 	audio->drv_ops.out_flush(audio);
 	audio->drv_ops.in_flush(audio);
-	audio_aio_unmap_pmem_region(audio);
+	audio_aio_unmap_ion_region(audio);
 	audio_aio_disable(audio);
-	audio_aio_reset_pmem_region(audio);
+	audio_aio_reset_ion_region(audio);
 	audio->event_abort = 1;
 	wake_up(&audio->event_wait);
 	audio_aio_reset_event_queue(audio);
@@ -746,14 +748,14 @@
 		pr_debug("%s[%p]:posted AUDIO_EVENT_WRITE_DONE to user\n",
 			__func__, audio);
 		mutex_lock(&audio->write_lock);
-		audio_aio_pmem_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+		audio_aio_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
 		drv_evt->payload.aio_buf.buf_len, 0, 0);
 		mutex_unlock(&audio->write_lock);
 	} else if (drv_evt->event_type == AUDIO_EVENT_READ_DONE) {
 		pr_debug("%s[%p]:posted AUDIO_EVENT_READ_DONE to user\n",
 			__func__, audio);
 		mutex_lock(&audio->read_lock);
-		audio_aio_pmem_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+		audio_aio_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
 		drv_evt->payload.aio_buf.buf_len, 0, 0);
 		mutex_unlock(&audio->read_lock);
 	}
@@ -773,13 +775,13 @@
 	return rc;
 }
 
-static int audio_aio_pmem_check(struct q6audio_aio *audio,
+static int audio_aio_ion_check(struct q6audio_aio *audio,
 				void *vaddr, unsigned long len)
 {
-	struct audio_aio_pmem_region *region_elt;
-	struct audio_aio_pmem_region t = {.vaddr = vaddr, .len = len };
+	struct audio_aio_ion_region *region_elt;
+	struct audio_aio_ion_region t = {.vaddr = vaddr, .len = len };
 
-	list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
+	list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
 		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
 			OVERLAPS(region_elt, &t)) {
 			pr_err("%s[%p]:region (vaddr %p len %ld)"
@@ -795,13 +797,18 @@
 	return 0;
 }
 
-static int audio_aio_pmem_add(struct q6audio_aio *audio,
-				struct msm_audio_pmem_info *info)
+static int audio_aio_ion_add(struct q6audio_aio *audio,
+				struct msm_audio_ion_info *info)
 {
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct audio_aio_pmem_region *region;
+	ion_phys_addr_t paddr;
+	size_t len;
+	unsigned long kvaddr;
+	struct audio_aio_ion_region *region;
 	int rc = -EINVAL;
+	struct ion_handle *handle;
+	struct ion_client *client;
+	unsigned long ionflag;
+	void *temp_ptr;
 
 	pr_debug("%s[%p]:\n", __func__, audio);
 	region = kmalloc(sizeof(*region), GFP_KERNEL);
@@ -811,50 +818,89 @@
 		goto end;
 	}
 
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
-		kfree(region);
-		goto end;
+	client = msm_ion_client_create(UINT_MAX, "Audio_Dec_Client");
+	if (IS_ERR_OR_NULL(client)) {
+		pr_err("Unable to create ION client\n");
+		goto client_error;
 	}
 
-	rc = audio_aio_pmem_check(audio, info->vaddr, len);
+	handle = ion_import_fd(client, info->fd);
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: could not get handle of the given fd\n", __func__);
+		goto import_error;
+	}
+
+	rc = ion_handle_get_flags(client, handle, &ionflag);
+	if (rc) {
+		pr_err("%s: could not get flags for the handle\n", __func__);
+		goto flag_error;
+	}
+
+	temp_ptr = ion_map_kernel(client, handle, ionflag);
+	if (IS_ERR_OR_NULL(temp_ptr)) {
+		pr_err("%s: could not get virtual address\n", __func__);
+		goto map_error;
+	}
+	kvaddr = (unsigned long)temp_ptr;
+
+	rc = ion_phys(client, handle, &paddr, &len);
+	if (rc) {
+		pr_err("%s: could not get physical address\n", __func__);
+		goto ion_error;
+	}
+
+	rc = audio_aio_ion_check(audio, info->vaddr, len);
 	if (rc < 0) {
-		put_pmem_file(file);
-		kfree(region);
-		goto end;
+		pr_err("%s: audio_aio_ion_check failed\n", __func__);
+		goto ion_error;
 	}
 
+	region->client = client;
+	region->handle = handle;
 	region->vaddr = info->vaddr;
 	region->fd = info->fd;
 	region->paddr = paddr;
 	region->kvaddr = kvaddr;
 	region->len = len;
-	region->file = file;
 	region->ref_cnt = 0;
 	pr_debug("%s[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
 		__func__, audio,
 		region->paddr, region->vaddr, region->len, region->kvaddr);
-	list_add_tail(&region->list, &audio->pmem_region_queue);
-
+	list_add_tail(&region->list, &audio->ion_region_queue);
 	rc = q6asm_memory_map(audio->ac, (uint32_t) paddr, IN, (uint32_t) len,
 				1);
-	if (rc < 0)
+	if (rc < 0) {
 		pr_err("%s[%p]: memory map failed\n", __func__, audio);
+		goto ion_error;
+	} else {
+		goto end;
+	}
+
+ion_error:
+	ion_unmap_kernel(client, handle);
+map_error:
+	ion_free(client, handle);
+flag_error:
+import_error:
+	ion_client_destroy(client);
+client_error:
+	kfree(region);
 end:
 	return rc;
 }
 
-static int audio_aio_pmem_remove(struct q6audio_aio *audio,
-				struct msm_audio_pmem_info *info)
+static int audio_aio_ion_remove(struct q6audio_aio *audio,
+				struct msm_audio_ion_info *info)
 {
-	struct audio_aio_pmem_region *region;
+	struct audio_aio_ion_region *region;
 	struct list_head *ptr, *next;
 	int rc = -EINVAL;
 
 	pr_debug("%s[%p]:info fd %d vaddr %p\n",
 		__func__, audio, info->fd, info->vaddr);
 
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audio_aio_pmem_region, list);
+	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+		region = list_entry(ptr, struct audio_aio_ion_region, list);
 
 		if ((region->fd == info->fd) &&
 			(region->vaddr == info->vaddr)) {
@@ -873,7 +919,9 @@
 					__func__, audio);
 
 			list_del(&region->list);
-			put_pmem_file(region->file);
+			ion_unmap_kernel(region->client, region->handle);
+			ion_free(region->client, region->handle);
+			ion_client_destroy(region->client);
 			kfree(region);
 			rc = 0;
 			break;
@@ -989,8 +1037,7 @@
 	pr_debug("%s[%p]:node %p dir %x buf_addr %p buf_len %d data_len \
 		%d\n", __func__, audio, buf_node, dir, buf_node->buf.buf_addr,
 		buf_node->buf.buf_len, buf_node->buf.data_len);
-
-	buf_node->paddr = audio_aio_pmem_fixup(audio, buf_node->buf.buf_addr,
+	buf_node->paddr = audio_aio_ion_fixup(audio, buf_node->buf.buf_addr,
 						buf_node->buf.buf_len, 1,
 						&buf_node->kvaddr);
 	if (dir) {
@@ -1125,7 +1172,7 @@
 	init_waitqueue_head(&audio->event_wait);
 	INIT_LIST_HEAD(&audio->out_queue);
 	INIT_LIST_HEAD(&audio->in_queue);
-	INIT_LIST_HEAD(&audio->pmem_region_queue);
+	INIT_LIST_HEAD(&audio->ion_region_queue);
 	INIT_LIST_HEAD(&audio->free_event_queue);
 	INIT_LIST_HEAD(&audio->event_queue);
 
@@ -1281,25 +1328,25 @@
 		mutex_unlock(&audio->lock);
 		break;
 	}
-	case AUDIO_REGISTER_PMEM: {
-		struct msm_audio_pmem_info info;
-		pr_debug("%s[%p]:AUDIO_REGISTER_PMEM\n", __func__, audio);
+	case AUDIO_REGISTER_ION: {
+		struct msm_audio_ion_info info;
+		pr_debug("%s[%p]:AUDIO_REGISTER_ION\n", __func__, audio);
 		mutex_lock(&audio->lock);
 		if (copy_from_user(&info, (void *)arg, sizeof(info)))
 			rc = -EFAULT;
 		else
-			rc = audio_aio_pmem_add(audio, &info);
+			rc = audio_aio_ion_add(audio, &info);
 		mutex_unlock(&audio->lock);
 		break;
 	}
-	case AUDIO_DEREGISTER_PMEM: {
-		struct msm_audio_pmem_info info;
+	case AUDIO_DEREGISTER_ION: {
+		struct msm_audio_ion_info info;
 		mutex_lock(&audio->lock);
-		pr_debug("%s[%p]:AUDIO_DEREGISTER_PMEM\n", __func__, audio);
+		pr_debug("%s[%p]:AUDIO_DEREGISTER_ION\n", __func__, audio);
 		if (copy_from_user(&info, (void *)arg, sizeof(info)))
 			rc = -EFAULT;
 		else
-			rc = audio_aio_pmem_remove(audio, &info);
+			rc = audio_aio_ion_remove(audio, &info);
 		mutex_unlock(&audio->lock);
 		break;
 	}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
index ebf3668..a25ca4d 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
@@ -1,6 +1,6 @@
 /* Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -23,15 +23,13 @@
 #include <linux/msm_audio.h>
 #include <linux/debugfs.h>
 #include <linux/list.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
+#include <linux/ion.h>
 #include <asm/ioctls.h>
 #include <asm/atomic.h>
 #include <sound/q6asm.h>
 #include <sound/apr_audio.h>
 
-
-
 #define TUNNEL_MODE     0x0000
 #define NON_TUNNEL_MODE 0x0001
 
@@ -114,9 +112,10 @@
 #define FRAME_NUM               (2)
 #define FRAME_SIZE	((4*1536) + sizeof(struct dec_meta_in))
 
-struct audio_aio_pmem_region {
+struct audio_aio_ion_region {
 	struct list_head list;
-	struct file *file;
+	struct ion_handle *handle;
+	struct ion_client *client;
 	int fd;
 	void *vaddr;
 	unsigned long paddr;
@@ -174,7 +173,7 @@
 	struct list_head in_queue;      /* queue to retain input buffers */
 	struct list_head free_event_queue;
 	struct list_head event_queue;
-	struct list_head pmem_region_queue;     /* protected by lock */
+	struct list_head ion_region_queue;     /* protected by lock */
 	struct audio_aio_drv_operations drv_ops;
 	union msm_audio_event_payload eos_write_payload;
 
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_in.c b/arch/arm/mach-msm/qdsp6v2/pcm_in.c
index 1f20aa7..667628c 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_in.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2009 Google, Inc.
  * Copyright (C) 2009 HTC Corporation
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -72,6 +72,9 @@
 	case ASM_DATA_EVENT_READ_DONE:
 		pcm_in_get_dsp_buffers(pcm, token, payload);
 		break;
+	case RESET_EVENTS:
+		reset_device();
+		break;
 	default:
 		break;
 	}
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_out.c b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
index a4a6b72..733d5e3 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_out.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2009 Google, Inc.
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -66,6 +66,9 @@
 		atomic_inc(&pcm->out_count);
 		wake_up(&pcm->write_wait);
 		break;
+	case RESET_EVENTS:
+		reset_device();
+		break;
 	default:
 		break;
 	}
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index 6794a88..cdb0cbe 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -333,6 +333,38 @@
 }
 EXPORT_SYMBOL(scm_call_atomic2);
 
+s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2,
+		u32 arg3, u32 arg4, u32 *ret1, u32 *ret2)
+{
+	int ret;
+	int context_id;
+	register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 4);
+	register u32 r1 asm("r1") = (u32)&context_id;
+	register u32 r2 asm("r2") = arg1;
+	register u32 r3 asm("r3") = arg2;
+	register u32 r4 asm("r4") = arg3;
+	register u32 r5 asm("r5") = arg4;
+
+	asm volatile(
+		__asmeq("%0", "r0")
+		__asmeq("%1", "r1")
+		__asmeq("%2", "r2")
+		__asmeq("%3", "r0")
+		__asmeq("%4", "r1")
+		__asmeq("%5", "r2")
+		__asmeq("%6", "r3")
+		"smc	#0	@ switch to secure world\n"
+		: "=r" (r0), "=r" (r1), "=r" (r2)
+		: "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5));
+	ret = r0;
+	if (ret1)
+		*ret1 = r1;
+	if (ret2)
+		*ret2 = r2;
+	return r0;
+}
+EXPORT_SYMBOL(scm_call_atomic4_3);
+
 u32 scm_get_version(void)
 {
 	int context_id;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index bca1e0c..9321b40 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -72,6 +72,7 @@
 	MSM_SMSM_DEBUG = 1U << 1,
 	MSM_SMD_INFO = 1U << 2,
 	MSM_SMSM_INFO = 1U << 3,
+	MSM_SMx_POWER_INFO = 1U << 4,
 };
 
 struct smsm_shared_info {
@@ -117,29 +118,34 @@
 };
 
 static irqreturn_t smd_modem_irq_handler(int irq, void *data);
+static irqreturn_t smsm_modem_irq_handler(int irq, void *data);
 static irqreturn_t smd_dsp_irq_handler(int irq, void *data);
+static irqreturn_t smsm_dsp_irq_handler(int irq, void *data);
 static irqreturn_t smd_dsps_irq_handler(int irq, void *data);
+static irqreturn_t smsm_dsps_irq_handler(int irq, void *data);
 static irqreturn_t smd_wcnss_irq_handler(int irq, void *data);
+static irqreturn_t smsm_wcnss_irq_handler(int irq, void *data);
 static irqreturn_t smsm_irq_handler(int irq, void *data);
 
 static struct interrupt_config private_intr_config[NUM_SMD_SUBSYSTEMS] = {
 	[SMD_MODEM] = {
 		.smd.irq_handler = smd_modem_irq_handler,
-		.smsm.irq_handler = smsm_irq_handler,
+		.smsm.irq_handler = smsm_modem_irq_handler,
 	},
 	[SMD_Q6] = {
 		.smd.irq_handler = smd_dsp_irq_handler,
-		.smsm.irq_handler = smsm_irq_handler,
+		.smsm.irq_handler = smsm_dsp_irq_handler,
 	},
 	[SMD_DSPS] = {
 		.smd.irq_handler = smd_dsps_irq_handler,
-		.smsm.irq_handler = smsm_irq_handler,
+		.smsm.irq_handler = smsm_dsps_irq_handler,
 	},
 	[SMD_WCNSS] = {
 		.smd.irq_handler = smd_wcnss_irq_handler,
-		.smsm.irq_handler = smsm_irq_handler,
+		.smsm.irq_handler = smsm_wcnss_irq_handler,
 	},
 };
+struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
 
 #define SMSM_STATE_ADDR(entry)           (smsm_info.state + entry)
 #define SMSM_INTR_MASK_ADDR(entry, host) (smsm_info.intr_mask + \
@@ -175,11 +181,16 @@
 		if (msm_smd_debug_mask & MSM_SMSM_INFO) \
 			printk(KERN_INFO x);		\
 	} while (0)
+#define SMx_POWER_INFO(x...) do {				\
+		if (msm_smd_debug_mask & MSM_SMx_POWER_INFO) \
+			printk(KERN_INFO x);		\
+	} while (0)
 #else
 #define SMD_DBG(x...) do { } while (0)
 #define SMSM_DBG(x...) do { } while (0)
 #define SMD_INFO(x...) do { } while (0)
 #define SMSM_INFO(x...) do { } while (0)
+#define SMx_POWER_INFO(x...) do { } while (0)
 #endif
 
 static unsigned last_heap_free = 0xffffffff;
@@ -214,24 +225,6 @@
 #define MSM_TRIG_A2DSPS_SMSM_INT
 #define MSM_TRIG_A2WCNSS_SMD_INT
 #define MSM_TRIG_A2WCNSS_SMSM_INT
-#elif defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_MSM8930) || \
-	defined(CONFIG_ARCH_APQ8064)
-#define MSM_TRIG_A2M_SMD_INT     \
-			(smd_write_intr(1 << 3, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMD_INT    \
-			(smd_write_intr(1 << 15, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2M_SMSM_INT    \
-			(smd_write_intr(1 << 4, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMSM_INT   \
-			(smd_write_intr(1 << 14, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2DSPS_SMD_INT  \
-			(smd_write_intr(1, MSM_SIC_NON_SECURE_BASE + 0x4080))
-#define MSM_TRIG_A2DSPS_SMSM_INT \
-			(smd_write_intr(1, MSM_SIC_NON_SECURE_BASE + 0x4094))
-#define MSM_TRIG_A2WCNSS_SMD_INT  \
-			(smd_write_intr(1 << 25, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2WCNSS_SMSM_INT  \
-			(smd_write_intr(1 << 23, MSM_APCS_GCC_BASE + 0x8))
 #elif defined(CONFIG_ARCH_MSM9615)
 #define MSM_TRIG_A2M_SMD_INT     \
 			(smd_write_intr(1 << 3, MSM_APCS_GCC_BASE + 0x8))
@@ -258,15 +251,33 @@
 #define MSM_TRIG_A2DSPS_SMSM_INT
 #define MSM_TRIG_A2WCNSS_SMD_INT
 #define MSM_TRIG_A2WCNSS_SMSM_INT
-#else
+#elif defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7x25)
 #define MSM_TRIG_A2M_SMD_INT     \
 			(smd_write_intr(1, MSM_CSR_BASE + 0x400 + (0) * 4))
-#define MSM_TRIG_A2Q6_SMD_INT    \
-			(smd_write_intr(1, MSM_CSR_BASE + 0x400 + (8) * 4))
+#define MSM_TRIG_A2Q6_SMD_INT
 #define MSM_TRIG_A2M_SMSM_INT    \
 			(smd_write_intr(1, MSM_CSR_BASE + 0x400 + (5) * 4))
-#define MSM_TRIG_A2Q6_SMSM_INT   \
-			(smd_write_intr(1, MSM_CSR_BASE + 0x400 + (8) * 4))
+#define MSM_TRIG_A2Q6_SMSM_INT
+#define MSM_TRIG_A2DSPS_SMD_INT
+#define MSM_TRIG_A2DSPS_SMSM_INT
+#define MSM_TRIG_A2WCNSS_SMD_INT
+#define MSM_TRIG_A2WCNSS_SMSM_INT
+#elif defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM7X27A)
+#define MSM_TRIG_A2M_SMD_INT     \
+			(smd_write_intr(1, MSM_CSR_BASE + 0x400 + (0) * 4))
+#define MSM_TRIG_A2Q6_SMD_INT
+#define MSM_TRIG_A2M_SMSM_INT    \
+			(smd_write_intr(1, MSM_CSR_BASE + 0x400 + (5) * 4))
+#define MSM_TRIG_A2Q6_SMSM_INT
+#define MSM_TRIG_A2DSPS_SMD_INT
+#define MSM_TRIG_A2DSPS_SMSM_INT
+#define MSM_TRIG_A2WCNSS_SMD_INT
+#define MSM_TRIG_A2WCNSS_SMSM_INT
+#else /* use platform device / device tree configuration */
+#define MSM_TRIG_A2M_SMD_INT
+#define MSM_TRIG_A2Q6_SMD_INT
+#define MSM_TRIG_A2M_SMSM_INT
+#define MSM_TRIG_A2Q6_SMSM_INT
 #define MSM_TRIG_A2DSPS_SMD_INT
 #define MSM_TRIG_A2DSPS_SMSM_INT
 #define MSM_TRIG_A2WCNSS_SMD_INT
@@ -349,33 +360,42 @@
 {
 	static const struct interrupt_config_item *intr
 	   = &private_intr_config[SMD_MODEM].smd;
-	if (intr->out_base)
+	if (intr->out_base) {
+		++interrupt_stats[SMD_MODEM].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
-	else
+	} else {
+		++interrupt_stats[SMD_MODEM].smd_out_hardcode_count;
 		MSM_TRIG_A2M_SMD_INT;
+	}
 }
 
 static inline void notify_dsp_smd(void)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_Q6].smd;
-	if (intr->out_base)
+	if (intr->out_base) {
+		++interrupt_stats[SMD_Q6].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
-	else
+	} else {
+		++interrupt_stats[SMD_Q6].smd_out_hardcode_count;
 		MSM_TRIG_A2Q6_SMD_INT;
+	}
 }
 
 static inline void notify_dsps_smd(void)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_DSPS].smd;
-	if (intr->out_base)
+	if (intr->out_base) {
+		++interrupt_stats[SMD_DSPS].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
-	else
+	} else {
+		++interrupt_stats[SMD_DSPS].smd_out_hardcode_count;
 		MSM_TRIG_A2DSPS_SMD_INT;
+	}
 }
 
 static inline void notify_wcnss_smd(void)
@@ -384,44 +404,56 @@
 		= &private_intr_config[SMD_WCNSS].smd;
 	wakeup_v1_riva();
 
-	if (intr->out_base)
+	if (intr->out_base) {
+		++interrupt_stats[SMD_WCNSS].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
-	else
+	} else {
+		++interrupt_stats[SMD_WCNSS].smd_out_hardcode_count;
 		MSM_TRIG_A2WCNSS_SMD_INT;
+	}
 }
 
 static inline void notify_modem_smsm(void)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_MODEM].smsm;
-	if (intr->out_base)
+	if (intr->out_base) {
+		++interrupt_stats[SMD_MODEM].smsm_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
-	else
+	} else {
+		++interrupt_stats[SMD_MODEM].smsm_out_hardcode_count;
 		MSM_TRIG_A2M_SMSM_INT;
+	}
 }
 
 static inline void notify_dsp_smsm(void)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_Q6].smsm;
-	if (intr->out_base)
+	if (intr->out_base) {
+		++interrupt_stats[SMD_Q6].smsm_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
-	else
+	} else {
+		++interrupt_stats[SMD_Q6].smsm_out_hardcode_count;
 		MSM_TRIG_A2Q6_SMSM_INT;
+	}
 }
 
 static inline void notify_dsps_smsm(void)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_DSPS].smsm;
-	if (intr->out_base)
+	if (intr->out_base) {
+		++interrupt_stats[SMD_DSPS].smsm_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
-	else
+	} else {
+		++interrupt_stats[SMD_DSPS].smsm_out_hardcode_count;
 		MSM_TRIG_A2DSPS_SMSM_INT;
+	}
 }
 
 static inline void notify_wcnss_smsm(void)
@@ -430,11 +462,14 @@
 		= &private_intr_config[SMD_WCNSS].smsm;
 	wakeup_v1_riva();
 
-	if (intr->out_base)
+	if (intr->out_base) {
+		++interrupt_stats[SMD_WCNSS].smsm_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
-	else
+	} else {
+		++interrupt_stats[SMD_WCNSS].smsm_out_hardcode_count;
 		MSM_TRIG_A2WCNSS_SMSM_INT;
+	}
 }
 
 static void notify_other_smsm(uint32_t smsm_entry, uint32_t notify_mask)
@@ -589,27 +624,28 @@
 struct edge_to_pid {
 	uint32_t	local_pid;
 	uint32_t	remote_pid;
+	char		subsys_name[SMD_MAX_CH_NAME_LEN];
 };
 
 /**
  * Maps edge type to local and remote processor ID's.
  */
 static struct edge_to_pid edge_to_pids[] = {
-	[SMD_APPS_MODEM] = {SMSM_APPS, SMSM_MODEM},
-	[SMD_APPS_QDSP] = {SMSM_APPS, SMSM_Q6},
-	[SMD_MODEM_QDSP] = {SMSM_MODEM, SMSM_Q6},
-	[SMD_APPS_DSPS] = {SMSM_APPS, SMSM_DSPS},
-	[SMD_MODEM_DSPS] = {SMSM_MODEM, SMSM_DSPS},
-	[SMD_QDSP_DSPS] = {SMSM_Q6, SMSM_DSPS},
-	[SMD_APPS_WCNSS] = {SMSM_APPS, SMSM_WCNSS},
-	[SMD_MODEM_WCNSS] = {SMSM_MODEM, SMSM_WCNSS},
-	[SMD_QDSP_WCNSS] = {SMSM_Q6, SMSM_WCNSS},
-	[SMD_DSPS_WCNSS] = {SMSM_DSPS, SMSM_WCNSS},
-	[SMD_APPS_Q6FW] = {SMSM_APPS, SMD_MODEM_Q6_FW},
-	[SMD_MODEM_Q6FW] = {SMSM_MODEM, SMD_MODEM_Q6_FW},
-	[SMD_QDSP_Q6FW] = {SMSM_Q6, SMD_MODEM_Q6_FW},
-	[SMD_DSPS_Q6FW] = {SMSM_DSPS, SMD_MODEM_Q6_FW},
-	[SMD_WCNSS_Q6FW] = {SMSM_WCNSS, SMD_MODEM_Q6_FW},
+	[SMD_APPS_MODEM] = {SMD_APPS, SMD_MODEM, "modem"},
+	[SMD_APPS_QDSP] = {SMD_APPS, SMD_Q6, "q6"},
+	[SMD_MODEM_QDSP] = {SMD_MODEM, SMD_Q6},
+	[SMD_APPS_DSPS] = {SMD_APPS, SMD_DSPS, "dsps"},
+	[SMD_MODEM_DSPS] = {SMD_MODEM, SMD_DSPS},
+	[SMD_QDSP_DSPS] = {SMD_Q6, SMD_DSPS},
+	[SMD_APPS_WCNSS] = {SMD_APPS, SMD_WCNSS, "wcnss"},
+	[SMD_MODEM_WCNSS] = {SMD_MODEM, SMD_WCNSS},
+	[SMD_QDSP_WCNSS] = {SMD_Q6, SMD_WCNSS},
+	[SMD_DSPS_WCNSS] = {SMD_DSPS, SMD_WCNSS},
+	[SMD_APPS_Q6FW] = {SMD_APPS, SMD_MODEM_Q6_FW},
+	[SMD_MODEM_Q6FW] = {SMD_MODEM, SMD_MODEM_Q6_FW},
+	[SMD_QDSP_Q6FW] = {SMD_Q6, SMD_MODEM_Q6_FW},
+	[SMD_DSPS_Q6FW] = {SMD_DSPS, SMD_MODEM_Q6_FW},
+	[SMD_WCNSS_Q6FW] = {SMD_WCNSS, SMD_MODEM_Q6_FW},
 };
 
 struct restart_notifier_block {
@@ -721,6 +757,50 @@
 	return ret;
 }
 
+/*
+ * Returns a pointer to the subsystem name or NULL if no
+ * subsystem name is available.
+ *
+ * @type - Edge definition
+ */
+const char *smd_edge_to_subsystem(uint32_t type)
+{
+	const char *subsys = NULL;
+
+	if (type < ARRAY_SIZE(edge_to_pids)) {
+		subsys = edge_to_pids[type].subsys_name;
+		if (subsys[0] == 0x0)
+			subsys = NULL;
+	}
+	return subsys;
+}
+EXPORT_SYMBOL(smd_edge_to_subsystem);
+
+/*
+ * Returns a pointer to the subsystem name given the
+ * remote processor ID.
+ *
+ * @pid     Remote processor ID
+ * @returns Pointer to subsystem name or NULL if not found
+ */
+const char *smd_pid_to_subsystem(uint32_t pid)
+{
+	const char *subsys = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(edge_to_pids); ++i) {
+		if (pid == edge_to_pids[i].remote_pid &&
+			edge_to_pids[i].subsys_name[0] != 0x0
+			) {
+			subsys = edge_to_pids[i].subsys_name;
+			break;
+		}
+	}
+
+	return subsys;
+}
+EXPORT_SYMBOL(smd_pid_to_subsystem);
+
 static void smd_reset_edge(struct smd_half_channel *ch, unsigned new_state)
 {
 	if (ch->state != SMD_SS_CLOSED) {
@@ -796,9 +876,10 @@
 
 		/* notify SMSM processors */
 		smsm_irq_handler(0, 0);
-		MSM_TRIG_A2M_SMSM_INT;
-		MSM_TRIG_A2Q6_SMSM_INT;
-		MSM_TRIG_A2DSPS_SMSM_INT;
+		notify_modem_smsm();
+		notify_dsp_smsm();
+		notify_dsps_smsm();
+		notify_wcnss_smsm();
 	}
 
 	/* change all remote states to CLOSING */
@@ -1110,15 +1191,24 @@
 		}
 		tmp = ch->recv->state;
 		if (tmp != ch->last_state) {
+			SMx_POWER_INFO("SMD ch%d '%s' State change %d->%d\n",
+					ch->n, ch->name, ch->last_state, tmp);
 			smd_state_change(ch, ch->last_state, tmp);
 			state_change = 1;
 		}
-		if (ch_flags) {
+		if (ch_flags & 0x3) {
 			ch->update_state(ch);
+			SMx_POWER_INFO("SMD ch%d '%s' Data event r%d/w%d\n",
+					ch->n, ch->name,
+					ch->read_avail(ch),
+					ch->fifo_size - ch->write_avail(ch));
 			ch->notify(ch->priv, SMD_EVENT_DATA);
 		}
-		if (ch_flags & 0x4 && !state_change)
+		if (ch_flags & 0x4 && !state_change) {
+			SMx_POWER_INFO("SMD ch%d '%s' State update\n",
+					ch->n, ch->name);
 			ch->notify(ch->priv, SMD_EVENT_STATUS);
+		}
 	}
 	spin_unlock_irqrestore(&smd_lock, flags);
 	do_smd_probe();
@@ -1126,6 +1216,8 @@
 
 static irqreturn_t smd_modem_irq_handler(int irq, void *data)
 {
+	SMx_POWER_INFO("SMD Int Modem->Apps\n");
+	++interrupt_stats[SMD_MODEM].smd_in_count;
 	handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
@@ -1133,6 +1225,8 @@
 
 static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
 {
+	SMx_POWER_INFO("SMD Int LPASS->Apps\n");
+	++interrupt_stats[SMD_Q6].smd_in_count;
 	handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
@@ -1140,6 +1234,8 @@
 
 static irqreturn_t smd_dsps_irq_handler(int irq, void *data)
 {
+	SMx_POWER_INFO("SMD Int DSPS->Apps\n");
+	++interrupt_stats[SMD_DSPS].smd_in_count;
 	handle_smd_irq(&smd_ch_list_dsps, notify_dsps_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
@@ -1147,6 +1243,8 @@
 
 static irqreturn_t smd_wcnss_irq_handler(int irq, void *data)
 {
+	SMx_POWER_INFO("SMD Int WCNSS->Apps\n");
+	++interrupt_stats[SMD_WCNSS].smd_in_count;
 	handle_smd_irq(&smd_ch_list_wcnss, notify_wcnss_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
@@ -2286,6 +2384,34 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t smsm_modem_irq_handler(int irq, void *data)
+{
+	SMx_POWER_INFO("SMSM Int Modem->Apps\n");
+	++interrupt_stats[SMD_MODEM].smsm_in_count;
+	return smsm_irq_handler(irq, data);
+}
+
+static irqreturn_t smsm_dsp_irq_handler(int irq, void *data)
+{
+	SMx_POWER_INFO("SMSM Int LPASS->Apps\n");
+	++interrupt_stats[SMD_Q6].smsm_in_count;
+	return smsm_irq_handler(irq, data);
+}
+
+static irqreturn_t smsm_dsps_irq_handler(int irq, void *data)
+{
+	SMx_POWER_INFO("SMSM Int DSPS->Apps\n");
+	++interrupt_stats[SMD_DSPS].smsm_in_count;
+	return smsm_irq_handler(irq, data);
+}
+
+static irqreturn_t smsm_wcnss_irq_handler(int irq, void *data)
+{
+	SMx_POWER_INFO("SMSM Int WCNSS->Apps\n");
+	++interrupt_stats[SMD_WCNSS].smsm_in_count;
+	return smsm_irq_handler(irq, data);
+}
+
 int smsm_change_intr_mask(uint32_t smsm_entry,
 			  uint32_t clear_mask, uint32_t set_mask)
 {
@@ -2417,6 +2543,9 @@
 
 			state_changes = state_info->last_value ^ new_state;
 			if (state_changes) {
+				SMx_POWER_INFO("SMSM Change %d: %08x->%08x\n",
+						n, state_info->last_value,
+						new_state);
 				list_for_each_entry(cb_info,
 					&state_info->callbacks, cb_list) {
 
@@ -2567,7 +2696,7 @@
 		pr_err("smd_core_init: "
 		       "enable_irq_wake failed for INT_A9_M2A_0\n");
 
-	r = request_irq(INT_A9_M2A_5, smsm_irq_handler,
+	r = request_irq(INT_A9_M2A_5, smsm_modem_irq_handler,
 			flags, "smsm_dev", 0);
 	if (r < 0) {
 		free_irq(INT_A9_M2A_0, 0);
@@ -2590,8 +2719,8 @@
 		return r;
 	}
 
-	r = request_irq(INT_ADSP_A11_SMSM, smsm_irq_handler,
-			flags, "smsm_dev", smsm_irq_handler);
+	r = request_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler,
+			flags, "smsm_dev", smsm_dsp_irq_handler);
 	if (r < 0) {
 		free_irq(INT_A9_M2A_0, 0);
 		free_irq(INT_A9_M2A_5, 0);
@@ -2620,7 +2749,7 @@
 		free_irq(INT_A9_M2A_0, 0);
 		free_irq(INT_A9_M2A_5, 0);
 		free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
-		free_irq(INT_ADSP_A11_SMSM, smsm_irq_handler);
+		free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
 		return r;
 	}
 
@@ -2637,7 +2766,7 @@
 		free_irq(INT_A9_M2A_0, 0);
 		free_irq(INT_A9_M2A_5, 0);
 		free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
-		free_irq(INT_ADSP_A11_SMSM, smsm_irq_handler);
+		free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
 		free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
 		return r;
 	}
@@ -2647,13 +2776,13 @@
 		pr_err("smd_core_init: "
 		       "enable_irq_wake failed for INT_WCNSS_A11\n");
 
-	r = request_irq(INT_WCNSS_A11_SMSM, smsm_irq_handler,
-			flags, "smsm_dev", smsm_irq_handler);
+	r = request_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler,
+			flags, "smsm_dev", smsm_wcnss_irq_handler);
 	if (r < 0) {
 		free_irq(INT_A9_M2A_0, 0);
 		free_irq(INT_A9_M2A_5, 0);
 		free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
-		free_irq(INT_ADSP_A11_SMSM, smsm_irq_handler);
+		free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
 		free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
 		free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
 		return r;
@@ -2666,16 +2795,16 @@
 #endif
 
 #if defined(CONFIG_DSPS_SMSM)
-	r = request_irq(INT_DSPS_A11_SMSM, smsm_irq_handler,
-			flags, "smsm_dev", smsm_irq_handler);
+	r = request_irq(INT_DSPS_A11_SMSM, smsm_dsps_irq_handler,
+			flags, "smsm_dev", smsm_dsps_irq_handler);
 	if (r < 0) {
 		free_irq(INT_A9_M2A_0, 0);
 		free_irq(INT_A9_M2A_5, 0);
 		free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
-		free_irq(INT_ADSP_A11_SMSM, smsm_irq_handler);
+		free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
 		free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
 		free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
-		free_irq(INT_WCNSS_A11_SMSM, smsm_irq_handler);
+		free_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler);
 		return r;
 	}
 
@@ -2770,6 +2899,9 @@
 				cfg->smsm_int.irq_name);
 			break;
 		}
+
+		strncpy(edge_to_pids[cfg->edge].subsys_name,
+				cfg->subsys_name, SMD_MAX_CH_NAME_LEN);
 	}
 
 	if (err_ret < 0) {
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index b95a35c..764102d 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -95,6 +95,61 @@
 	return max;
 }
 
+static int debug_int_stats(char *buf, int max)
+{
+	int i = 0;
+	int subsys;
+	struct interrupt_stat *stats = interrupt_stats;
+	const char *subsys_name;
+
+	i += scnprintf(buf + i, max - i,
+		"   Subsystem    |     In    | Out (Hardcoded) |"
+		" Out (Configured) |\n");
+
+	for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
+		subsys_name = smd_pid_to_subsystem(subsys);
+		if (subsys_name) {
+			i += scnprintf(buf + i, max - i,
+				"%-10s %4s | %9u |       %9u |        %9u |\n",
+				smd_pid_to_subsystem(subsys), "smd",
+				stats->smd_in_count,
+				stats->smd_out_hardcode_count,
+				stats->smd_out_config_count);
+
+			i += scnprintf(buf + i, max - i,
+				"%-10s %4s | %9u |       %9u |        %9u |\n",
+				smd_pid_to_subsystem(subsys), "smsm",
+				stats->smsm_in_count,
+				stats->smsm_out_hardcode_count,
+				stats->smsm_out_config_count);
+		}
+		++stats;
+	}
+
+	return i;
+}
+
+static int debug_int_stats_reset(char *buf, int max)
+{
+	int i = 0;
+	int subsys;
+	struct interrupt_stat *stats = interrupt_stats;
+
+	i += scnprintf(buf + i, max - i, "Resetting interrupt stats.\n");
+
+	for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
+		stats->smd_in_count = 0;
+		stats->smd_out_hardcode_count = 0;
+		stats->smd_out_config_count = 0;
+		stats->smsm_in_count = 0;
+		stats->smsm_out_hardcode_count = 0;
+		stats->smsm_out_config_count = 0;
+		++stats;
+	}
+
+	return i;
+}
+
 static int debug_diag(char *buf, int max)
 {
 	int i = 0;
@@ -694,6 +749,8 @@
 	debug_create("modem_err_f3", 0444, dent, debug_modem_err_f3);
 	debug_create("print_diag", 0444, dent, debug_diag);
 	debug_create("print_f3", 0444, dent, debug_f3);
+	debug_create("int_stats", 0444, dent, debug_int_stats);
+	debug_create("int_stats_reset", 0444, dent, debug_int_stats_reset);
 
 	/* NNV: this is google only stuff */
 	debug_create("build", 0444, dent, debug_read_build_id);
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 63c5fef..158015a 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -66,6 +66,7 @@
 
 	int blocking_write;
 	int is_open;
+	int poll_mode;
 	unsigned ch_size;
 	uint open_modem_wait;
 
@@ -74,6 +75,7 @@
 	struct completion ch_allocated;
 	struct wake_lock pa_wake_lock;		/* Packet Arrival Wake lock*/
 	struct work_struct packet_arrival_work;
+	struct spinlock pa_spinlock;
 } *smd_pkt_devp[NUM_SMD_PKT_PORTS];
 
 struct class *smd_pkt_classp;
@@ -236,6 +238,7 @@
 	int pkt_size;
 	struct smd_pkt_dev *smd_pkt_devp;
 	struct smd_channel *chl;
+	unsigned long flags;
 
 	D(KERN_ERR "%s: read %i bytes\n",
 	  __func__, count);
@@ -316,6 +319,16 @@
 	D_DUMP_BUFFER("read: ", bytes_read, buf);
 	mutex_unlock(&smd_pkt_devp->rx_lock);
 
+	mutex_lock(&smd_pkt_devp->ch_lock);
+	spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
+	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->poll_mode = 0;
+	}
+	spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
+	mutex_unlock(&smd_pkt_devp->ch_lock);
+
 	D(KERN_ERR "%s: just read %i bytes\n",
 	  __func__, bytes_read);
 
@@ -409,6 +422,7 @@
 	if (!smd_pkt_devp)
 		return POLLERR;
 
+	smd_pkt_devp->poll_mode = 1;
 	poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait);
 	if (smd_read_avail(smd_pkt_devp->ch))
 		mask |= POLLIN | POLLRDNORM;
@@ -419,6 +433,7 @@
 static void check_and_wakeup_reader(struct smd_pkt_dev *smd_pkt_devp)
 {
 	int sz;
+	unsigned long flags;
 
 	if (!smd_pkt_devp || !smd_pkt_devp->ch)
 		return;
@@ -437,6 +452,9 @@
 
 	/* 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);
+	spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
 	schedule_work(&smd_pkt_devp->packet_arrival_work);
 	D(KERN_ERR "%s: after wake_up\n", __func__);
 }
@@ -589,7 +607,7 @@
 {
 	int r = 0;
 	struct smd_pkt_dev *smd_pkt_devp;
-	char *peripheral = NULL;
+	const char *peripheral = NULL;
 
 	smd_pkt_devp = container_of(inode->i_cdev, struct smd_pkt_dev, cdev);
 
@@ -604,12 +622,8 @@
 
 	mutex_lock(&smd_pkt_devp->ch_lock);
 	if (smd_pkt_devp->ch == 0) {
-
-		if (smd_ch_edge[smd_pkt_devp->i] == SMD_APPS_MODEM)
-			peripheral = "modem";
-		else if (smd_ch_edge[smd_pkt_devp->i] == SMD_APPS_QDSP)
-			peripheral = "q6";
-
+		peripheral = smd_edge_to_subsystem(
+				smd_ch_edge[smd_pkt_devp->i]);
 		if (peripheral) {
 			smd_pkt_devp->pil = pil_get(peripheral);
 			if (IS_ERR(smd_pkt_devp->pil)) {
@@ -707,6 +721,7 @@
 		r = smd_close(smd_pkt_devp->ch);
 		smd_pkt_devp->ch = 0;
 		smd_pkt_devp->blocking_write = 0;
+		smd_pkt_devp->poll_mode = 0;
 		if (smd_pkt_devp->pil)
 			pil_put(smd_pkt_devp->pil);
 	}
@@ -776,8 +791,10 @@
 		init_waitqueue_head(&smd_pkt_devp[i]->ch_read_wait_queue);
 		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;
 		init_waitqueue_head(&smd_pkt_devp[i]->ch_opened_wait_queue);
 
+		spin_lock_init(&smd_pkt_devp[i]->pa_spinlock);
 		mutex_init(&smd_pkt_devp[i]->ch_lock);
 		mutex_init(&smd_pkt_devp[i]->rx_lock);
 		mutex_init(&smd_pkt_devp[i]->tx_lock);
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index a4c60e8..e39c57b 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/smd_private.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <mach/msm_smsm.h>
+#include <mach/msm_smd.h>
 
 #define PC_APPS  0
 #define PC_MODEM 1
@@ -208,4 +209,15 @@
 
 void smd_diag(void);
 
+struct interrupt_stat {
+	uint32_t smd_in_count;
+	uint32_t smd_out_hardcode_count;
+	uint32_t smd_out_config_count;
+
+	uint32_t smsm_in_count;
+	uint32_t smsm_out_hardcode_count;
+	uint32_t smsm_out_config_count;
+};
+extern struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
+
 #endif
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 4248be4..d856024 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -235,7 +235,7 @@
 	int res = 0;
 	unsigned int n = tty->index;
 	struct smd_tty_info *info;
-	char *peripheral = NULL;
+	const char *peripheral = NULL;
 
 
 	if (n >= MAX_SMD_TTYS || !smd_tty[n].smd)
@@ -247,9 +247,7 @@
 	tty->driver_data = info;
 
 	if (info->open_count++ == 0) {
-		if (smd_tty[n].smd->edge == SMD_APPS_MODEM)
-			peripheral = "modem";
-
+		peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
 		if (peripheral) {
 			info->pil = pil_get(peripheral);
 			if (IS_ERR(info->pil)) {
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 9970c90..59abfe6 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,7 @@
 static void riva_fatal_fn(struct work_struct *);
 static DECLARE_WORK(riva_fatal_work, riva_fatal_fn);
 
+static struct delayed_work cancel_vote_work;
 static void *riva_ramdump_dev;
 static int riva_crash;
 static int ss_restart_inprogress;
@@ -97,20 +98,24 @@
 	smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
 }
 
-/* Subsystem handlers */
-static int riva_shutdown(const struct subsys_data *subsys)
+static void riva_post_bootup(struct work_struct *work)
 {
 	struct platform_device *pdev = wcnss_get_platform_device();
 	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
-	int    ret = -1;
 
+	pr_debug(MODULE_NAME ": Cancel APPS vote for Iris & Riva\n");
+
+	wcnss_wlan_power(&pdev->dev, pwlanconfig,
+		WCNSS_WLAN_SWITCH_OFF);
+}
+
+/* Subsystem handlers */
+static int riva_shutdown(const struct subsys_data *subsys)
+{
 	pil_force_shutdown("wcnss");
+	flush_delayed_work(&cancel_vote_work);
 
-	/* proxy vote on behalf of Riva */
-	if (pdev && pwlanconfig)
-		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
-					WCNSS_WLAN_SWITCH_OFF);
-	return ret;
+	return 0;
 }
 
 static int riva_powerup(const struct subsys_data *subsys)
@@ -131,6 +136,7 @@
 	}
 	ss_restart_inprogress = false;
 	enable_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
+	schedule_delayed_work(&cancel_vote_work, msecs_to_jiffies(5000));
 
 	return ret;
 }
@@ -222,6 +228,8 @@
 		ret = -ENOMEM;
 		goto out;
 	}
+	INIT_DELAYED_WORK(&cancel_vote_work, riva_post_bootup);
+
 	pr_info("%s: module initialized\n", MODULE_NAME);
 out:
 	return ret;
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 3bce534..f748109 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -55,7 +55,7 @@
 	cmp	r1, #2				@ see what cache we have at this level
 	blt	skip				@ skip if no cache, or just i-cache
 #ifdef CONFIG_PREEMPT
-	save_and_disable_irqs r9		@ make cssr&csidr read atomic
+	save_and_disable_irqs_notrace r9	@ make cssr&csidr read atomic
 #endif
 	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
 	isb					@ isb to sych the new cssr&csidr
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 8dcce03..edede47 100755
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1139,3 +1139,5 @@
 mpq8064_hrd		MACH_MPQ8064_HRD	MPQ8064_HRD		3994
 mpq8064_dtv		MACH_MPQ8064_DTV	MPQ8064_DTV		3995
 msm7627a_qrd3		MACH_MSM7627A_QRD3	MSM7627A_QRD3		4005
+msm8625_surf		MACH_MSM8625_SURF	MSM8625_SURF		4037
+msm8625_evb		MACH_MSM8625_EVB	MSM8625_EVB		4042
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 371d319..a701773 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -228,6 +228,7 @@
 	int hsic_ch;
 	int hsic_device_enabled;
 	int hsic_device_opened;
+	int hsic_suspend;
 	int read_len_mdm;
 	int in_busy_hsic_read_on_mdm;
 	int in_busy_hsic_write_on_mdm;
@@ -238,6 +239,8 @@
 	struct workqueue_struct *diag_hsic_wq;
 	struct work_struct diag_read_mdm_work;
 	struct work_struct diag_read_hsic_work;
+	struct work_struct diag_disconnect_work;
+	struct work_struct diag_usb_read_complete_work;
 	struct diag_request *usb_read_mdm_ptr;
 	struct diag_request *write_ptr_mdm;
 #endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index efba92b..d9f12ac 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -48,7 +48,7 @@
 };
 /* The following variables can be specified by module options */
  /* for copy buffer */
-static unsigned int itemsize = 2048; /*Size of item in the mempool */
+static unsigned int itemsize = 4096; /*Size of item in the mempool */
 static unsigned int poolsize = 10; /*Number of items in the mempool */
 /* for hdlc buffer */
 static unsigned int itemsize_hdlc = 8192; /*Size of item in the mempool */
@@ -768,6 +768,14 @@
 		return 0;
 	}
 
+	if (payload_size > itemsize) {
+		pr_err("diag: Dropping packet, packet payload size crosses"
+				"4KB limit. Current payload size %d\n",
+				payload_size);
+		driver->dropped_count++;
+		return -EBADMSG;
+	}
+
 	buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
 	if (!buf_copy) {
 		driver->dropped_count++;
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index ac5722f..b2080b3 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -102,14 +102,16 @@
 						driver->write_ptr_mdm);
 		}
 	} else {
-		pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
+		pr_debug("%s: actual_size: %d\n", __func__, actual_size);
 	}
 
 	/*
 	 * If for some reason there was no hsic data to write to the
 	 * mdm channel, set up another read
 	 */
-	if (!driver->in_busy_hsic_write_on_mdm)
+	if (!driver->in_busy_hsic_write_on_mdm &&
+			driver->usb_mdm_connected &&
+			!driver->hsic_suspend)
 		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
 }
 
@@ -127,13 +129,34 @@
 	if (actual_size < 0)
 		pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
 
-	queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+	if (driver->usb_mdm_connected)
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+}
+
+static int diag_hsic_suspend(void *ctxt)
+{
+	if (driver->in_busy_hsic_write)
+		return -EBUSY;
+
+	driver->hsic_suspend = 1;
+
+	return 0;
+}
+
+static void diag_hsic_resume(void *ctxt)
+{
+	driver->hsic_suspend = 0;
+
+	if (!driver->in_busy_hsic_write_on_mdm && driver->usb_mdm_connected)
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
 }
 
 static struct diag_bridge_ops hsic_diag_bridge_ops = {
 	.ctxt = NULL,
 	.read_complete_cb = diag_hsic_read_complete_callback,
 	.write_complete_cb = diag_hsic_write_complete_callback,
+	.suspend = diag_hsic_suspend,
+	.resume = diag_hsic_resume,
 };
 
 static int diag_hsic_close(void)
@@ -177,11 +200,11 @@
 				pr_err("DIAG: HSIC channel open error: %d\n",
 					err);
 			} else {
-				pr_info("DIAG: opened HSIC channel\n");
+				pr_debug("DIAG: opened HSIC channel\n");
 				driver->hsic_device_opened = 1;
 			}
 		} else {
-			pr_info("DIAG: HSIC channel already open\n");
+			pr_debug("DIAG: HSIC channel already open\n");
 		}
 
 		/*
@@ -220,9 +243,7 @@
 	driver->in_busy_hsic_read = 1;
 
 	/* Turn off communication over usb mdm and hsic */
-	driver->hsic_ch = 0;
-
-	return 0;
+	return diag_hsic_close();
 }
 
 /*
@@ -311,10 +332,11 @@
 		diagfwd_connect_hsic();
 		break;
 	case USB_DIAG_DISCONNECT:
-		diagfwd_disconnect_hsic();
+		queue_work(driver->diag_hsic_wq, &driver->diag_disconnect_work);
 		break;
 	case USB_DIAG_READ_DONE:
-		diagfwd_read_complete_hsic(d_req);
+		queue_work(driver->diag_hsic_wq,
+				&driver->diag_usb_read_complete_work);
 		break;
 	case USB_DIAG_WRITE_DONE:
 		diagfwd_write_complete_hsic();
@@ -326,6 +348,16 @@
 	}
 }
 
+static void diag_usb_read_complete_fn(struct work_struct *w)
+{
+	diagfwd_read_complete_hsic(driver->usb_read_mdm_ptr);
+}
+
+static void diag_disconnect_work_fn(struct work_struct *w)
+{
+	diagfwd_disconnect_hsic();
+}
+
 static void diag_read_mdm_work_fn(struct work_struct *work)
 {
 	if (!driver->hsic_ch) {
@@ -380,7 +412,6 @@
 		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
@@ -413,23 +444,22 @@
 		}
 	}
 
-	/* The hsic (diag_bridge) platform device driver is enabled */
-	err = diag_bridge_open(&hsic_diag_bridge_ops);
-	if (err) {
-		pr_err("DIAG could not open HSIC channel, err: %d\n", err);
-		driver->hsic_device_opened = 0;
-		return err;
-	}
-
-	pr_info("DIAG opened HSIC channel\n");
-	driver->hsic_device_opened = 1;
-
 	/*
 	 * The probe function was called after the usb was connected
 	 * on the legacy channel. Communication over usb mdm and hsic
 	 * needs to be turned on.
 	 */
-	if (driver->usb_connected) {
+	if (driver->usb_mdm_connected) {
+		/* The hsic (diag_bridge) platform device driver is enabled */
+		err = diag_bridge_open(&hsic_diag_bridge_ops);
+		if (err) {
+			pr_err("DIAG could not open HSIC, err: %d\n", err);
+			driver->hsic_device_opened = 0;
+			return err;
+		}
+
+		pr_debug("DIAG opened HSIC channel\n");
+		driver->hsic_device_opened = 1;
 		driver->hsic_ch = 1;
 		driver->in_busy_hsic_write_on_mdm = 0;
 		driver->in_busy_hsic_read_on_mdm = 0;
@@ -448,7 +478,7 @@
 
 static int diag_hsic_remove(struct platform_device *pdev)
 {
-	pr_info("DIAG: %s called\n", __func__);
+	pr_debug("DIAG: %s called\n", __func__);
 	diag_hsic_close();
 	return 0;
 }
@@ -487,6 +517,11 @@
 
 	pr_debug("DIAG in %s\n", __func__);
 
+	driver->diag_hsic_wq = create_singlethread_workqueue("diag_hsic_wq");
+	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);
 	if (IS_ERR(driver->mdm_ch)) {
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index bd48925..3d9c9d1 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -749,7 +749,8 @@
 }
 
 static int get_img(struct msmfb_data *fbd, unsigned long *start,
-	unsigned long *len, struct file **p_file, struct ion_handle **p_ihdl)
+	unsigned long *len, struct file **p_file, int *p_need,
+	struct ion_handle **p_ihdl)
 {
 	int ret = 0;
 #ifdef CONFIG_FB
@@ -760,6 +761,8 @@
 	unsigned long vstart;
 #endif
 
+	*p_need = 0;
+
 #ifdef CONFIG_FB
 	if (fbd->flags & MDP_MEMORY_ID_TYPE_FB) {
 		file = fget_light(fbd->memory_id, &put_needed);
@@ -770,8 +773,10 @@
 			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
 			if (get_fb_phys_info(start, len, fb_num))
 				ret = -1;
-			else
+			else {
 				*p_file = file;
+				*p_need = put_needed;
+			}
 		} else
 			ret = -1;
 		if (ret)
@@ -822,6 +827,7 @@
 	struct file *srcp1_file = NULL, *dstp1_file = NULL;
 	struct ion_handle *srcp0_ihdl = NULL, *dstp0_ihdl = NULL;
 	struct ion_handle *srcp1_ihdl = NULL, *dstp1_ihdl = NULL;
+	int ps0_need, p_need;
 	unsigned int in_chroma_paddr = 0, out_chroma_paddr = 0;
 	unsigned int in_chroma2_paddr = 0;
 	struct msm_rotator_img_info *img_info;
@@ -872,8 +878,9 @@
 		goto do_rotate_unlock_mutex;
 	}
 
+
 	rc = get_img(&info.src, (unsigned long *)&in_paddr,
-			(unsigned long *)&src_len, &srcp0_file, &srcp0_ihdl);
+		(unsigned long *)&src_len, &srcp0_file, &ps0_need, &srcp0_ihdl);
 	if (rc) {
 		pr_err("%s: in get_img() failed id=0x%08x\n",
 			DRIVER_NAME, info.src.memory_id);
@@ -881,7 +888,7 @@
 	}
 
 	rc = get_img(&info.dst, (unsigned long *)&out_paddr,
-			(unsigned long *)&dst_len, &dstp0_file, &dstp0_ihdl);
+		(unsigned long *)&dst_len, &dstp0_file, &p_need, &dstp0_ihdl);
 	if (rc) {
 		pr_err("%s: out get_img() failed id=0x%08x\n",
 		       DRIVER_NAME, info.dst.memory_id);
@@ -911,7 +918,7 @@
 
 		rc = get_img(&info.src_chroma,
 				(unsigned long *)&in_chroma_paddr,
-				(unsigned long *)&src_len, &srcp1_file,
+				(unsigned long *)&src_len, &srcp1_file, &p_need,
 				&srcp1_ihdl);
 		if (rc) {
 			pr_err("%s: in chroma get_img() failed id=0x%08x\n",
@@ -921,7 +928,7 @@
 
 		rc = get_img(&info.dst_chroma,
 				(unsigned long *)&out_chroma_paddr,
-				(unsigned long *)&dst_len, &dstp1_file,
+				(unsigned long *)&dst_len, &dstp1_file, &p_need,
 				&dstp1_ihdl);
 		if (rc) {
 			pr_err("%s: out chroma get_img() failed id=0x%08x\n",
@@ -1089,7 +1096,12 @@
 	put_img(dstp1_file, dstp1_ihdl);
 	put_img(srcp1_file, srcp1_ihdl);
 	put_img(dstp0_file, dstp0_ihdl);
-	put_img(srcp0_file, srcp0_ihdl);
+
+	/* only source may use frame buffer */
+	if (info.src.flags & MDP_MEMORY_ID_TYPE_FB)
+		fput_light(srcp0_file, ps0_need);
+	else
+		put_img(srcp0_file, srcp0_ihdl);
 	mutex_unlock(&msm_rotator_dev->rotator_lock);
 	dev_dbg(msm_rotator_dev->device, "%s() returning rc = %d\n",
 		__func__, rc);
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index a6c36c8..9b1e548 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -613,6 +613,11 @@
 	struct ion_iommu_map *iommu_map;
 	int ret = 0;
 
+	if (ION_IS_CACHED(flags)) {
+		pr_err("%s: Cannot map iommu as cached.\n", __func__);
+		return -EINVAL;
+	}
+
 	mutex_lock(&client->lock);
 	if (!ion_handle_validate(client, handle)) {
 		pr_err("%s: invalid handle passed to map_kernel.\n",
@@ -631,11 +636,6 @@
 		goto out;
 	}
 
-	if (ion_validate_buffer_flags(buffer, flags)) {
-		ret = -EEXIST;
-		goto out;
-	}
-
 	/*
 	 * If clients don't want a custom iova length, just use whatever
 	 * the buffer size is
@@ -882,7 +882,7 @@
 	return ret;
 }
 
-static int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
 			void *uaddr, unsigned long offset, unsigned long len,
 			unsigned int cmd)
 {
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 1d40aef..36758fa 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -271,4 +271,23 @@
 void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base,
 				void *virt_base, unsigned long flags);
 
+/**
+ * ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @uaddr -  virtual address to operate on.
+ * @offset - offset from physical address.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ *		ION_IOC_CLEAN_CACHES
+ *		ION_IOC_INV_CACHES
+ *		ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+			void *uaddr, unsigned long offset, unsigned long len,
+			unsigned int cmd);
+
 #endif /* _ION_PRIV_H */
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index a81dbd3..203b41a 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -43,6 +43,13 @@
 }
 EXPORT_SYMBOL(msm_ion_unsecure_heap);
 
+int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+			void *vaddr, unsigned long len, unsigned int cmd)
+{
+	return ion_do_cache_op(client, handle, vaddr, 0, len, cmd);
+}
+EXPORT_SYMBOL(msm_ion_do_cache_op);
+
 static unsigned long msm_ion_get_base(unsigned long size, int memory_type,
 				    unsigned int align)
 {
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 73d00b3..ea16c31 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -136,6 +136,9 @@
 	{ ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID,
 		"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
 		512, 384, 3},
+	{ ADRENO_REV_A203, 0, 1, 1, ANY_ID,
+		"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
+		512, 384, 3},
 	{ ADRENO_REV_A205, 0, 1, 0, ANY_ID,
 		"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
 		512, 384, 3},
@@ -400,11 +403,14 @@
 
 	/* 8x50 returns 0 for patch release, but it should be 1 */
 	/* 8960v3 returns 5 for patch release, but it should be 6 */
+	/* 8x25 returns 0 for minor id, but it should be 1 */
 	if (cpu_is_qsd8x50())
 		patchid = 1;
 	else if (cpu_is_msm8960() &&
 			SOCINFO_VERSION_MAJOR(soc_platform_version) == 3)
 		patchid = 6;
+	else if (cpu_is_msm8625() && minorid == 0)
+		minorid = 1;
 
 	chipid |= (minorid << 8) | patchid;
 
@@ -604,6 +610,8 @@
 	unsigned int soptimestamp;
 	unsigned int eoptimestamp;
 	struct adreno_context *drawctxt;
+	struct kgsl_context *context;
+	int next = 0;
 
 	KGSL_DRV_ERR(device, "Starting recovery from 3D GPU hang....\n");
 	rb_buffer = vmalloc(rb->buffer_desc.size);
@@ -672,6 +680,24 @@
 
 	drawctxt->flags |= CTXT_FLAGS_GPU_HANG;
 
+	/*
+	 * Set the reset status of all contexts to
+	 * INNOCENT_CONTEXT_RESET_EXT except for the bad context
+	 * since thats the guilty party
+	 */
+	while ((context = idr_get_next(&device->context_idr, &next))) {
+		if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
+			context->reset_status) {
+			if (context->devctxt != drawctxt)
+				context->reset_status =
+				KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
+			else
+				context->reset_status =
+				KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
+		}
+		next = next + 1;
+	}
+
 	/* Restore valid commands in ringbuffer */
 	adreno_ringbuffer_restore(rb, rb_buffer, num_rb_contents);
 	rb->timestamp = timestamp;
@@ -1248,7 +1274,7 @@
 	default:
 		KGSL_DRV_INFO(dev_priv->device,
 			"invalid ioctl code %08x\n", cmd);
-		result = -EINVAL;
+		result = -ENOIOCTLCMD;
 		break;
 	}
 	return result;
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9498b80..74f36c3 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -44,6 +44,7 @@
 enum adreno_gpurev {
 	ADRENO_REV_UNKNOWN = 0,
 	ADRENO_REV_A200 = 200,
+	ADRENO_REV_A203 = 203,
 	ADRENO_REV_A205 = 205,
 	ADRENO_REV_A220 = 220,
 	ADRENO_REV_A225 = 225,
@@ -129,15 +130,19 @@
 	return (adreno_dev->gpurev == ADRENO_REV_A200);
 }
 
+static inline int adreno_is_a203(struct adreno_device *adreno_dev)
+{
+	return (adreno_dev->gpurev == ADRENO_REV_A203);
+}
+
 static inline int adreno_is_a205(struct adreno_device *adreno_dev)
 {
-	return (adreno_dev->gpurev == ADRENO_REV_A200);
+	return (adreno_dev->gpurev == ADRENO_REV_A205);
 }
 
 static inline int adreno_is_a20x(struct adreno_device *adreno_dev)
 {
-	return (adreno_dev->gpurev  == ADRENO_REV_A200 ||
-		adreno_dev->gpurev == ADRENO_REV_A205);
+	return (adreno_dev->gpurev <= 209);
 }
 
 static inline int adreno_is_a220(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index b53ca8f..68299cf 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -23,7 +23,8 @@
 #include "a2xx_reg.h"
 
 unsigned int kgsl_cff_dump_enable;
-int kgsl_pm_regs_enabled;
+int adreno_pm_regs_enabled;
+int adreno_pm_ib_enabled;
 
 static struct dentry *pm_d_debugfs;
 
@@ -46,20 +47,37 @@
 
 static int pm_regs_enabled_set(void *data, u64 val)
 {
-	kgsl_pm_regs_enabled = val ? 1 : 0;
+	adreno_pm_regs_enabled = val ? 1 : 0;
 	return 0;
 }
 
 static int pm_regs_enabled_get(void *data, u64 *val)
 {
-	*val = kgsl_pm_regs_enabled;
+	*val = adreno_pm_regs_enabled;
 	return 0;
 }
 
+static int pm_ib_enabled_set(void *data, u64 val)
+{
+	adreno_pm_ib_enabled = val ? 1 : 0;
+	return 0;
+}
+
+static int pm_ib_enabled_get(void *data, u64 *val)
+{
+	*val = adreno_pm_ib_enabled;
+	return 0;
+}
+
+
 DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
 			pm_regs_enabled_get,
 			pm_regs_enabled_set, "%llu\n");
 
+DEFINE_SIMPLE_ATTRIBUTE(pm_ib_enabled_fops,
+			pm_ib_enabled_get,
+			pm_ib_enabled_set, "%llu\n");
+
 
 static int kgsl_cff_dump_enable_set(void *data, u64 val)
 {
@@ -358,4 +376,6 @@
 			    &pm_dump_fops);
 	debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
 			    &pm_regs_enabled_fops);
+	debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
+				    &pm_ib_enabled_fops);
 }
diff --git a/drivers/gpu/msm/adreno_debugfs.h b/drivers/gpu/msm/adreno_debugfs.h
index 0356ac6..5f8d89a 100644
--- a/drivers/gpu/msm/adreno_debugfs.h
+++ b/drivers/gpu/msm/adreno_debugfs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,11 +17,17 @@
 
 int adreno_debugfs_init(struct kgsl_device *device);
 
-extern int kgsl_pm_regs_enabled;
+extern int adreno_pm_regs_enabled;
+extern int adreno_pm_ib_enabled;
 
-static inline int kgsl_pmregs_enabled(void)
+static inline int is_adreno_pm_regs_enabled(void)
 {
-	return kgsl_pm_regs_enabled;
+	return adreno_pm_regs_enabled;
+}
+
+static inline int is_adreno_pm_ib_enabled(void)
+{
+	return adreno_pm_ib_enabled;
 }
 
 #else
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 7902f30..f9e498f 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -294,15 +294,6 @@
 	}
 }
 
-static bool adreno_ib_dump_enabled(void)
-{
-#ifdef CONFIG_MSM_KGSL_PSTMRTMDMP_NO_IB_DUMP
-	return 0;
-#else
-	return 1;
-#endif
-}
-
 struct log_field {
 	bool show;
 	const char *display;
@@ -817,7 +808,7 @@
 		cp_rb_base, cp_rb_rptr, cp_rb_wptr, read_idx);
 	adreno_dump_rb(device, rb_copy, num_item<<2, read_idx, rb_count);
 
-	if (adreno_ib_dump_enabled()) {
+	if (is_adreno_pm_ib_enabled()) {
 		for (read_idx = NUM_DWORDS_OF_RINGBUFFER_HISTORY;
 			read_idx >= 0; --read_idx) {
 			uint32_t this_cmd = rb_copy[read_idx];
@@ -849,16 +840,17 @@
 	}
 
 	/* Dump the registers if the user asked for it */
-
-	if (adreno_is_a20x(adreno_dev))
-		adreno_dump_regs(device, a200_registers,
-			a200_registers_count);
-	else if (adreno_is_a22x(adreno_dev))
-		adreno_dump_regs(device, a220_registers,
-			a220_registers_count);
-	else if (adreno_is_a3xx(adreno_dev))
-		adreno_dump_regs(device, a3xx_registers,
-			a3xx_registers_count);
+	if (is_adreno_pm_regs_enabled()) {
+		if (adreno_is_a20x(adreno_dev))
+			adreno_dump_regs(device, a200_registers,
+					a200_registers_count);
+		else if (adreno_is_a22x(adreno_dev))
+			adreno_dump_regs(device, a220_registers,
+					a220_registers_count);
+		else if (adreno_is_a3xx(adreno_dev))
+			adreno_dump_regs(device, a3xx_registers,
+					a3xx_registers_count);
+	}
 
 error_vfree:
 	vfree(rb_copy);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9333dca..b7356ac 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -789,6 +789,40 @@
 
 		break;
 	}
+	case KGSL_PROP_GPU_RESET_STAT:
+	{
+		/* Return reset status of given context and clear it */
+		uint32_t id;
+		struct kgsl_context *context;
+
+		if (param->sizebytes != sizeof(unsigned int)) {
+			result = -EINVAL;
+			break;
+		}
+		/* We expect the value passed in to contain the context id */
+		if (copy_from_user(&id, param->value,
+			sizeof(unsigned int))) {
+			result = -EFAULT;
+			break;
+		}
+		context = kgsl_find_context(dev_priv, id);
+		if (!context) {
+			result = -EINVAL;
+			break;
+		}
+		/*
+		 * Copy the reset status to value which also serves as
+		 * the out parameter
+		 */
+		if (copy_to_user(param->value, &(context->reset_status),
+			sizeof(unsigned int))) {
+			result = -EFAULT;
+			break;
+		}
+		/* Clear reset status once its been queried */
+		context->reset_status = KGSL_CTX_STAT_NO_ERROR;
+		break;
+	}
 	default:
 		result = dev_priv->device->ftbl->getproperty(
 					dev_priv->device, param->type,
@@ -990,6 +1024,7 @@
 	spin_lock(&entry->priv->mem_lock);
 	list_del(&entry->list);
 	spin_unlock(&entry->priv->mem_lock);
+	trace_kgsl_mem_timestamp_free(entry, timestamp);
 	kgsl_mem_entry_put(entry);
 }
 
@@ -1000,12 +1035,18 @@
 	int result = 0;
 	struct kgsl_cmdstream_freememontimestamp *param = data;
 	struct kgsl_mem_entry *entry = NULL;
+	struct kgsl_device *device = dev_priv->device;
+	unsigned int cur;
 
 	spin_lock(&dev_priv->process_priv->mem_lock);
 	entry = kgsl_sharedmem_find(dev_priv->process_priv, param->gpuaddr);
 	spin_unlock(&dev_priv->process_priv->mem_lock);
 
 	if (entry) {
+		cur = device->ftbl->readtimestamp(device,
+						KGSL_TIMESTAMP_RETIRED);
+
+		trace_kgsl_mem_timestamp_queue(entry, cur);
 		result = kgsl_add_event(dev_priv->device, param->timestamp,
 					kgsl_freemem_event_cb, entry, dev_priv);
 	} else {
@@ -1084,6 +1125,7 @@
 	spin_unlock(&private->mem_lock);
 
 	if (entry) {
+		trace_kgsl_mem_free(entry);
 		kgsl_mem_entry_put(entry);
 	} else {
 		KGSL_CORE_ERR("invalid gpuaddr %08x\n", param->gpuaddr);
@@ -1184,6 +1226,7 @@
 
 	kgsl_mem_entry_attach_process(entry, private);
 
+	trace_kgsl_mem_alloc(entry);
 	/* Process specific statistics */
 	kgsl_process_add_stats(private, entry->memtype, len);
 
@@ -1618,6 +1661,7 @@
 	kgsl_process_add_stats(private, entry->memtype, param->len);
 
 	kgsl_mem_entry_attach_process(entry, private);
+	trace_kgsl_mem_map(entry, param->fd);
 
 	kgsl_check_idle(dev_priv->device);
 	return result;
@@ -1684,6 +1728,7 @@
 		param->gpuaddr = entry->memdesc.gpuaddr;
 
 		kgsl_process_add_stats(private, entry->memtype, param->size);
+		trace_kgsl_mem_alloc(entry);
 	} else
 		kfree(entry);
 
@@ -1930,7 +1975,7 @@
 		if (!func) {
 			KGSL_DRV_INFO(dev_priv->device,
 				      "invalid ioctl code %08x\n", cmd);
-			ret = -EINVAL;
+			ret = -ENOIOCTLCMD;
 			goto done;
 		}
 		lock = 1;
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 2fb1e43..06432f9 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -197,6 +197,11 @@
 
 	/* Pointer to the device specific context information */
 	void *devctxt;
+	/*
+	 * Status indicating whether a gpu reset occurred and whether this
+	 * context was responsible for causing it
+	 */
+	unsigned int reset_status;
 };
 
 struct kgsl_process_private {
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 389ed6d..7264c25 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -150,7 +150,7 @@
 #endif
 	MEM_ENTRY_STAT(KGSL_MEM_ENTRY_USER, user),
 #ifdef CONFIG_ION
-	MEM_ENTRY_STAT(KGSL_MEM_ENTRY_USER, ion),
+	MEM_ENTRY_STAT(KGSL_MEM_ENTRY_ION, ion),
 #endif
 };
 
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index de39ee4..93fdc08 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/vmalloc.h>
 #include <linux/time.h>
 #include <linux/sysfs.h>
 #include <linux/utsname.h>
@@ -299,6 +298,10 @@
 	/* Freeze the snapshot on a hang until it gets read */
 	device->snapshot_frozen = (hang) ? 1 : 0;
 
+	/* log buffer info to aid in ramdump recovery */
+	KGSL_DRV_ERR(device, "snapshot created at va %p pa %lx size %d\n",
+			device->snapshot, __pa(device->snapshot),
+			device->snapshot_size);
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_device_snapshot);
@@ -448,7 +451,7 @@
 	int ret;
 
 	if (device->snapshot == NULL)
-		device->snapshot = vmalloc(KGSL_SNAPSHOT_MEMSIZE);
+		device->snapshot = kzalloc(KGSL_SNAPSHOT_MEMSIZE, GFP_KERNEL);
 
 	if (device->snapshot == NULL)
 		return -ENOMEM;
@@ -491,7 +494,7 @@
 
 	kobject_put(&device->snapshot_kobj);
 
-	vfree(device->snapshot);
+	kfree(device->snapshot);
 
 	device->snapshot = NULL;
 	device->snapshot_maxsize = 0;
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 86a9adc..22bc576 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.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
@@ -257,6 +257,122 @@
 	TP_ARGS(device, state)
 );
 
+TRACE_EVENT(kgsl_mem_alloc,
+
+	TP_PROTO(struct kgsl_mem_entry *mem_entry),
+
+	TP_ARGS(mem_entry),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, gpuaddr)
+		__field(unsigned int, size)
+	),
+
+	TP_fast_assign(
+		__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+		__entry->size = mem_entry->memdesc.size;
+	),
+
+	TP_printk(
+		"gpuaddr=0x%08x size=%d",
+		__entry->gpuaddr, __entry->size
+	)
+);
+
+TRACE_EVENT(kgsl_mem_map,
+
+	TP_PROTO(struct kgsl_mem_entry *mem_entry, int fd),
+
+	TP_ARGS(mem_entry, fd),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, gpuaddr)
+		__field(unsigned int, size)
+		__field(int, fd)
+		__field(int, type)
+	),
+
+	TP_fast_assign(
+		__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+		__entry->size = mem_entry->memdesc.size;
+		__entry->fd = fd;
+		__entry->type = mem_entry->memtype;
+	),
+
+	TP_printk(
+		"gpuaddr=0x%08x size=%d type=%d fd=%d",
+		__entry->gpuaddr, __entry->size,
+		__entry->type, __entry->fd
+	)
+);
+
+TRACE_EVENT(kgsl_mem_free,
+
+	TP_PROTO(struct kgsl_mem_entry *mem_entry),
+
+	TP_ARGS(mem_entry),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, gpuaddr)
+		__field(unsigned int, size)
+		__field(int, type)
+		__field(int, fd)
+	),
+
+	TP_fast_assign(
+		__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+		__entry->size = mem_entry->memdesc.size;
+		__entry->type = mem_entry->memtype;
+	),
+
+	TP_printk(
+		"gpuaddr=0x%08x size=%d type=%d",
+		__entry->gpuaddr, __entry->size, __entry->type
+	)
+);
+
+DECLARE_EVENT_CLASS(kgsl_mem_timestamp_template,
+
+	TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned int curr_ts),
+
+	TP_ARGS(mem_entry, curr_ts),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, gpuaddr)
+		__field(unsigned int, size)
+		__field(int, type)
+		__field(unsigned int, drawctxt_id)
+		__field(unsigned int, curr_ts)
+		__field(unsigned int, free_ts)
+	),
+
+	TP_fast_assign(
+		__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+		__entry->size = mem_entry->memdesc.size;
+		__entry->drawctxt_id = 1337;
+		__entry->type = mem_entry->memtype;
+		__entry->curr_ts = curr_ts;
+		__entry->free_ts = mem_entry->free_timestamp;
+	),
+
+	TP_printk(
+		"gpuaddr=0x%08x size=%d type=%d ctx=%u curr_ts=0x%08x free_ts=0x%08x",
+		__entry->gpuaddr, __entry->size, __entry->type,
+		__entry->drawctxt_id, __entry->curr_ts, __entry->free_ts
+	)
+);
+
+DEFINE_EVENT(kgsl_mem_timestamp_template, kgsl_mem_timestamp_queue,
+	TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned int curr_ts),
+	TP_ARGS(mem_entry, curr_ts)
+);
+
+DEFINE_EVENT(kgsl_mem_timestamp_template, kgsl_mem_timestamp_free,
+	TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned int curr_ts),
+	TP_ARGS(mem_entry, curr_ts)
+);
+
+
 #endif /* _KGSL_TRACE_H */
 
 /* This part must be outside protection */
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cb3da90..6c43a75 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -339,13 +339,15 @@
 	*p++ = ADDR_VGV3_LAST << 24;
 }
 
-static void z180_cmdstream_start(struct kgsl_device *device)
+static void z180_cmdstream_start(struct kgsl_device *device, int init_ram)
 {
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 	unsigned int cmd = VGV3_NEXTCMD_JUMP << VGV3_NEXTCMD_NEXTCMD_FSHIFT;
 
-	z180_dev->timestamp = 0;
-	z180_dev->current_timestamp = 0;
+	if (init_ram) {
+		z180_dev->timestamp = 0;
+		z180_dev->current_timestamp = 0;
+	}
 
 	addmarker(&z180_dev->ringbuffer, 0);
 
@@ -566,7 +568,7 @@
 	if (status)
 		goto error_clk_off;
 
-	z180_cmdstream_start(device);
+	z180_cmdstream_start(device, init_ram);
 
 	mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 40aae69..f18c2d0 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -25,6 +25,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/regulator/consumer.h>
+#include <linux/string.h>
 
 #if defined(CONFIG_HAS_EARLYSUSPEND)
 #include <linux/earlysuspend.h>
@@ -42,15 +43,32 @@
 #define MXT_VER_21		21
 #define MXT_VER_22		22
 
-/* Slave addresses */
-#define MXT_APP_LOW		0x4a
-#define MXT_APP_HIGH		0x4b
-#define MXT_BOOT_LOW		0x24
-#define MXT_BOOT_HIGH		0x25
+/* I2C slave address pairs */
+struct mxt_address_pair {
+	int bootloader;
+	int application;
+};
+
+static const struct mxt_address_pair mxt_slave_addresses[] = {
+	{ 0x24, 0x4a },
+	{ 0x25, 0x4b },
+	{ 0x25, 0x4b },
+	{ 0x26, 0x4c },
+	{ 0x27, 0x4d },
+	{ 0x34, 0x5a },
+	{ 0x35, 0x5b },
+	{ 0 },
+};
+
+enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
 
 /* Firmware */
 #define MXT_FW_NAME		"maxtouch.fw"
 
+/* Firmware frame size including frame data and CRC */
+#define MXT_SINGLE_FW_MAX_FRAME_SIZE	278
+#define MXT_CHIPSET_FW_MAX_FRAME_SIZE	534
+
 /* Registers */
 #define MXT_FAMILY_ID		0x00
 #define MXT_VARIANT_ID		0x01
@@ -215,7 +233,7 @@
 #define MXT_RESET_TIME		250	/* msec */
 #define MXT_RESET_NOCHGREAD	400	/* msec */
 
-#define MXT_FWRESET_TIME	175	/* msec */
+#define MXT_FWRESET_TIME	1000	/* msec */
 
 #define MXT_WAKE_TIME		25
 
@@ -231,6 +249,8 @@
 #define MXT_FRAME_CRC_PASS	0x04
 #define MXT_APP_CRC_FAIL	0x40	/* valid 7 8 bit only */
 #define MXT_BOOT_STATUS_MASK	0x3f
+#define MXT_BOOT_EXTENDED_ID	(1 << 5)
+#define MXT_BOOT_ID_MASK	0x1f
 
 /* Touch status */
 #define MXT_SUPPRESS		(1 << 1)
@@ -299,6 +319,7 @@
 	struct input_dev *input_dev;
 	const struct mxt_platform_data *pdata;
 	const struct mxt_config_info *config_info;
+	enum mxt_device_state state;
 	struct mxt_object *object_table;
 	struct mxt_info info;
 	struct mxt_finger finger[MXT_MAX_FINGER];
@@ -323,6 +344,7 @@
 	u8 t15_min_reportid;
 	u8 curr_cfg_version;
 	int cfg_version_idx;
+	const char *fw_name;
 };
 
 static struct dentry *debug_base;
@@ -409,8 +431,91 @@
 	dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
 }
 
+static int mxt_switch_to_bootloader_address(struct mxt_data *data)
+{
+	int i;
+	struct i2c_client *client = data->client;
+
+	if (data->state == BOOTLOADER) {
+		dev_err(&client->dev, "Already in BOOTLOADER state\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; mxt_slave_addresses[i].application != 0;  i++) {
+		if (mxt_slave_addresses[i].application == client->addr) {
+			dev_info(&client->dev, "Changing to bootloader address: "
+				"%02x -> %02x",
+				client->addr,
+				mxt_slave_addresses[i].bootloader);
+
+			client->addr = mxt_slave_addresses[i].bootloader;
+			data->state = BOOTLOADER;
+			return 0;
+		}
+	}
+
+	dev_err(&client->dev, "Address 0x%02x not found in address table",
+								client->addr);
+	return -EINVAL;
+}
+
+static int mxt_switch_to_appmode_address(struct mxt_data *data)
+{
+	int i;
+	struct i2c_client *client = data->client;
+
+	if (data->state == APPMODE) {
+		dev_err(&client->dev, "Already in APPMODE state\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; mxt_slave_addresses[i].application != 0;  i++) {
+		if (mxt_slave_addresses[i].bootloader == client->addr) {
+			dev_info(&client->dev,
+				"Changing to application mode address: "
+							"0x%02x -> 0x%02x",
+				client->addr,
+				mxt_slave_addresses[i].application);
+
+			client->addr = mxt_slave_addresses[i].application;
+			data->state = APPMODE;
+			return 0;
+		}
+	}
+
+	dev_err(&client->dev, "Address 0x%02x not found in address table",
+								client->addr);
+	return -EINVAL;
+}
+
+static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
+{
+	u8 buf[3];
+
+	if (val | MXT_BOOT_EXTENDED_ID)	{
+		dev_dbg(&client->dev,
+				"Retrieving extended mode ID information");
+
+		if (i2c_master_recv(client, &buf[0], 3) != 3) {
+			dev_err(&client->dev, "%s: i2c recv failed\n",
+								__func__);
+			return -EIO;
+		}
+
+		dev_info(&client->dev, "Bootloader ID:%d Version:%d",
+			buf[1], buf[2]);
+
+		return buf[0];
+	} else {
+		dev_info(&client->dev, "Bootloader ID:%d",
+			val & MXT_BOOT_ID_MASK);
+
+		return val;
+	}
+}
+
 static int mxt_check_bootloader(struct i2c_client *client,
-				     unsigned int state)
+				unsigned int state)
 {
 	u8 val;
 
@@ -422,19 +527,28 @@
 
 	switch (state) {
 	case MXT_WAITING_BOOTLOAD_CMD:
+		val = mxt_get_bootloader_version(client, val);
+		val &= ~MXT_BOOT_STATUS_MASK;
+		break;
 	case MXT_WAITING_FRAME_DATA:
+	case MXT_APP_CRC_FAIL:
 		val &= ~MXT_BOOT_STATUS_MASK;
 		break;
 	case MXT_FRAME_CRC_PASS:
 		if (val == MXT_FRAME_CRC_CHECK)
 			goto recheck;
+		if (val == MXT_FRAME_CRC_FAIL) {
+			dev_err(&client->dev, "Bootloader CRC fail\n");
+			return -EINVAL;
+		}
 		break;
 	default:
 		return -EINVAL;
 	}
 
 	if (val != state) {
-		dev_err(&client->dev, "Unvalid bootloader mode state\n");
+		dev_err(&client->dev, "Invalid bootloader mode state %X\n",
+			val);
 		return -EINVAL;
 	}
 
@@ -457,7 +571,7 @@
 }
 
 static int mxt_fw_write(struct i2c_client *client,
-			     const u8 *data, unsigned int frame_size)
+			const u8 *data, unsigned int frame_size)
 {
 	if (i2c_master_send(client, data, frame_size) != frame_size) {
 		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
@@ -735,6 +849,11 @@
 	int id;
 	u8 reportid;
 
+	if (data->state != APPMODE) {
+		dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
+		return IRQ_HANDLED;
+	}
+
 	do {
 		if (mxt_read_message(data, &message)) {
 			dev_err(dev, "Failed to read message\n");
@@ -921,11 +1040,13 @@
 			if (data->curr_cfg_version == cfg_version ||
 				!version_match) {
 				data->config_info = cfg_info;
+				data->fw_name = pdata->config_array[i].fw_name;
 				return 0;
 			}
 		}
 	}
 
+	data->fw_name = NULL;
 	dev_info(&data->client->dev,
 		"Config not found: F: %d, V: %d, FW: %d.%d.%d, CFG: %d\n",
 		info->family_id, info->variant_id,
@@ -1003,8 +1124,30 @@
 	struct mxt_object *t15_object;
 
 	error = mxt_get_info(data);
-	if (error)
-		return error;
+	if (error) {
+		/* Try bootloader mode */
+		error = mxt_switch_to_bootloader_address(data);
+		if (error)
+			return error;
+
+		error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
+		if (error)
+			return error;
+
+		dev_err(&client->dev, "Application CRC failure\n");
+		data->state = BOOTLOADER;
+
+		return 0;
+	}
+
+	dev_info(&client->dev,
+			"Family ID: %d Variant ID: %d Version: %d.%d "
+			"Build: 0x%02X Object Num: %d\n",
+			info->family_id, info->variant_id,
+			info->version >> 4, info->version & 0xf,
+			info->build, info->object_num);
+
+	data->state = APPMODE;
 
 	data->object_table = kcalloc(info->object_num,
 				     sizeof(struct mxt_object),
@@ -1112,14 +1255,8 @@
 	info->matrix_ysize = val;
 
 	dev_info(&client->dev,
-			"Family ID: %d Variant ID: %d Version: %d Build: %d\n",
-			info->family_id, info->variant_id, info->version,
-			info->build);
-
-	dev_info(&client->dev,
-			"Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
-			info->matrix_xsize, info->matrix_ysize,
-			info->object_num);
+			"Matrix X Size: %d Matrix Y Size: %d\n",
+			info->matrix_xsize, info->matrix_ysize);
 
 	return 0;
 
@@ -1175,74 +1312,139 @@
 	return count;
 }
 
+static int strtobyte(const char *data, u8 *value)
+{
+	char str[3];
+
+	str[0] = data[0];
+	str[1] = data[1];
+	str[2] = '\0';
+
+	return kstrtou8(str, 16, value);
+}
+
 static int mxt_load_fw(struct device *dev, const char *fn)
 {
 	struct mxt_data *data = dev_get_drvdata(dev);
 	struct i2c_client *client = data->client;
 	const struct firmware *fw = NULL;
 	unsigned int frame_size;
+	unsigned int retry = 0;
 	unsigned int pos = 0;
-	int ret;
+	int ret, i, max_frame_size;
+	u8 *frame;
 
-	ret = request_firmware(&fw, fn, dev);
-	if (ret) {
-		dev_err(dev, "Unable to open firmware %s\n", fn);
-		return ret;
+	switch (data->info.family_id) {
+	case MXT224_ID:
+		max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
+		break;
+	case MXT1386_ID:
+		max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
+		break;
+	default:
+		return -EINVAL;
 	}
 
-	/* Change to the bootloader mode */
-	mxt_write_object(data, MXT_GEN_COMMAND_T6,
-			MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+	frame = kmalloc(max_frame_size, GFP_KERNEL);
+	if (!frame) {
+		dev_err(dev, "Unable to allocate memory for frame data\n");
+		return -ENOMEM;
+	}
 
-	mxt_reset_delay(data);
+	ret = request_firmware(&fw, fn, dev);
+	if (ret < 0) {
+		dev_err(dev, "Unable to open firmware %s\n", fn);
+		goto free_frame;
+	}
 
-	/* Change to slave address of bootloader */
-	if (client->addr == MXT_APP_LOW)
-		client->addr = MXT_BOOT_LOW;
-	else
-		client->addr = MXT_BOOT_HIGH;
+	if (data->state != BOOTLOADER) {
+		/* Change to the bootloader mode */
+		mxt_write_object(data, MXT_GEN_COMMAND_T6,
+				MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+		mxt_reset_delay(data);
+
+		ret = mxt_switch_to_bootloader_address(data);
+		if (ret)
+			goto release_firmware;
+	}
 
 	ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
-	if (ret)
-		goto out;
+	if (ret) {
+		/* Bootloader may still be unlocked from previous update
+		 * attempt */
+		ret = mxt_check_bootloader(client,
+			MXT_WAITING_FRAME_DATA);
 
-	/* Unlock bootloader */
-	mxt_unlock_bootloader(client);
+		if (ret)
+			goto return_to_app_mode;
+	} else {
+		dev_info(dev, "Unlocking bootloader\n");
+		/* Unlock bootloader */
+		mxt_unlock_bootloader(client);
+	}
 
 	while (pos < fw->size) {
 		ret = mxt_check_bootloader(client,
 						MXT_WAITING_FRAME_DATA);
 		if (ret)
-			goto out;
+			goto release_firmware;
 
-		frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+		/* Get frame length MSB */
+		ret = strtobyte(fw->data + pos, frame);
+		if (ret)
+			goto release_firmware;
+
+		/* Get frame length LSB */
+		ret = strtobyte(fw->data + pos + 2, frame + 1);
+		if (ret)
+			goto release_firmware;
+
+		frame_size = ((*frame << 8) | *(frame + 1));
 
 		/* We should add 2 at frame size as the the firmware data is not
 		 * included the CRC bytes.
 		 */
 		frame_size += 2;
 
+		if (frame_size > max_frame_size) {
+			dev_err(dev, "Invalid frame size - %d\n", frame_size);
+			ret = -EINVAL;
+			goto release_firmware;
+		}
+
+		/* Convert frame data and CRC from hex to binary */
+		for (i = 2; i < frame_size; i++) {
+			ret = strtobyte(fw->data + pos + i * 2, frame + i);
+			if (ret)
+				goto release_firmware;
+		}
+
 		/* Write one frame to device */
-		mxt_fw_write(client, fw->data + pos, frame_size);
+		mxt_fw_write(client, frame, frame_size);
 
 		ret = mxt_check_bootloader(client,
 						MXT_FRAME_CRC_PASS);
-		if (ret)
-			goto out;
+		if (ret) {
+			retry++;
 
-		pos += frame_size;
+			/* Back off by 20ms per retry */
+			msleep(retry * 20);
 
-		dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+			if (retry > 20)
+				goto release_firmware;
+		} else {
+			retry = 0;
+			pos += frame_size * 2;
+			dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
+		}
 	}
 
-out:
+return_to_app_mode:
+	mxt_switch_to_appmode_address(data);
+release_firmware:
 	release_firmware(fw);
-
-	/* Change to slave address of application */
-	if (client->addr == MXT_BOOT_LOW)
-		client->addr = MXT_APP_LOW;
-	else
-		client->addr = MXT_APP_HIGH;
+free_frame:
+	kfree(frame);
 
 	return ret;
 }
@@ -1254,29 +1456,41 @@
 	struct mxt_data *data = dev_get_drvdata(dev);
 	int error;
 
+	/* If fw_name is set, then the existing firmware has an upgrade */
+	if (!data->fw_name) {
+		dev_err(dev, "Firmware name not specifed in platform data\n");
+		return -EINVAL;
+	}
+
+	dev_info(dev, "Upgrading the firmware file to %s\n", data->fw_name);
+
 	disable_irq(data->irq);
 
-	error = mxt_load_fw(dev, MXT_FW_NAME);
+	error = mxt_load_fw(dev, data->fw_name);
 	if (error) {
 		dev_err(dev, "The firmware update failed(%d)\n", error);
 		count = error;
 	} else {
-		dev_dbg(dev, "The firmware update succeeded\n");
+		dev_info(dev, "The firmware update succeeded\n");
 
 		/* Wait for reset */
 		msleep(MXT_FWRESET_TIME);
 
+		data->state = INIT;
 		kfree(data->object_table);
 		data->object_table = NULL;
+		data->cfg_version_idx = 0;
 
 		mxt_initialize(data);
 	}
 
-	enable_irq(data->irq);
+	if (data->state == APPMODE) {
+		enable_irq(data->irq);
 
-	error = mxt_make_highchg(data);
-	if (error)
-		return error;
+		error = mxt_make_highchg(data);
+		if (error)
+			return error;
+	}
 
 	return count;
 }
@@ -1818,6 +2032,7 @@
 		goto err_free_mem;
 	}
 
+	data->state = INIT;
 	input_dev->name = "atmel_mxt_ts";
 	input_dev->id.bustype = BUS_I2C;
 	input_dev->dev.parent = &client->dev;
@@ -1941,9 +2156,13 @@
 		goto err_free_object;
 	}
 
-	error = mxt_make_highchg(data);
-	if (error)
-		goto err_free_irq;
+	if (data->state == APPMODE) {
+		error = mxt_make_highchg(data);
+		if (error) {
+			dev_err(&client->dev, "Failed to make high CHG\n");
+			goto err_free_irq;
+		}
+	}
 
 	error = input_register_device(input_dev);
 	if (error)
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 84d441d..78c474e 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -163,6 +163,10 @@
 		if (!rc)
 			rc = -ETIMEDOUT;
 		if (rc < 0) {
+			rcmd = msm_dequeue(queue, list_control);
+			if (!rcmd)
+				free_qcmd(rcmd);
+			kfree(isp_event);
 			pr_err("%s: wait_event error %d\n", __func__, rc);
 			return rc;
 		}
@@ -518,6 +522,7 @@
 	ctrlcmd.value = (void *)ctrl_data;
 	memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
 	ctrlcmd.timeout_ms = 1000;
+	ctrlcmd.vnode_id = pcam->vnode_id;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
@@ -543,6 +548,7 @@
 	ctrlcmd.value = (void *)ctrl_data;
 	memcpy(ctrlcmd.value, queryctrl, ctrlcmd.length);
 	ctrlcmd.timeout_ms = 1000;
+	ctrlcmd.vnode_id = pcam->vnode_id;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in userspace, and get return value */
@@ -943,7 +949,8 @@
 		not in use when we free the buffers */
 	mutex_lock(&pcam->vid_lock);
 	pcam_inst->streamon = 0;
-	rc = msm_server_streamoff(pcam, pcam_inst->my_index);
+	if (g_server_dev.use_count > 0)
+		rc = msm_server_streamoff(pcam, pcam_inst->my_index);
 	mutex_unlock(&pcam->vid_lock);
 	if (rc < 0)
 		pr_err("%s: hw failed to stop streaming\n", __func__);
@@ -1448,6 +1455,7 @@
 		}
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		pcam->mctl.client = msm_ion_client_create(-1, "camera");
+		kref_init(&pcam->mctl.refcount);
 #endif
 		/* Should be set to sensor ops if any but right now its OK!! */
 		if (!pcam->mctl.mctl_open) {
@@ -1502,6 +1510,7 @@
 
 
 	if (pcam->use_count == 1) {
+		msm_queue_init(&g_server_dev.ctrl_q, "control");
 		rc = msm_send_open_server(pcam->vnode_id);
 		if (rc < 0) {
 			mutex_unlock(&pcam->vid_lock);
@@ -1573,6 +1582,14 @@
 	return rc;
 }
 
+void msm_release_ion_client(struct kref *ref)
+{
+	struct msm_cam_media_controller *mctl = container_of(ref,
+			struct msm_cam_media_controller, refcount);
+	pr_err("%s Calling ion_client_destroy ", __func__);
+	ion_client_destroy(mctl->client);
+}
+
 static int msm_close(struct file *f)
 {
 	int rc = 0;
@@ -1581,13 +1598,11 @@
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 	pcam = pcam_inst->pcam;
-	D("%s\n", __func__);
 	if (!pcam) {
 		pr_err("%s NULL pointer of camera device!\n", __func__);
 		return -EINVAL;
 	}
 
-
 	mutex_lock(&pcam->vid_lock);
 	pcam_inst->streamon = 0;
 	pcam->use_count--;
@@ -1610,17 +1625,21 @@
 		if (rc < 0)
 			pr_err("msm_cam_server_close_session fails %d\n", rc);
 
-		rc = msm_send_close_server(pcam->vnode_id);
-		if (rc < 0)
-			pr_err("msm_send_close_server failed %d\n", rc);
+		if (g_server_dev.use_count > 0) {
+			rc = msm_send_close_server(pcam->vnode_id);
+			if (rc < 0)
+				pr_err("msm_send_close_server failed %d\n", rc);
+		}
 		if (pcam->mctl.mctl_release) {
 			rc = pcam->mctl.mctl_release(&(pcam->mctl));
 			if (rc < 0)
 				pr_err("mctl_release fails %d\n", rc);
 		}
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-		ion_client_destroy(pcam->mctl.client);
+		kref_put(&pcam->mctl.refcount, msm_release_ion_client);
 #endif
+		if (g_server_dev.use_count == 0)
+			mutex_unlock(&g_server_dev.server_lock);
 	}
 	mutex_unlock(&pcam->vid_lock);
 	return rc;
@@ -1879,16 +1898,17 @@
 {
 	int rc;
 	D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
-
+	mutex_lock(&g_server_dev.server_lock);
 	rc = nonseekable_open(inode, fp);
 	if (rc < 0) {
 		pr_err("%s: nonseekable_open error %d\n", __func__, rc);
+		mutex_unlock(&g_server_dev.server_lock);
 		return rc;
 	}
 	g_server_dev.use_count++;
 	if (g_server_dev.use_count == 1)
 		msm_queue_init(&g_server_dev.ctrl_q, "control");
-
+	mutex_unlock(&g_server_dev.server_lock);
 	return rc;
 }
 
@@ -1909,6 +1929,29 @@
 	return rc;
 }
 
+static int msm_close_server(struct inode *inode, struct file *fp)
+{
+	mutex_lock(&g_server_dev.server_lock);
+	if (g_server_dev.use_count > 0)
+		g_server_dev.use_count--;
+	mutex_unlock(&g_server_dev.server_lock);
+	if (g_server_dev.use_count == 0) {
+		if (g_server_dev.pcam_active) {
+			struct v4l2_event v4l2_ev;
+			mutex_lock(&g_server_dev.server_lock);
+
+			v4l2_ev.type = V4L2_EVENT_PRIVATE_START
+				+ MSM_CAM_APP_NOTIFY_ERROR_EVENT;
+			ktime_get_ts(&v4l2_ev.timestamp);
+			v4l2_event_queue(
+				g_server_dev.pcam_active->pvdev, &v4l2_ev);
+		}
+		msm_queue_drain(&g_server_dev.ctrl_q, list_control);
+	}
+	return 0;
+}
+
+
 static long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
 		unsigned int cmd, unsigned long evt)
 {
@@ -2147,10 +2190,19 @@
 	spin_lock_init(&config_cam->p_mctl->sync.pmem_stats_spinlock);
 
 	config_cam->p_mctl->config_device = config_cam;
+	kref_get(&config_cam->p_mctl->refcount);
 	fp->private_data = config_cam;
 	return rc;
 }
 
+static int msm_close_config(struct inode *node, struct file *f)
+{
+	struct msm_cam_config_dev *config_cam = f->private_data;
+	D("%s Decrementing ref count of config node ", __func__);
+	kref_put(&config_cam->p_mctl->refcount, msm_release_ion_client);
+	return 0;
+}
+
 static struct v4l2_file_operations g_msm_fops = {
 	.owner   = THIS_MODULE,
 	.open	= msm_open,
@@ -2169,6 +2221,7 @@
 	.open  = msm_open_server,
 	.poll  = msm_poll_server,
 	.unlocked_ioctl = msm_ioctl_server,
+	.release = msm_close_server,
 };
 
 static const struct file_operations msm_fops_config = {
@@ -2177,6 +2230,7 @@
 	.poll  = msm_poll_config,
 	.unlocked_ioctl = msm_ioctl_config,
 	.mmap	= msm_mmap_config,
+	.release = msm_close_config,
 };
 
 int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
@@ -2294,6 +2348,7 @@
 		return rc;
 	}
 
+	mutex_init(&g_server_dev.server_lock);
 	g_server_dev.pcam_active = NULL;
 	g_server_dev.camera_info.num_cameras = 0;
 	atomic_set(&g_server_dev.number_pcam_active, 0);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 55c0da1..c90ab44 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -239,6 +239,7 @@
 	struct pm_qos_request_list pm_qos_req_list;
 	struct msm_mctl_pp_info pp_info;
 	struct ion_client *client;
+	struct kref refcount;
 	/* VFE output mode.
 	* Used to interpret the Primary/Secondary messages
 	* to preview/video/main/thumbnail image types*/
@@ -409,6 +410,7 @@
 	struct msm_isp_ops *isp_subdev[MSM_MAX_CAMERA_CONFIGS];
 	/* info of MCTL nodes successfully probed*/
 	struct msm_mctl_node_info mctl_node_info;
+	struct mutex server_lock;
 };
 
 /* camera server related functions */
@@ -525,6 +527,7 @@
 			int image_mode, struct msm_frame_buffer *buf);
 int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
 					void __user *arg);
+void msm_release_ion_client(struct kref *ref);
 #endif /* __KERNEL__ */
 
 #endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 54458d1..492bcce 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -890,7 +890,7 @@
 		return rc;
 	}
 	pcam_inst->vbqueue_initialized = 0;
-
+	kref_get(&pcam->mctl.refcount);
 	f->private_data = &pcam_inst->eventHandle;
 
 	D("f->private_data = 0x%x, pcam = 0x%x\n",
@@ -961,6 +961,7 @@
 	v4l2_fh_exit(&pcam_inst->eventHandle);
 
 	kfree(pcam_inst);
+	kref_put(&pcam->mctl.refcount, msm_release_ion_client);
 	f->private_data = NULL;
 	mutex_unlock(&pcam->mctl_node.dev_lock);
 	D("%s : X ", __func__);
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index e3d9d2d..6c52e21 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -699,7 +699,8 @@
 }
 
 static long venc_set_h264_intra_period(struct video_client_ctx *client_ctx,
-		__s32 period) {
+		__s32 period)
+{
 	struct vcd_property_i_period vcd_property_i_period;
 	struct vcd_property_codec vcd_property_codec;
 	struct vcd_property_hdr vcd_property_hdr;
@@ -726,7 +727,7 @@
 	vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
 
 	vcd_property_i_period.p_frames = period - 1;
-	vcd_property_i_period.b_frames = 1;
+	vcd_property_i_period.b_frames = 0;
 
 	rc = vcd_set_property(client_ctx->vcd_handle,
 				&vcd_property_hdr, &vcd_property_i_period);
@@ -740,6 +741,47 @@
 	return rc;
 }
 
+static long venc_get_h264_intra_period(struct video_client_ctx *client_ctx,
+		__s32 *period)
+{
+	struct vcd_property_i_period vcd_property_i_period;
+	struct vcd_property_codec vcd_property_codec;
+	struct vcd_property_hdr vcd_property_hdr;
+	int rc = 0;
+
+	vcd_property_hdr.prop_id = VCD_I_CODEC;
+	vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
+
+	rc = vcd_get_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_codec);
+
+	if (rc < 0) {
+		WFD_MSG_ERR("Error getting codec property\n");
+		goto err;
+	}
+
+	if (vcd_property_codec.codec != VCD_CODEC_H264) {
+		rc = -ENOTSUPP;
+		WFD_MSG_ERR("Control not supported for non H264 codec\n");
+		goto err;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_INTRA_PERIOD;
+	vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
+
+	rc = vcd_get_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_i_period);
+
+	if (rc < 0) {
+		WFD_MSG_ERR("Error getting intra period\n");
+		goto err;
+	}
+
+	*period = vcd_property_i_period.p_frames + 1;
+err:
+	return rc;
+}
+
 static long venc_request_frame(struct video_client_ctx *client_ctx, __s32 type)
 {
 	struct vcd_property_req_i_frame vcd_property_req_i_frame;
@@ -950,6 +992,212 @@
 	return rc;
 }
 
+static long venc_set_qp_value(struct video_client_ctx *client_ctx,
+		__s32 frametype, __s32 qp)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_session_qp vcd_property_session_qp;
+	int rc = 0;
+
+	if (!client_ctx) {
+		WFD_MSG_ERR("Invalid parameters\n");
+		return -EINVAL;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_SESSION_QP;
+	vcd_property_hdr.sz = sizeof(vcd_property_session_qp);
+
+	rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&vcd_property_session_qp);
+
+	if (rc) {
+		WFD_MSG_ERR("Failed to get session qp\n");
+		goto err;
+	}
+
+	switch (frametype) {
+	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+		vcd_property_session_qp.i_frame_qp = qp;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+		vcd_property_session_qp.p_frame_qp = qp;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+		vcd_property_session_qp.b_frame_qp = qp;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+		rc = -ENOTSUPP;
+		goto err;
+	default:
+		rc = -EINVAL;
+		goto err;
+	}
+
+
+	rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&vcd_property_session_qp);
+
+	if (rc) {
+		WFD_MSG_ERR("Failed to set session qp\n");
+		goto err;
+	}
+err:
+	return rc;
+}
+
+static long venc_get_qp_value(struct video_client_ctx *client_ctx,
+		__s32 frametype, __s32 *qp)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_session_qp vcd_property_session_qp;
+	int rc = 0;
+
+	if (!client_ctx) {
+		WFD_MSG_ERR("Invalid parameters\n");
+		return -EINVAL;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_SESSION_QP;
+	vcd_property_hdr.sz = sizeof(vcd_property_session_qp);
+
+	rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&vcd_property_session_qp);
+
+	if (rc) {
+		WFD_MSG_ERR("Failed to get session qp\n");
+		goto err;
+	}
+
+	switch (frametype) {
+	case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+		*qp = vcd_property_session_qp.i_frame_qp;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+		*qp = vcd_property_session_qp.p_frame_qp;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+		*qp = vcd_property_session_qp.b_frame_qp;
+		break;
+	default:
+		rc = -EINVAL;
+		goto err;
+	}
+
+err:
+	return rc;
+}
+
+static long venc_set_qp_range(struct video_client_ctx *client_ctx,
+		__s32 type, __s32 qp)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_qp_range vcd_property_qp_range;
+	int rc = 0;
+
+	if (!client_ctx) {
+		WFD_MSG_ERR("Invalid parameters\n");
+		return -EINVAL;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_QP_RANGE;
+	vcd_property_hdr.sz = sizeof(vcd_property_qp_range);
+
+	rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&vcd_property_qp_range);
+
+	if (rc) {
+		WFD_MSG_ERR("Failed to get qp range\n");
+		goto err;
+	}
+
+	switch (type) {
+	case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+		vcd_property_qp_range.min_qp = qp;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+		vcd_property_qp_range.max_qp = qp;
+		break;
+	default:
+		rc = -EINVAL;
+		goto err;
+	}
+
+	rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&vcd_property_qp_range);
+
+	if (rc) {
+		WFD_MSG_ERR("Failed to set qp range\n");
+		goto err;
+	}
+err:
+	return rc;
+}
+
+static long venc_get_qp_range(struct video_client_ctx *client_ctx,
+		__s32 type, __s32 *qp)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_qp_range vcd_property_qp_range;
+	int rc = 0;
+
+	if (!client_ctx) {
+		WFD_MSG_ERR("Invalid parameters\n");
+		return -EINVAL;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_QP_RANGE;
+	vcd_property_hdr.sz = sizeof(vcd_property_qp_range);
+
+	rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&vcd_property_qp_range);
+
+	if (rc) {
+		WFD_MSG_ERR("Failed to get qp range\n");
+		goto err;
+	}
+
+	switch (type) {
+	case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+		*qp = vcd_property_qp_range.min_qp;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+		*qp = vcd_property_qp_range.max_qp;
+		break;
+	default:
+		rc = -EINVAL;
+		goto err;
+	}
+
+	rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&vcd_property_qp_range);
+
+	if (rc) {
+		WFD_MSG_ERR("Failed to set qp range\n");
+		goto err;
+	}
+err:
+	return rc;
+}
+
 static long venc_alloc_input_buffer(struct v4l2_subdev *sd, void *arg)
 {
 	struct mem_region *mregion = arg;
@@ -1220,6 +1468,25 @@
 	case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
 		rc = venc_request_frame(client_ctx, ctrl->value);
 		break;
+	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+		rc = venc_set_qp_value(client_ctx, ctrl->id, ctrl->value);
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+		rc = venc_set_qp_range(client_ctx, ctrl->id, ctrl->value);
+		break;
 	default:
 		WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
 		rc = -ENOTSUPP;
@@ -1248,6 +1515,28 @@
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
 		rc = venc_get_codec_profile(client_ctx, ctrl->id, &ctrl->value);
 		break;
+	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+		rc = venc_get_h264_intra_period(client_ctx, &ctrl->value);
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+		rc = venc_get_qp_value(client_ctx, ctrl->id, &ctrl->value);
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+		rc = venc_get_qp_range(client_ctx, ctrl->id, &ctrl->value);
+		break;
 	default:
 		WFD_MSG_ERR("Get property not suported: %d\n", ctrl->id);
 		rc = -ENOTSUPP;
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.c b/drivers/media/video/msm/wfd/vsg-subdev.c
index 53b6e20..8e385a4 100644
--- a/drivers/media/video/msm/wfd/vsg-subdev.c
+++ b/drivers/media/video/msm/wfd/vsg-subdev.c
@@ -76,10 +76,29 @@
 	}
 }
 
+static void vsg_encode_helper_func(struct work_struct *task)
+{
+	struct vsg_encode_work *work =
+		container_of(task, struct vsg_encode_work, work);
+
+	/*
+	 * Note: don't need to lock for context below as we only
+	 * access fields that are "static".
+	 */
+	int rc = vsg_encode_frame(work->context, work->buf);
+	if (rc < 0) {
+		mutex_lock(&work->context->mutex);
+		work->context->state = VSG_STATE_ERROR;
+		mutex_unlock(&work->context->mutex);
+	}
+	kfree(work);
+}
+
 static void vsg_work_func(struct work_struct *task)
 {
 	struct vsg_work *work =
 		container_of(task, struct vsg_work, work);
+	struct vsg_encode_work *encode_work;
 	struct vsg_context *context = work->context;
 	struct vsg_buf_info *buf_info = NULL, *temp = NULL;
 	int rc = 0;
@@ -88,8 +107,9 @@
 	if (list_empty(&context->free_queue.node)) {
 		WFD_MSG_DBG("%s: queue empty doing nothing\n", __func__);
 		goto err_skip_encode;
-	} else if (context->stopped) {
-		WFD_MSG_DBG("%s: vsg is stopped doing nothing\n", __func__);
+	} else if (context->state != VSG_STATE_STARTED) {
+		WFD_MSG_DBG("%s: vsg is stopped or in error state "
+				"doing nothing\n", __func__);
 		goto err_skip_encode;
 	}
 
@@ -114,18 +134,46 @@
 		}
 	}
 
-	mutex_unlock(&context->mutex);
-	rc = vsg_encode_frame(context, buf_info);
-	if (rc < 0) {
-		WFD_MSG_ERR("frame encode failed");
-		goto err_encode_fail;
+	encode_work = kmalloc(sizeof(*encode_work), GFP_KERNEL);
+	encode_work->buf = buf_info;
+	encode_work->context = context;
+	INIT_WORK(&encode_work->work, vsg_encode_helper_func);
+	rc = queue_work(context->work_queue, &encode_work->work);
+	if (!rc) {
+		WFD_MSG_ERR("Queueing buffer for encode failed\n");
+		kfree(encode_work);
+		encode_work = NULL;
+		goto err_queue_encode_fail;
 	}
-	mutex_lock(&context->mutex);
+
+	buf_info->flags |= VSG_BUF_BEING_ENCODED;
+	if (!(buf_info->flags & VSG_NEVER_SET_LAST_BUFFER)) {
+		bool is_same_buffer = context->last_buffer &&
+			mdp_buf_info_equals(
+				&context->last_buffer->mdp_buf_info,
+				&buf_info->mdp_buf_info);
+
+		if (!context->last_buffer || !is_same_buffer) {
+			struct vsg_buf_info *old_last_buffer =
+				context->last_buffer;
+			bool last_buf_with_us = old_last_buffer &&
+				!(old_last_buffer->flags &
+					VSG_BUF_BEING_ENCODED);
+
+			if (old_last_buffer && last_buf_with_us) {
+				vsg_release_input_buffer(context,
+					old_last_buffer);
+				kfree(old_last_buffer);
+			}
+
+			vsg_set_last_buffer(context, buf_info);
+		}
+	}
 
 	list_add_tail(&buf_info->node, &context->busy_queue.node);
 err_skip_encode:
 	mutex_unlock(&context->mutex);
-err_encode_fail:
+err_queue_encode_fail:
 	kfree(work);
 }
 
@@ -139,7 +187,7 @@
 
 	mutex_lock(&context->mutex);
 
-	if (context->stopped)
+	if (context->state != VSG_STATE_STARTED)
 		goto err_locked;
 
 	if (list_empty(&context->free_queue.node)
@@ -256,7 +304,7 @@
 	context->last_buffer = context->regen_buffer = NULL;
 	context->send_regen_buffer = false;
 	context->mode = DEFAULT_MODE;
-	context->stopped = false;
+	context->state = VSG_STATE_NONE;
 	mutex_init(&context->mutex);
 
 	sd->dev_priv = context;
@@ -287,6 +335,16 @@
 	}
 
 	context = (struct vsg_context *)sd->dev_priv;
+
+	if (context->state == VSG_STATE_STARTED) {
+		WFD_MSG_ERR("VSG not stopped, start not allowed\n");
+		return -EINPROGRESS;
+	} else if (context->state == VSG_STATE_ERROR) {
+		WFD_MSG_ERR("VSG in error state, not allowed to restart\n");
+		return -ENOTRECOVERABLE;
+	}
+
+	context->state = VSG_STATE_STARTED;
 	mod_timer(&context->threshold_timer, jiffies +
 			nsecs_to_jiffies(context->max_frame_interval));
 	return 0;
@@ -304,7 +362,7 @@
 	context = (struct vsg_context *)sd->dev_priv;
 
 	mutex_lock(&context->mutex);
-	context->stopped = true;
+	context->state = VSG_STATE_STOPPED;
 	{ /*delete pending buffers as we're not going to encode them*/
 		struct list_head *pos, *next;
 		list_for_each_safe(pos, next, &context->free_queue.node) {
@@ -371,10 +429,10 @@
 			if (!is_last_buffer && !is_regen_buffer &&
 				!(temp->flags & VSG_NEVER_RELEASE)) {
 				vsg_release_input_buffer(context, temp);
+				kfree(temp);
 			}
 
 			list_del(&temp->node);
-			kfree(temp);
 		}
 	}
 
@@ -436,27 +494,26 @@
 	WFD_MSG_DBG("Return frame with paddr %p\n",
 			(void *)buf_info->mdp_buf_info.paddr);
 
+	if (!expected_buffer) {
+		WFD_MSG_ERR("Unexpectedly received buffer from enc with "
+			"paddr %p\n", (void *)buf_info->mdp_buf_info.paddr);
+		goto return_ip_buf_bad_buf;
+	}
+
+	expected_buffer->flags &= ~VSG_BUF_BEING_ENCODED;
 	if (mdp_buf_info_equals(&expected_buffer->mdp_buf_info,
 				&buf_info->mdp_buf_info)) {
-		list_del(&expected_buffer->node);
-
-		if (!(expected_buffer->flags & VSG_NEVER_SET_LAST_BUFFER)) {
-			bool is_same_buffer = context->last_buffer &&
-				mdp_buf_info_equals(
+		bool is_same_buffer = context->last_buffer &&
+			mdp_buf_info_equals(
 					&context->last_buffer->mdp_buf_info,
 					&expected_buffer->mdp_buf_info);
 
-			if (!context->last_buffer || !is_same_buffer) {
-				struct vsg_buf_info *old_last_buffer =
-					context->last_buffer;
-				if (context->last_buffer)
-					vsg_release_input_buffer(context,
-							context->last_buffer);
-				vsg_set_last_buffer(context, expected_buffer);
-				kfree(old_last_buffer);
-			}
-		} else
-			WFD_MSG_WARN("Couldn't set the last buffer\n");
+		list_del(&expected_buffer->node);
+		if (!is_same_buffer &&
+			!(expected_buffer->flags & VSG_NEVER_RELEASE)) {
+			vsg_release_input_buffer(context, expected_buffer);
+			kfree(expected_buffer);
+		}
 	} else {
 		WFD_MSG_ERR("Returned buffer %p is not latest buffer, "
 				"expected %p\n",
@@ -497,7 +554,7 @@
 	*regen_buffer = *buf_info;
 	regen_buffer->flags = VSG_NEVER_RELEASE | VSG_NEVER_SET_LAST_BUFFER;
 	context->regen_buffer = regen_buffer;
-	WFD_MSG_ERR("setting buffer with paddr %p as scratch buffer\n",
+	WFD_MSG_DBG("setting buffer with paddr %p as scratch buffer\n",
 			(void *)regen_buffer->mdp_buf_info.paddr);
 	mutex_unlock(&context->mutex);
 set_scratch_buf_err_bad_param:
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.h b/drivers/media/video/msm/wfd/vsg-subdev.h
index 1db45e8..826105c 100644
--- a/drivers/media/video/msm/wfd/vsg-subdev.h
+++ b/drivers/media/video/msm/wfd/vsg-subdev.h
@@ -26,6 +26,7 @@
 enum vsg_flags {
 	VSG_NEVER_RELEASE = 1<<0,
 	VSG_NEVER_SET_LAST_BUFFER = 1<<1,
+	VSG_BUF_BEING_ENCODED = 1<<2,
 };
 
 enum vsg_modes {
@@ -33,6 +34,13 @@
 	VSG_MODE_VFR,
 };
 
+enum vsg_states {
+	VSG_STATE_NONE,
+	VSG_STATE_STARTED,
+	VSG_STATE_STOPPED,
+	VSG_STATE_ERROR
+};
+
 struct vsg_buf_info {
 	struct mdp_buf_info mdp_buf_info;
 	struct timespec time;
@@ -58,7 +66,7 @@
 	struct vsg_buf_info *last_buffer, *regen_buffer;
 	bool send_regen_buffer;
 	int mode;
-	bool stopped;
+	int state;
 };
 
 struct vsg_work {
@@ -66,6 +74,12 @@
 	struct work_struct work;
 };
 
+struct vsg_encode_work {
+	struct vsg_buf_info *buf;
+	struct vsg_context *context;
+	struct work_struct work;
+};
+
 #define VSG_OPEN  _IO(VSG_MAGIC_IOCTL, 1)
 #define VSG_CLOSE  _IO(VSG_MAGIC_IOCTL, 2)
 #define VSG_START  _IO(VSG_MAGIC_IOCTL, 3)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 77ac845..54e1b9a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -879,6 +879,16 @@
 	  voltage leaves the accepatable range which then calls a notifier call
 	  chain.
 
+config WCD9304_CODEC
+        tristate "WCD9304 Codec"
+        select SLIMBUS
+        select MFD_CORE
+        default n
+        help
+          Enables the WCD9304 core driver. The core driver provides
+          read/write capability to registers which are part of the
+          WCD9304 core and gives the ability to use the WCD9304 codec.
+
 config WCD9310_CODEC
         tristate "WCD9310 Codec"
         select SLIMBUS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c8fcf5f..fd887ea 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -69,7 +69,8 @@
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
 obj-$(CONFIG_MCP_UCB1200_TS)	+= ucb1x00-ts.o
 
-obj-$(CONFIG_WCD9310_CODEC)       += wcd9310-core.o wcd9310-irq.o wcd9310-slimslave.o
+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
 
 ifeq ($(CONFIG_SA1100_ASSABET),y)
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-assabet.o
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 8049975..66b98a1 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -754,6 +754,11 @@
 	}
 
 	if (version != PM8XXX_VERSION_8917) {
+		if (pdata->pwm_pdata) {
+			pwm_cell.platform_data = pdata->pwm_pdata;
+			pwm_cell.pdata_size =
+				sizeof(struct pm8xxx_pwm_platform_data);
+		}
 		ret = mfd_add_devices(pmic->dev, 0, &pwm_cell, 1, NULL, 0);
 		if (ret) {
 			pr_err("Failed to add pwm subdevice ret=%d\n", ret);
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index 05f02c4..022cfb6 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -64,6 +64,7 @@
 #define SSBI_REG_ADDR_LPG_BANK_EN	0x144
 #define SSBI_REG_ADDR_LPG_LUT_CFG0	0x145
 #define SSBI_REG_ADDR_LPG_LUT_CFG1	0x146
+#define SSBI_REG_ADDR_LPG_TEST		0x147
 
 /* LPG Control 0 */
 #define PM8XXX_PWM_1KHZ_COUNT_MASK	0xF0
@@ -137,6 +138,10 @@
 /* LPG LUT_CFG1 */
 #define PM8XXX_PWM_LUT_READ			0x40
 
+/* TEST */
+#define PM8XXX_PWM_DTEST_MASK		0x38
+#define PM8XXX_PWM_DTEST_SHIFT		3
+#define PM8XXX_PWM_DTEST_BANK_MASK	0x07
 
 /*
  * PWM Frequency = Clock Frequency / (N * T)
@@ -200,6 +205,7 @@
 	int			irq;
 	struct pm8xxx_pwm_chip	*chip;
 	int			bypass_lut;
+	int			dtest_mode_supported;
 };
 
 struct pm8xxx_pwm_chip {
@@ -638,6 +644,28 @@
 	return rc;
 }
 
+static int pm8xxx_pwm_set_dtest(struct pwm_device *pwm, int enable)
+{
+	int	rc;
+	u8	reg;
+
+	reg = pwm->pwm_id & PM8XXX_PWM_DTEST_BANK_MASK;
+
+	if (enable) {
+		/* Observe LPG_OUT on DTEST1*/
+		reg |= (1 << PM8XXX_PWM_DTEST_SHIFT) &
+				PM8XXX_PWM_DTEST_MASK;
+	}
+
+	rc = pm8xxx_writeb(pwm->chip->dev->parent,
+			SSBI_REG_ADDR_LPG_TEST, reg);
+	if (rc)
+		pr_err("pm8xxx_write(DTEST=0x%x) failed: rc=%d\n",
+							reg, rc);
+
+	return rc;
+}
+
 /* APIs */
 /**
  * pwm_request - request a PWM device
@@ -785,6 +813,8 @@
 		rc = -EINVAL;
 	} else {
 		if (pwm_chip->is_lpg_supported) {
+			if (pwm->dtest_mode_supported)
+				pm8xxx_pwm_set_dtest(pwm, 1);
 			rc = pm8xxx_pwm_bank_enable(pwm, 1);
 			pm8xxx_pwm_bank_sel(pwm);
 			pm8xxx_pwm_start(pwm, 1, 0);
@@ -811,6 +841,8 @@
 	mutex_lock(&pwm->chip->pwm_mutex);
 	if (pwm->in_use) {
 		if (pwm_chip->is_lpg_supported) {
+			if (pwm->dtest_mode_supported)
+				pm8xxx_pwm_set_dtest(pwm, 0);
 			pm8xxx_pwm_bank_sel(pwm);
 			pm8xxx_pwm_start(pwm, 0, 0);
 			pm8xxx_pwm_bank_enable(pwm, 0);
@@ -1030,11 +1062,17 @@
 
 	mutex_lock(&pwm->chip->pwm_mutex);
 	if (start) {
+		if (pwm->dtest_mode_supported)
+			pm8xxx_pwm_set_dtest(pwm, 1);
+
 		pm8xxx_pwm_bank_enable(pwm, 1);
 
 		pm8xxx_pwm_bank_sel(pwm);
 		pm8xxx_pwm_start(pwm, 1, 1);
 	} else {
+		if (pwm->dtest_mode_supported)
+			pm8xxx_pwm_set_dtest(pwm, 0);
+
 		pm8xxx_pwm_bank_sel(pwm);
 		pm8xxx_pwm_start(pwm, 0, 0);
 
@@ -1324,8 +1362,9 @@
 
 static int __devinit pm8xxx_pwm_probe(struct platform_device *pdev)
 {
+	const struct pm8xxx_pwm_platform_data *pdata = pdev->dev.platform_data;
 	struct pm8xxx_pwm_chip	*chip;
-	int	i;
+	int	i, dtest_channel;
 	enum pm8xxx_version version;
 
 	chip = kzalloc(sizeof *chip, GFP_KERNEL);
@@ -1334,6 +1373,11 @@
 		return -ENOMEM;
 	}
 
+	if (pdata != NULL)
+		dtest_channel = pdata->dtest_channel;
+	else
+		dtest_channel = -1;
+
 	mutex_init(&chip->pwm_mutex);
 
 	chip->dev = &pdev->dev;
@@ -1374,6 +1418,8 @@
 	for (i = 0; i < chip->pwm_channels; i++) {
 		chip->pwm_dev[i].pwm_id = i;
 		chip->pwm_dev[i].chip = chip;
+		if (i == dtest_channel)
+			chip->pwm_dev[i].dtest_mode_supported = 1;
 	}
 
 	platform_set_drvdata(pdev, chip);
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
deleted file mode 100644
index d1d9132..0000000
--- a/drivers/mfd/wcd9310-core.c
+++ /dev/null
@@ -1,1151 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
-#include <linux/mfd/wcd9310/pdata.h>
-#include <linux/mfd/wcd9310/registers.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/debugfs.h>
-#include <linux/regulator/consumer.h>
-#include <linux/i2c.h>
-#include <sound/soc.h>
-
-#define TABLA_SLIM_GLA_MAX_RETRIES 5
-#define TABLA_REGISTER_START_OFFSET 0x800
-#define TABLA_SLIM_RW_MAX_TRIES 3
-
-#define MAX_TABLA_DEVICE	4
-#define TABLA_I2C_MODE	0x03
-
-struct tabla_i2c {
-	struct i2c_client *client;
-	struct i2c_msg xfer_msg[2];
-	struct mutex xfer_lock;
-	int mod_id;
-};
-
-struct tabla_i2c tabla_modules[MAX_TABLA_DEVICE];
-static int tabla_intf;
-
-static int tabla_read(struct tabla *tabla, unsigned short reg,
-		       int bytes, void *dest, bool interface_reg)
-{
-	int ret;
-	u8 *buf = dest;
-
-	if (bytes <= 0) {
-		dev_err(tabla->dev, "Invalid byte read length %d\n", bytes);
-		return -EINVAL;
-	}
-
-	ret = tabla->read_dev(tabla, reg, bytes, dest, interface_reg);
-	if (ret < 0) {
-		dev_err(tabla->dev, "Tabla read failed\n");
-		return ret;
-	} else
-		dev_dbg(tabla->dev, "Read 0x%02x from R%d(0x%x)\n",
-			 *buf, reg, reg);
-
-	return 0;
-}
-int tabla_reg_read(struct tabla *tabla, unsigned short reg)
-{
-	u8 val;
-	int ret;
-
-	mutex_lock(&tabla->io_lock);
-	ret = tabla_read(tabla, reg, 1, &val, false);
-	mutex_unlock(&tabla->io_lock);
-
-	if (ret < 0)
-		return ret;
-	else
-		return val;
-}
-EXPORT_SYMBOL_GPL(tabla_reg_read);
-
-static int tabla_write(struct tabla *tabla, unsigned short reg,
-			int bytes, void *src, bool interface_reg)
-{
-	u8 *buf = src;
-
-	if (bytes <= 0) {
-		pr_err("%s: Error, invalid write length\n", __func__);
-		return -EINVAL;
-	}
-
-	dev_dbg(tabla->dev, "Write %02x to R%d(0x%x)\n",
-		 *buf, reg, reg);
-
-	return tabla->write_dev(tabla, reg, bytes, src, interface_reg);
-}
-
-int tabla_reg_write(struct tabla *tabla, unsigned short reg,
-		     u8 val)
-{
-	int ret;
-
-	mutex_lock(&tabla->io_lock);
-	ret = tabla_write(tabla, reg, 1, &val, false);
-	mutex_unlock(&tabla->io_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tabla_reg_write);
-
-static u8 tabla_pgd_la;
-static u8 tabla_inf_la;
-
-int tabla_get_logical_addresses(u8 *pgd_la, u8 *inf_la)
-{
-	*pgd_la = tabla_pgd_la;
-	*inf_la = tabla_inf_la;
-	return 0;
-
-}
-EXPORT_SYMBOL_GPL(tabla_get_logical_addresses);
-
-int tabla_interface_reg_read(struct tabla *tabla, unsigned short reg)
-{
-	u8 val;
-	int ret;
-
-	mutex_lock(&tabla->io_lock);
-	ret = tabla_read(tabla, reg, 1, &val, true);
-	mutex_unlock(&tabla->io_lock);
-
-	if (ret < 0)
-		return ret;
-	else
-		return val;
-}
-EXPORT_SYMBOL_GPL(tabla_interface_reg_read);
-
-int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg,
-		     u8 val)
-{
-	int ret;
-
-	mutex_lock(&tabla->io_lock);
-	ret = tabla_write(tabla, reg, 1, &val, true);
-	mutex_unlock(&tabla->io_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tabla_interface_reg_write);
-
-int tabla_bulk_read(struct tabla *tabla, unsigned short reg,
-		     int count, u8 *buf)
-{
-	int ret;
-
-	mutex_lock(&tabla->io_lock);
-
-	ret = tabla_read(tabla, reg, count, buf, false);
-
-	mutex_unlock(&tabla->io_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tabla_bulk_read);
-
-int tabla_bulk_write(struct tabla *tabla, unsigned short reg,
-		     int count, u8 *buf)
-{
-	int ret;
-
-	mutex_lock(&tabla->io_lock);
-
-	ret = tabla_write(tabla, reg, count, buf, false);
-
-	mutex_unlock(&tabla->io_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tabla_bulk_write);
-
-static int tabla_slim_read_device(struct tabla *tabla, unsigned short reg,
-				int bytes, void *dest, bool interface)
-{
-	int ret;
-	struct slim_ele_access msg;
-	int slim_read_tries = TABLA_SLIM_RW_MAX_TRIES;
-	msg.start_offset = TABLA_REGISTER_START_OFFSET + reg;
-	msg.num_bytes = bytes;
-	msg.comp = NULL;
-
-	while (1) {
-		mutex_lock(&tabla->xfer_lock);
-		ret = slim_request_val_element(interface ?
-					       tabla->slim_slave : tabla->slim,
-					       &msg, dest, bytes);
-		mutex_unlock(&tabla->xfer_lock);
-		if (likely(ret == 0) || (--slim_read_tries == 0))
-			break;
-		usleep_range(5000, 5000);
-	}
-
-	if (ret)
-		pr_err("%s: Error, Tabla read failed (%d)\n", __func__, ret);
-
-	return ret;
-}
-/* Interface specifies whether the write is to the interface or general
- * registers.
- */
-static int tabla_slim_write_device(struct tabla *tabla, unsigned short reg,
-				   int bytes, void *src, bool interface)
-{
-	int ret;
-	struct slim_ele_access msg;
-	int slim_write_tries = TABLA_SLIM_RW_MAX_TRIES;
-	msg.start_offset = TABLA_REGISTER_START_OFFSET + reg;
-	msg.num_bytes = bytes;
-	msg.comp = NULL;
-
-	while (1) {
-		mutex_lock(&tabla->xfer_lock);
-		ret = slim_change_val_element(interface ?
-					      tabla->slim_slave : tabla->slim,
-					      &msg, src, bytes);
-		mutex_unlock(&tabla->xfer_lock);
-		if (likely(ret == 0) || (--slim_write_tries == 0))
-			break;
-		usleep_range(5000, 5000);
-	}
-
-	if (ret)
-		pr_err("%s: Error, Tabla write failed (%d)\n", __func__, ret);
-
-	return ret;
-}
-
-static struct mfd_cell tabla_devs[] = {
-	{
-		.name = "tabla_codec",
-	},
-};
-
-static struct mfd_cell tabla1x_devs[] = {
-	{
-		.name = "tabla1x_codec",
-	},
-};
-
-static void tabla_bring_up(struct tabla *tabla)
-{
-	tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x4);
-	tabla_reg_write(tabla, TABLA_A_CDC_CTL, 0);
-	usleep_range(5000, 5000);
-	tabla_reg_write(tabla, TABLA_A_CDC_CTL, 3);
-	tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 3);
-}
-
-static void tabla_bring_down(struct tabla *tabla)
-{
-	tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x7);
-	tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x6);
-	tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0xe);
-	tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x8);
-}
-
-static int tabla_reset(struct tabla *tabla)
-{
-	int ret;
-
-	if (tabla->reset_gpio) {
-		ret = gpio_request(tabla->reset_gpio, "CDC_RESET");
-		if (ret) {
-			pr_err("%s: Failed to request gpio %d\n", __func__,
-				tabla->reset_gpio);
-			tabla->reset_gpio = 0;
-			return ret;
-		}
-
-		gpio_direction_output(tabla->reset_gpio, 1);
-		msleep(20);
-		gpio_direction_output(tabla->reset_gpio, 0);
-		msleep(20);
-		gpio_direction_output(tabla->reset_gpio, 1);
-		msleep(20);
-	}
-	return 0;
-}
-
-static void tabla_free_reset(struct tabla *tabla)
-{
-	if (tabla->reset_gpio) {
-		gpio_free(tabla->reset_gpio);
-		tabla->reset_gpio = 0;
-	}
-}
-
-struct tabla_regulator {
-	const char *name;
-	int min_uV;
-	int max_uV;
-	int optimum_uA;
-	struct regulator *regulator;
-};
-
-
-/*
- *	format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
- *
- *	<POWER_SUPPLY_PIN_NAME> from Tabla objective spec
-*/
-
-#define  TABLA_CDC_VDDA_CP_CUR_MAX	500000
-#define  TABLA_CDC_VDDA_RX_CUR_MAX	20000
-#define  TABLA_CDC_VDDA_TX_CUR_MAX	20000
-#define  TABLA_VDDIO_CDC_CUR_MAX	5000
-
-#define  TABLA_VDDD_CDC_D_CUR_MAX	5000
-#define  TABLA_VDDD_CDC_A_CUR_MAX	5000
-
-static struct tabla_regulator tabla_regulators[] = {
-	{
-		.name = "CDC_VDD_CP",
-		.min_uV = 1800000,
-		.max_uV = 1800000,
-		.optimum_uA = TABLA_CDC_VDDA_CP_CUR_MAX,
-	},
-	{
-		.name = "CDC_VDDA_RX",
-		.min_uV = 1800000,
-		.max_uV = 1800000,
-		.optimum_uA = TABLA_CDC_VDDA_RX_CUR_MAX,
-	},
-	{
-		.name = "CDC_VDDA_TX",
-		.min_uV = 1800000,
-		.max_uV = 1800000,
-		.optimum_uA = TABLA_CDC_VDDA_TX_CUR_MAX,
-	},
-	{
-		.name = "VDDIO_CDC",
-		.min_uV = 1800000,
-		.max_uV = 1800000,
-		.optimum_uA = TABLA_VDDIO_CDC_CUR_MAX,
-	},
-	{
-		.name = "VDDD_CDC_D",
-		.min_uV = 1225000,
-		.max_uV = 1225000,
-		.optimum_uA = TABLA_VDDD_CDC_D_CUR_MAX,
-	},
-	{
-		.name = "CDC_VDDA_A_1P2V",
-		.min_uV = 1225000,
-		.max_uV = 1225000,
-		.optimum_uA = TABLA_VDDD_CDC_A_CUR_MAX,
-	},
-};
-
-static int tabla_device_init(struct tabla *tabla, int irq)
-{
-	int ret;
-	struct mfd_cell *tabla_dev;
-	int tabla_dev_size;
-
-	mutex_init(&tabla->io_lock);
-	mutex_init(&tabla->xfer_lock);
-
-	mutex_init(&tabla->pm_lock);
-	tabla->wlock_holders = 0;
-	tabla->pm_state = TABLA_PM_SLEEPABLE;
-	init_waitqueue_head(&tabla->pm_wq);
-	wake_lock_init(&tabla->wlock, WAKE_LOCK_IDLE, "wcd9310-irq");
-
-	dev_set_drvdata(tabla->dev, tabla);
-
-	tabla_bring_up(tabla);
-
-	ret = tabla_irq_init(tabla);
-	if (ret) {
-		pr_err("IRQ initialization failed\n");
-		goto err;
-	}
-	tabla->version = tabla_reg_read(tabla, TABLA_A_CHIP_VERSION) & 0x1F;
-	pr_info("%s : Tabla version %u initialized\n",
-		__func__, tabla->version);
-
-	if (TABLA_IS_1_X(tabla->version)) {
-		tabla_dev = tabla1x_devs;
-		tabla_dev_size = ARRAY_SIZE(tabla1x_devs);
-	} else {
-		tabla_dev = tabla_devs;
-		tabla_dev_size = ARRAY_SIZE(tabla_devs);
-	}
-	ret = mfd_add_devices(tabla->dev, -1,
-			      tabla_dev, tabla_dev_size,
-			      NULL, 0);
-	if (ret != 0) {
-		dev_err(tabla->dev, "Failed to add children: %d\n", ret);
-		goto err_irq;
-	}
-
-	tabla->version = tabla_reg_read(tabla, TABLA_A_CHIP_VERSION) & 0x1F;
-	pr_info("%s : Tabla version %u initialized\n",
-		__func__, tabla->version);
-
-	return ret;
-err_irq:
-	tabla_irq_exit(tabla);
-err:
-	tabla_bring_down(tabla);
-	wake_lock_destroy(&tabla->wlock);
-	mutex_destroy(&tabla->pm_lock);
-	mutex_destroy(&tabla->io_lock);
-	mutex_destroy(&tabla->xfer_lock);
-	return ret;
-}
-
-static void tabla_device_exit(struct tabla *tabla)
-{
-	tabla_irq_exit(tabla);
-	tabla_bring_down(tabla);
-	tabla_free_reset(tabla);
-	mutex_destroy(&tabla->pm_lock);
-	wake_lock_destroy(&tabla->wlock);
-	mutex_destroy(&tabla->io_lock);
-	mutex_destroy(&tabla->xfer_lock);
-}
-
-
-#ifdef CONFIG_DEBUG_FS
-struct tabla *debugTabla;
-
-static struct dentry *debugfs_tabla_dent;
-static struct dentry *debugfs_peek;
-static struct dentry *debugfs_poke;
-
-static unsigned char read_data;
-
-static int codec_debug_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static int get_parameters(char *buf, long int *param1, int num_of_par)
-{
-	char *token;
-	int base, cnt;
-
-	token = strsep(&buf, " ");
-
-	for (cnt = 0; cnt < num_of_par; cnt++) {
-		if (token != NULL) {
-			if ((token[1] == 'x') || (token[1] == 'X'))
-				base = 16;
-			else
-				base = 10;
-
-			if (strict_strtoul(token, base, &param1[cnt]) != 0)
-				return -EINVAL;
-
-			token = strsep(&buf, " ");
-		} else
-			return -EINVAL;
-	}
-	return 0;
-}
-
-static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
-				size_t count, loff_t *ppos)
-{
-	char lbuf[8];
-
-	snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
-	return simple_read_from_buffer(ubuf, count, ppos, lbuf,
-		strnlen(lbuf, 7));
-}
-
-
-static ssize_t codec_debug_write(struct file *filp,
-	const char __user *ubuf, size_t cnt, loff_t *ppos)
-{
-	char *access_str = filp->private_data;
-	char lbuf[32];
-	int rc;
-	long int param[5];
-
-	if (cnt > sizeof(lbuf) - 1)
-		return -EINVAL;
-
-	rc = copy_from_user(lbuf, ubuf, cnt);
-	if (rc)
-		return -EFAULT;
-
-	lbuf[cnt] = '\0';
-
-	if (!strncmp(access_str, "poke", 6)) {
-		/* write */
-		rc = get_parameters(lbuf, param, 2);
-		if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
-			(rc == 0))
-			tabla_interface_reg_write(debugTabla, param[0],
-				param[1]);
-		else
-			rc = -EINVAL;
-	} else if (!strncmp(access_str, "peek", 6)) {
-		/* read */
-		rc = get_parameters(lbuf, param, 1);
-		if ((param[0] <= 0x3FF) && (rc == 0))
-			read_data = tabla_interface_reg_read(debugTabla,
-				param[0]);
-		else
-			rc = -EINVAL;
-	}
-
-	if (rc == 0)
-		rc = cnt;
-	else
-		pr_err("%s: rc = %d\n", __func__, rc);
-
-	return rc;
-}
-
-static const struct file_operations codec_debug_ops = {
-	.open = codec_debug_open,
-	.write = codec_debug_write,
-	.read = codec_debug_read
-};
-#endif
-
-static int tabla_enable_supplies(struct tabla *tabla)
-{
-	int ret;
-	int i;
-
-	tabla->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
-				   ARRAY_SIZE(tabla_regulators),
-				   GFP_KERNEL);
-	if (!tabla->supplies) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(tabla_regulators); i++)
-		tabla->supplies[i].supply = tabla_regulators[i].name;
-
-	ret = regulator_bulk_get(tabla->dev, ARRAY_SIZE(tabla_regulators),
-				 tabla->supplies);
-	if (ret != 0) {
-		dev_err(tabla->dev, "Failed to get supplies: err = %d\n", ret);
-		goto err_supplies;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(tabla_regulators); i++) {
-		ret = regulator_set_voltage(tabla->supplies[i].consumer,
-			tabla_regulators[i].min_uV, tabla_regulators[i].max_uV);
-		if (ret) {
-			pr_err("%s: Setting regulator voltage failed for "
-				"regulator %s err = %d\n", __func__,
-				tabla->supplies[i].supply, ret);
-			goto err_get;
-		}
-
-		ret = regulator_set_optimum_mode(tabla->supplies[i].consumer,
-			tabla_regulators[i].optimum_uA);
-		if (ret < 0) {
-			pr_err("%s: Setting regulator optimum mode failed for "
-				"regulator %s err = %d\n", __func__,
-				tabla->supplies[i].supply, ret);
-			goto err_get;
-		}
-	}
-
-	ret = regulator_bulk_enable(ARRAY_SIZE(tabla_regulators),
-				    tabla->supplies);
-	if (ret != 0) {
-		dev_err(tabla->dev, "Failed to enable supplies: err = %d\n",
-				ret);
-		goto err_configure;
-	}
-	return ret;
-
-err_configure:
-	for (i = 0; i < ARRAY_SIZE(tabla_regulators); i++) {
-		regulator_set_voltage(tabla->supplies[i].consumer, 0,
-			tabla_regulators[i].max_uV);
-		regulator_set_optimum_mode(tabla->supplies[i].consumer, 0);
-	}
-err_get:
-	regulator_bulk_free(ARRAY_SIZE(tabla_regulators), tabla->supplies);
-err_supplies:
-	kfree(tabla->supplies);
-err:
-	return ret;
-}
-
-static void tabla_disable_supplies(struct tabla *tabla)
-{
-	int i;
-
-	regulator_bulk_disable(ARRAY_SIZE(tabla_regulators),
-				    tabla->supplies);
-	for (i = 0; i < ARRAY_SIZE(tabla_regulators); i++) {
-		regulator_set_voltage(tabla->supplies[i].consumer, 0,
-			tabla_regulators[i].max_uV);
-		regulator_set_optimum_mode(tabla->supplies[i].consumer, 0);
-	}
-	regulator_bulk_free(ARRAY_SIZE(tabla_regulators), tabla->supplies);
-	kfree(tabla->supplies);
-}
-
-int tabla_get_intf_type(void)
-{
-	return tabla_intf;
-}
-EXPORT_SYMBOL_GPL(tabla_get_intf_type);
-
-struct tabla_i2c *get_i2c_tabla_device_info(u16 reg)
-{
-	u16 mask = 0x0f00;
-	int value = 0;
-	struct tabla_i2c *tabla = NULL;
-	value = ((reg & mask) >> 8) & 0x000f;
-	switch (value) {
-	case 0:
-		tabla = &tabla_modules[0];
-		break;
-	case 1:
-		tabla = &tabla_modules[1];
-		break;
-	case 2:
-		tabla = &tabla_modules[2];
-		break;
-	case 3:
-		tabla = &tabla_modules[3];
-		break;
-	default:
-		break;
-	}
-	return tabla;
-}
-
-int tabla_i2c_write_device(u16 reg, u8 *value,
-				u32 bytes)
-{
-
-	struct i2c_msg *msg;
-	int ret = 0;
-	u8 reg_addr = 0;
-	u8 data[bytes + 1];
-	struct tabla_i2c *tabla;
-
-	tabla = get_i2c_tabla_device_info(reg);
-	if (tabla == NULL || tabla->client == NULL) {
-		pr_err("failed to get device info\n");
-		return -ENODEV;
-	}
-	reg_addr = (u8)reg;
-	msg = &tabla->xfer_msg[0];
-	msg->addr = tabla->client->addr;
-	msg->len = bytes + 1;
-	msg->flags = 0;
-	data[0] = reg;
-	data[1] = *value;
-	msg->buf = data;
-	ret = i2c_transfer(tabla->client->adapter, tabla->xfer_msg, 1);
-	/* Try again if the write fails */
-	if (ret != 1) {
-		ret = i2c_transfer(tabla->client->adapter,
-						tabla->xfer_msg, 1);
-		if (ret != 1) {
-			pr_err("failed to write the device\n");
-			return ret;
-		}
-	}
-	pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
-	return 0;
-}
-
-
-int tabla_i2c_read_device(unsigned short reg,
-				  int bytes, unsigned char *dest)
-{
-	struct i2c_msg *msg;
-	int ret = 0;
-	u8 reg_addr = 0;
-	struct tabla_i2c *tabla;
-	u8 i = 0;
-
-	tabla = get_i2c_tabla_device_info(reg);
-	if (tabla == NULL || tabla->client == NULL) {
-		pr_err("failed to get device info\n");
-		return -ENODEV;
-	}
-	for (i = 0; i < bytes; i++) {
-		reg_addr = (u8)reg++;
-		msg = &tabla->xfer_msg[0];
-		msg->addr = tabla->client->addr;
-		msg->len = 1;
-		msg->flags = 0;
-		msg->buf = &reg_addr;
-
-		msg = &tabla->xfer_msg[1];
-		msg->addr = tabla->client->addr;
-		msg->len = 1;
-		msg->flags = I2C_M_RD;
-		msg->buf = dest++;
-		ret = i2c_transfer(tabla->client->adapter, tabla->xfer_msg, 2);
-
-		/* Try again if read fails first time */
-		if (ret != 2) {
-			ret = i2c_transfer(tabla->client->adapter,
-							tabla->xfer_msg, 2);
-			if (ret != 2) {
-				pr_err("failed to read tabla register\n");
-				return ret;
-			}
-		}
-	}
-	return 0;
-}
-
-int tabla_i2c_read(struct tabla *tabla, unsigned short reg,
-		   int bytes, void *dest, bool interface_reg)
-{
-	return tabla_i2c_read_device(reg, bytes, dest);
-}
-
-int tabla_i2c_write(struct tabla *tabla, unsigned short reg,
-		    int bytes, void *src, bool interface_reg)
-{
-	return tabla_i2c_write_device(reg, src, bytes);
-}
-
-static int __devinit tabla_i2c_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
-{
-	struct tabla *tabla;
-	struct tabla_pdata *pdata = client->dev.platform_data;
-	int val = 0;
-	int ret = 0;
-	static int device_id;
-
-	if (device_id > 0) {
-		tabla_modules[device_id++].client = client;
-		pr_info("probe for other slaves devices of tabla\n");
-		return ret;
-	}
-
-	tabla = kzalloc(sizeof(struct tabla), GFP_KERNEL);
-	if (tabla == NULL) {
-		pr_err("%s: error, allocation failed\n", __func__);
-		ret = -ENOMEM;
-		goto fail;
-	}
-
-	if (!pdata) {
-		dev_dbg(&client->dev, "no platform data?\n");
-		ret = -EINVAL;
-		goto err_tabla;
-	}
-	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
-		dev_dbg(&client->dev, "can't talk I2C?\n");
-		ret = -EIO;
-		goto err_tabla;
-	}
-	tabla->dev = &client->dev;
-	tabla->reset_gpio = pdata->reset_gpio;
-
-	ret = tabla_enable_supplies(tabla);
-	if (ret) {
-		pr_err("%s: Fail to enable Tabla supplies\n", __func__);
-		goto err_tabla;
-	}
-
-	usleep_range(5, 5);
-	ret = tabla_reset(tabla);
-	if (ret) {
-		pr_err("%s: Resetting Tabla failed\n", __func__);
-		goto err_supplies;
-	}
-	tabla_modules[device_id++].client = client;
-
-	tabla->read_dev = tabla_i2c_read;
-	tabla->write_dev = tabla_i2c_write;
-	tabla->irq = pdata->irq;
-	tabla->irq_base = pdata->irq_base;
-
-	/*read the tabla status before initializing the device type*/
-	ret = tabla_read(tabla, TABLA_A_CHIP_STATUS, 1, &val, 0);
-	if ((ret < 0) || (val != TABLA_I2C_MODE)) {
-		pr_err("failed to read the tabla status\n");
-		goto err_device_init;
-	}
-
-	ret = tabla_device_init(tabla, tabla->irq);
-	if (ret) {
-		pr_err("%s: error, initializing device failed\n", __func__);
-		goto err_device_init;
-	}
-	tabla_intf = TABLA_INTERFACE_TYPE_I2C;
-
-	return ret;
-err_device_init:
-	tabla_free_reset(tabla);
-err_supplies:
-	tabla_disable_supplies(tabla);
-err_tabla:
-	kfree(tabla);
-fail:
-	return ret;
-}
-
-static int __devexit tabla_i2c_remove(struct i2c_client *client)
-{
-	struct tabla *tabla;
-
-	pr_debug("exit\n");
-	tabla = dev_get_drvdata(&client->dev);
-	tabla_device_exit(tabla);
-	tabla_disable_supplies(tabla);
-	kfree(tabla);
-	return 0;
-}
-
-static int tabla_slim_probe(struct slim_device *slim)
-{
-	struct tabla *tabla;
-	struct tabla_pdata *pdata;
-	int ret = 0;
-	int sgla_retry_cnt;
-
-	dev_info(&slim->dev, "Initialized slim device %s\n", slim->name);
-	pdata = slim->dev.platform_data;
-
-	if (!pdata) {
-		dev_err(&slim->dev, "Error, no platform data\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	tabla = kzalloc(sizeof(struct tabla), GFP_KERNEL);
-	if (tabla == NULL) {
-		pr_err("%s: error, allocation failed\n", __func__);
-		ret = -ENOMEM;
-		goto err;
-	}
-	if (!slim->ctrl) {
-		pr_err("Error, no SLIMBUS control data\n");
-		ret = -EINVAL;
-		goto err_tabla;
-	}
-	tabla->slim = slim;
-	slim_set_clientdata(slim, tabla);
-	tabla->reset_gpio = pdata->reset_gpio;
-	tabla->dev = &slim->dev;
-
-	ret = tabla_enable_supplies(tabla);
-	if (ret) {
-		pr_err("%s: Fail to enable Tabla supplies\n", __func__);
-		goto err_tabla;
-	}
-	usleep_range(5, 5);
-
-	ret = tabla_reset(tabla);
-	if (ret) {
-		pr_err("%s: Resetting Tabla failed\n", __func__);
-		goto err_supplies;
-	}
-
-	ret = slim_get_logical_addr(tabla->slim, tabla->slim->e_addr,
-		ARRAY_SIZE(tabla->slim->e_addr), &tabla->slim->laddr);
-	if (ret) {
-		pr_err("fail to get slimbus logical address %d\n", ret);
-		goto err_reset;
-	}
-	tabla->read_dev = tabla_slim_read_device;
-	tabla->write_dev = tabla_slim_write_device;
-	tabla->irq = pdata->irq;
-	tabla->irq_base = pdata->irq_base;
-	tabla_pgd_la = tabla->slim->laddr;
-
-	if (pdata->num_irqs < TABLA_NUM_IRQS) {
-		pr_err("%s: Error, not enough interrupt lines allocated\n",
-			__func__);
-		goto err_reset;
-	}
-
-	tabla->slim_slave = &pdata->slimbus_slave_device;
-
-	ret = slim_add_device(slim->ctrl, tabla->slim_slave);
-	if (ret) {
-		pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
-		goto err_reset;
-	}
-
-	sgla_retry_cnt = 0;
-
-	while (1) {
-		ret = slim_get_logical_addr(tabla->slim_slave,
-			tabla->slim_slave->e_addr,
-			ARRAY_SIZE(tabla->slim_slave->e_addr),
-			&tabla->slim_slave->laddr);
-		if (ret) {
-			if (sgla_retry_cnt++ < TABLA_SLIM_GLA_MAX_RETRIES) {
-				/* Give SLIMBUS slave time to report present
-				   and be ready.
-				 */
-				usleep_range(1000, 1000);
-				pr_debug("%s: retry slim_get_logical_addr()\n",
-					__func__);
-				continue;
-			}
-			pr_err("fail to get slimbus slave logical address"
-				" %d\n", ret);
-			goto err_slim_add;
-		}
-		break;
-	}
-	tabla_inf_la = tabla->slim_slave->laddr;
-	tabla_intf = TABLA_INTERFACE_TYPE_SLIMBUS;
-
-	ret = tabla_device_init(tabla, tabla->irq);
-	if (ret) {
-		pr_err("%s: error, initializing device failed\n", __func__);
-		goto err_slim_add;
-	}
-	tabla_init_slimslave(tabla, tabla_pgd_la);
-#ifdef CONFIG_DEBUG_FS
-	debugTabla = tabla;
-
-	debugfs_tabla_dent = debugfs_create_dir
-		("wcd9310_slimbus_interface_device", 0);
-	if (!IS_ERR(debugfs_tabla_dent)) {
-		debugfs_peek = debugfs_create_file("peek",
-		S_IFREG | S_IRUGO, debugfs_tabla_dent,
-		(void *) "peek", &codec_debug_ops);
-
-		debugfs_poke = debugfs_create_file("poke",
-		S_IFREG | S_IRUGO, debugfs_tabla_dent,
-		(void *) "poke", &codec_debug_ops);
-	}
-#endif
-
-	return ret;
-
-err_slim_add:
-	slim_remove_device(tabla->slim_slave);
-err_reset:
-	tabla_free_reset(tabla);
-err_supplies:
-	tabla_disable_supplies(tabla);
-err_tabla:
-	kfree(tabla);
-err:
-	return ret;
-}
-
-static int tabla_slim_remove(struct slim_device *pdev)
-{
-	struct tabla *tabla;
-
-#ifdef CONFIG_DEBUG_FS
-	debugfs_remove(debugfs_peek);
-	debugfs_remove(debugfs_poke);
-	debugfs_remove(debugfs_tabla_dent);
-#endif
-
-	tabla = slim_get_devicedata(pdev);
-	tabla_deinit_slimslave(tabla);
-	tabla_disable_supplies(tabla);
-	slim_remove_device(tabla->slim_slave);
-	tabla_device_exit(tabla);
-	return 0;
-}
-
-static int tabla_resume(struct tabla *tabla)
-{
-	int ret = 0;
-
-	pr_debug("%s: enter\n", __func__);
-	mutex_lock(&tabla->pm_lock);
-	if (tabla->pm_state == TABLA_PM_ASLEEP) {
-		pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
-			 tabla->pm_state, tabla->wlock_holders);
-		tabla->pm_state = TABLA_PM_SLEEPABLE;
-	} else {
-		pr_warn("%s: system is already awake, state %d wlock %d\n",
-			__func__, tabla->pm_state, tabla->wlock_holders);
-	}
-	mutex_unlock(&tabla->pm_lock);
-	wake_up_all(&tabla->pm_wq);
-
-	return ret;
-}
-
-static int tabla_slim_resume(struct slim_device *sldev)
-{
-	struct tabla *tabla = slim_get_devicedata(sldev);
-	return tabla_resume(tabla);
-}
-
-static int tabla_i2c_resume(struct i2c_client *i2cdev)
-{
-	struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
-	return tabla_resume(tabla);
-}
-
-static int tabla_suspend(struct tabla *tabla, pm_message_t pmesg)
-{
-	int ret = 0;
-
-	pr_debug("%s: enter\n", __func__);
-	/* wake_lock() can be called after this suspend chain call started.
-	 * thus suspend can be called while wlock is being held */
-	mutex_lock(&tabla->pm_lock);
-	if (tabla->pm_state == TABLA_PM_SLEEPABLE) {
-		pr_debug("%s: suspending system, state %d, wlock %d\n",
-			 __func__, tabla->pm_state, tabla->wlock_holders);
-		tabla->pm_state = TABLA_PM_ASLEEP;
-	} else if (tabla->pm_state == TABLA_PM_AWAKE) {
-		/* unlock to wait for pm_state == TABLA_PM_SLEEPABLE
-		 * then set to TABLA_PM_ASLEEP */
-		pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
-			 __func__, tabla->pm_state, tabla->wlock_holders);
-		mutex_unlock(&tabla->pm_lock);
-		if (!(wait_event_timeout(tabla->pm_wq,
-					 tabla_pm_cmpxchg(tabla,
-							  TABLA_PM_SLEEPABLE,
-							  TABLA_PM_ASLEEP) ==
-							     TABLA_PM_SLEEPABLE,
-					 HZ))) {
-			pr_debug("%s: suspend failed state %d, wlock %d\n",
-				 __func__, tabla->pm_state,
-				 tabla->wlock_holders);
-			ret = -EBUSY;
-		} else {
-			pr_debug("%s: done, state %d, wlock %d\n", __func__,
-				 tabla->pm_state, tabla->wlock_holders);
-		}
-		mutex_lock(&tabla->pm_lock);
-	} else if (tabla->pm_state == TABLA_PM_ASLEEP) {
-		pr_warn("%s: system is already suspended, state %d, wlock %dn",
-			__func__, tabla->pm_state, tabla->wlock_holders);
-	}
-	mutex_unlock(&tabla->pm_lock);
-
-	return ret;
-}
-
-static int tabla_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
-{
-	struct tabla *tabla = slim_get_devicedata(sldev);
-	return tabla_suspend(tabla, pmesg);
-}
-
-static int tabla_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
-{
-	struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
-	return tabla_suspend(tabla, pmesg);
-}
-
-static const struct slim_device_id slimtest_id[] = {
-	{"tabla-slim", 0},
-	{}
-};
-
-static struct slim_driver tabla_slim_driver = {
-	.driver = {
-		.name = "tabla-slim",
-		.owner = THIS_MODULE,
-	},
-	.probe = tabla_slim_probe,
-	.remove = tabla_slim_remove,
-	.id_table = slimtest_id,
-	.resume = tabla_slim_resume,
-	.suspend = tabla_slim_suspend,
-};
-
-static const struct slim_device_id slimtest2x_id[] = {
-	{"tabla2x-slim", 0},
-	{}
-};
-
-static struct slim_driver tabla2x_slim_driver = {
-	.driver = {
-		.name = "tabla2x-slim",
-		.owner = THIS_MODULE,
-	},
-	.probe = tabla_slim_probe,
-	.remove = tabla_slim_remove,
-	.id_table = slimtest2x_id,
-	.resume = tabla_slim_resume,
-	.suspend = tabla_slim_suspend,
-};
-
-#define TABLA_I2C_TOP_LEVEL 0
-#define TABLA_I2C_ANALOG       1
-#define TABLA_I2C_DIGITAL_1    2
-#define TABLA_I2C_DIGITAL_2    3
-
-static struct i2c_device_id tabla_id_table[] = {
-	{"tabla top level", TABLA_I2C_TOP_LEVEL},
-	{"tabla analog", TABLA_I2C_TOP_LEVEL},
-	{"tabla digital1", TABLA_I2C_TOP_LEVEL},
-	{"tabla digital2", TABLA_I2C_TOP_LEVEL},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, tabla_id_table);
-
-static struct i2c_driver tabla_i2c_driver = {
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = "tabla-i2c-core",
-	},
-	.id_table = tabla_id_table,
-	.probe = tabla_i2c_probe,
-	.remove = __devexit_p(tabla_i2c_remove),
-	.resume	= tabla_i2c_resume,
-	.suspend = tabla_i2c_suspend,
-};
-
-static int __init tabla_init(void)
-{
-	int ret1, ret2, ret3;
-
-	ret1 = slim_driver_register(&tabla_slim_driver);
-	if (ret1 != 0)
-		pr_err("Failed to register tabla SB driver: %d\n", ret1);
-
-	ret2 = slim_driver_register(&tabla2x_slim_driver);
-	if (ret2 != 0)
-		pr_err("Failed to register tabla2x SB driver: %d\n", ret2);
-
-	ret3 = i2c_add_driver(&tabla_i2c_driver);
-	if (ret3 != 0)
-		pr_err("failed to add the I2C driver\n");
-
-	return (ret1 && ret2 && ret3) ? -1 : 0;
-}
-module_init(tabla_init);
-
-static void __exit tabla_exit(void)
-{
-}
-module_exit(tabla_exit);
-
-MODULE_DESCRIPTION("Tabla core driver");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/wcd9310-irq.c b/drivers/mfd/wcd9310-irq.c
deleted file mode 100644
index c6a9c23..0000000
--- a/drivers/mfd/wcd9310-irq.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/irq.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/registers.h>
-#include <linux/interrupt.h>
-
-#define BYTE_BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_BYTE))
-#define BIT_BYTE(nr)			((nr) / BITS_PER_BYTE)
-
-struct tabla_irq {
-	bool level;
-};
-
-static struct tabla_irq tabla_irqs[TABLA_NUM_IRQS] = {
-	[0] = { .level = 1},
-/* All other tabla interrupts are edge triggered */
-};
-
-static inline int irq_to_tabla_irq(struct tabla *tabla, int irq)
-{
-	return irq - tabla->irq_base;
-}
-
-static void tabla_irq_lock(struct irq_data *data)
-{
-	struct tabla *tabla = irq_data_get_irq_chip_data(data);
-	mutex_lock(&tabla->irq_lock);
-}
-
-static void tabla_irq_sync_unlock(struct irq_data *data)
-{
-	struct tabla *tabla = irq_data_get_irq_chip_data(data);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(tabla->irq_masks_cur); i++) {
-		/* If there's been a change in the mask write it back
-		 * to the hardware.
-		 */
-		if (tabla->irq_masks_cur[i] != tabla->irq_masks_cache[i]) {
-			tabla->irq_masks_cache[i] = tabla->irq_masks_cur[i];
-			tabla_reg_write(tabla, TABLA_A_INTR_MASK0+i,
-				tabla->irq_masks_cur[i]);
-		}
-	}
-
-	mutex_unlock(&tabla->irq_lock);
-}
-
-static void tabla_irq_enable(struct irq_data *data)
-{
-	struct tabla *tabla = irq_data_get_irq_chip_data(data);
-	int tabla_irq = irq_to_tabla_irq(tabla, data->irq);
-	tabla->irq_masks_cur[BIT_BYTE(tabla_irq)] &=
-		~(BYTE_BIT_MASK(tabla_irq));
-}
-
-static void tabla_irq_disable(struct irq_data *data)
-{
-	struct tabla *tabla = irq_data_get_irq_chip_data(data);
-	int tabla_irq = irq_to_tabla_irq(tabla, data->irq);
-	tabla->irq_masks_cur[BIT_BYTE(tabla_irq)] |= BYTE_BIT_MASK(tabla_irq);
-}
-
-static struct irq_chip tabla_irq_chip = {
-	.name = "tabla",
-	.irq_bus_lock = tabla_irq_lock,
-	.irq_bus_sync_unlock = tabla_irq_sync_unlock,
-	.irq_disable = tabla_irq_disable,
-	.irq_enable = tabla_irq_enable,
-};
-
-enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
-				     enum tabla_pm_state n)
-{
-	enum tabla_pm_state old;
-	mutex_lock(&tabla->pm_lock);
-	old = tabla->pm_state;
-	if (old == o)
-		tabla->pm_state = n;
-	mutex_unlock(&tabla->pm_lock);
-	return old;
-}
-EXPORT_SYMBOL_GPL(tabla_pm_cmpxchg);
-
-void tabla_lock_sleep(struct tabla *tabla)
-{
-	enum tabla_pm_state os;
-
-	/* tabla_{lock/unlock}_sleep will be called by tabla_irq_thread
-	 * and its subroutines only motly.
-	 * but btn0_lpress_fn is not tabla_irq_thread's subroutine and
-	 * it can race with tabla_irq_thread.
-	 * so need to embrace wlock_holders with mutex.
-	 */
-	mutex_lock(&tabla->pm_lock);
-	if (tabla->wlock_holders++ == 0)
-		wake_lock(&tabla->wlock);
-	mutex_unlock(&tabla->pm_lock);
-	while (!wait_event_timeout(tabla->pm_wq,
-			((os = tabla_pm_cmpxchg(tabla, TABLA_PM_SLEEPABLE,
-						TABLA_PM_AWAKE)) ==
-						    TABLA_PM_SLEEPABLE ||
-			 (os == TABLA_PM_AWAKE)),
-			5 * HZ)) {
-		pr_err("%s: system didn't resume within 5000ms, state %d, "
-		       "wlock %d\n", __func__, tabla->pm_state,
-		       tabla->wlock_holders);
-		WARN_ON_ONCE(1);
-	}
-	wake_up_all(&tabla->pm_wq);
-}
-EXPORT_SYMBOL_GPL(tabla_lock_sleep);
-
-void tabla_unlock_sleep(struct tabla *tabla)
-{
-	mutex_lock(&tabla->pm_lock);
-	if (--tabla->wlock_holders == 0) {
-		tabla->pm_state = TABLA_PM_SLEEPABLE;
-		wake_unlock(&tabla->wlock);
-	}
-	mutex_unlock(&tabla->pm_lock);
-	wake_up_all(&tabla->pm_wq);
-}
-EXPORT_SYMBOL_GPL(tabla_unlock_sleep);
-
-static irqreturn_t tabla_irq_thread(int irq, void *data)
-{
-	int ret;
-	struct tabla *tabla = data;
-	u8 status[TABLA_NUM_IRQ_REGS];
-	unsigned int i;
-
-	tabla_lock_sleep(tabla);
-	ret = tabla_bulk_read(tabla, TABLA_A_INTR_STATUS0,
-			       TABLA_NUM_IRQ_REGS, status);
-	if (ret < 0) {
-		dev_err(tabla->dev, "Failed to read interrupt status: %d\n",
-			ret);
-		tabla_unlock_sleep(tabla);
-		return IRQ_NONE;
-	}
-	/* Apply masking */
-	for (i = 0; i < TABLA_NUM_IRQ_REGS; i++)
-		status[i] &= ~tabla->irq_masks_cur[i];
-
-	/* Find out which interrupt was triggered and call that interrupt's
-	 * handler function
-	 */
-	for (i = 0; i < TABLA_NUM_IRQS; i++) {
-		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
-			if ((i <= TABLA_IRQ_MBHC_INSERTION) &&
-				(i >= TABLA_IRQ_MBHC_REMOVAL)) {
-				tabla_reg_write(tabla, TABLA_A_INTR_CLEAR0 +
-					BIT_BYTE(i), BYTE_BIT_MASK(i));
-				if (tabla_get_intf_type() ==
-					TABLA_INTERFACE_TYPE_I2C)
-					tabla_reg_write(tabla,
-						TABLA_A_INTR_MODE, 0x02);
-				handle_nested_irq(tabla->irq_base + i);
-			} else {
-				handle_nested_irq(tabla->irq_base + i);
-				tabla_reg_write(tabla, TABLA_A_INTR_CLEAR0 +
-					BIT_BYTE(i), BYTE_BIT_MASK(i));
-				if (tabla_get_intf_type() ==
-					TABLA_INTERFACE_TYPE_I2C)
-					tabla_reg_write(tabla,
-						TABLA_A_INTR_MODE, 0x02);
-			}
-			break;
-		}
-	}
-	tabla_unlock_sleep(tabla);
-
-	return IRQ_HANDLED;
-}
-
-int tabla_irq_init(struct tabla *tabla)
-{
-	int ret;
-	unsigned int i, cur_irq;
-
-	mutex_init(&tabla->irq_lock);
-
-	if (!tabla->irq) {
-		dev_warn(tabla->dev,
-			 "No interrupt specified, no interrupts\n");
-		tabla->irq_base = 0;
-		return 0;
-	}
-
-	if (!tabla->irq_base) {
-		dev_err(tabla->dev,
-			"No interrupt base specified, no interrupts\n");
-		return 0;
-	}
-	/* Mask the individual interrupt sources */
-	for (i = 0, cur_irq = tabla->irq_base; i < TABLA_NUM_IRQS; i++,
-		cur_irq++) {
-
-		irq_set_chip_data(cur_irq, tabla);
-
-		if (tabla_irqs[i].level)
-			irq_set_chip_and_handler(cur_irq, &tabla_irq_chip,
-					 handle_level_irq);
-		else
-			irq_set_chip_and_handler(cur_irq, &tabla_irq_chip,
-					 handle_edge_irq);
-
-		irq_set_nested_thread(cur_irq, 1);
-
-		/* ARM needs us to explicitly flag the IRQ as valid
-		 * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
-		set_irq_flags(cur_irq, IRQF_VALID);
-#else
-		set_irq_noprobe(cur_irq);
-#endif
-
-		tabla->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
-		tabla->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
-		tabla->irq_level[BIT_BYTE(i)] |= tabla_irqs[i].level <<
-			(i % BITS_PER_BYTE);
-	}
-	for (i = 0; i < TABLA_NUM_IRQ_REGS; i++) {
-		/* Initialize interrupt mask and level registers */
-		tabla_reg_write(tabla, TABLA_A_INTR_LEVEL0 + i,
-			tabla->irq_level[i]);
-		tabla_reg_write(tabla, TABLA_A_INTR_MASK0 + i,
-			tabla->irq_masks_cur[i]);
-	}
-
-	ret = request_threaded_irq(tabla->irq, NULL, tabla_irq_thread,
-				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-				   "tabla", tabla);
-	if (ret != 0)
-		dev_err(tabla->dev, "Failed to request IRQ %d: %d\n",
-			tabla->irq, ret);
-	else {
-		ret = enable_irq_wake(tabla->irq);
-		if (ret == 0) {
-			ret = device_init_wakeup(tabla->dev, 1);
-			if (ret) {
-				dev_err(tabla->dev, "Failed to init device"
-					"wakeup : %d\n", ret);
-				disable_irq_wake(tabla->irq);
-			}
-		} else
-			dev_err(tabla->dev, "Failed to set wake interrupt on"
-				" IRQ %d: %d\n", tabla->irq, ret);
-		if (ret)
-			free_irq(tabla->irq, tabla);
-	}
-
-	if (ret)
-		mutex_destroy(&tabla->irq_lock);
-
-	return ret;
-}
-
-void tabla_irq_exit(struct tabla *tabla)
-{
-	if (tabla->irq) {
-		disable_irq_wake(tabla->irq);
-		free_irq(tabla->irq, tabla);
-		device_init_wakeup(tabla->dev, 0);
-	}
-	mutex_destroy(&tabla->irq_lock);
-}
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
new file mode 100644
index 0000000..59a4283
--- /dev/null
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -0,0 +1,1126 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/debugfs.h>
+#include <linux/regulator/consumer.h>
+#include <linux/i2c.h>
+#include <sound/soc.h>
+
+#define WCD9XXX_SLIM_GLA_MAX_RETRIES 5
+#define WCD9XXX_REGISTER_START_OFFSET 0x800
+#define WCD9XXX_SLIM_RW_MAX_TRIES 3
+
+#define MAX_WCD9XXX_DEVICE	4
+#define WCD9XXX_I2C_MODE	0x03
+
+struct wcd9xxx_i2c {
+	struct i2c_client *client;
+	struct i2c_msg xfer_msg[2];
+	struct mutex xfer_lock;
+	int mod_id;
+};
+
+struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
+static int wcd9xxx_intf;
+
+static int wcd9xxx_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		       int bytes, void *dest, bool interface_reg)
+{
+	int ret;
+	u8 *buf = dest;
+
+	if (bytes <= 0) {
+		dev_err(wcd9xxx->dev, "Invalid byte read length %d\n", bytes);
+		return -EINVAL;
+	}
+
+	ret = wcd9xxx->read_dev(wcd9xxx, reg, bytes, dest, interface_reg);
+	if (ret < 0) {
+		dev_err(wcd9xxx->dev, "Codec read failed\n");
+		return ret;
+	} else
+		dev_dbg(wcd9xxx->dev, "Read 0x%02x from R%d(0x%x)\n",
+			 *buf, reg, reg);
+
+	return 0;
+}
+int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
+{
+	u8 val;
+	int ret;
+
+	mutex_lock(&wcd9xxx->io_lock);
+	ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false);
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	if (ret < 0)
+		return ret;
+	else
+		return val;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_reg_read);
+
+static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			int bytes, void *src, bool interface_reg)
+{
+	u8 *buf = src;
+
+	if (bytes <= 0) {
+		pr_err("%s: Error, invalid write length\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(wcd9xxx->dev, "Write %02x to R%d(0x%x)\n",
+		 *buf, reg, reg);
+
+	return wcd9xxx->write_dev(wcd9xxx, reg, bytes, src, interface_reg);
+}
+
+int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		     u8 val)
+{
+	int ret;
+
+	mutex_lock(&wcd9xxx->io_lock);
+	ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, false);
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_reg_write);
+
+static u8 wcd9xxx_pgd_la;
+static u8 wcd9xxx_inf_la;
+
+int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
+{
+	u8 val;
+	int ret;
+
+	mutex_lock(&wcd9xxx->io_lock);
+	ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, true);
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	if (ret < 0)
+		return ret;
+	else
+		return val;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_read);
+
+int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		     u8 val)
+{
+	int ret;
+
+	mutex_lock(&wcd9xxx->io_lock);
+	ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, true);
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_write);
+
+int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		     int count, u8 *buf)
+{
+	int ret;
+
+	mutex_lock(&wcd9xxx->io_lock);
+
+	ret = wcd9xxx_read(wcd9xxx, reg, count, buf, false);
+
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_bulk_read);
+
+int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		     int count, u8 *buf)
+{
+	int ret;
+
+	mutex_lock(&wcd9xxx->io_lock);
+
+	ret = wcd9xxx_write(wcd9xxx, reg, count, buf, false);
+
+	mutex_unlock(&wcd9xxx->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_bulk_write);
+
+static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
+				int bytes, void *dest, bool interface)
+{
+	int ret;
+	struct slim_ele_access msg;
+	int slim_read_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
+	msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
+	msg.num_bytes = bytes;
+	msg.comp = NULL;
+
+	while (1) {
+		mutex_lock(&wcd9xxx->xfer_lock);
+		ret = slim_request_val_element(interface ?
+			       wcd9xxx->slim_slave : wcd9xxx->slim,
+			       &msg, dest, bytes);
+		mutex_unlock(&wcd9xxx->xfer_lock);
+		if (likely(ret == 0) || (--slim_read_tries == 0))
+			break;
+		usleep_range(5000, 5000);
+	}
+
+	if (ret)
+		pr_err("%s: Error, Codec read failed (%d)\n", __func__, ret);
+
+	return ret;
+}
+/* Interface specifies whether the write is to the interface or general
+ * registers.
+ */
+static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,
+		unsigned short reg, int bytes, void *src, bool interface)
+{
+	int ret;
+	struct slim_ele_access msg;
+	int slim_write_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
+	msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
+	msg.num_bytes = bytes;
+	msg.comp = NULL;
+
+	while (1) {
+		mutex_lock(&wcd9xxx->xfer_lock);
+		ret = slim_change_val_element(interface ?
+			      wcd9xxx->slim_slave : wcd9xxx->slim,
+			      &msg, src, bytes);
+		mutex_unlock(&wcd9xxx->xfer_lock);
+		if (likely(ret == 0) || (--slim_write_tries == 0))
+			break;
+		usleep_range(5000, 5000);
+	}
+
+	if (ret)
+		pr_err("%s: Error, Codec write failed (%d)\n", __func__, ret);
+
+	return ret;
+}
+
+static struct mfd_cell tabla1x_devs[] = {
+	{
+		.name = "tabla1x_codec",
+	},
+};
+
+static struct mfd_cell tabla_devs[] = {
+	{
+		.name = "tabla_codec",
+	},
+};
+
+static struct mfd_cell sitar_devs[] = {
+	{
+		.name = "sitar_codec",
+	},
+};
+
+static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
+{
+	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
+	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
+	usleep_range(5000, 5000);
+	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
+	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
+}
+
+static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
+{
+	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
+	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
+	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
+	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
+}
+
+static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
+{
+	int ret;
+
+	if (wcd9xxx->reset_gpio) {
+		ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
+		if (ret) {
+			pr_err("%s: Failed to request gpio %d\n", __func__,
+				wcd9xxx->reset_gpio);
+			wcd9xxx->reset_gpio = 0;
+			return ret;
+		}
+
+		gpio_direction_output(wcd9xxx->reset_gpio, 1);
+		msleep(20);
+		gpio_direction_output(wcd9xxx->reset_gpio, 0);
+		msleep(20);
+		gpio_direction_output(wcd9xxx->reset_gpio, 1);
+		msleep(20);
+	}
+	return 0;
+}
+
+static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
+{
+	if (wcd9xxx->reset_gpio) {
+		gpio_free(wcd9xxx->reset_gpio);
+		wcd9xxx->reset_gpio = 0;
+	}
+}
+
+static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx, int irq)
+{
+	int ret;
+	u8 idbyte_0, idbyte_1, idbyte_2, idbyte_3;
+	struct mfd_cell *wcd9xxx_dev = NULL;
+	int wcd9xxx_dev_size = 0;
+
+	mutex_init(&wcd9xxx->io_lock);
+	mutex_init(&wcd9xxx->xfer_lock);
+
+	mutex_init(&wcd9xxx->pm_lock);
+	wcd9xxx->wlock_holders = 0;
+	wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
+	init_waitqueue_head(&wcd9xxx->pm_wq);
+	wake_lock_init(&wcd9xxx->wlock, WAKE_LOCK_IDLE, "wcd9310-irq");
+
+	dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
+
+	wcd9xxx_bring_up(wcd9xxx);
+
+	ret = wcd9xxx_irq_init(wcd9xxx);
+	if (ret) {
+		pr_err("IRQ initialization failed\n");
+		goto err;
+	}
+
+	idbyte_0 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0);
+	idbyte_1 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_1);
+	idbyte_2 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2);
+	idbyte_3 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_3);
+
+	wcd9xxx->version = wcd9xxx_reg_read(wcd9xxx,
+			WCD9XXX_A_CHIP_VERSION) & 0x1F;
+	pr_info("%s : Codec version %u initialized\n",
+		__func__, wcd9xxx->version);
+	pr_info("idbyte_0[%08x] idbyte_1[%08x] idbyte_2[%08x] idbyte_3[%08x]\n",
+			idbyte_0, idbyte_1, idbyte_2, idbyte_3);
+
+	if (!strncmp(wcd9xxx->slim->name, "tabla", 5)) {
+		if (TABLA_IS_1_X(wcd9xxx->version)) {
+			wcd9xxx_dev = tabla1x_devs;
+			wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
+		} else {
+			wcd9xxx_dev = tabla_devs;
+			wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
+		}
+	} else {
+		wcd9xxx_dev = sitar_devs;
+		wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
+	}
+
+	ret = mfd_add_devices(wcd9xxx->dev, -1,
+		      wcd9xxx_dev, wcd9xxx_dev_size,
+		      NULL, 0);
+	if (ret != 0) {
+		dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
+		goto err_irq;
+	}
+	return ret;
+err_irq:
+	wcd9xxx_irq_exit(wcd9xxx);
+err:
+	wcd9xxx_bring_down(wcd9xxx);
+	wake_lock_destroy(&wcd9xxx->wlock);
+	mutex_destroy(&wcd9xxx->pm_lock);
+	mutex_destroy(&wcd9xxx->io_lock);
+	mutex_destroy(&wcd9xxx->xfer_lock);
+	return ret;
+}
+
+static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
+{
+	wcd9xxx_irq_exit(wcd9xxx);
+	wcd9xxx_bring_down(wcd9xxx);
+	wcd9xxx_free_reset(wcd9xxx);
+	mutex_destroy(&wcd9xxx->pm_lock);
+	wake_lock_destroy(&wcd9xxx->wlock);
+	mutex_destroy(&wcd9xxx->io_lock);
+	mutex_destroy(&wcd9xxx->xfer_lock);
+	slim_remove_device(wcd9xxx->slim_slave);
+	kfree(wcd9xxx);
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+struct wcd9xxx *debugCodec;
+
+static struct dentry *debugfs_wcd9xxx_dent;
+static struct dentry *debugfs_peek;
+static struct dentry *debugfs_poke;
+
+static unsigned char read_data;
+
+static int codec_debug_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int get_parameters(char *buf, long int *param1, int num_of_par)
+{
+	char *token;
+	int base, cnt;
+
+	token = strsep(&buf, " ");
+
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token != NULL) {
+			if ((token[1] == 'x') || (token[1] == 'X'))
+				base = 16;
+			else
+				base = 10;
+
+			if (strict_strtoul(token, base, &param1[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	char lbuf[8];
+
+	snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
+	return simple_read_from_buffer(ubuf, count, ppos, lbuf,
+		strnlen(lbuf, 7));
+}
+
+
+static ssize_t codec_debug_write(struct file *filp,
+	const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	char *access_str = filp->private_data;
+	char lbuf[32];
+	int rc;
+	long int param[5];
+
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+
+	if (!strncmp(access_str, "poke", 6)) {
+		/* write */
+		rc = get_parameters(lbuf, param, 2);
+		if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
+			(rc == 0))
+			wcd9xxx_interface_reg_write(debugCodec, param[0],
+				param[1]);
+		else
+			rc = -EINVAL;
+	} else if (!strncmp(access_str, "peek", 6)) {
+		/* read */
+		rc = get_parameters(lbuf, param, 1);
+		if ((param[0] <= 0x3FF) && (rc == 0))
+			read_data = wcd9xxx_interface_reg_read(debugCodec,
+				param[0]);
+		else
+			rc = -EINVAL;
+	}
+
+	if (rc == 0)
+		rc = cnt;
+	else
+		pr_err("%s: rc = %d\n", __func__, rc);
+
+	return rc;
+}
+
+static const struct file_operations codec_debug_ops = {
+	.open = codec_debug_open,
+	.write = codec_debug_write,
+	.read = codec_debug_read
+};
+#endif
+
+static int wcd9xxx_enable_supplies(struct wcd9xxx *wcd9xxx)
+{
+	int ret;
+	int i;
+	struct wcd9xxx_pdata *pdata = wcd9xxx->slim->dev.platform_data;
+
+	wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
+				   ARRAY_SIZE(pdata->regulator),
+				   GFP_KERNEL);
+	if (!wcd9xxx->supplies) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++)
+		wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
+
+	ret = regulator_bulk_get(wcd9xxx->dev, ARRAY_SIZE(pdata->regulator),
+				 wcd9xxx->supplies);
+	if (ret != 0) {
+		dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
+							ret);
+		goto err_supplies;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+		ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
+			pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
+		if (ret) {
+			pr_err("%s: Setting regulator voltage failed for "
+				"regulator %s err = %d\n", __func__,
+				wcd9xxx->supplies[i].supply, ret);
+			goto err_get;
+		}
+
+		ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
+			pdata->regulator[i].optimum_uA);
+		if (ret < 0) {
+			pr_err("%s: Setting regulator optimum mode failed for "
+				"regulator %s err = %d\n", __func__,
+				wcd9xxx->supplies[i].supply, ret);
+			goto err_get;
+		}
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(pdata->regulator),
+				    wcd9xxx->supplies);
+	if (ret != 0) {
+		dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
+				ret);
+		goto err_configure;
+	}
+	return ret;
+
+err_configure:
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+		regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
+			pdata->regulator[i].max_uV);
+		regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
+	}
+err_get:
+	regulator_bulk_free(ARRAY_SIZE(pdata->regulator), wcd9xxx->supplies);
+err_supplies:
+	kfree(wcd9xxx->supplies);
+err:
+	return ret;
+}
+
+static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx)
+{
+	int i;
+	struct wcd9xxx_pdata *pdata = wcd9xxx->slim->dev.platform_data;
+
+	regulator_bulk_disable(ARRAY_SIZE(pdata->regulator),
+				    wcd9xxx->supplies);
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+		regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
+			pdata->regulator[i].max_uV);
+		regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
+	}
+	regulator_bulk_free(ARRAY_SIZE(pdata->regulator), wcd9xxx->supplies);
+	kfree(wcd9xxx->supplies);
+}
+
+int wcd9xxx_get_intf_type(void)
+{
+	return wcd9xxx_intf;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
+
+struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
+{
+	u16 mask = 0x0f00;
+	int value = 0;
+	struct wcd9xxx_i2c *wcd9xxx = NULL;
+	value = ((reg & mask) >> 8) & 0x000f;
+	switch (value) {
+	case 0:
+		wcd9xxx = &wcd9xxx_modules[0];
+		break;
+	case 1:
+		wcd9xxx = &wcd9xxx_modules[1];
+		break;
+	case 2:
+		wcd9xxx = &wcd9xxx_modules[2];
+		break;
+	case 3:
+		wcd9xxx = &wcd9xxx_modules[3];
+		break;
+	default:
+		break;
+	}
+	return wcd9xxx;
+}
+
+int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
+				u32 bytes)
+{
+
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	u8 data[bytes + 1];
+	struct wcd9xxx_i2c *wcd9xxx;
+
+	wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
+	if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
+		pr_err("failed to get device info\n");
+		return -ENODEV;
+	}
+	reg_addr = (u8)reg;
+	msg = &wcd9xxx->xfer_msg[0];
+	msg->addr = wcd9xxx->client->addr;
+	msg->len = bytes + 1;
+	msg->flags = 0;
+	data[0] = reg;
+	data[1] = *value;
+	msg->buf = data;
+	ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
+	/* Try again if the write fails */
+	if (ret != 1) {
+		ret = i2c_transfer(wcd9xxx->client->adapter,
+						wcd9xxx->xfer_msg, 1);
+		if (ret != 1) {
+			pr_err("failed to write the device\n");
+			return ret;
+		}
+	}
+	pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
+	return 0;
+}
+
+
+int wcd9xxx_i2c_read_device(unsigned short reg,
+				  int bytes, unsigned char *dest)
+{
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	struct wcd9xxx_i2c *wcd9xxx;
+	u8 i = 0;
+
+	wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
+	if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
+		pr_err("failed to get device info\n");
+		return -ENODEV;
+	}
+	for (i = 0; i < bytes; i++) {
+		reg_addr = (u8)reg++;
+		msg = &wcd9xxx->xfer_msg[0];
+		msg->addr = wcd9xxx->client->addr;
+		msg->len = 1;
+		msg->flags = 0;
+		msg->buf = &reg_addr;
+
+		msg = &wcd9xxx->xfer_msg[1];
+		msg->addr = wcd9xxx->client->addr;
+		msg->len = 1;
+		msg->flags = I2C_M_RD;
+		msg->buf = dest++;
+		ret = i2c_transfer(wcd9xxx->client->adapter,
+				wcd9xxx->xfer_msg, 2);
+
+		/* Try again if read fails first time */
+		if (ret != 2) {
+			ret = i2c_transfer(wcd9xxx->client->adapter,
+							wcd9xxx->xfer_msg, 2);
+			if (ret != 2) {
+				pr_err("failed to read wcd9xxx register\n");
+				return ret;
+			}
+		}
+	}
+	return 0;
+}
+
+int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			int bytes, void *dest, bool interface_reg)
+{
+	return wcd9xxx_i2c_read_device(reg, bytes, dest);
+}
+
+int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			 int bytes, void *src, bool interface_reg)
+{
+	return wcd9xxx_i2c_write_device(reg, src, bytes);
+}
+
+static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct wcd9xxx *wcd9xxx;
+	struct wcd9xxx_pdata *pdata = client->dev.platform_data;
+	int val = 0;
+	int ret = 0;
+	static int device_id;
+
+	if (device_id > 0) {
+		wcd9xxx_modules[device_id++].client = client;
+		pr_info("probe for other slaves devices of tabla\n");
+		return ret;
+	}
+
+	wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
+	if (wcd9xxx == NULL) {
+		pr_err("%s: error, allocation failed\n", __func__);
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	if (!pdata) {
+		dev_dbg(&client->dev, "no platform data?\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
+		dev_dbg(&client->dev, "can't talk I2C?\n");
+		ret = -EIO;
+		goto fail;
+	}
+	dev_set_drvdata(&client->dev, wcd9xxx);
+	wcd9xxx->dev = &client->dev;
+	wcd9xxx->reset_gpio = pdata->reset_gpio;
+
+	ret = wcd9xxx_enable_supplies(wcd9xxx);
+	if (ret) {
+		pr_err("%s: Fail to enable Codec supplies\n", __func__);
+		goto err_codec;
+	}
+
+	usleep_range(5, 5);
+	ret = wcd9xxx_reset(wcd9xxx);
+	if (ret) {
+		pr_err("%s: Resetting Codec failed\n", __func__);
+		goto err_supplies;
+	}
+	wcd9xxx_modules[device_id++].client = client;
+
+	wcd9xxx->read_dev = wcd9xxx_i2c_read;
+	wcd9xxx->write_dev = wcd9xxx_i2c_write;
+	wcd9xxx->irq = pdata->irq;
+	wcd9xxx->irq_base = pdata->irq_base;
+
+	/*read the tabla status before initializing the device type*/
+	ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
+	if ((ret < 0) || (val != WCD9XXX_I2C_MODE)) {
+		pr_err("failed to read the wcd9xxx status\n");
+		goto err_device_init;
+	}
+
+	ret = wcd9xxx_device_init(wcd9xxx, wcd9xxx->irq);
+	if (ret) {
+		pr_err("%s: error, initializing device failed\n", __func__);
+		goto err_device_init;
+	}
+	wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
+
+	return ret;
+err_device_init:
+	wcd9xxx_free_reset(wcd9xxx);
+err_supplies:
+	wcd9xxx_disable_supplies(wcd9xxx);
+err_codec:
+	kfree(wcd9xxx);
+fail:
+	return ret;
+}
+
+static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
+{
+	struct wcd9xxx *wcd9xxx;
+
+	pr_debug("exit\n");
+	wcd9xxx = dev_get_drvdata(&client->dev);
+	wcd9xxx_disable_supplies(wcd9xxx);
+	wcd9xxx_device_exit(wcd9xxx);
+	return 0;
+}
+
+static int wcd9xxx_slim_probe(struct slim_device *slim)
+{
+	struct wcd9xxx *wcd9xxx;
+	struct wcd9xxx_pdata *pdata;
+	int ret = 0;
+	int sgla_retry_cnt;
+
+	dev_info(&slim->dev, "Initialized slim device %s\n", slim->name);
+	pdata = slim->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&slim->dev, "Error, no platform data\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
+	if (wcd9xxx == NULL) {
+		pr_err("%s: error, allocation failed\n", __func__);
+		ret = -ENOMEM;
+		goto err;
+	}
+	if (!slim->ctrl) {
+		pr_err("Error, no SLIMBUS control data\n");
+		ret = -EINVAL;
+		goto err_codec;
+	}
+	wcd9xxx->slim = slim;
+	slim_set_clientdata(slim, wcd9xxx);
+	wcd9xxx->reset_gpio = pdata->reset_gpio;
+	wcd9xxx->dev = &slim->dev;
+
+	ret = wcd9xxx_enable_supplies(wcd9xxx);
+	if (ret)
+		goto err_codec;
+	usleep_range(5, 5);
+
+	ret = wcd9xxx_reset(wcd9xxx);
+	if (ret) {
+		pr_err("%s: Resetting Codec failed\n", __func__);
+		goto err_supplies;
+	}
+
+	ret = slim_get_logical_addr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
+		ARRAY_SIZE(wcd9xxx->slim->e_addr), &wcd9xxx->slim->laddr);
+	if (ret) {
+		pr_err("fail to get slimbus logical address %d\n", ret);
+		goto err_reset;
+	}
+	wcd9xxx->read_dev = wcd9xxx_slim_read_device;
+	wcd9xxx->write_dev = wcd9xxx_slim_write_device;
+	wcd9xxx->irq = pdata->irq;
+	wcd9xxx->irq_base = pdata->irq_base;
+	wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
+
+	if (pdata->num_irqs < TABLA_NUM_IRQS) {
+		pr_err("%s: Error, not enough interrupt lines allocated\n",
+			__func__);
+		goto err_reset;
+	}
+
+	wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
+
+	ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
+	if (ret) {
+		pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
+		goto err_reset;
+	}
+
+	sgla_retry_cnt = 0;
+
+	while (1) {
+		ret = slim_get_logical_addr(wcd9xxx->slim_slave,
+			wcd9xxx->slim_slave->e_addr,
+			ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
+			&wcd9xxx->slim_slave->laddr);
+		if (ret) {
+			if (sgla_retry_cnt++ < WCD9XXX_SLIM_GLA_MAX_RETRIES) {
+				/* Give SLIMBUS slave time to report present
+				   and be ready.
+				 */
+				usleep_range(1000, 1000);
+				pr_debug("%s: retry slim_get_logical_addr()\n",
+					__func__);
+				continue;
+			}
+			pr_err("fail to get slimbus slave logical address"
+				" %d\n", ret);
+			goto err_slim_add;
+		}
+		break;
+	}
+	wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
+	wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
+
+	ret = wcd9xxx_device_init(wcd9xxx, wcd9xxx->irq);
+	if (ret) {
+		pr_err("%s: error, initializing device failed\n", __func__);
+		goto err_slim_add;
+	}
+	wcd9xxx_init_slimslave(wcd9xxx, wcd9xxx_pgd_la);
+#ifdef CONFIG_DEBUG_FS
+	debugCodec = wcd9xxx;
+
+	debugfs_wcd9xxx_dent = debugfs_create_dir
+		("wcd9310_slimbus_interface_device", 0);
+	if (!IS_ERR(debugfs_wcd9xxx_dent)) {
+		debugfs_peek = debugfs_create_file("peek",
+		S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
+		(void *) "peek", &codec_debug_ops);
+
+		debugfs_poke = debugfs_create_file("poke",
+		S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
+		(void *) "poke", &codec_debug_ops);
+	}
+#endif
+
+	return ret;
+
+err_slim_add:
+	slim_remove_device(wcd9xxx->slim_slave);
+err_reset:
+	wcd9xxx_free_reset(wcd9xxx);
+err_supplies:
+	wcd9xxx_disable_supplies(wcd9xxx);
+err_codec:
+	kfree(wcd9xxx);
+err:
+	return ret;
+}
+static int wcd9xxx_slim_remove(struct slim_device *pdev)
+{
+	struct wcd9xxx *wcd9xxx;
+
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove(debugfs_peek);
+	debugfs_remove(debugfs_poke);
+	debugfs_remove(debugfs_wcd9xxx_dent);
+#endif
+	wcd9xxx = slim_get_devicedata(pdev);
+	wcd9xxx_deinit_slimslave(wcd9xxx);
+	slim_remove_device(wcd9xxx->slim_slave);
+	wcd9xxx_disable_supplies(wcd9xxx);
+	wcd9xxx_device_exit(wcd9xxx);
+	return 0;
+}
+
+static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
+{
+	int ret = 0;
+
+	pr_debug("%s: enter\n", __func__);
+	mutex_lock(&wcd9xxx->pm_lock);
+	if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
+		pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
+			 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+		wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
+	} else {
+		pr_warn("%s: system is already awake, state %d wlock %d\n",
+			__func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+	}
+	mutex_unlock(&wcd9xxx->pm_lock);
+	wake_up_all(&wcd9xxx->pm_wq);
+
+	return ret;
+}
+
+static int wcd9xxx_slim_resume(struct slim_device *sldev)
+{
+	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+	return wcd9xxx_resume(wcd9xxx);
+}
+
+static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
+{
+	struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
+	if (wcd9xxx)
+		return wcd9xxx_resume(wcd9xxx);
+	else
+		return 0;
+}
+
+static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
+{
+	int ret = 0;
+
+	pr_debug("%s: enter\n", __func__);
+	/* wake_lock() can be called after this suspend chain call started.
+	 * thus suspend can be called while wlock is being held */
+	mutex_lock(&wcd9xxx->pm_lock);
+	if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
+		pr_debug("%s: suspending system, state %d, wlock %d\n",
+			 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+		wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
+	} else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
+		/* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
+		 * then set to WCD9XXX_PM_ASLEEP */
+		pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
+			 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+		mutex_unlock(&wcd9xxx->pm_lock);
+		if (!(wait_event_timeout(wcd9xxx->pm_wq,
+					 wcd9xxx_pm_cmpxchg(wcd9xxx,
+						  WCD9XXX_PM_SLEEPABLE,
+						  WCD9XXX_PM_ASLEEP) ==
+							WCD9XXX_PM_SLEEPABLE,
+					 HZ))) {
+			pr_debug("%s: suspend failed state %d, wlock %d\n",
+				 __func__, wcd9xxx->pm_state,
+				 wcd9xxx->wlock_holders);
+			ret = -EBUSY;
+		} else {
+			pr_debug("%s: done, state %d, wlock %d\n", __func__,
+				 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+		}
+		mutex_lock(&wcd9xxx->pm_lock);
+	} else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
+		pr_warn("%s: system is already suspended, state %d, wlock %dn",
+			__func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+	}
+	mutex_unlock(&wcd9xxx->pm_lock);
+
+	return ret;
+}
+
+static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
+{
+	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+	return wcd9xxx_suspend(wcd9xxx, pmesg);
+}
+
+static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
+{
+	struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
+	if (wcd9xxx)
+		return wcd9xxx_suspend(wcd9xxx, pmesg);
+	else
+		return 0;
+}
+
+static const struct slim_device_id sitar_slimtest_id[] = {
+	{"sitar-slim", 0},
+	{}
+};
+static struct slim_driver sitar_slim_driver = {
+	.driver = {
+		.name = "sitar-slim",
+		.owner = THIS_MODULE,
+	},
+	.probe = wcd9xxx_slim_probe,
+	.remove = wcd9xxx_slim_remove,
+	.id_table = sitar_slimtest_id,
+	.resume = wcd9xxx_slim_resume,
+	.suspend = wcd9xxx_slim_suspend,
+};
+
+static const struct slim_device_id slimtest_id[] = {
+	{"tabla-slim", 0},
+	{}
+};
+
+static struct slim_driver tabla_slim_driver = {
+	.driver = {
+		.name = "tabla-slim",
+		.owner = THIS_MODULE,
+	},
+	.probe = wcd9xxx_slim_probe,
+	.remove = wcd9xxx_slim_remove,
+	.id_table = slimtest_id,
+	.resume = wcd9xxx_slim_resume,
+	.suspend = wcd9xxx_slim_suspend,
+};
+
+static const struct slim_device_id slimtest2x_id[] = {
+	{"tabla2x-slim", 0},
+	{}
+};
+
+static struct slim_driver tabla2x_slim_driver = {
+	.driver = {
+		.name = "tabla2x-slim",
+		.owner = THIS_MODULE,
+	},
+	.probe = wcd9xxx_slim_probe,
+	.remove = wcd9xxx_slim_remove,
+	.id_table = slimtest2x_id,
+	.resume = wcd9xxx_slim_resume,
+	.suspend = wcd9xxx_slim_suspend,
+};
+
+#define TABLA_I2C_TOP_LEVEL 0
+#define TABLA_I2C_ANALOG       1
+#define TABLA_I2C_DIGITAL_1    2
+#define TABLA_I2C_DIGITAL_2    3
+
+static struct i2c_device_id tabla_id_table[] = {
+	{"tabla top level", TABLA_I2C_TOP_LEVEL},
+	{"tabla analog", TABLA_I2C_TOP_LEVEL},
+	{"tabla digital1", TABLA_I2C_TOP_LEVEL},
+	{"tabla digital2", TABLA_I2C_TOP_LEVEL},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tabla_id_table);
+
+static struct i2c_driver tabla_i2c_driver = {
+	.driver                 = {
+		.owner          =       THIS_MODULE,
+		.name           =       "tabla-i2c-core",
+	},
+	.id_table               =       tabla_id_table,
+	.probe                  =       wcd9xxx_i2c_probe,
+	.remove                 =       __devexit_p(wcd9xxx_i2c_remove),
+	.resume	= wcd9xxx_i2c_resume,
+	.suspend = wcd9xxx_i2c_suspend,
+};
+
+static int __init wcd9xxx_init(void)
+{
+	int ret1, ret2, ret3, ret4;
+
+	ret1 = slim_driver_register(&tabla_slim_driver);
+	if (ret1 != 0)
+		pr_err("Failed to register tabla SB driver: %d\n", ret1);
+
+	ret2 = slim_driver_register(&tabla2x_slim_driver);
+	if (ret2 != 0)
+		pr_err("Failed to register tabla2x SB driver: %d\n", ret2);
+
+	ret3 = i2c_add_driver(&tabla_i2c_driver);
+	if (ret3 != 0)
+		pr_err("failed to add the I2C driver\n");
+
+	ret4 = slim_driver_register(&sitar_slim_driver);
+	if (ret1 != 0)
+		pr_err("Failed to register sitar SB driver: %d\n", ret4);
+
+	return (ret1 && ret2 && ret3 && ret4) ? -1 : 0;
+}
+module_init(wcd9xxx_init);
+
+static void __exit wcd9xxx_exit(void)
+{
+}
+module_exit(wcd9xxx_exit);
+
+MODULE_DESCRIPTION("Codec core driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
new file mode 100644
index 0000000..86c01ee
--- /dev/null
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -0,0 +1,286 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9310_registers.h>
+#include <linux/interrupt.h>
+
+#define BYTE_BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_BYTE))
+#define BIT_BYTE(nr)			((nr) / BITS_PER_BYTE)
+
+struct wcd9xxx_irq {
+	bool level;
+};
+
+static struct wcd9xxx_irq wcd9xxx_irqs[TABLA_NUM_IRQS] = {
+	[0] = { .level = 1},
+/* All other wcd9xxx interrupts are edge triggered */
+};
+
+static inline int irq_to_wcd9xxx_irq(struct wcd9xxx *wcd9xxx, int irq)
+{
+	return irq - wcd9xxx->irq_base;
+}
+
+static void wcd9xxx_irq_lock(struct irq_data *data)
+{
+	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+	mutex_lock(&wcd9xxx->irq_lock);
+}
+
+static void wcd9xxx_irq_sync_unlock(struct irq_data *data)
+{
+	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wcd9xxx->irq_masks_cur); i++) {
+		/* If there's been a change in the mask write it back
+		 * to the hardware.
+		 */
+		if (wcd9xxx->irq_masks_cur[i] != wcd9xxx->irq_masks_cache[i]) {
+			wcd9xxx->irq_masks_cache[i] = wcd9xxx->irq_masks_cur[i];
+			wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_MASK0+i,
+				wcd9xxx->irq_masks_cur[i]);
+		}
+	}
+
+	mutex_unlock(&wcd9xxx->irq_lock);
+}
+
+static void wcd9xxx_irq_enable(struct irq_data *data)
+{
+	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+	int wcd9xxx_irq = irq_to_wcd9xxx_irq(wcd9xxx, data->irq);
+	wcd9xxx->irq_masks_cur[BIT_BYTE(wcd9xxx_irq)] &=
+		~(BYTE_BIT_MASK(wcd9xxx_irq));
+}
+
+static void wcd9xxx_irq_disable(struct irq_data *data)
+{
+	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+	int wcd9xxx_irq = irq_to_wcd9xxx_irq(wcd9xxx, data->irq);
+	wcd9xxx->irq_masks_cur[BIT_BYTE(wcd9xxx_irq)]
+			|= BYTE_BIT_MASK(wcd9xxx_irq);
+}
+
+static struct irq_chip wcd9xxx_irq_chip = {
+	.name = "wcd9xxx",
+	.irq_bus_lock = wcd9xxx_irq_lock,
+	.irq_bus_sync_unlock = wcd9xxx_irq_sync_unlock,
+	.irq_disable = wcd9xxx_irq_disable,
+	.irq_enable = wcd9xxx_irq_enable,
+};
+
+enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(struct wcd9xxx *wcd9xxx,
+		enum wcd9xxx_pm_state o,
+		enum wcd9xxx_pm_state n)
+{
+	enum wcd9xxx_pm_state old;
+	mutex_lock(&wcd9xxx->pm_lock);
+	old = wcd9xxx->pm_state;
+	if (old == o)
+		wcd9xxx->pm_state = n;
+	mutex_unlock(&wcd9xxx->pm_lock);
+	return old;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_pm_cmpxchg);
+
+void wcd9xxx_lock_sleep(struct wcd9xxx *wcd9xxx)
+{
+	enum wcd9xxx_pm_state os;
+
+	/* wcd9xxx_{lock/unlock}_sleep will be called by wcd9xxx_irq_thread
+	 * and its subroutines only motly.
+	 * but btn0_lpress_fn is not wcd9xxx_irq_thread's subroutine and
+	 * it can race with wcd9xxx_irq_thread.
+	 * so need to embrace wlock_holders with mutex.
+	 */
+	mutex_lock(&wcd9xxx->pm_lock);
+	if (wcd9xxx->wlock_holders++ == 0)
+		wake_lock(&wcd9xxx->wlock);
+	mutex_unlock(&wcd9xxx->pm_lock);
+	while (!wait_event_timeout(wcd9xxx->pm_wq,
+			((os = wcd9xxx_pm_cmpxchg(wcd9xxx, WCD9XXX_PM_SLEEPABLE,
+						WCD9XXX_PM_AWAKE)) ==
+						    WCD9XXX_PM_SLEEPABLE ||
+			 (os == WCD9XXX_PM_AWAKE)),
+			5 * HZ)) {
+		pr_err("%s: system didn't resume within 5000ms, state %d, "
+		       "wlock %d\n", __func__, wcd9xxx->pm_state,
+		       wcd9xxx->wlock_holders);
+		WARN_ON_ONCE(1);
+	}
+	wake_up_all(&wcd9xxx->pm_wq);
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_lock_sleep);
+
+void wcd9xxx_unlock_sleep(struct wcd9xxx *wcd9xxx)
+{
+	mutex_lock(&wcd9xxx->pm_lock);
+	if (--wcd9xxx->wlock_holders == 0) {
+		wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
+		wake_unlock(&wcd9xxx->wlock);
+	}
+	mutex_unlock(&wcd9xxx->pm_lock);
+	wake_up_all(&wcd9xxx->pm_wq);
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_unlock_sleep);
+
+static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
+{
+	int ret;
+	struct wcd9xxx *wcd9xxx = data;
+	u8 status[WCD9XXX_NUM_IRQ_REGS];
+	unsigned int i;
+
+	wcd9xxx_lock_sleep(wcd9xxx);
+	ret = wcd9xxx_bulk_read(wcd9xxx, TABLA_A_INTR_STATUS0,
+			       WCD9XXX_NUM_IRQ_REGS, status);
+	if (ret < 0) {
+		dev_err(wcd9xxx->dev, "Failed to read interrupt status: %d\n",
+			ret);
+		wcd9xxx_unlock_sleep(wcd9xxx);
+		return IRQ_NONE;
+	}
+	/* Apply masking */
+	for (i = 0; i < WCD9XXX_NUM_IRQ_REGS; i++)
+		status[i] &= ~wcd9xxx->irq_masks_cur[i];
+
+	/* Find out which interrupt was triggered and call that interrupt's
+	 * handler function
+	 */
+	for (i = 0; i < TABLA_NUM_IRQS; i++) {
+		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
+			if ((i <= TABLA_IRQ_MBHC_INSERTION) &&
+				(i >= TABLA_IRQ_MBHC_REMOVAL)) {
+				wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_CLEAR0 +
+					BIT_BYTE(i), BYTE_BIT_MASK(i));
+				if (wcd9xxx_get_intf_type() ==
+					WCD9XXX_INTERFACE_TYPE_I2C)
+					wcd9xxx_reg_write(wcd9xxx,
+						TABLA_A_INTR_MODE, 0x02);
+				handle_nested_irq(wcd9xxx->irq_base + i);
+			} else {
+				handle_nested_irq(wcd9xxx->irq_base + i);
+				wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_CLEAR0 +
+					BIT_BYTE(i), BYTE_BIT_MASK(i));
+				if (wcd9xxx_get_intf_type() ==
+					WCD9XXX_INTERFACE_TYPE_I2C)
+					wcd9xxx_reg_write(wcd9xxx,
+						TABLA_A_INTR_MODE, 0x02);
+			}
+			break;
+		}
+	}
+	wcd9xxx_unlock_sleep(wcd9xxx);
+
+	return IRQ_HANDLED;
+}
+
+int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx)
+{
+	int ret;
+	unsigned int i, cur_irq;
+
+	mutex_init(&wcd9xxx->irq_lock);
+
+	if (!wcd9xxx->irq) {
+		dev_warn(wcd9xxx->dev,
+			 "No interrupt specified, no interrupts\n");
+		wcd9xxx->irq_base = 0;
+		return 0;
+	}
+
+	if (!wcd9xxx->irq_base) {
+		dev_err(wcd9xxx->dev,
+			"No interrupt base specified, no interrupts\n");
+		return 0;
+	}
+	/* Mask the individual interrupt sources */
+	for (i = 0, cur_irq = wcd9xxx->irq_base; i < TABLA_NUM_IRQS; i++,
+		cur_irq++) {
+
+		irq_set_chip_data(cur_irq, wcd9xxx);
+
+		if (wcd9xxx_irqs[i].level)
+			irq_set_chip_and_handler(cur_irq, &wcd9xxx_irq_chip,
+					 handle_level_irq);
+		else
+			irq_set_chip_and_handler(cur_irq, &wcd9xxx_irq_chip,
+					 handle_edge_irq);
+
+		irq_set_nested_thread(cur_irq, 1);
+
+		/* ARM needs us to explicitly flag the IRQ as valid
+		 * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+		set_irq_flags(cur_irq, IRQF_VALID);
+#else
+		set_irq_noprobe(cur_irq);
+#endif
+
+		wcd9xxx->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+		wcd9xxx->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+		wcd9xxx->irq_level[BIT_BYTE(i)] |= wcd9xxx_irqs[i].level <<
+			(i % BITS_PER_BYTE);
+	}
+	for (i = 0; i < WCD9XXX_NUM_IRQ_REGS; i++) {
+		/* Initialize interrupt mask and level registers */
+		wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_LEVEL0 + i,
+			wcd9xxx->irq_level[i]);
+		wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_MASK0 + i,
+			wcd9xxx->irq_masks_cur[i]);
+	}
+
+	ret = request_threaded_irq(wcd9xxx->irq, NULL, wcd9xxx_irq_thread,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   "wcd9xxx", wcd9xxx);
+	if (ret != 0)
+		dev_err(wcd9xxx->dev, "Failed to request IRQ %d: %d\n",
+			wcd9xxx->irq, ret);
+	else {
+		ret = enable_irq_wake(wcd9xxx->irq);
+		if (ret == 0) {
+			ret = device_init_wakeup(wcd9xxx->dev, 1);
+			if (ret) {
+				dev_err(wcd9xxx->dev, "Failed to init device"
+					"wakeup : %d\n", ret);
+				disable_irq_wake(wcd9xxx->irq);
+			}
+		} else
+			dev_err(wcd9xxx->dev, "Failed to set wake interrupt on"
+				" IRQ %d: %d\n", wcd9xxx->irq, ret);
+		if (ret)
+			free_irq(wcd9xxx->irq, wcd9xxx);
+	}
+
+	if (ret)
+		mutex_destroy(&wcd9xxx->irq_lock);
+
+	return ret;
+}
+
+void wcd9xxx_irq_exit(struct wcd9xxx *wcd9xxx)
+{
+	if (wcd9xxx->irq) {
+		disable_irq_wake(wcd9xxx->irq);
+		free_irq(wcd9xxx->irq, wcd9xxx);
+		device_init_wakeup(wcd9xxx->dev, 0);
+	}
+	mutex_destroy(&wcd9xxx->irq_lock);
+}
diff --git a/drivers/mfd/wcd9310-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
similarity index 72%
rename from drivers/mfd/wcd9310-slimslave.c
rename to drivers/mfd/wcd9xxx-slimslave.c
index 12ac27f..acef55e 100644
--- a/drivers/mfd/wcd9310-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -11,45 +11,47 @@
  */
 #include <linux/slab.h>
 #include <linux/mutex.h>
-#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
 
-struct tabla_slim_sch_rx {
+struct wcd9xxx_slim_sch_rx {
 	u32 sph;
 	u32 ch_num;
 	u16 ch_h;
 	u16 grph;
 };
 
-struct tabla_slim_sch_tx {
+struct wcd9xxx_slim_sch_tx {
 	u32 sph;
 	u32 ch_num;
 	u16 ch_h;
 	u16 grph;
 };
 
-struct tabla_slim_sch {
-	struct tabla_slim_sch_rx rx[SLIM_MAX_RX_PORTS];
-	struct tabla_slim_sch_tx tx[SLIM_MAX_TX_PORTS];
+struct wcd9xxx_slim_sch {
+	struct wcd9xxx_slim_sch_rx rx[SLIM_MAX_RX_PORTS];
+	struct wcd9xxx_slim_sch_tx tx[SLIM_MAX_TX_PORTS];
 };
 
-static struct tabla_slim_sch sh_ch;
+static struct wcd9xxx_slim_sch sh_ch;
 
-static int tabla_alloc_slim_sh_ch_rx(struct tabla *tabla, u8 tabla_pgd_la);
-static int tabla_alloc_slim_sh_ch_tx(struct tabla *tabla, u8 tabla_pgd_la);
-static int tabla_dealloc_slim_sh_ch_rx(struct tabla *tab);
-static int tabla_dealloc_slim_sh_ch_tx(struct tabla *tab);
+static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
+					u8 wcd9xxx_pgd_la);
+static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
+					u8 wcd9xxx_pgd_la);
+static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx);
+static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx);
 
-int tabla_init_slimslave(struct tabla *tabla, u8 tabla_pgd_la)
+int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la)
 {
 	int ret = 0;
 
-	ret = tabla_alloc_slim_sh_ch_rx(tabla, tabla_pgd_la);
+	ret = wcd9xxx_alloc_slim_sh_ch_rx(wcd9xxx, wcd9xxx_pgd_la);
 	if (ret) {
 		pr_err("%s: Failed to alloc rx slimbus shared channels\n",
 								__func__);
 		goto rx_err;
 	}
-	ret = tabla_alloc_slim_sh_ch_tx(tabla, tabla_pgd_la);
+	ret = wcd9xxx_alloc_slim_sh_ch_tx(wcd9xxx, wcd9xxx_pgd_la);
 	if (ret) {
 		pr_err("%s: Failed to alloc tx slimbus shared channels\n",
 								__func__);
@@ -57,21 +59,21 @@
 	}
 	return 0;
 tx_err:
-	tabla_dealloc_slim_sh_ch_rx(tabla);
+	wcd9xxx_dealloc_slim_sh_ch_rx(wcd9xxx);
 rx_err:
 	return ret;
 }
 
 
-int tabla_deinit_slimslave(struct tabla *tabla)
+int wcd9xxx_deinit_slimslave(struct wcd9xxx *wcd9xxx)
 {
 	int ret = 0;
-	ret = tabla_dealloc_slim_sh_ch_rx(tabla);
+	ret = wcd9xxx_dealloc_slim_sh_ch_rx(wcd9xxx);
 	if (ret < 0) {
 		pr_err("%s: fail to dealloc rx slim ports\n", __func__);
 		goto err;
 	}
-	ret = tabla_dealloc_slim_sh_ch_tx(tabla);
+	ret = wcd9xxx_dealloc_slim_sh_ch_tx(wcd9xxx);
 	if (ret < 0) {
 		pr_err("%s: fail to dealloc tx slim ports\n", __func__);
 		goto err;
@@ -80,13 +82,13 @@
 	return ret;
 }
 
-int tabla_get_channel(struct tabla *tabla,
+int wcd9xxx_get_channel(struct wcd9xxx *wcd9xxx,
 		unsigned int *rx_ch,
 		unsigned int *tx_ch)
 {
 	int ch_idx = 0;
-	struct tabla_slim_sch_rx *rx = sh_ch.rx;
-	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+	struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
+	struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
 
 	for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++)
 		rx_ch[ch_idx] = rx[ch_idx].ch_num;
@@ -95,23 +97,23 @@
 	return 0;
 }
 
-static int tabla_alloc_slim_sh_ch_rx(struct tabla *tabla, u8 tabla_pgd_la)
+static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
+			u8 wcd9xxx_pgd_la)
 {
 	int ret = 0;
 	u8 ch_idx ;
 	u16 slave_port_id = 0;
-	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+	struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
 
-	/* DSP requires channel number to be between 128 and 255. For RX port
-	 * use channel numbers from 138 to 144, for TX port
-	 * use channel numbers from 128 to 137
+	/*
+	 * DSP requires channel number to be between 128 and 255.
 	 */
-	pr_debug("%s: pgd_la[%d]\n", __func__, tabla_pgd_la);
+	pr_debug("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
 	for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++) {
 		slave_port_id = (ch_idx + 1 +
 				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS);
 		rx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
-		ret = slim_get_slaveport(tabla_pgd_la, slave_port_id,
+		ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id,
 					&rx[ch_idx].sph, SLIM_SINK);
 		if (ret < 0) {
 			pr_err("%s: slave port failure id[%d] ret[%d]\n",
@@ -119,7 +121,7 @@
 			goto err;
 		}
 
-		ret = slim_query_ch(tabla->slim, rx[ch_idx].ch_num,
+		ret = slim_query_ch(wcd9xxx->slim, rx[ch_idx].ch_num,
 							&rx[ch_idx].ch_h);
 		if (ret < 0) {
 			pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
@@ -131,14 +133,15 @@
 	return ret;
 }
 
-static int tabla_alloc_slim_sh_ch_tx(struct tabla *tabla, u8 tabla_pgd_la)
+static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
+			u8 wcd9xxx_pgd_la)
 {
 	int ret = 0;
 	u8 ch_idx ;
-	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+	struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
 	u16 slave_port_id = 0;
 
-	pr_debug("%s: pgd_la[%d]\n", __func__, tabla_pgd_la);
+	pr_err("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
 	/* DSP requires channel number to be between 128 and 255. For RX port
 	 * use channel numbers from 138 to 144, for TX port
 	 * use channel numbers from 128 to 137
@@ -146,14 +149,14 @@
 	for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++) {
 		slave_port_id = ch_idx;
 		tx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
-		ret = slim_get_slaveport(tabla_pgd_la, slave_port_id,
+		ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id,
 					&tx[ch_idx].sph, SLIM_SRC);
 		if (ret < 0) {
 			pr_err("%s: slave port failure id[%d] ret[%d]\n",
 					__func__, slave_port_id, ret);
 			goto err;
 		}
-		ret = slim_query_ch(tabla->slim, tx[ch_idx].ch_num,
+		ret = slim_query_ch(wcd9xxx->slim, tx[ch_idx].ch_num,
 							&tx[ch_idx].ch_h);
 		if (ret < 0) {
 			pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
@@ -165,14 +168,14 @@
 	return ret;
 }
 
-static int tabla_dealloc_slim_sh_ch_rx(struct tabla *tab)
+static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx)
 {
 	int idx = 0;
 	int ret = 0;
-	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+	struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
 	/* slim_dealloc_ch */
 	for (idx = 0; idx < SLIM_MAX_RX_PORTS; idx++) {
-		ret = slim_dealloc_ch(tab->slim, rx[idx].ch_h);
+		ret = slim_dealloc_ch(wcd9xxx->slim, rx[idx].ch_h);
 		if (ret < 0) {
 			pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
 				__func__, ret, rx[idx].ch_h);
@@ -182,14 +185,14 @@
 	return ret;
 }
 
-static int tabla_dealloc_slim_sh_ch_tx(struct tabla *tab)
+static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx)
 {
 	int idx = 0;
 	int ret = 0;
-	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+	struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
 	/* slim_dealloc_ch */
 	for (idx = 0; idx < SLIM_MAX_TX_PORTS; idx++) {
-		ret = slim_dealloc_ch(tab->slim, tx[idx].ch_h);
+		ret = slim_dealloc_ch(wcd9xxx->slim, tx[idx].ch_h);
 		if (ret < 0) {
 			pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
 				__func__, ret, tx[idx].ch_h);
@@ -200,7 +203,7 @@
 }
 
 /* Enable slimbus slave device for RX path */
-int tabla_cfg_slim_sch_rx(struct tabla *tab, unsigned int *ch_num,
+int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
 				unsigned int ch_cnt, unsigned int rate)
 {
 	u8 i = 0;
@@ -211,15 +214,15 @@
 	u8  payload_rx = 0, wm_payload = 0;
 	int ret, idx = 0;
 	unsigned short  multi_chan_cfg_reg_addr;
-	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+	struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
 	struct slim_ch prop;
 
 	/* Configure slave interface device */
-	pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
+	pr_err("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
 
 	for (i = 0; i < ch_cnt; i++) {
 		idx = (ch_num[i] - BASE_CH_NUM -
-				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+			SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
 		ch_h[i] = rx[idx].ch_h;
 		sph[i] = rx[idx].sph;
 		slave_port_id = idx + 1;
@@ -249,7 +252,8 @@
 		multi_chan_cfg_reg_addr =
 				SB_PGD_RX_PORT_MULTI_CHANNEL_0(slave_port_id);
 		/* write to interface device */
-		ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
+				multi_chan_cfg_reg_addr,
 				payload_rx);
 		if (ret < 0) {
 			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
@@ -262,7 +266,7 @@
 		wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
 				SLAVE_PORT_WATER_MARK_SHIFT) +
 				SLAVE_PORT_ENABLE;
-		ret = tabla_interface_reg_write(tab,
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
 				SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
 				wm_payload);
 		if (ret < 0) {
@@ -279,7 +283,7 @@
 	prop.ratem = (rate/4000);
 	prop.sampleszbits = 16;
 
-	ret = slim_define_ch(tab->slim, &prop, ch_h, ch_cnt,
+	ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
 					true, &grph);
 	if (ret < 0) {
 		pr_err("%s: slim_define_ch failed ret[%d]\n",
@@ -287,7 +291,7 @@
 		goto err;
 	}
 	for (i = 0; i < ch_cnt; i++) {
-		ret = slim_connect_sink(tab->slim, &sph[i],
+		ret = slim_connect_sink(wcd9xxx->slim, &sph[i],
 							1, ch_h[i]);
 		if (ret < 0) {
 			pr_err("%s: slim_connect_sink failed ret[%d]\n",
@@ -296,7 +300,7 @@
 		}
 	}
 	/* slim_control_ch */
-	ret = slim_control_ch(tab->slim, grph, SLIM_CH_ACTIVATE,
+	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE,
 					true);
 	if (ret < 0) {
 		pr_err("%s: slim_control_ch failed ret[%d]\n",
@@ -312,14 +316,14 @@
 
 err_close_slim_sch:
 	/*  release all acquired handles */
-	tabla_close_slim_sch_rx(tab, ch_num, ch_cnt);
+	wcd9xxx_close_slim_sch_rx(wcd9xxx, ch_num, ch_cnt);
 err:
 	return ret;
 }
-EXPORT_SYMBOL_GPL(tabla_cfg_slim_sch_rx);
+EXPORT_SYMBOL_GPL(wcd9xxx_cfg_slim_sch_rx);
 
 /* Enable slimbus slave device for RX path */
-int tabla_cfg_slim_sch_tx(struct tabla *tab, unsigned int *ch_num,
+int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
 				unsigned int ch_cnt, unsigned int rate)
 {
 	u8 i = 0;
@@ -331,7 +335,7 @@
 	int ret = 0;
 	unsigned short  multi_chan_cfg_reg_addr;
 
-	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+	struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
 	struct slim_ch prop;
 
 	pr_debug("%s: ch_cnt[%d] rate[%d]\n", __func__, ch_cnt, rate);
@@ -366,7 +370,8 @@
 		multi_chan_cfg_reg_addr =
 				SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id);
 		/* write to interface device */
-		ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
+				multi_chan_cfg_reg_addr,
 				payload_tx_0);
 		if (ret < 0) {
 			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
@@ -378,7 +383,8 @@
 		multi_chan_cfg_reg_addr =
 				SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id);
 		/* ports 8,9 */
-		ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
+				multi_chan_cfg_reg_addr,
 				payload_tx_1);
 		if (ret < 0) {
 			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
@@ -391,7 +397,7 @@
 		wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
 				SLAVE_PORT_WATER_MARK_SHIFT) +
 				SLAVE_PORT_ENABLE;
-		ret = tabla_interface_reg_write(tab,
+		ret = wcd9xxx_interface_reg_write(wcd9xxx,
 				SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
 				wm_payload);
 		if (ret < 0) {
@@ -408,7 +414,7 @@
 	prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
 	prop.ratem = (rate/4000);
 	prop.sampleszbits = 16;
-	ret = slim_define_ch(tab->slim, &prop, ch_h, ch_cnt,
+	ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
 					true, &grph);
 	if (ret < 0) {
 		pr_err("%s: slim_define_ch failed ret[%d]\n",
@@ -416,7 +422,7 @@
 		goto err;
 	}
 	for (i = 0; i < ch_cnt; i++) {
-		ret = slim_connect_src(tab->slim, sph[i],
+		ret = slim_connect_src(wcd9xxx->slim, sph[i],
 							ch_h[i]);
 		if (ret < 0) {
 			pr_err("%s: slim_connect_src failed ret[%d]\n",
@@ -425,7 +431,7 @@
 		}
 	}
 	/* slim_control_ch */
-	ret = slim_control_ch(tab->slim, grph, SLIM_CH_ACTIVATE,
+	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE,
 					true);
 	if (ret < 0) {
 		pr_err("%s: slim_control_ch failed ret[%d]\n",
@@ -439,21 +445,21 @@
 	return 0;
 err:
 	/* release all acquired handles */
-	tabla_close_slim_sch_tx(tab, ch_num, ch_cnt);
+	wcd9xxx_close_slim_sch_tx(wcd9xxx, ch_num, ch_cnt);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(tabla_cfg_slim_sch_tx);
+EXPORT_SYMBOL_GPL(wcd9xxx_cfg_slim_sch_tx);
 
-int tabla_close_slim_sch_rx(struct tabla *tab, unsigned int *ch_num,
+int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
 				unsigned int ch_cnt)
 {
 	u16 grph = 0;
 	u32 sph[SLIM_MAX_RX_PORTS] = {0};
 	int i = 0 , idx = 0;
 	int ret = 0;
-	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+	struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
 
-	pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+	pr_err("%s: ch_cnt[%d]\n", __func__, ch_cnt);
 	for (i = 0; i < ch_cnt; i++) {
 		idx = (ch_num[i] - BASE_CH_NUM -
 				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
@@ -462,13 +468,13 @@
 	}
 
 	/* slim_disconnect_port */
-	ret = slim_disconnect_ports(tab->slim, sph, ch_cnt);
+	ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
 	if (ret < 0) {
 		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
 				__func__, ret);
 	}
 	/* slim_control_ch (REMOVE) */
-	ret = slim_control_ch(tab->slim, grph, SLIM_CH_REMOVE, true);
+	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
 	if (ret < 0) {
 		pr_err("%s: slim_control_ch failed ret[%d]\n",
 				__func__, ret);
@@ -482,31 +488,31 @@
 err:
 	return ret;
 }
-EXPORT_SYMBOL_GPL(tabla_close_slim_sch_rx);
+EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_rx);
 
-int tabla_close_slim_sch_tx(struct tabla *tab, unsigned int *ch_num,
+int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
 				unsigned int ch_cnt)
 {
 	u16 grph = 0;
 	u32 sph[SLIM_MAX_TX_PORTS] = {0};
 	int ret = 0;
 	int i = 0 , idx = 0;
-	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+	struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
 
-	pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+	pr_err("%s: ch_cnt[%d]\n", __func__, ch_cnt);
 	for (i = 0; i < ch_cnt; i++) {
 		idx = (ch_num[i] - BASE_CH_NUM);
 		sph[i] = tx[idx].sph;
 		grph = tx[idx].grph;
 	}
 	/* slim_disconnect_port */
-	ret = slim_disconnect_ports(tab->slim, sph, ch_cnt);
+	ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
 	if (ret < 0) {
 		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
 				__func__, ret);
 	}
 	/* slim_control_ch (REMOVE) */
-	ret = slim_control_ch(tab->slim, grph, SLIM_CH_REMOVE, true);
+	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
 	if (ret < 0) {
 		pr_err("%s: slim_control_ch failed ret[%d]\n",
 				__func__, ret);
@@ -519,4 +525,4 @@
 err:
 	return ret;
 }
-EXPORT_SYMBOL_GPL(tabla_close_slim_sch_tx);
+EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_tx);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index e4c3152..a8f9f35 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -199,7 +199,7 @@
 };
 
 static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
-		struct qseecom_register_listener_req svc)
+		struct qseecom_register_listener_req *svc)
 {
 	struct qseecom_registered_listener_list *ptr;
 	int unique = 1;
@@ -207,7 +207,7 @@
 
 	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
 	list_for_each_entry(ptr, &qseecom.registered_listener_list_head, list) {
-		if (ptr->svc.listener_id == svc.listener_id) {
+		if (ptr->svc.listener_id == svc->listener_id) {
 			pr_err("Service id: %u is already registered\n",
 					ptr->svc.listener_id);
 			unique = 0;
@@ -333,16 +333,12 @@
 		pr_err("copy_from_user failed\n");
 		return ret;
 	}
-
-	if (!__qseecom_is_svc_unique(data, rcvd_lstnr)) {
+	data->listener.id = 0;
+	data->service = true;
+	if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
 		pr_err("Service is not unique and is already registered\n");
-		return ret;
-	}
-
-	ret = copy_to_user(argp, &rcvd_lstnr, sizeof(rcvd_lstnr));
-	if (ret) {
-		pr_err("copy_to_user failed\n");
-		return ret;
+		data->released = true;
+		return -EBUSY;
 	}
 
 	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
@@ -360,13 +356,14 @@
 		kzfree(new_entry);
 		return -ENOMEM;
 	}
+
 	data->listener.id = rcvd_lstnr.listener_id;
-	data->service = true;
 	init_waitqueue_head(&new_entry->rcv_req_wq);
 
 	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
 	list_add_tail(&new_entry->list, &qseecom.registered_listener_list_head);
 	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+
 	return ret;
 }
 
@@ -743,6 +740,7 @@
 					break;
 				} else {
 					ptr_app->ref_cnt--;
+					data->released = true;
 					break;
 				}
 			}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e364eac..0d2b11d 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2877,15 +2877,22 @@
  * Select the 3/4 of the range and configure the DLL with the
  * selected DLL clock output phase.
 */
-static u8 find_most_appropriate_phase(struct msmsdcc_host *host,
+static int find_most_appropriate_phase(struct msmsdcc_host *host,
 				u8 *phase_table, u8 total_phases)
 {
-	u8 ret, ranges[16][16] = { {0}, {0} };
+	int ret;
+	u8 ranges[16][16] = { {0}, {0} };
 	u8 phases_per_row[16] = {0};
 	int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
 	int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
 	bool phase_0_found = false, phase_15_found = false;
 
+	if (total_phases > 16) {
+		pr_err("%s: %s: invalid argument: total_phases=%d\n",
+			mmc_hostname(host->mmc), __func__, total_phases);
+		return -EINVAL;
+	}
+
 	for (cnt = 0; cnt < total_phases; cnt++) {
 		ranges[row_index][col_index] = phase_table[cnt];
 		phases_per_row[row_index] += 1;
@@ -2943,7 +2950,7 @@
 	}
 
 	i = ((curr_max * 3) / 4) - 1;
-	ret = ranges[selected_row_index][i];
+	ret = (int)ranges[selected_row_index][i];
 
 	return ret;
 }
@@ -3022,8 +3029,13 @@
 	} while (++phase < 16);
 
 	if (tuned_phase_cnt) {
-		phase = find_most_appropriate_phase(host, tuned_phases,
+		rc = find_most_appropriate_phase(host, tuned_phases,
 							tuned_phase_cnt);
+		if (rc < 0)
+			goto kfree;
+		else
+			phase = (u8)rc;
+
 		/*
 		 * Finally set the selected phase in delay
 		 * line hw block.
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index b693b18..5a016bb 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -264,19 +264,10 @@
 {
 	int	retval = 0;
 
-	retval = usb_autopm_get_interface(dev->intf);
-	if (retval < 0) {
-		dev_err(dev->devicep, "%s Resumption fail\n", __func__);
-		goto done_nopm;
-	}
-
 	retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
 	if (retval < 0)
 		dev_err(dev->devicep, "%s Intr submit %d\n", __func__, retval);
 
-	usb_autopm_put_interface(dev->intf);
-
-done_nopm:
 	return retval;
 }
 
@@ -342,35 +333,19 @@
 }
 static int rmnet_usb_ctrl_write_cmd(struct rmnet_ctrl_dev *dev)
 {
-	int			retval = 0;
 	struct usb_device	*udev;
 
 	if (!is_dev_connected(dev))
 		return -ENODEV;
 
 	udev = interface_to_usbdev(dev->intf);
-	retval = usb_autopm_get_interface(dev->intf);
-	if (retval < 0) {
-		dev_err(dev->devicep, "%s: Unable to resume interface: %d\n",
-			__func__, retval);
-
-		/*
-		* Revisit if (retval == -EPERM)
-		*		rmnet_usb_suspend(dev->intf, PMSG_SUSPEND);
-		*/
-
-		return retval;
-	}
 	dev->set_ctrl_line_state_cnt++;
-	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+	return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 		USB_CDC_REQ_SET_CONTROL_LINE_STATE,
 		(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE),
 		dev->cbits_tomdm,
 		dev->intf->cur_altsetting->desc.bInterfaceNumber,
 		NULL, 0, USB_CTRL_SET_TIMEOUT);
-	usb_autopm_put_interface(dev->intf);
-
-	return retval;
 }
 
 static void ctrl_write_callback(struct urb *urb)
@@ -428,7 +403,7 @@
 			     (unsigned char *)out_ctlreq, (void *)buf, size,
 			     ctrl_write_callback, dev);
 
-	result = usb_autopm_get_interface_async(dev->intf);
+	result = usb_autopm_get_interface(dev->intf);
 	if (result < 0) {
 		dev_err(dev->devicep, "%s: Unable to resume interface: %d\n",
 			__func__, result);
@@ -450,7 +425,7 @@
 		dev_err(dev->devicep, "%s: Submit URB error %d\n",
 			__func__, result);
 		dev->snd_encap_cmd_cnt--;
-		usb_autopm_put_interface_async(dev->intf);
+		usb_autopm_put_interface(dev->intf);
 		usb_unanchor_urb(sndurb);
 		usb_free_urb(sndurb);
 		kfree(out_ctlreq);
@@ -573,7 +548,7 @@
 
 ctrl_read:
 	if (!is_dev_connected(dev)) {
-		dev_err(dev->devicep, "%s: Device not connected\n",
+		dev_dbg(dev->devicep, "%s: Device not connected\n",
 			__func__);
 		return -ENETRESET;
 	}
@@ -662,6 +637,8 @@
 static int rmnet_ctrl_tiocmset(struct rmnet_ctrl_dev *dev, unsigned int set,
 		unsigned int clear)
 {
+	int retval;
+
 	mutex_lock(&dev->dev_lock);
 	if (set & TIOCM_DTR)
 		dev->cbits_tomdm |= ACM_CTRL_DTR;
@@ -681,7 +658,17 @@
 
 	mutex_unlock(&dev->dev_lock);
 
-	return rmnet_usb_ctrl_write_cmd(dev);
+	retval = usb_autopm_get_interface(dev->intf);
+	if (retval < 0) {
+		dev_err(dev->devicep, "%s: Unable to resume interface: %d\n",
+			__func__, retval);
+		return retval;
+	}
+
+	retval = rmnet_usb_ctrl_write_cmd(dev);
+
+	usb_autopm_put_interface(dev->intf);
+	return retval;
 }
 
 static int rmnet_ctrl_tiocmget(struct rmnet_ctrl_dev *dev)
@@ -774,6 +761,10 @@
 	dev->tx_ctrl_err_cnt = 0;
 	dev->set_ctrl_line_state_cnt = 0;
 
+	ret = rmnet_usb_ctrl_write_cmd(dev);
+	if (ret < 0)
+		return ret;
+
 	dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->inturb) {
 		dev_err(dev->devicep, "Error allocating int urb\n");
@@ -799,19 +790,15 @@
 		dev->intf->cur_altsetting->desc.bInterfaceNumber;
 	dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
 
-	interval =
-		max((int)int_in->desc.bInterval,
-		(udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL);
+	interval = max((int)int_in->desc.bInterval,
+			(udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL
+							: FS_LS_INTERVAL);
 
 	usb_fill_int_urb(dev->inturb, udev,
 			 dev->int_pipe,
 			 dev->intbuf, wMaxPacketSize,
 			 notification_available_cb, dev, interval);
 
-	ret = rmnet_usb_ctrl_write_cmd(dev);
-	if (ret < 0)
-		return ret;
-
 	return rmnet_usb_ctrl_start_rx(dev);
 }
 
@@ -828,6 +815,8 @@
 	dev->intf = NULL;
 	mutex_unlock(&dev->dev_lock);
 
+	wake_up(&dev->read_wait_queue);
+
 	usb_free_urb(dev->inturb);
 	dev->inturb = NULL;
 
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index ffdfce1..1eb6845 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -148,7 +148,6 @@
 
 	retval = usbnet_resume(iface);
 	if (!retval) {
-
 		if (oldstate & PM_EVENT_SUSPEND)
 			retval = rmnet_usb_ctrl_start(dev);
 	}
@@ -260,6 +259,12 @@
 	return 1;
 }
 
+static int rmnet_usb_manage_power(struct usbnet *dev, int on)
+{
+	dev->intf->needs_remote_wakeup = on;
+	return 0;
+}
+
 static int rmnet_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if (0 > new_mtu || RMNET_DATA_LEN < new_mtu)
@@ -494,12 +499,14 @@
 /*bit position represents interface number*/
 #define PID9034_IFACE_MASK	0xF0
 #define PID9048_IFACE_MASK	0x1E0
+#define PID904C_IFACE_MASK	0x1C0
 
 static const struct driver_info rmnet_info_pid9034 = {
 	.description   = "RmNET net device",
 	.bind          = rmnet_usb_bind,
 	.tx_fixup      = rmnet_usb_tx_fixup,
 	.rx_fixup      = rmnet_usb_rx_fixup,
+	.manage_power  = rmnet_usb_manage_power,
 	.data          = PID9034_IFACE_MASK,
 };
 
@@ -508,9 +515,19 @@
 	.bind          = rmnet_usb_bind,
 	.tx_fixup      = rmnet_usb_tx_fixup,
 	.rx_fixup      = rmnet_usb_rx_fixup,
+	.manage_power  = rmnet_usb_manage_power,
 	.data          = PID9048_IFACE_MASK,
 };
 
+static const struct driver_info rmnet_info_pid904c = {
+	.description   = "RmNET net device",
+	.bind          = rmnet_usb_bind,
+	.tx_fixup      = rmnet_usb_tx_fixup,
+	.rx_fixup      = rmnet_usb_rx_fixup,
+	.manage_power  = rmnet_usb_manage_power,
+	.data          = PID904C_IFACE_MASK,
+};
+
 static const struct usb_device_id vidpids[] = {
 	{
 		USB_DEVICE(0x05c6, 0x9034), /* MDM9x15*/
@@ -520,6 +537,10 @@
 		USB_DEVICE(0x05c6, 0x9048), /* MDM9x15*/
 		.driver_info = (unsigned long)&rmnet_info_pid9048,
 	},
+	{
+		USB_DEVICE(0x05c6, 0x904c), /* MDM9x15*/
+		.driver_info = (unsigned long)&rmnet_info_pid904c,
+	},
 
 	{ }, /* Terminating entry */
 };
diff --git a/drivers/of/of_spmi.c b/drivers/of/of_spmi.c
index 9f2a396..2032b46 100644
--- a/drivers/of/of_spmi.c
+++ b/drivers/of/of_spmi.c
@@ -19,62 +19,93 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 
-/**
- * Allocate resources for a child of a spmi-container node.
- */
-static int of_spmi_allocate_resources(struct spmi_controller *ctrl,
-				      struct spmi_boardinfo *info,
-				      struct device_node *node,
-				      uint32_t num_reg)
+struct of_spmi_dev_info {
+	struct spmi_controller *ctrl;
+	struct spmi_boardinfo b_info;
+};
+
+struct of_spmi_res_info {
+	struct device_node *node;
+	uint32_t num_reg;
+	uint32_t num_irq;
+};
+
+static void of_spmi_sum_resources(struct of_spmi_res_info *r_info, bool has_reg)
 {
-	int i, num_irq = 0;
+	struct of_irq oirq;
 	uint64_t size;
 	uint32_t flags;
+
+	while (of_irq_map_one(r_info->node, r_info->num_irq, &oirq) == 0)
+		r_info->num_irq++;
+
+	if (!has_reg)
+		return;
+
+	/*
+	 * We can't use of_address_to_resource here since it includes
+	 * address translation; and address translation assumes that no
+	 * parent buses have a size-cell of 0. But SPMI does have a
+	 * size-cell of 0.
+	 */
+	while (of_get_address(r_info->node, r_info->num_reg,
+						&size, &flags) != NULL)
+		r_info->num_reg++;
+}
+
+/**
+ * Allocate resources for a child of a spmi-slave node.
+ */
+static int of_spmi_allocate_resources(struct of_spmi_dev_info *d_info,
+				      struct of_spmi_res_info *r_info)
+
+{
+	uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg;
+	int i;
 	struct resource *res;
 	const  __be32 *addrp;
-	struct of_irq oirq;
-
-	while (of_irq_map_one(node, num_irq, &oirq) == 0)
-		num_irq++;
+	uint64_t size;
+	uint32_t flags;
 
 	if (num_irq || num_reg) {
 		res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
 		if (!res)
 			return -ENOMEM;
 
-		info->num_resources = num_reg + num_irq;
-		info->resource = res;
+		d_info->b_info.num_resources = num_reg + num_irq;
+		d_info->b_info.resource = res;
 		for (i = 0; i < num_reg; i++, res++) {
 			/* Addresses are always 16 bits */
-			addrp = of_get_address(node, i, &size, &flags);
+			addrp = of_get_address(r_info->node, i, &size, &flags);
 			BUG_ON(!addrp);
 			res->start = be32_to_cpup(addrp);
 			res->end = res->start + size - 1;
 			res->flags = flags;
 		}
-		WARN_ON(of_irq_to_resource_table(node, res, num_irq) !=
+		WARN_ON(of_irq_to_resource_table(r_info->node, res, num_irq) !=
 								num_irq);
 	}
 
 	return 0;
 }
 
-static int of_spmi_create_device(struct spmi_controller *ctrl,
-				 struct spmi_boardinfo *info,
-			  struct device_node *node)
+static int of_spmi_create_device(struct of_spmi_dev_info *d_info,
+				 struct device_node *node)
 {
+	struct spmi_controller *ctrl = d_info->ctrl;
+	struct spmi_boardinfo *b_info = &d_info->b_info;
 	void *result;
 	int rc;
 
-	rc = of_modalias_node(node, info->name, sizeof(info->name));
+	rc = of_modalias_node(node, b_info->name, sizeof(b_info->name));
 	if (rc < 0) {
 		dev_err(&ctrl->dev, "of_spmi modalias failure on %s\n",
 				node->full_name);
 		return rc;
 	}
 
-	info->of_node = of_node_get(node);
-	result = spmi_new_device(ctrl, info);
+	b_info->of_node = of_node_get(node);
+	result = spmi_new_device(ctrl, b_info);
 
 	if (result == NULL) {
 		dev_err(&ctrl->dev, "of_spmi: Failure registering %s\n",
@@ -86,32 +117,26 @@
 	return 0;
 }
 
-static void of_spmi_walk_container_children(struct spmi_controller *ctrl,
-				     struct spmi_boardinfo *info,
-				     struct device_node *container)
+static void of_spmi_walk_slave_container(struct of_spmi_dev_info *d_info,
+					struct device_node *container)
 {
+	struct spmi_controller *ctrl = d_info->ctrl;
 	struct device_node *node;
-	uint64_t size;
-	uint32_t flags, num_reg = 0;
 	int rc;
 
 	for_each_child_of_node(container, node) {
-		/*
-		 * We can't use of_address_to_resource here since it includes
-		 * address translation; and address translation assumes that no
-		 * parent buses have a size-cell of 0. But SPMI does have a
-		 * size-cell of 0.
-		 */
-		while (of_get_address(node, num_reg, &size, &flags) != NULL)
-			num_reg++;
+		struct of_spmi_res_info r_info;
 
-		rc = of_spmi_allocate_resources(ctrl, info, node, num_reg);
+		r_info.node = node;
+		of_spmi_sum_resources(&r_info, 1);
+
+		rc = of_spmi_allocate_resources(d_info, &r_info);
 		if (rc) {
 			dev_err(&ctrl->dev, "%s: unable to allocate"
 						" resources\n", __func__);
 			return;
 		}
-		rc = of_spmi_create_device(ctrl, info, node);
+		rc = of_spmi_create_device(d_info, node);
 		if (rc) {
 			dev_err(&ctrl->dev, "%s: unable to create device for"
 				     " node %s\n", __func__, node->full_name);
@@ -129,7 +154,7 @@
 		return -ENODEV;
 
 	for_each_child_of_node(ctrl->dev.of_node, node) {
-		struct spmi_boardinfo info = {};
+		struct of_spmi_dev_info d_info = {};
 		const __be32 *slave_id;
 		int len, rc;
 
@@ -140,16 +165,21 @@
 			continue;
 		}
 
-		info.slave_id = be32_to_cpup(slave_id);
+		d_info.b_info.slave_id = be32_to_cpup(slave_id);
+		d_info.ctrl = ctrl;
 
-		if (of_get_property(node, "spmi-dev-container", NULL)) {
-			of_spmi_walk_container_children(ctrl, &info, node);
+		if (of_get_property(node, "spmi-slave-container", NULL)) {
+			of_spmi_walk_slave_container(&d_info, node);
 			continue;
 		} else {
-			rc = of_spmi_allocate_resources(ctrl, &info, node, 0);
+			struct of_spmi_res_info r_info;
+
+			r_info.node = node;
+			of_spmi_sum_resources(&r_info, 0);
+			rc = of_spmi_allocate_resources(&d_info, &r_info);
 			if (rc)
 				continue;
-			of_spmi_create_device(ctrl, &info, node);
+			of_spmi_create_device(&d_info, node);
 		}
 	}
 
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 709583a..f157ff3 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -25,8 +25,10 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/mutex.h>
 
 #define BMS_CONTROL		0x224
+#define BMS_S1_DELAY		0x225
 #define BMS_OUTPUT0		0x230
 #define BMS_OUTPUT1		0x231
 #define BMS_TOLERANCES		0x232
@@ -97,7 +99,7 @@
 	unsigned int		batt_id_channel;
 	unsigned int		pmic_bms_irq[PM_BMS_MAX_INTS];
 	DECLARE_BITMAP(enabled_irqs, PM_BMS_MAX_INTS);
-	spinlock_t		bms_output_lock;
+	struct mutex		bms_output_lock;
 	spinlock_t		bms_100_lock;
 	struct single_row_lut	*adjusted_fcc_temp_lut;
 	unsigned int		charging_began;
@@ -353,14 +355,6 @@
 		return -EINVAL;
 	}
 
-	/* make sure the bms registers are locked */
-	rc = pm8xxx_readb(chip->dev->parent, BMS_CONTROL, &reg);
-	if (rc) {
-		pr_err("fail to read BMS_OUTPUT0 for type %d rc = %d\n",
-			type, rc);
-		return rc;
-	}
-
 	rc = pm_bms_masked_write(chip, BMS_CONTROL, SELECT_OUTPUT_DATA,
 					type << SELECT_OUTPUT_TYPE_SHIFT);
 	if (rc) {
@@ -775,12 +769,56 @@
 	return 100;
 }
 
+#define BMS_MODE_BIT	BIT(6)
+#define EN_VBAT_BIT	BIT(5)
+#define OVERRIDE_MODE_DELAY_MS	20
+int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
+								int *vbat_uv)
+{
+	int16_t vsense_raw;
+	int16_t vbat_raw;
+	int vsense_uv;
+
+	if (the_chip == NULL) {
+		pr_err("Called to early\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&the_chip->bms_output_lock);
+
+	pm8xxx_writeb(the_chip->dev->parent, BMS_S1_DELAY, 0x00);
+	pm_bms_masked_write(the_chip, BMS_CONTROL,
+			BMS_MODE_BIT | EN_VBAT_BIT, BMS_MODE_BIT | EN_VBAT_BIT);
+
+	msleep(OVERRIDE_MODE_DELAY_MS);
+
+	pm_bms_lock_output_data(the_chip);
+	pm_bms_read_output_data(the_chip, VSENSE_AVG, &vsense_raw);
+	pm_bms_read_output_data(the_chip, VBATT_AVG, &vbat_raw);
+	pm_bms_unlock_output_data(the_chip);
+	pm_bms_masked_write(the_chip, BMS_CONTROL,
+			BMS_MODE_BIT | EN_VBAT_BIT, 0);
+
+	pm8xxx_writeb(the_chip->dev->parent, BMS_S1_DELAY, 0x0B);
+
+	mutex_unlock(&the_chip->bms_output_lock);
+
+	convert_vbatt_raw_to_uv(the_chip, vbat_raw, vbat_uv);
+	convert_vsense_to_uv(the_chip, vsense_raw, &vsense_uv);
+	*ibat_ua = vsense_uv * 1000 / (int)the_chip->r_sense;
+
+	pr_debug("vsense_raw = 0x%x vbat_raw = 0x%x"
+			" ibat_ua = %d vbat_uv = %d\n",
+			(uint16_t)vsense_raw, (uint16_t)vbat_raw,
+			*ibat_ua, *vbat_uv);
+	return 0;
+}
+EXPORT_SYMBOL(pm8921_bms_get_simultaneous_battery_voltage_and_current);
+
 static int read_soc_params_raw(struct pm8921_bms_chip *chip,
 				struct pm8921_soc_params *raw)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->bms_output_lock, flags);
+	mutex_lock(&chip->bms_output_lock);
 	pm_bms_lock_output_data(chip);
 
 	pm_bms_read_output_data(chip,
@@ -794,7 +832,7 @@
 	read_cc(chip, &raw->cc);
 
 	pm_bms_unlock_output_data(chip);
-	spin_unlock_irqrestore(&chip->bms_output_lock, flags);
+	mutex_unlock(&chip->bms_output_lock);
 
 	convert_vbatt_raw_to_uv(chip,
 			raw->vbatt_for_rbatt_raw, &raw->vbatt_for_rbatt_uv);
@@ -808,6 +846,18 @@
 	if (raw->last_good_ocv_uv)
 		last_ocv_uv = raw->last_good_ocv_uv;
 
+	pr_debug("0p625 = %duV\n", chip->xoadc_v0625);
+	pr_debug("1p25 = %duV\n", chip->xoadc_v125);
+
+	pr_debug("vbatt_for_rbatt_raw = 0x%x, vbatt_for_rbatt= %duV\n",
+			raw->vbatt_for_rbatt_raw, raw->vbatt_for_rbatt_uv);
+	pr_debug("ocv_for_rbatt_raw = 0x%x, ocv_for_rbatt= %duV\n",
+			raw->ocv_for_rbatt_raw, raw->ocv_for_rbatt_uv);
+	pr_debug("vsense_for_rbatt_raw = 0x%x, vsense_for_rbatt= %duV\n",
+			raw->vsense_for_rbatt_raw, raw->vsense_for_rbatt_uv);
+	pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
+			raw->last_good_ocv_raw, raw->last_good_ocv_uv);
+	pr_debug("cc_raw= 0x%x\n", raw->cc);
 	return 0;
 }
 
@@ -1077,8 +1127,14 @@
 					- unusable_charge_uah;
 
 	pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
-	soc = (remaining_usable_charge_uah * 100)
-		/ (fcc_uah - unusable_charge_uah);
+	if (fcc_uah - unusable_charge_uah <= 0) {
+		pr_warn("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
+						fcc_uah, unusable_charge_uah);
+		soc = 0;
+	} else {
+		soc = (remaining_usable_charge_uah * 100)
+			/ (fcc_uah - unusable_charge_uah);
+	}
 
 	if (soc > 100)
 		soc = 100;
@@ -1162,12 +1218,18 @@
 	calib_hkadc(chip);
 }
 
+void pm8921_bms_calibrate_hkadc(void)
+{
+	schedule_work(&the_chip->calib_hkadc_work);
+}
+
 static void calibrate_ccadc_work(struct work_struct *work)
 {
 	struct pm8921_bms_chip *chip = container_of(work,
 				struct pm8921_bms_chip, calib_ccadc_work.work);
 
 	pm8xxx_calib_ccadc();
+	calib_hkadc(chip);
 	schedule_delayed_work(&chip->calib_ccadc_work,
 			round_jiffies_relative(msecs_to_jiffies
 			(chip->calib_delay_ms)));
@@ -1176,14 +1238,13 @@
 int pm8921_bms_get_vsense_avg(int *result)
 {
 	int rc = -EINVAL;
-	unsigned long flags;
 
 	if (the_chip) {
-		spin_lock_irqsave(&the_chip->bms_output_lock, flags);
+		mutex_lock(&the_chip->bms_output_lock);
 		pm_bms_lock_output_data(the_chip);
 		rc = read_vsense_avg(the_chip, result);
 		pm_bms_unlock_output_data(the_chip);
-		spin_unlock_irqrestore(&the_chip->bms_output_lock, flags);
+		mutex_unlock(&the_chip->bms_output_lock);
 	}
 
 	pr_err("called before initialization\n");
@@ -1193,7 +1254,6 @@
 
 int pm8921_bms_get_battery_current(int *result_ua)
 {
-	unsigned long flags;
 	int vsense;
 
 	if (!the_chip) {
@@ -1205,15 +1265,15 @@
 		return -EINVAL;
 	}
 
-	spin_lock_irqsave(&the_chip->bms_output_lock, flags);
+	mutex_lock(&the_chip->bms_output_lock);
 	pm_bms_lock_output_data(the_chip);
 	read_vsense_avg(the_chip, &vsense);
 	pm_bms_unlock_output_data(the_chip);
-	spin_unlock_irqrestore(&the_chip->bms_output_lock, flags);
-	pr_debug("vsense=%d\n", vsense);
+	mutex_unlock(&the_chip->bms_output_lock);
+	pr_debug("vsense=%duV\n", vsense);
 	/* cast for signed division */
 	*result_ua = vsense * 1000 / (int)the_chip->r_sense;
-
+	pr_debug("ibat=%duA\n", *result_ua);
 	return 0;
 }
 EXPORT_SYMBOL(pm8921_bms_get_battery_current);
@@ -1621,13 +1681,14 @@
 		return 0;
 }
 
-enum {
+enum bms_request_operation {
 	CALC_RBATT,
 	CALC_FCC,
 	CALC_PC,
 	CALC_SOC,
 	CALIB_HKADC,
 	CALIB_CCADC,
+	GET_VBAT_VSENSE_SIMULTANEOUS,
 };
 
 static int test_batt_temp = 5;
@@ -1678,6 +1739,7 @@
 {
 	int param = (int)data;
 	int ret = 0;
+	int ibat_ua, vbat_uv;
 	struct pm8921_soc_params raw;
 
 	read_soc_params_raw(the_chip, &raw);
@@ -1711,6 +1773,13 @@
 		*val = 0;
 		pm8xxx_calib_ccadc();
 		break;
+	case GET_VBAT_VSENSE_SIMULTANEOUS:
+		/* reading this will call simultaneous vbat and vsense */
+		*val =
+		pm8921_bms_get_simultaneous_battery_voltage_and_current(
+			&ibat_ua,
+			&vbat_uv);
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -1854,6 +1923,9 @@
 	debugfs_create_file("calib_ccadc", 0644, chip->dent,
 				(void *)CALIB_CCADC, &calc_fops);
 
+	debugfs_create_file("simultaneous", 0644, chip->dent,
+			(void *)GET_VBAT_VSENSE_SIMULTANEOUS, &calc_fops);
+
 	for (i = 0; i < ARRAY_SIZE(bms_irq_data); i++) {
 		if (chip->pmic_bms_irq[bms_irq_data[i].irq_id])
 			debugfs_create_file(bms_irq_data[i].name, 0444,
@@ -1881,7 +1953,7 @@
 		pr_err("Cannot allocate pm_bms_chip\n");
 		return -ENOMEM;
 	}
-	spin_lock_init(&chip->bms_output_lock);
+	mutex_init(&chip->bms_output_lock);
 	spin_lock_init(&chip->bms_100_lock);
 	chip->dev = &pdev->dev;
 	chip->r_sense = pdata->r_sense;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index aca724a..60d4e64 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -256,9 +256,9 @@
 	int				thermal_levels;
 	struct delayed_work		update_heartbeat_work;
 	struct delayed_work		eoc_work;
-	struct delayed_work		unplug_wrkarnd_restore_work;
+	struct work_struct		unplug_ovp_fet_open_work;
 	struct delayed_work		unplug_check_work;
-	struct wake_lock		unplug_wrkarnd_restore_wake_lock;
+	struct wake_lock		unplug_ovp_fet_open_wake_lock;
 	struct wake_lock		eoc_wake_lock;
 	enum pm8921_chg_cold_thr	cold_thr;
 	enum pm8921_chg_hot_thr		hot_thr;
@@ -417,23 +417,28 @@
 
 #define PM8921_CHG_V_MIN_MV	3240
 #define PM8921_CHG_V_STEP_MV	20
-#define PM8921_CHG_V_STEP_10_MV_BIT	BIT(7)
+#define PM8921_CHG_V_STEP_10MV_OFFSET_BIT	BIT(7)
 #define PM8921_CHG_VDDMAX_MAX	4500
 #define PM8921_CHG_VDDMAX_MIN	3400
 #define PM8921_CHG_V_MASK	0x7F
 static int __pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
 {
-	int remainder, voltage_20_step;
+	int remainder;
 	u8 temp = 0;
 
-	voltage_20_step = voltage;
-	remainder = voltage % 20;
-	if (remainder >= 10) {
-		voltage_20_step += 10;
-		temp = PM8921_CHG_V_STEP_10_MV_BIT;
+	if (voltage < PM8921_CHG_VDDMAX_MIN
+			|| voltage > PM8921_CHG_VDDMAX_MAX) {
+		pr_err("bad mV=%d asked to set\n", voltage);
+		return -EINVAL;
 	}
 
-	temp |= (voltage_20_step - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
+	temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
+
+	remainder = voltage % 20;
+	if (remainder >= 10) {
+		temp |= PM8921_CHG_V_STEP_10MV_OFFSET_BIT;
+	}
+
 	pr_debug("voltage=%d setting %02x\n", voltage, temp);
 	return pm8xxx_writeb(chip->dev->parent, CHG_VDD_MAX, temp);
 }
@@ -449,10 +454,10 @@
 		*voltage = 0;
 		return rc;
 	}
-	temp &= PM8921_CHG_V_MASK;
-	*voltage = (int)temp * PM8921_CHG_V_STEP_MV + PM8921_CHG_V_MIN_MV;
-	if (temp & PM8921_CHG_V_STEP_10_MV_BIT)
-		*voltage = *voltage - 10;
+	*voltage = (int)(temp & PM8921_CHG_V_MASK) * PM8921_CHG_V_STEP_MV
+							+ PM8921_CHG_V_MIN_MV;
+	if (temp & PM8921_CHG_V_STEP_10MV_OFFSET_BIT)
+		*voltage =  *voltage + 10;
 	return 0;
 }
 
@@ -841,6 +846,56 @@
 					 temp);
 }
 
+static void disable_input_voltage_regulation(struct pm8921_chg_chip *chip)
+{
+	u8 temp;
+	int rc;
+
+	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x70);
+	if (rc) {
+		pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
+		return;
+	}
+	rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
+	if (rc) {
+		pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
+		return;
+	}
+	/* set the input voltage disable bit and the write bit */
+	temp |= 0x81;
+	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
+	if (rc) {
+		pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
+		return;
+	}
+}
+
+static void enable_input_voltage_regulation(struct pm8921_chg_chip *chip)
+{
+	u8 temp;
+	int rc;
+
+	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x70);
+	if (rc) {
+		pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
+		return;
+	}
+	rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
+	if (rc) {
+		pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
+		return;
+	}
+	/* unset the input voltage disable bit */
+	temp &= 0xFE;
+	/* set the write bit */
+	temp |= 0x80;
+	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
+	if (rc) {
+		pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
+		return;
+	}
+}
+
 static int64_t read_battery_id(struct pm8921_chg_chip *chip)
 {
 	int rc;
@@ -1623,7 +1678,11 @@
 		schedule_delayed_work(&chip->unplug_check_work,
 			round_jiffies_relative(msecs_to_jiffies
 				(UNPLUG_CHECK_WAIT_PERIOD_MS)));
+		pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
+	} else {
+		pm8921_chg_disable_irq(chip, CHG_GONE_IRQ);
 	}
+	enable_input_voltage_regulation(chip);
 	bms_notify_check(chip);
 }
 
@@ -1702,26 +1761,94 @@
 	wake_lock(&chip->eoc_wake_lock);
 }
 
-#define WRITE_BANK_4		0xC0
-static void unplug_wrkarnd_restore_worker(struct work_struct *work)
+static void turn_off_usb_ovp_fet(struct pm8921_chg_chip *chip)
 {
 	u8 temp;
 	int rc;
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct pm8921_chg_chip *chip = container_of(dwork,
-				struct pm8921_chg_chip,
-				unplug_wrkarnd_restore_work);
 
-	pr_debug("restoring vin_min to %d mV\n", chip->vin_min);
-	rc = pm_chg_vinmin_set(the_chip, chip->vin_min);
-
-	temp = WRITE_BANK_4 | 0xA;
-	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
+	rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, 0x30);
 	if (rc) {
-		pr_err("Error %d writing %d to addr %d\n", rc,
-					temp, CHG_BUCK_CTRL_TEST3);
+		pr_err("Failed to write 0x30 to USB_OVP_TEST rc = %d\n", rc);
+		return;
 	}
-	wake_unlock(&chip->unplug_wrkarnd_restore_wake_lock);
+	rc = pm8xxx_readb(chip->dev->parent, USB_OVP_TEST, &temp);
+	if (rc) {
+		pr_err("Failed to read from USB_OVP_TEST rc = %d\n", rc);
+		return;
+	}
+	/* set ovp fet disable bit and the write bit */
+	temp |= 0x81;
+	rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, temp);
+	if (rc) {
+		pr_err("Failed to write 0x%x USB_OVP_TEST rc=%d\n", temp, rc);
+		return;
+	}
+}
+
+static void turn_on_usb_ovp_fet(struct pm8921_chg_chip *chip)
+{
+	u8 temp;
+	int rc;
+
+	rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, 0x30);
+	if (rc) {
+		pr_err("Failed to write 0x30 to USB_OVP_TEST rc = %d\n", rc);
+		return;
+	}
+	rc = pm8xxx_readb(chip->dev->parent, USB_OVP_TEST, &temp);
+	if (rc) {
+		pr_err("Failed to read from USB_OVP_TEST rc = %d\n", rc);
+		return;
+	}
+	/* unset ovp fet disable bit and set the write bit */
+	temp &= 0xFE;
+	temp |= 0x80;
+	rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, temp);
+	if (rc) {
+		pr_err("Failed to write 0x%x to USB_OVP_TEST rc = %d\n",
+								temp, rc);
+		return;
+	}
+}
+
+static int param_open_ovp_counter = 10;
+module_param(param_open_ovp_counter, int, 0644);
+
+#define WRITE_BANK_4		0xC0
+#define USB_OVP_DEBOUNCE_TIME 0x06
+static void unplug_ovp_fet_open_worker(struct work_struct *work)
+{
+	struct pm8921_chg_chip *chip = container_of(work,
+				struct pm8921_chg_chip,
+				unplug_ovp_fet_open_work);
+	int chg_gone, usb_chg_plugged_in;
+	int count = 0;
+
+	while (count++ < param_open_ovp_counter) {
+		pm_chg_masked_write(chip, USB_OVP_CONTROL,
+						USB_OVP_DEBOUNCE_TIME, 0x0);
+		usleep(10);
+		usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
+		chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
+		pr_debug("OVP FET count = %d chg_gone=%d, usb_valid = %d\n",
+					count, chg_gone, usb_chg_plugged_in);
+
+		/* note usb_chg_plugged_in=0 => chg_gone=1 */
+		if (chg_gone == 1 && usb_chg_plugged_in == 1) {
+			pr_debug("since chg_gone = 1 dis ovp_fet for 20msec\n");
+			turn_off_usb_ovp_fet(chip);
+
+			msleep(20);
+
+			turn_on_usb_ovp_fet(chip);
+		} else {
+			pm_chg_masked_write(chip, USB_OVP_CONTROL,
+						USB_OVP_DEBOUNCE_TIME, 0x1);
+			pr_debug("Exit count=%d chg_gone=%d, usb_valid=%d\n",
+					count, chg_gone, usb_chg_plugged_in);
+			return;
+		}
+	}
 }
 static irqreturn_t usbin_valid_irq_handler(int irq, void *data)
 {
@@ -1799,8 +1926,7 @@
 
 static irqreturn_t vcp_irq_handler(int irq, void *data)
 {
-	pr_warning("VCP triggered BATDET forced on\n");
-	pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
+	pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
 	return IRQ_HANDLED;
 }
 
@@ -1867,6 +1993,29 @@
 	return IRQ_HANDLED;
 }
 
+static int param_vin_disable_counter = 5;
+module_param(param_vin_disable_counter, int, 0644);
+
+static void attempt_reverse_boost_fix(struct pm8921_chg_chip *chip,
+							int count, int usb_ma)
+{
+	pm8921_charger_vbus_draw(500);
+	pr_debug("count = %d iusb=500mA\n", count);
+	disable_input_voltage_regulation(chip);
+	pr_debug("count = %d disable_input_regulation\n", count);
+
+	msleep(20);
+
+	pr_debug("count = %d end sleep 20ms chg_gone=%d, usb_valid = %d\n",
+				count,
+				pm_chg_get_rt_status(chip, CHG_GONE_IRQ),
+				is_usb_chg_plugged_in(chip));
+	pr_debug("count = %d restoring input regulation and usb_ma = %d\n",
+		 count, usb_ma);
+	enable_input_voltage_regulation(chip);
+	pm8921_charger_vbus_draw(usb_ma);
+}
+
 #define VIN_ACTIVE_BIT BIT(0)
 #define UNPLUG_WRKARND_RESTORE_WAIT_PERIOD_US 200
 #define VIN_MIN_INCREASE_MV 100
@@ -1877,6 +2026,8 @@
 				struct pm8921_chg_chip, unplug_check_work);
 	u8 reg_loop;
 	int ibat, usb_chg_plugged_in;
+	int usb_ma;
+	int chg_gone = 0;
 
 	usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
 	if (!usb_chg_plugged_in) {
@@ -1888,8 +2039,25 @@
 			);
 		return;
 	}
+
+	pm_chg_iusbmax_get(chip, &usb_ma);
+	if (usb_ma  ==  500) {
+		pr_debug("Stopping Unplug Check Worker since USB == 500mA\n");
+		disable_input_voltage_regulation(chip);
+		return;
+	}
+
+	if (usb_ma <= 100) {
+		pr_debug(
+			"Unenumerated yet or suspended usb_ma = %d skipping\n",
+			usb_ma);
+		goto check_again_later;
+	}
+	if (pm8921_chg_is_enabled(chip, CHG_GONE_IRQ))
+		pr_debug("chg gone irq is enabled\n");
+
 	reg_loop = pm_chg_get_regulation_loop(chip);
-	pr_debug("reg_loop=0x%x\n", reg_loop);
+	pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
 
 	if (reg_loop & VIN_ACTIVE_BIT) {
 		ibat = get_prop_batt_current(chip);
@@ -1897,28 +2065,28 @@
 		pr_debug("ibat = %d fsm = %d reg_loop = 0x%x\n",
 				ibat, pm_chg_get_fsm_state(chip), reg_loop);
 		if (ibat > 0) {
-			int err;
-			u8 temp;
+			int count = 0;
 
-			temp = WRITE_BANK_4 | 0xE;
-			err = pm8xxx_writeb(chip->dev->parent,
-						CHG_BUCK_CTRL_TEST3, temp);
-			if (err) {
-				pr_err("Error %d writing %d to addr %d\n", err,
-						temp, CHG_BUCK_CTRL_TEST3);
+			while (count++ < param_vin_disable_counter
+					&& usb_chg_plugged_in == 1) {
+				attempt_reverse_boost_fix(chip, count, usb_ma);
+				usb_chg_plugged_in
+					= is_usb_chg_plugged_in(chip);
 			}
-
-			pm_chg_vinmin_set(chip,
-					chip->vin_min + VIN_MIN_INCREASE_MV);
-
-			wake_lock(&chip->unplug_wrkarnd_restore_wake_lock);
-			schedule_delayed_work(
-				&chip->unplug_wrkarnd_restore_work,
-				round_jiffies_relative(usecs_to_jiffies
-				(UNPLUG_WRKARND_RESTORE_WAIT_PERIOD_US)));
 		}
 	}
 
+	usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
+	chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
+
+	if (chg_gone == 1  && usb_chg_plugged_in == 1) {
+		/* run the worker directly */
+		pr_debug(" ver5 step: chg_gone=%d, usb_valid = %d\n",
+						chg_gone, usb_chg_plugged_in);
+		schedule_work(&chip->unplug_ovp_fet_open_work);
+	}
+
+check_again_later:
 	schedule_delayed_work(&chip->unplug_check_work,
 		      round_jiffies_relative(msecs_to_jiffies
 				(UNPLUG_CHECK_WAIT_PERIOD_MS)));
@@ -2008,6 +2176,13 @@
 static irqreturn_t chg_gone_irq_handler(int irq, void *data)
 {
 	struct pm8921_chg_chip *chip = data;
+	int chg_gone, usb_chg_plugged_in;
+
+	usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
+	chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
+
+	pr_debug("chg_gone=%d, usb_valid = %d\n", chg_gone, usb_chg_plugged_in);
+	schedule_work(&chip->unplug_ovp_fet_open_work);
 
 	pr_debug("Chg gone fsm_state=%d\n", pm_chg_get_fsm_state(data));
 	power_supply_changed(&chip->batt_psy);
@@ -2540,6 +2715,7 @@
 		schedule_delayed_work(&chip->unplug_check_work,
 			round_jiffies_relative(msecs_to_jiffies
 				(UNPLUG_CHECK_WAIT_PERIOD_MS)));
+		pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
 	}
 
 	pm8921_chg_enable_irq(chip, DCIN_VALID_IRQ);
@@ -2621,7 +2797,8 @@
 	CHG_IRQ(CHGHOT_IRQ, IRQF_TRIGGER_RISING, chghot_irq_handler),
 	CHG_IRQ(BATTTEMP_COLD_IRQ, IRQF_TRIGGER_RISING,
 						batttemp_cold_irq_handler),
-	CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING, chg_gone_irq_handler),
+	CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+						chg_gone_irq_handler),
 	CHG_IRQ(BAT_TEMP_OK_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 						bat_temp_ok_irq_handler),
 	CHG_IRQ(COARSE_DET_LOW_IRQ, IRQF_TRIGGER_RISING,
@@ -3320,11 +3497,11 @@
 	the_chip = chip;
 
 	wake_lock_init(&chip->eoc_wake_lock, WAKE_LOCK_SUSPEND, "pm8921_eoc");
-	wake_lock_init(&chip->unplug_wrkarnd_restore_wake_lock,
+	wake_lock_init(&chip->unplug_ovp_fet_open_wake_lock,
 			WAKE_LOCK_SUSPEND, "pm8921_unplug_wrkarnd");
 	INIT_DELAYED_WORK(&chip->eoc_work, eoc_worker);
-	INIT_DELAYED_WORK(&chip->unplug_wrkarnd_restore_work,
-					unplug_wrkarnd_restore_worker);
+	INIT_WORK(&chip->unplug_ovp_fet_open_work,
+					unplug_ovp_fet_open_worker);
 	INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
 
 	rc = request_irqs(chip, pdev);
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 7768eed..6d12c7e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -25,5 +25,13 @@
 	bool "MSM QPNP"
 	help
 	  Say 'y' here to include support for the Qualcomm QPNP
+
+config MSM_QPNP_INT
+	depends on SPARSE_IRQ
+	depends on ARCH_MSMCOPPER
+	depends on OF_SPMI
+	bool "MSM QPNP INT"
+	help
+	  Say 'y' here to include support for the Qualcomm QPNP interrupt
 	  support. QPNP is a SPMI based PMIC implementation.
 endif
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 659e886..d59a610 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -4,3 +4,4 @@
 obj-$(CONFIG_SPMI)			+= spmi.o
 obj-$(CONFIG_SPMI_MSM_PMIC_ARB)		+= spmi-pmic-arb.o
 obj-$(CONFIG_MSM_QPNP)                  += qpnp.o
+obj-$(CONFIG_MSM_QPNP_INT)		+= qpnp-int.o
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
new file mode 100644
index 0000000..2998c01
--- /dev/null
+++ b/drivers/spmi/qpnp-int.c
@@ -0,0 +1,510 @@
+/* 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/init.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/spmi.h>
+#include <linux/radix-tree.h>
+#include <linux/slab.h>
+#include <linux/printk.h>
+
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <mach/qpnp-int.h>
+
+#define QPNPINT_MAX_BUSSES 1
+
+/* 16 slave_ids, 256 per_ids per slave, and 8 ints per per_id */
+#define QPNPINT_NR_IRQS (16 * 256 * 8)
+
+enum qpnpint_regs {
+	QPNPINT_REG_RT_STS		= 0x10,
+	QPNPINT_REG_SET_TYPE		= 0x11,
+	QPNPINT_REG_POLARITY_HIGH	= 0x12,
+	QPNPINT_REG_POLARITY_LOW	= 0x13,
+	QPNPINT_REG_LATCHED_CLR		= 0x14,
+	QPNPINT_REG_EN_SET		= 0x15,
+	QPNPINT_REG_EN_CLR		= 0x16,
+	QPNPINT_REG_LATCHED_STS		= 0x18,
+};
+
+struct q_perip_data {
+	uint8_t type;	    /* bitmap */
+	uint8_t pol_high;   /* bitmap */
+	uint8_t pol_low;    /* bitmap */
+	uint8_t int_en;     /* bitmap */
+	uint8_t use_count;
+};
+
+struct q_irq_data {
+	uint32_t priv_d; /* data to optimize arbiter interactions */
+	struct q_chip_data *chip_d;
+	struct q_perip_data *per_d;
+	uint8_t mask_shift;
+	uint8_t spmi_slave;
+	uint16_t spmi_offset;
+};
+
+struct q_chip_data {
+	int bus_nr;
+	struct irq_domain domain;
+	struct qpnp_local_int cb;
+	struct spmi_controller *spmi_ctrl;
+	struct radix_tree_root per_tree;
+};
+
+static struct q_chip_data chip_data[QPNPINT_MAX_BUSSES] __read_mostly;
+
+/**
+ * qpnpint_encode_hwirq - translate between qpnp_irq_spec and
+ *			  hwirq representation.
+ *
+ * slave_offset = (addr->slave * 256 * 8);
+ * perip_offset = slave_offset + (addr->perip * 8);
+ * return perip_offset + addr->irq;
+ */
+static inline int qpnpint_encode_hwirq(struct qpnp_irq_spec *spec)
+{
+	uint32_t hwirq;
+
+	if (spec->slave > 15 || spec->irq > 7)
+		return -EINVAL;
+
+	hwirq = (spec->slave << 11);
+	hwirq |= (spec->per << 3);
+	hwirq |= spec->irq;
+
+	return hwirq;
+}
+/**
+ * qpnpint_decode_hwirq - translate between hwirq and
+ *			  qpnp_irq_spec representation.
+ */
+static inline int qpnpint_decode_hwirq(unsigned long hwirq,
+					struct qpnp_irq_spec *spec)
+{
+	if (hwirq > 65535)
+		return -EINVAL;
+
+	spec->slave = (hwirq >> 11) & 0xF;
+	spec->per = (hwirq >> 3) & 0xFF;
+	spec->irq = hwirq & 0x7;
+	return 0;
+}
+
+static int qpnpint_spmi_write(struct q_irq_data *irq_d, uint8_t reg,
+			      void *buf, uint32_t len)
+{
+	struct q_chip_data *chip_d = irq_d->chip_d;
+	int rc;
+
+	if (!chip_d->spmi_ctrl)
+		return -ENODEV;
+
+	rc = spmi_ext_register_writel(chip_d->spmi_ctrl, irq_d->spmi_slave,
+				      irq_d->spmi_offset + reg, buf, len);
+	return rc;
+}
+
+static void qpnpint_irq_mask(struct irq_data *d)
+{
+	struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d);
+	struct q_chip_data *chip_d = irq_d->chip_d;
+	struct q_perip_data *per_d = irq_d->per_d;
+	struct qpnp_irq_spec q_spec;
+	int rc;
+
+	pr_debug("hwirq %lu irq: %d\n", d->hwirq, d->irq);
+
+	if (chip_d->cb.mask) {
+		rc = qpnpint_decode_hwirq(d->hwirq, &q_spec);
+		if (rc)
+			pr_err("%s: decode failed on hwirq %lu\n",
+						 __func__, d->hwirq);
+		else
+			chip_d->cb.mask(chip_d->spmi_ctrl, &q_spec,
+								irq_d->priv_d);
+	}
+
+	per_d->int_en &= ~irq_d->mask_shift;
+
+	rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_EN_CLR,
+					(u8 *)&irq_d->mask_shift, 1);
+	if (rc)
+		pr_err("%s: spmi failure on irq %d\n",
+						 __func__, d->irq);
+}
+
+static void qpnpint_irq_mask_ack(struct irq_data *d)
+{
+	struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d);
+	struct q_chip_data *chip_d = irq_d->chip_d;
+	struct q_perip_data *per_d = irq_d->per_d;
+	struct qpnp_irq_spec q_spec;
+	int rc;
+
+	pr_debug("hwirq %lu irq: %d mask: 0x%x\n", d->hwirq, d->irq,
+							irq_d->mask_shift);
+
+	if (chip_d->cb.mask) {
+		rc = qpnpint_decode_hwirq(d->hwirq, &q_spec);
+		if (rc)
+			pr_err("%s: decode failed on hwirq %lu\n",
+						 __func__, d->hwirq);
+		else
+			chip_d->cb.mask(chip_d->spmi_ctrl, &q_spec,
+								irq_d->priv_d);
+	}
+
+	per_d->int_en &= ~irq_d->mask_shift;
+
+	rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_EN_CLR,
+							&irq_d->mask_shift, 1);
+	if (rc)
+		pr_err("%s: spmi failure on irq %d\n",
+						 __func__, d->irq);
+
+	rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_LATCHED_CLR,
+							&irq_d->mask_shift, 1);
+	if (rc)
+		pr_err("%s: spmi failure on irq %d\n",
+						 __func__, d->irq);
+}
+
+static void qpnpint_irq_unmask(struct irq_data *d)
+{
+	struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d);
+	struct q_chip_data *chip_d = irq_d->chip_d;
+	struct q_perip_data *per_d = irq_d->per_d;
+	struct qpnp_irq_spec q_spec;
+	int rc;
+
+	pr_debug("hwirq %lu irq: %d\n", d->hwirq, d->irq);
+
+	if (chip_d->cb.unmask) {
+		rc = qpnpint_decode_hwirq(d->hwirq, &q_spec);
+		if (rc)
+			pr_err("%s: decode failed on hwirq %lu\n",
+						 __func__, d->hwirq);
+		else
+			chip_d->cb.unmask(chip_d->spmi_ctrl, &q_spec,
+								irq_d->priv_d);
+	}
+
+	per_d->int_en |= irq_d->mask_shift;
+	rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_EN_SET,
+					&irq_d->mask_shift, 1);
+	if (rc)
+		pr_err("%s: spmi failure on irq %d\n",
+						 __func__, d->irq);
+}
+
+static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d);
+	struct q_perip_data *per_d = irq_d->per_d;
+	int rc;
+	u8 buf[3];
+
+	pr_debug("hwirq %lu irq: %d flow: 0x%x\n", d->hwirq,
+							d->irq, flow_type);
+
+	per_d->pol_high &= ~irq_d->mask_shift;
+	per_d->pol_low &= ~irq_d->mask_shift;
+	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+		per_d->type |= irq_d->mask_shift; /* edge trig */
+		if (flow_type & IRQF_TRIGGER_RISING)
+			per_d->pol_high |= irq_d->mask_shift;
+		if (flow_type & IRQF_TRIGGER_FALLING)
+			per_d->pol_low |= irq_d->mask_shift;
+	} else {
+		if ((flow_type & IRQF_TRIGGER_HIGH) &&
+		    (flow_type & IRQF_TRIGGER_LOW))
+			return -EINVAL;
+		per_d->type &= ~irq_d->mask_shift; /* level trig */
+		if (flow_type & IRQF_TRIGGER_HIGH)
+			per_d->pol_high |= irq_d->mask_shift;
+		else
+			per_d->pol_high &= ~irq_d->mask_shift;
+	}
+
+	buf[0] = per_d->type;
+	buf[1] = per_d->pol_high;
+	buf[2] = per_d->pol_low;
+
+	rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_SET_TYPE, &buf, 3);
+	if (rc)
+		pr_err("%s: spmi failure on irq %d\n",
+						 __func__, d->irq);
+	return rc;
+}
+
+static struct irq_chip qpnpint_chip = {
+	.name		= "qpnp-int",
+	.irq_mask	= qpnpint_irq_mask,
+	.irq_mask_ack	= qpnpint_irq_mask_ack,
+	.irq_unmask	= qpnpint_irq_unmask,
+	.irq_set_type	= qpnpint_irq_set_type,
+};
+
+static int qpnpint_init_irq_data(struct q_chip_data *chip_d,
+				 struct q_irq_data *irq_d,
+				 unsigned long hwirq)
+{
+	struct qpnp_irq_spec q_spec;
+	int rc;
+
+	irq_d->mask_shift = 1 << (hwirq & 0x7);
+	rc = qpnpint_decode_hwirq(hwirq, &q_spec);
+	if (rc < 0)
+		return rc;
+	irq_d->spmi_slave = q_spec.slave;
+	irq_d->spmi_offset = q_spec.per << 8;
+	irq_d->per_d->use_count++;
+	irq_d->chip_d = chip_d;
+
+	if (chip_d->cb.register_priv_data)
+		rc = chip_d->cb.register_priv_data(chip_d->spmi_ctrl, &q_spec,
+							&irq_d->priv_d);
+	return rc;
+}
+
+static struct q_irq_data *qpnpint_alloc_irq_data(
+					struct q_chip_data *chip_d,
+					unsigned long hwirq)
+{
+	struct q_irq_data *irq_d;
+	struct q_perip_data *per_d;
+
+	irq_d = kzalloc(sizeof(struct q_irq_data), GFP_KERNEL);
+	if (!irq_d)
+		return ERR_PTR(-ENOMEM);
+
+	/**
+	 * The Peripheral Tree is keyed from the slave + per_id. We're
+	 * ignoring the irq bits here since this peripheral structure
+	 * should be common for all irqs on the same peripheral.
+	 */
+	per_d = radix_tree_lookup(&chip_d->per_tree, (hwirq & ~0x7));
+	if (!per_d) {
+		per_d = kzalloc(sizeof(struct q_perip_data), GFP_KERNEL);
+		if (!per_d)
+			return ERR_PTR(-ENOMEM);
+		radix_tree_insert(&chip_d->per_tree,
+				  (hwirq & ~0x7), per_d);
+	}
+	irq_d->per_d = per_d;
+
+	return irq_d;
+}
+
+static int qpnpint_register_int(uint32_t busno, unsigned long hwirq)
+{
+	int irq, rc;
+	struct irq_domain *domain;
+	struct q_irq_data *irq_d;
+
+	pr_debug("busno = %u hwirq = %lu\n", busno, hwirq);
+
+	if (hwirq < 0 || hwirq >= 32768) {
+		pr_err("%s: hwirq %lu out of qpnp interrupt bounds\n",
+							__func__, hwirq);
+		return -EINVAL;
+	}
+
+	if (busno < 0 || busno > QPNPINT_MAX_BUSSES) {
+		pr_err("%s: invalid bus number %d\n", __func__, busno);
+		return -EINVAL;
+	}
+
+	domain = &chip_data[busno].domain;
+	irq = irq_domain_to_irq(domain, hwirq);
+
+	rc = irq_alloc_desc_at(irq, numa_node_id());
+	if (rc < 0) {
+		if (rc != -EEXIST)
+			pr_err("%s: failed to alloc irq at %d with "
+					"rc %d\n", __func__, irq, rc);
+		return rc;
+	}
+	irq_d = qpnpint_alloc_irq_data(&chip_data[busno], hwirq);
+	if (IS_ERR(irq_d)) {
+		pr_err("%s: failed to alloc irq data %d with "
+					"rc %d\n", __func__, irq, rc);
+		rc = PTR_ERR(irq_d);
+		goto register_err_cleanup;
+	}
+	rc = qpnpint_init_irq_data(&chip_data[busno], irq_d, hwirq);
+	if (rc) {
+		pr_err("%s: failed to init irq data %d with "
+					"rc %d\n", __func__, irq, rc);
+		goto register_err_cleanup;
+	}
+
+	irq_domain_register_irq(domain, hwirq);
+
+	irq_set_chip_and_handler(irq,
+			&qpnpint_chip,
+			handle_level_irq);
+	irq_set_chip_data(irq, irq_d);
+#ifdef CONFIG_ARM
+	set_irq_flags(irq, IRQF_VALID);
+#else
+	irq_set_noprobe(irq);
+#endif
+	return 0;
+
+register_err_cleanup:
+	irq_free_desc(irq);
+	if (!IS_ERR(irq_d)) {
+		if (irq_d->per_d->use_count == 1)
+			kfree(irq_d->per_d);
+		else
+			irq_d->per_d->use_count--;
+		kfree(irq_d);
+	}
+	return rc;
+}
+
+static int qpnpint_irq_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)
+{
+	struct qpnp_irq_spec addr;
+	struct q_chip_data *chip_d = d->priv;
+	int ret;
+
+	pr_debug("%s: intspec[0] 0x%x intspec[1] 0x%x intspec[2] 0x%x\n",
+				__func__, intspec[0], intspec[1], intspec[2]);
+
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize != 3)
+		return -EINVAL;
+
+	addr.irq = intspec[2] & 0x7;
+	addr.per = intspec[1] & 0xFF;
+	addr.slave = intspec[0] & 0xF;
+
+	ret = qpnpint_encode_hwirq(&addr);
+	if (ret < 0) {
+		pr_err("%s: invalid intspec\n", __func__);
+		return ret;
+	}
+	*out_hwirq = ret;
+	*out_type = IRQ_TYPE_NONE;
+
+	/**
+	 * Register the interrupt if it's not already registered.
+	 * This implies that mapping a qpnp interrupt allocates
+	 * resources.
+	 */
+	ret = qpnpint_register_int(chip_d->bus_nr, *out_hwirq);
+	if (ret && ret != -EEXIST) {
+		pr_err("%s: Cannot register hwirq %lu\n", __func__, *out_hwirq);
+		return ret;
+	}
+
+	return 0;
+}
+
+const struct irq_domain_ops qpnpint_irq_domain_ops = {
+	.dt_translate = qpnpint_irq_domain_dt_translate,
+};
+
+int qpnpint_register_controller(unsigned int busno,
+				struct qpnp_local_int *li_cb)
+{
+	if (busno >= QPNPINT_MAX_BUSSES)
+		return -EINVAL;
+	chip_data[busno].cb = *li_cb;
+	chip_data[busno].spmi_ctrl = spmi_busnum_to_ctrl(busno);
+	if (!chip_data[busno].spmi_ctrl)
+		return -ENOENT;
+
+	return 0;
+}
+EXPORT_SYMBOL(qpnpint_register_controller);
+
+int qpnpint_handle_irq(struct spmi_controller *spmi_ctrl,
+		       struct qpnp_irq_spec *spec)
+{
+	struct irq_domain *domain;
+	unsigned long hwirq, busno;
+	int irq;
+
+	pr_debug("spec slave = %u per = %u irq = %u\n",
+					spec->slave, spec->per, spec->irq);
+
+	if (!spec || !spmi_ctrl)
+		return -EINVAL;
+
+	busno = spmi_ctrl->nr;
+	if (busno >= QPNPINT_MAX_BUSSES)
+		return -EINVAL;
+
+	hwirq = qpnpint_encode_hwirq(spec);
+	if (hwirq < 0) {
+		pr_err("%s: invalid irq spec passed\n", __func__);
+		return -EINVAL;
+	}
+
+	domain = &chip_data[busno].domain;
+	irq = irq_domain_to_irq(domain, hwirq);
+
+	generic_handle_irq(irq);
+
+	return 0;
+}
+EXPORT_SYMBOL(qpnpint_handle_irq);
+
+/**
+ * This assumes that there's a relationship between the order of the interrupt
+ * controllers specified to of_irq_match() is the SPMI device topology. If
+ * this ever turns out to be a bad assumption, then of_irq_init_cb_t should
+ * be modified to pass a parameter to this function.
+ */
+static int qpnpint_cnt __initdata;
+
+int __init qpnpint_of_init(struct device_node *node, struct device_node *parent)
+{
+	struct q_chip_data *chip_d = &chip_data[qpnpint_cnt];
+	struct irq_domain *domain = &chip_d->domain;
+
+	INIT_RADIX_TREE(&chip_d->per_tree, GFP_ATOMIC);
+
+	domain->irq_base = irq_domain_find_free_range(0, QPNPINT_NR_IRQS);
+	domain->nr_irq = QPNPINT_NR_IRQS;
+	domain->of_node = of_node_get(node);
+	domain->priv = chip_d;
+	domain->ops = &qpnpint_irq_domain_ops;
+	irq_domain_add(domain);
+
+	pr_info("irq_base = %d\n", domain->irq_base);
+
+	qpnpint_cnt++;
+
+	return 0;
+}
+EXPORT_SYMBOL(qpnpint_of_init);
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index f49769d..04dd590 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -639,7 +639,7 @@
 	/* enable TX & RX */
 	msm_hsl_write(port, data, regmap[vid][UARTDM_CR]);
 
-	msm_hsl_write(port, RESET_STALE_INT, UARTDM_CR_ADDR);
+	msm_hsl_write(port, RESET_STALE_INT, regmap[vid][UARTDM_CR]);
 	/* turn on RX and CTS interrupts */
 	msm_hsl_port->imr = UARTDM_ISR_RXSTALE_BMSK
 		| UARTDM_ISR_DELTA_CTS_BMSK | UARTDM_ISR_RXLEV_BMSK;
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index aab5b98..9794918 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -82,6 +82,7 @@
 			urb->status, urb->actual_length);
 
 	if (urb->status == -EPROTO) {
+		dev_err(&dev->udev->dev, "%s: proto error\n", __func__);
 		/* save error so that subsequent read/write returns ESHUTDOWN */
 		dev->err = urb->status;
 		return;
@@ -119,27 +120,36 @@
 	if (dev->err)
 		return -ESHUTDOWN;
 
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
 		dev_err(&dev->udev->dev, "unable to allocate urb\n");
 		return -ENOMEM;
 	}
 
+	ret = usb_autopm_get_interface(dev->ifc);
+	if (ret < 0) {
+		dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret);
+		usb_free_urb(urb);
+		return ret;
+	}
+
 	pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr);
 	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
 				diag_bridge_read_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
 	dev->pending_reads++;
 
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret) {
 		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
 		dev->pending_reads--;
 		usb_unanchor_urb(urb);
 		usb_free_urb(urb);
+		usb_autopm_put_interface(dev->ifc);
 		return ret;
 	}
 
+	usb_autopm_put_interface(dev->ifc);
 	usb_free_urb(urb);
 
 	return 0;
@@ -153,7 +163,10 @@
 
 	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
 
+	usb_autopm_put_interface_async(dev->ifc);
+
 	if (urb->status == -EPROTO) {
+		dev_err(&dev->udev->dev, "%s: proto error\n", __func__);
 		/* save error so that subsequent read/write returns ESHUTDOWN */
 		dev->err = urb->status;
 		return;
@@ -191,24 +204,32 @@
 	if (dev->err)
 		return -ESHUTDOWN;
 
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
 		err("unable to allocate urb");
 		return -ENOMEM;
 	}
 
+	ret = usb_autopm_get_interface(dev->ifc);
+	if (ret < 0) {
+		dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret);
+		usb_free_urb(urb);
+		return ret;
+	}
+
 	pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr);
 	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
 				diag_bridge_write_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
 	dev->pending_writes++;
 
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret) {
 		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
 		dev->pending_writes--;
 		usb_unanchor_urb(urb);
 		usb_free_urb(urb);
+		usb_autopm_put_interface(dev->ifc);
 		return ret;
 	}
 
@@ -381,6 +402,37 @@
 	usb_set_intfdata(ifc, NULL);
 }
 
+static int diag_bridge_suspend(struct usb_interface *ifc, pm_message_t message)
+{
+	struct diag_bridge	*dev = usb_get_intfdata(ifc);
+	struct diag_bridge_ops	*cbs = dev->ops;
+	int ret = 0;
+
+	if (cbs && cbs->suspend) {
+		ret = cbs->suspend(cbs->ctxt);
+		if (ret) {
+			dev_dbg(&dev->udev->dev,
+				"%s: diag veto'd suspend\n", __func__);
+			return ret;
+		}
+
+		usb_kill_anchored_urbs(&dev->submitted);
+	}
+
+	return ret;
+}
+
+static int diag_bridge_resume(struct usb_interface *ifc)
+{
+	struct diag_bridge	*dev = usb_get_intfdata(ifc);
+	struct diag_bridge_ops	*cbs = dev->ops;
+
+
+	if (cbs && cbs->resume)
+		cbs->resume(cbs->ctxt);
+
+	return 0;
+}
 
 #define VALID_INTERFACE_NUM	0
 static const struct usb_device_id diag_bridge_ids[] = {
@@ -390,6 +442,8 @@
 	.driver_info = VALID_INTERFACE_NUM, },
 	{ USB_DEVICE(0x5c6, 0x9048),
 	.driver_info = VALID_INTERFACE_NUM, },
+	{ USB_DEVICE(0x5c6, 0x904C),
+	.driver_info = VALID_INTERFACE_NUM, },
 
 	{} /* terminating entry */
 };
@@ -399,7 +453,10 @@
 	.name =		"diag_bridge",
 	.probe =	diag_bridge_probe,
 	.disconnect =	diag_bridge_disconnect,
+	.suspend =	diag_bridge_suspend,
+	.resume =	diag_bridge_resume,
 	.id_table =	diag_bridge_ids,
+	.supports_autosuspend = 1,
 };
 
 static int __init diag_bridge_init(void)
@@ -408,8 +465,7 @@
 
 	ret = usb_register(&diag_bridge_driver);
 	if (ret) {
-		err("%s: unable to register diag driver",
-				__func__);
+		err("%s: unable to register diag driver", __func__);
 		return ret;
 	}
 
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 584503a..c23c7b1 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.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
@@ -38,8 +38,9 @@
 #define ACM_CTRL_DTR		(1 << 0)
 #define DEFAULT_READ_URB_LENGTH	4096
 
-struct ctrl_bridge {
+#define SUSPENDED		BIT(0)
 
+struct ctrl_bridge {
 	struct usb_device	*udev;
 	struct usb_interface	*intf;
 
@@ -51,11 +52,14 @@
 	void			*readbuf;
 
 	struct usb_anchor	tx_submitted;
+	struct usb_anchor	tx_deferred;
 	struct usb_ctrlrequest	*in_ctlreq;
 
 	struct bridge		*brdg;
 	struct platform_device	*pdev;
 
+	unsigned long		flags;
+
 	/* input control lines (DSR, CTS, CD, RI) */
 	unsigned int		cbits_tohost;
 
@@ -68,7 +72,6 @@
 	unsigned int		resp_avail;
 	unsigned int		set_ctrl_line_sts;
 	unsigned int		notify_ser_state;
-
 };
 
 static struct ctrl_bridge	*__dev[MAX_BRIDGE_DEVICES];
@@ -157,11 +160,14 @@
 
 	if (resubmit_urb) {
 		/*re- submit int urb to check response available*/
+		usb_anchor_urb(dev->inturb, &dev->tx_submitted);
 		status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
-		if (status)
+		if (status) {
 			dev_err(&udev->dev,
 				"%s: Error re-submitting Int URB %d\n",
 				__func__, status);
+			usb_unanchor_urb(dev->inturb);
+		}
 	}
 }
 
@@ -210,11 +216,13 @@
 					DEFAULT_READ_URB_LENGTH,
 					resp_avail_cb, dev);
 
+		usb_anchor_urb(dev->readurb, &dev->tx_submitted);
 		status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
 		if (status) {
 			dev_err(&udev->dev,
 				"%s: Error submitting Read URB %d\n",
 				__func__, status);
+			usb_unanchor_urb(dev->readurb);
 			goto resubmit_int_urb;
 		}
 		return;
@@ -238,52 +246,42 @@
 	}
 
 resubmit_int_urb:
+	usb_anchor_urb(urb, &dev->tx_submitted);
 	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status)
+	if (status) {
 		dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n",
 		__func__, status);
+		usb_unanchor_urb(urb);
+	}
 }
 
 int ctrl_bridge_start_read(struct ctrl_bridge *dev)
 {
-	int			retval = 0;
-	struct usb_device	*udev;
+	int	retval = 0;
 
-	udev = interface_to_usbdev(dev->intf);
-
-	retval = usb_autopm_get_interface_async(dev->intf);
-	if (retval < 0) {
-		dev_err(&udev->dev, "%s resumption fail\n", __func__);
-		goto done_nopm;
+	if (!dev->inturb) {
+		dev_err(&dev->udev->dev, "%s: inturb is NULL\n", __func__);
+		return -ENODEV;
 	}
 
-	retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
-	if (retval < 0)
-		dev_err(&udev->dev, "%s intr submit %d\n", __func__, retval);
+	if (!dev->inturb->anchor) {
+		usb_anchor_urb(dev->inturb, &dev->tx_submitted);
+		retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
+		if (retval < 0) {
+			dev_err(&dev->udev->dev,
+				"%s error submitting int urb %d\n",
+				__func__, retval);
+			usb_unanchor_urb(dev->inturb);
+		}
+	}
 
-	usb_autopm_put_interface_async(dev->intf);
-done_nopm:
 	return retval;
 }
 
-static int ctrl_bridge_stop_read(struct ctrl_bridge *dev)
-{
-	if (dev->readurb) {
-		dev_dbg(&dev->udev->dev, "killing rcv urb\n");
-		usb_unlink_urb(dev->readurb);
-	}
-
-	if (dev->inturb) {
-		dev_dbg(&dev->udev->dev, "killing int urb\n");
-		usb_unlink_urb(dev->inturb);
-	}
-
-	return 0;
-}
-
 int ctrl_bridge_open(struct bridge *brdg)
 {
 	struct ctrl_bridge	*dev;
+	int			ret;
 
 	if (!brdg) {
 		err("bridge is null\n");
@@ -306,7 +304,16 @@
 	dev->set_ctrl_line_sts = 0;
 	dev->notify_ser_state = 0;
 
-	return ctrl_bridge_start_read(dev);
+	ret = usb_autopm_get_interface(dev->intf);
+	if (ret < 0) {
+		dev_err(&dev->udev->dev, "%s autopm_get fail: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = ctrl_bridge_start_read(dev);
+	usb_autopm_put_interface(dev->intf);
+	return ret;
 }
 EXPORT_SYMBOL(ctrl_bridge_open);
 
@@ -325,7 +332,6 @@
 
 	ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
 	usb_unlink_anchored_urbs(&dev->tx_submitted);
-	ctrl_bridge_stop_read(dev);
 
 	dev->brdg = NULL;
 }
@@ -423,6 +429,11 @@
 		goto free_ctrlreq;
 	}
 
+	if (test_bit(SUSPENDED, &dev->flags)) {
+		usb_anchor_urb(writeurb, &dev->tx_deferred);
+		goto deferred;
+	}
+
 	usb_anchor_urb(writeurb, &dev->tx_submitted);
 	result = usb_submit_urb(writeurb, GFP_ATOMIC);
 	if (result < 0) {
@@ -431,7 +442,7 @@
 		usb_autopm_put_interface_async(dev->intf);
 		goto unanchor_urb;
 	}
-
+deferred:
 	return size;
 
 unanchor_urb:
@@ -458,14 +469,16 @@
 	if (!dev)
 		return -ENODEV;
 
+	set_bit(SUSPENDED, &dev->flags);
 	usb_kill_anchored_urbs(&dev->tx_submitted);
 
-	return ctrl_bridge_stop_read(dev);
+	return 0;
 }
 
 int ctrl_bridge_resume(unsigned int id)
 {
 	struct ctrl_bridge	*dev;
+	struct urb		*urb;
 
 	if (id >= MAX_BRIDGE_DEVICES)
 		return -EINVAL;
@@ -474,7 +487,28 @@
 	if (!dev)
 		return -ENODEV;
 
-	return ctrl_bridge_start_read(dev);
+	if (!test_and_clear_bit(SUSPENDED, &dev->flags))
+		return 0;
+
+	/* submit pending write requests */
+	while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
+		int ret;
+		usb_anchor_urb(urb, &dev->tx_submitted);
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret < 0) {
+			usb_unanchor_urb(urb);
+			kfree(urb->setup_packet);
+			kfree(urb->transfer_buffer);
+			usb_free_urb(urb);
+			usb_autopm_put_interface_async(dev->intf);
+		}
+	}
+
+	/* if the bridge is open, resume reading */
+	if (dev->brdg)
+		return ctrl_bridge_start_read(dev);
+
+	return 0;
 }
 
 #if defined(CONFIG_DEBUG_FS)
@@ -505,7 +539,8 @@
 				"set ctrlline sts cnt: %u\n"
 				"notify ser state cnt: %u\n"
 				"cbits_tomdm: %d\n"
-				"cbits_tohost: %d\n",
+				"cbits_tohost: %d\n"
+				"suspended: %d\n",
 				dev->pdev->name, dev,
 				dev->snd_encap_cmd,
 				dev->get_encap_res,
@@ -513,8 +548,8 @@
 				dev->set_ctrl_line_sts,
 				dev->notify_ser_state,
 				dev->cbits_tomdm,
-				dev->cbits_tohost);
-
+				dev->cbits_tohost,
+				test_bit(SUSPENDED, &dev->flags));
 	}
 
 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
@@ -608,6 +643,7 @@
 	dev->intf = ifc;
 
 	init_usb_anchor(&dev->tx_submitted);
+	init_usb_anchor(&dev->tx_deferred);
 
 	/*use max pkt size from ep desc*/
 	ep = &dev->intf->cur_altsetting->endpoint[0].desc;
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index 687c8c5..a77d98f 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -61,6 +61,8 @@
 struct data_bridge {
 	struct usb_interface		*intf;
 	struct usb_device		*udev;
+	int				id;
+
 	unsigned int			bulk_in;
 	unsigned int			bulk_out;
 	int				err;
@@ -543,6 +545,9 @@
 	struct urb	*urb;
 	int		retval;
 
+	if (!test_and_clear_bit(SUSPENDED, &dev->flags))
+		return 0;
+
 	while ((urb = usb_get_from_anchor(&dev->delayed))) {
 		usb_anchor_urb(urb, &dev->tx_active);
 		atomic_inc(&dev->pending_txurbs);
@@ -559,8 +564,6 @@
 		dev->txurb_drp_cnt--;
 	}
 
-	clear_bit(SUSPENDED, &dev->flags);
-
 	if (dev->brdg)
 		queue_work(dev->wq, &dev->process_rx_w);
 
@@ -572,16 +575,16 @@
 	int			retval = 0;
 	int			oldstate;
 	struct data_bridge	*dev = usb_get_intfdata(iface);
-	struct bridge		*brdg = dev->brdg;
 
 	oldstate = iface->dev.power.power_state.event;
 	iface->dev.power.power_state.event = PM_EVENT_ON;
 
-	retval = data_bridge_resume(dev);
-	if (!retval) {
-		if (oldstate & PM_EVENT_SUSPEND && brdg)
-			retval = ctrl_bridge_resume(brdg->ch_id);
+	if (oldstate & PM_EVENT_SUSPEND) {
+		retval = data_bridge_resume(dev);
+		if (!retval)
+			retval = ctrl_bridge_resume(dev->id);
 	}
+
 	return retval;
 }
 
@@ -603,19 +606,13 @@
 {
 	int			retval;
 	struct data_bridge	*dev = usb_get_intfdata(intf);
-	struct bridge		*brdg = dev->brdg;
 
 	retval = data_bridge_suspend(dev, message);
 	if (!retval) {
-		if (message.event & PM_EVENT_SUSPEND) {
-			if (brdg)
-				retval = ctrl_bridge_suspend(brdg->ch_id);
-			intf->dev.power.power_state.event = message.event;
-		}
-	} else {
-		dev_dbg(&dev->udev->dev, "%s: device is busy,cannot suspend\n",
-			__func__);
+		retval = ctrl_bridge_suspend(dev->id);
+		intf->dev.power.power_state.event = message.event;
 	}
+
 	return retval;
 }
 
@@ -646,7 +643,7 @@
 	skb_queue_head_init(&dev->rx_done);
 
 	dev->wq = bridge_wq;
-
+	dev->id = id;
 	dev->udev = interface_to_usbdev(iface);
 	dev->intf = iface;
 
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 6964835..dd07d4e 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -67,6 +67,7 @@
 static DECLARE_COMPLETION(pmic_vbus_init);
 static struct msm_otg *the_msm_otg;
 static bool debug_aca_enabled;
+static bool debug_bus_voting_enabled;
 
 /* Prevent idle power collapse(pc) while operating in peripheral mode */
 static void otg_pm_qos_update_latency(struct msm_otg *dev, int vote)
@@ -1155,7 +1156,7 @@
 		 */
 		otg_pm_qos_update_latency(motg, 1);
 		/* Configure BUS performance parameters for MAX bandwidth */
-		if (motg->bus_perf_client) {
+		if (motg->bus_perf_client && debug_bus_voting_enabled) {
 			ret = msm_bus_scale_client_update_request(
 					motg->bus_perf_client, 1);
 			if (ret)
@@ -2232,13 +2233,64 @@
 	.release = single_release,
 };
 
+static int msm_otg_bus_show(struct seq_file *s, void *unused)
+{
+	if (debug_bus_voting_enabled)
+		seq_printf(s, "enabled\n");
+	else
+		seq_printf(s, "disabled\n");
+
+	return 0;
+}
+
+static int msm_otg_bus_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, msm_otg_bus_show, inode->i_private);
+}
+
+static ssize_t msm_otg_bus_write(struct file *file, const char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	char buf[8];
+	int ret;
+	struct seq_file *s = file->private_data;
+	struct msm_otg *motg = s->private;
+
+	memset(buf, 0x00, sizeof(buf));
+
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+		return -EFAULT;
+
+	if (!strncmp(buf, "enable", 6)) {
+		/* Do not vote here. Let OTG statemachine decide when to vote */
+		debug_bus_voting_enabled = true;
+	} else {
+		debug_bus_voting_enabled = false;
+		if (motg->bus_perf_client) {
+			ret = msm_bus_scale_client_update_request(
+					motg->bus_perf_client, 0);
+			if (ret)
+				dev_err(motg->otg.dev, "%s: Failed to devote "
+					   "for bus bw %d\n", __func__, ret);
+		}
+	}
+
+	return count;
+}
+
+const struct file_operations msm_otg_bus_fops = {
+	.open = msm_otg_bus_open,
+	.read = seq_read,
+	.write = msm_otg_bus_write,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
 static struct dentry *msm_otg_dbg_root;
-static struct dentry *msm_otg_dbg_mode;
-static struct dentry *msm_otg_chg_type;
-static struct dentry *msm_otg_dbg_aca;
 
 static int msm_otg_debugfs_init(struct msm_otg *motg)
 {
+	struct dentry *msm_otg_dentry;
 
 	msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
 
@@ -2248,35 +2300,43 @@
 	if (motg->pdata->mode == USB_OTG &&
 		motg->pdata->otg_control == OTG_USER_CONTROL) {
 
-		msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
+		msm_otg_dentry = debugfs_create_file("mode", S_IRUGO |
 			S_IWUSR, msm_otg_dbg_root, motg,
 			&msm_otg_mode_fops);
 
-		if (!msm_otg_dbg_mode) {
+		if (!msm_otg_dentry) {
 			debugfs_remove(msm_otg_dbg_root);
 			msm_otg_dbg_root = NULL;
 			return -ENODEV;
 		}
 	}
 
-	msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
+	msm_otg_dentry = debugfs_create_file("chg_type", S_IRUGO,
 		msm_otg_dbg_root, motg,
 		&msm_otg_chg_fops);
 
-	if (!msm_otg_chg_type) {
+	if (!msm_otg_dentry) {
 		debugfs_remove_recursive(msm_otg_dbg_root);
 		return -ENODEV;
 	}
 
-	msm_otg_dbg_aca = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
+	msm_otg_dentry = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
 		msm_otg_dbg_root, motg,
 		&msm_otg_aca_fops);
 
-	if (!msm_otg_dbg_aca) {
+	if (!msm_otg_dentry) {
 		debugfs_remove_recursive(msm_otg_dbg_root);
 		return -ENODEV;
 	}
 
+	msm_otg_dentry = debugfs_create_file("bus_voting", S_IRUGO | S_IWUSR,
+		msm_otg_dbg_root, motg,
+		&msm_otg_bus_fops);
+
+	if (!msm_otg_dentry) {
+		debugfs_remove_recursive(msm_otg_dbg_root);
+		return -ENODEV;
+	}
 	return 0;
 }
 
@@ -2642,6 +2702,8 @@
 		if (!motg->bus_perf_client)
 			dev_err(motg->otg.dev, "%s: Failed to register BUS "
 						"scaling client!!\n", __func__);
+		else
+			debug_bus_voting_enabled = true;
 	}
 
 	return 0;
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index b29a974..44e887c 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -1,7 +1,7 @@
 /*
  * Qualcomm Serial USB driver
  *
- *	Copyright (c) 2008 QUALCOMM Incorporated.
+ *	Copyright (c) 2008, 2012 QUALCOMM Incorporated.
  *	Copyright (c) 2009 Greg Kroah-Hartman <gregkh@suse.de>
  *	Copyright (c) 2009 Novell Inc.
  *
@@ -82,7 +82,8 @@
 	{USB_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */
 	{USB_DEVICE(0x05c6, 0x9204)},	/* Gobi 2000 QDL device */
 	{USB_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */
-	{USB_DEVICE(0x05c6, 0x9048)},
+	{USB_DEVICE(0x05c6, 0x9048)},	/* MDM9x15 device */
+	{USB_DEVICE(0x05c6, 0x904C)},	/* MDM9x15 device */
 	{ }				/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index ef357db..96d9487 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -2475,12 +2475,6 @@
 			goto error;
 		}
 
-		/*
-		 * A small delay is needed here to avoid device crash observed
-		 * during reauthentication in MSM8960
-		 */
-		msleep(20);
-
 		/* 0x0168 HDCP_RCVPORT_DATA12
 		   [23:8] BSTATUS
 		   [7:0] BCAPS */
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 6c5a9f9..d374b4c 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -738,6 +738,11 @@
 
 #ifdef CONFIG_MSM_BUS_SCALING
 int mdp_bus_scale_update_request(uint32_t index);
+#else
+static inline int mdp_bus_scale_update_request(uint32_t index)
+{
+	return 0;
+}
 #endif
 
 #ifdef MDP_HW_VSYNC
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 3ca8c9c..033a73c 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -402,7 +402,8 @@
 		pipe->op_mode |= MDP4_OP_SCALEY_EN;
 
 		if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
-			if (pipe->alpha_enable && pipe->dst_h > pipe->src_h)
+			if (pipe->flags & MDP_BACKEND_COMPOSITION &&
+				pipe->alpha_enable && pipe->dst_h > pipe->src_h)
 				pipe->op_mode |= MDP4_OP_SCALEY_PIXEL_RPT;
 			else if (pipe->dst_h <= (pipe->src_h / 4))
 				pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
@@ -424,7 +425,8 @@
 		pipe->op_mode |= MDP4_OP_SCALEX_EN;
 
 		if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
-			if (pipe->alpha_enable && pipe->dst_w > pipe->src_w)
+			if (pipe->flags & MDP_BACKEND_COMPOSITION &&
+				pipe->alpha_enable && pipe->dst_w > pipe->src_w)
 				pipe->op_mode |= MDP4_OP_SCALEX_PIXEL_RPT;
 			else if (pipe->dst_w <= (pipe->src_w / 4))
 				pipe->op_mode |= MDP4_OP_SCALEX_MN_PHASE;
@@ -1385,14 +1387,8 @@
 		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 	}
 
-	if (data) {
-		if (pipe_cnt == 1) {
-			mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
-#ifdef CONFIG_MSM_BUS_SCALING
-			mdp_bus_scale_update_request(2);
-#endif
-		}
-	}
+	if (data && pipe_cnt == 1)
+		mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
 }
 
 void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
@@ -1891,7 +1887,7 @@
 
 static int get_img(struct msmfb_data *img, struct fb_info *info,
 	unsigned long *start, unsigned long *len, struct file **srcp_file,
-	struct ion_handle **srcp_ihdl)
+	int *p_need, struct ion_handle **srcp_ihdl)
 {
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -1901,6 +1897,8 @@
 #ifdef CONFIG_ANDROID_PMEM
 	unsigned long vstart;
 #endif
+	*p_need = 0;
+
 	if (img->flags & MDP_BLIT_SRC_GEM) {
 		*srcp_file = NULL;
 		return kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
@@ -1916,8 +1914,10 @@
 			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
 			if (get_fb_phys_info(start, len, fb_num))
 				ret = -1;
-			else
+			else {
 				*srcp_file = file;
+				*p_need = put_needed;
+			}
 		} else
 			ret = -1;
 		if (ret)
@@ -2034,9 +2034,7 @@
 #define OVERLAY_720P_TILE_SIZE  0x0E6000
 #define OVERLAY_WSVGA_SIZE 0x98000 /* 1024x608, align 600 to 32bit */
 
-#ifdef CONFIG_MSM_BUS_SCALING
 #define OVERLAY_BUS_SCALE_TABLE_BASE	6
-#endif
 
 static int mdp4_overlay_is_rgb_type(int format)
 {
@@ -2058,7 +2056,7 @@
 static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req,
 					  struct msm_fb_data_type *mfd)
 {
-	int is_fg;
+	int is_fg, i, cnt;
 
 	if (req->is_fg && ((req->alpha & 0x0ff) == 0xff))
 		is_fg = 1;
@@ -2069,9 +2067,10 @@
 	if (req->flags & MDP_DEINTERLACE)
 		return OVERLAY_PERF_LEVEL1;
 
-	if (ctrl->plist[OVERLAY_PIPE_VG1].pipe_used &&
-	    ctrl->plist[OVERLAY_PIPE_VG2].pipe_used)
-		return OVERLAY_PERF_LEVEL1;
+	for (i = 0, cnt = 0; i < OVERLAY_PIPE_MAX; i++) {
+		if (ctrl->plist[i].pipe_used && ++cnt > 2)
+			return OVERLAY_PERF_LEVEL1;
+	}
 
 	if (mdp4_overlay_is_rgb_type(req->src.format) && is_fg &&
 		((req->src.width * req->src.height) <= OVERLAY_WSVGA_SIZE))
@@ -2114,6 +2113,8 @@
 	if (old_perf_level != cur_perf_level) {
 		mdp_set_core_clk(cur_perf_level);
 		old_perf_level = cur_perf_level;
+		mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
+					     - cur_perf_level);
 	}
 }
 
@@ -2140,6 +2141,21 @@
 	mfd->ov0_blt_state = mfd->use_ov0_blt;
 }
 
+static void mdp4_overlay1_update_blt_mode(struct msm_fb_data_type *mfd)
+{
+	if (mfd->ov1_blt_state == mfd->use_ov1_blt)
+		return;
+	if (mfd->use_ov1_blt) {
+		mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
+		mdp4_dtv_overlay_blt_start(mfd);
+		pr_debug("%s overlay1 writeback is enabled\n", __func__);
+	} else {
+		mdp4_dtv_overlay_blt_stop(mfd);
+		pr_debug("%s overlay1 writeback is disabled\n", __func__);
+	}
+	mfd->ov1_blt_state = mfd->use_ov1_blt;
+}
+
 static u32 mdp4_overlay_blt_enable(struct mdp_overlay *req,
 	struct msm_fb_data_type *mfd, uint32 perf_level)
 {
@@ -2150,7 +2166,8 @@
 		clk_rate = (&mfd->panel_info.mipi)->dsi_pclk_rate;
 
 	if ((mfd->panel_info.type == LCDC_PANEL) ||
-		(mfd->panel_info.type == MIPI_VIDEO_PANEL))
+	    (mfd->panel_info.type == MIPI_VIDEO_PANEL) ||
+	    (mfd->panel_info.type == DTV_PANEL))
 		pull_mode = 1;
 
 	if (pull_mode && (req->src_rect.h > req->dst_rect.h ||
@@ -2169,7 +2186,8 @@
 			if (req->dst_rect.x != 0)
 				use_blt = 1;
 		}
-		if (mfd->panel_info.xres > 1280)
+		if ((mfd->panel_info.xres > 1280) &&
+		    (mfd->panel_info.type != DTV_PANEL))
 			use_blt = 1;
 	}
 	return use_blt;
@@ -2197,8 +2215,6 @@
 		return -EINTR;
 	}
 
-	perf_level = mdp4_overlay_get_perf_level(req, mfd);
-
 	mixer = mfd->panel_info.pdest;	/* DISPLAY_1 or DISPLAY_2 */
 
 	ret = mdp4_overlay_req2pipe(req, mixer, &pipe, mfd);
@@ -2209,6 +2225,8 @@
 		return ret;
 	}
 
+	perf_level = mdp4_overlay_get_perf_level(req, mfd);
+
 	if (mixer == MDP4_MIXER0) {
 		u32 use_blt = mdp4_overlay_blt_enable(req, mfd,	perf_level);
 		mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
@@ -2252,8 +2270,12 @@
 	}
 
 	if (ctrl->panel_mode & MDP4_PANEL_DTV &&
-	    pipe->mixer_num == MDP4_MIXER1)
+	    pipe->mixer_num == MDP4_MIXER1) {
+		u32 use_blt = mdp4_overlay_blt_enable(req, mfd, perf_level);
 		mdp4_overlay_dtv_set(mfd, pipe);
+		mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
+		mfd->use_ov1_blt |= (use_blt << (pipe->pipe_ndx-1));
+	}
 
 	if (new_perf_level != perf_level) {
 		u32 old_level = new_perf_level;
@@ -2282,13 +2304,6 @@
 	}
 	mutex_unlock(&mfd->dma->ov_mutex);
 
-#ifdef CONFIG_MSM_BUS_SCALING
-	if (pipe->mixer_num == MDP4_MIXER0) {
-		mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
-						- perf_level);
-	}
-#endif
-
 	return 0;
 }
 
@@ -2333,8 +2348,7 @@
 #endif
 	}
 
-	if (mfd->mdp_rev >= MDP_REV_42 && !mfd->use_ov0_blt &&
-	    !(ctrl->panel_mode & (MDP4_PANEL_MDDI | MDP4_PANEL_DSI_CMD))) {
+	if (mfd->mdp_rev >= MDP_REV_42 && !mfd->use_ov0_blt) {
 		ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
 	} else {
 		mdp4_mixer_stage_down(pipe);
@@ -2344,6 +2358,11 @@
 			if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
 				if (mfd->panel_power_on)
 					mdp4_dsi_cmd_overlay_restore();
+			} else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+				pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+				if (mfd->panel_power_on)
+					mdp4_overlay_dsi_video_vsync_push(mfd,
+									  pipe);
 			}
 #else
 			if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
@@ -2354,13 +2373,24 @@
 					mdp4_mddi_overlay_restore();
 			}
 #endif
+			else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
+				pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+				if (mfd->panel_power_on)
+					mdp4_overlay_lcdc_vsync_push(mfd, pipe);
+			}
 			mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
 			mdp4_overlay_update_blt_mode(mfd);
 			if (!mfd->use_ov0_blt)
 				mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
 		} else {	/* mixer1, DTV, ATV */
-			if (ctrl->panel_mode & MDP4_PANEL_DTV)
+			if (ctrl->panel_mode & MDP4_PANEL_DTV) {
 				mdp4_overlay_dtv_unset(mfd, pipe);
+				mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
+				mdp4_overlay1_update_blt_mode(mfd);
+				if (!mfd->use_ov1_blt)
+					mdp4_free_writeback_buf(mfd,
+								MDP4_MIXER1);
+			}
 		}
 	}
 
@@ -2377,8 +2407,6 @@
 
 	mdp4_overlay_pipe_free(pipe);
 
-	mdp4_set_perf_level();
-
 	mutex_unlock(&mfd->dma->ov_mutex);
 
 	return 0;
@@ -2439,6 +2467,9 @@
 
 	mdp4_mixer_stage_commit(pipe->mixer_num);
 
+	if (mfd->use_ov1_blt)
+		mdp4_overlay1_update_blt_mode(mfd);
+
 	mdp4_overlay_dtv_wait_for_ov(mfd, pipe);
 
 	mutex_unlock(&mfd->dma->ov_mutex);
@@ -2456,6 +2487,7 @@
 	struct file *srcp1_file = NULL, *srcp2_file = NULL;
 	struct ion_handle *srcp0_ihdl = NULL;
 	struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
+	int ps0_need, p_need;
 	uint32_t overlay_version = 0;
 	int ret = 0;
 
@@ -2475,7 +2507,7 @@
 		return -EINTR;
 
 	img = &req->data;
-	get_img(img, info, &start, &len, &srcp0_file, &srcp0_ihdl);
+	get_img(img, info, &start, &len, &srcp0_file, &ps0_need, &srcp0_ihdl);
 	if (len == 0) {
 		mutex_unlock(&mfd->dma->ov_mutex);
 		pr_err("%s: pmem Error\n", __func__);
@@ -2494,7 +2526,7 @@
 		if (overlay_version > 0) {
 			img = &req->plane1_data;
 			get_img(img, info, &start, &len, &srcp1_file,
-				&srcp1_ihdl);
+				&p_need, &srcp1_ihdl);
 			if (len == 0) {
 				mutex_unlock(&mfd->dma->ov_mutex);
 				pr_err("%s: Error to get plane1\n", __func__);
@@ -2526,7 +2558,7 @@
 		if (overlay_version > 0) {
 			img = &req->plane1_data;
 			get_img(img, info, &start, &len, &srcp1_file,
-				&srcp1_ihdl);
+				&p_need, &srcp1_ihdl);
 			if (len == 0) {
 				mutex_unlock(&mfd->dma->ov_mutex);
 				pr_err("%s: Error to get plane1\n", __func__);
@@ -2537,7 +2569,7 @@
 
 			img = &req->plane2_data;
 			get_img(img, info, &start, &len, &srcp2_file,
-				&srcp2_ihdl);
+				&p_need, &srcp2_ihdl);
 			if (len == 0) {
 				mutex_unlock(&mfd->dma->ov_mutex);
 				pr_err("%s: Error to get plane2\n", __func__);
@@ -2580,6 +2612,9 @@
 	if (mfd->use_ov0_blt)
 		mdp4_overlay_update_blt_mode(mfd);
 
+	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 {
@@ -2605,8 +2640,11 @@
 	} else if (pipe->mixer_num == MDP4_MIXER1) {
 		ctrl->mixer1_played++;
 		/* enternal interface */
-		if (ctrl->panel_mode & MDP4_PANEL_DTV)
+		if (ctrl->panel_mode & MDP4_PANEL_DTV) {
 			mdp4_overlay_dtv_ov_done_push(mfd, pipe);
+			if (!mfd->use_ov1_blt)
+				mdp4_overlay1_update_blt_mode(mfd);
+			}
 	} else {
 
 		/* primary interface */
@@ -2659,9 +2697,13 @@
 	if (srcp2_file)
 		put_pmem_file(srcp2_file);
 #endif
+	/* only source may use frame buffer */
+	if (img->flags & MDP_MEMORY_ID_TYPE_FB)
+		fput_light(srcp0_file, ps0_need);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	if (!IS_ERR_OR_NULL(srcp0_ihdl))
+	else if (!IS_ERR_OR_NULL(srcp0_ihdl))
 		ion_free(mfd->iclient, srcp0_ihdl);
+
 	if (!IS_ERR_OR_NULL(srcp1_ihdl))
 		ion_free(mfd->iclient, srcp1_ihdl);
 	if (!IS_ERR_OR_NULL(srcp2_ihdl))
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 590ad65..d5c08e8 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -301,7 +301,7 @@
 		/* MSP_BORDER_COLOR */
 		MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5008,
 			(0x0 & 0xFFF));		/* 12-bit R */
-		mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 	} else {
 		switch (mfd->ibuf.bpp) {
 		case 2:
@@ -369,6 +369,9 @@
 {
 	int result = 0;
 
+	pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+	mdp4_overlay_dtv_ov_done_push(mfd, pipe);
+
 	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
 			pipe->pipe_type == OVERLAY_TYPE_RGB) {
 		result = mdp4_dtv_stop(mfd);
@@ -593,13 +596,11 @@
 
 void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd)
 {
-	mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
 	mdp4_dtv_do_blt(mfd, 1);
 }
 
 void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd)
 {
-	mdp4_free_writeback_buf(mfd, MDP4_MIXER1);
 	mdp4_dtv_do_blt(mfd, 0);
 }
 
diff --git a/drivers/video/msm/mipi_tc358764_dsi2lvds.c b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
index fcb5163..1624534 100644
--- a/drivers/video/msm/mipi_tc358764_dsi2lvds.c
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
@@ -226,10 +226,14 @@
 static u32 d2l_3d_gpio_enable;
 static u32 d2l_3d_gpio_mode;
 static int d2l_enable_3d;
+static struct i2c_client *d2l_i2c_client;
+static struct i2c_driver d2l_i2c_slave_driver;
 
 static int mipi_d2l_init(void);
 static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
 			      bool enable, bool mode);
+static u32 d2l_i2c_read_reg(struct i2c_client *client, u16 reg);
+static u32 d2l_i2c_write_reg(struct i2c_client *client, u16 reg, u32 val);
 
 /**
  * Read a bridge register
@@ -296,6 +300,20 @@
 	mipi_d2l_read_reg(mfd, SYSSTAT);		/* 0x500 */
 }
 
+static void mipi_d2l_read_status_via_i2c(struct i2c_client *client)
+{
+	u32 tmp = 0;
+
+	tmp = d2l_i2c_read_reg(client, DSIERRCNT);
+	d2l_i2c_write_reg(client, DSIERRCNT, 0xFFFF0000);
+
+	d2l_i2c_read_reg(client, DSI_LANESTATUS0);	/* 0x214 */
+	d2l_i2c_read_reg(client, DSI_LANESTATUS1);	/* 0x218 */
+	d2l_i2c_read_reg(client, DSI_INTSTATUS);	/* 0x220 */
+	d2l_i2c_read_reg(client, SYSSTAT);		/* 0x500 */
+
+	d2l_i2c_write_reg(client, DSIERRCNT, tmp);
+}
 /**
  * Init the D2L bridge via the DSI interface for Video.
  *
@@ -315,12 +333,19 @@
 	u32 vpctrl;
 	u32 htime1;
 	u32 vtime1;
+	u32 htime2;
+	u32 vtime2;
 	u32 ppi_tx_rx_ta; /* BTA Bus-Turn-Around */
 	u32 lvcfg;
 	u32 hbpr;	/* Horizontal Back Porch */
 	u32 hpw;	/* Horizontal Pulse Width */
 	u32 vbpr;	/* Vertical Back Porch */
 	u32 vpw;	/* Vertical Pulse Width */
+
+	u32 hfpr;	/* Horizontal Front Porch */
+	u32 hsize;	/* Horizontal Active size */
+	u32 vfpr;	/* Vertical Front Porch */
+	u32 vsize;	/* Vertical Active size */
 	bool vesa_rgb888 = false;
 
 	lanes_enable = 0x01; /* clock-lane enable */
@@ -345,8 +370,12 @@
 		return -EINVAL;
 	}
 
-	pr_debug("%s.xres=%d.yres=%d.\n",
-		__func__, mfd->panel_info.xres, mfd->panel_info.yres);
+	pr_debug("%s.xres=%d.yres=%d.fps=%d.dst_format=%d.\n",
+		__func__,
+		 mfd->panel_info.xres,
+		 mfd->panel_info.yres,
+		 mfd->panel_info.mipi.frame_rate,
+		 mfd->panel_info.mipi.dst_format);
 
 	hbpr = mfd->panel_info.lcdc.h_back_porch;
 	hpw	= mfd->panel_info.lcdc.h_pulse_width;
@@ -355,6 +384,15 @@
 
 	htime1 = (hbpr << 16) + hpw;
 	vtime1 = (vbpr << 16) + vpw;
+
+	hfpr = mfd->panel_info.lcdc.h_front_porch;
+	hsize = mfd->panel_info.xres;
+	vfpr = mfd->panel_info.lcdc.v_front_porch;
+	vsize = mfd->panel_info.yres;
+
+	htime2 = (hfpr << 16) + hsize;
+	vtime2 = (vfpr << 16) + vsize;
+
 	lvcfg = 0x0003; /* PCLK=DCLK/3, Dual Link, LVEN */
 	vpctrl = 0x01000120; /* Output RGB888 , Event-Mode , */
 	ppi_tx_rx_ta = 0x00040004;
@@ -403,6 +441,8 @@
 	mipi_d2l_write_reg(mfd, VPCTRL, vpctrl); /* RGB888 + Event mode */
 	mipi_d2l_write_reg(mfd, HTIM1, htime1);
 	mipi_d2l_write_reg(mfd, VTIM1, vtime1);
+	mipi_d2l_write_reg(mfd, HTIM2, htime2);
+	mipi_d2l_write_reg(mfd, VTIM2, vtime2);
 	mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
 	mipi_d2l_write_reg(mfd, LVCFG, lvcfg); /* Enables LVDS tx */
 
@@ -539,6 +579,9 @@
 
 	mipi_d2l_enable_3d(mfd, false, false);
 
+	/* Add I2C driver only after DSI-CLK is running */
+	i2c_add_driver(&d2l_i2c_slave_driver);
+
 	pr_info("%s.ret=%d.\n", __func__, ret);
 
 	return ret;
@@ -589,6 +632,103 @@
 	.set_backlight = mipi_d2l_set_backlight,
 };
 
+static u32 d2l_i2c_read_reg(struct i2c_client *client, u16 reg)
+{
+	int rc;
+	u32 val = 0;
+	u8 buf[6];
+
+	if (client == NULL) {
+		pr_err("%s.invalid i2c client.\n", __func__);
+		return -EINVAL;
+	}
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xFF;
+
+	rc = i2c_master_send(client, buf, sizeof(reg));
+	rc = i2c_master_recv(client, buf, 4);
+
+	if (rc >= 0) {
+		val = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
+		pr_debug("%s.reg=0x%x.val=0x%x.\n", __func__, reg, val);
+	} else
+		pr_err("%s.fail.reg=0x%x.\n", __func__, reg);
+
+	return val;
+}
+
+static u32 d2l_i2c_write_reg(struct i2c_client *client, u16 reg, u32 val)
+{
+	int rc;
+	u8 buf[6];
+
+	if (client == NULL) {
+		pr_err("%s.invalid i2c client.\n", __func__);
+		return -EINVAL;
+	}
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xFF;
+
+	buf[2] = (val >> 0) & 0xFF;
+	buf[3] = (val >> 8) & 0xFF;
+	buf[4] = (val >> 16) & 0xFF;
+	buf[5] = (val >> 24) & 0xFF;
+
+	rc = i2c_master_send(client, buf, sizeof(buf));
+
+	if (rc >= 0)
+		pr_debug("%s.reg=0x%x.val=0x%x.\n", __func__, reg, val);
+	else
+		pr_err("%s.fail.reg=0x%x.\n", __func__, reg);
+
+	return val;
+}
+
+static int __devinit d2l_i2c_slave_probe(struct i2c_client *client,
+					 const struct i2c_device_id *id)
+{
+	static const u32 i2c_funcs = I2C_FUNC_I2C;
+
+	d2l_i2c_client = client;
+
+	if (!i2c_check_functionality(client->adapter, i2c_funcs)) {
+		pr_err("%s.i2c_check_functionality failed.\n", __func__);
+		return -ENOSYS;
+	} else {
+		pr_debug("%s.i2c_check_functionality OK.\n", __func__);
+	}
+
+	d2l_i2c_read_reg(client, IDREG);
+
+	mipi_d2l_read_status_via_i2c(d2l_i2c_client);
+
+	return 0;
+}
+
+static __devexit int d2l_i2c_slave_remove(struct i2c_client *client)
+{
+	d2l_i2c_client = NULL;
+
+	return 0;
+}
+
+static const struct i2c_device_id d2l_i2c_id[] = {
+	{"tc358764-i2c", 0},
+	{}
+};
+
+static struct i2c_driver d2l_i2c_slave_driver = {
+	.driver = {
+		.name = "tc358764-i2c",
+		.owner = THIS_MODULE
+	},
+	.probe    = d2l_i2c_slave_probe,
+	.remove   = __devexit_p(d2l_i2c_slave_remove),
+	.id_table = d2l_i2c_id,
+};
+
 static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
 			      bool enable, bool mode)
 {
@@ -630,6 +770,8 @@
 			mipi_d2l_enable_3d(d2l_mfd, true, false);
 		else if (data == 0)
 			mipi_d2l_enable_3d(d2l_mfd, false, false);
+		else if (data == 9)
+			mipi_d2l_read_status_via_i2c(d2l_i2c_client);
 		else
 			pr_err("%s.Invalid value=%d.\n", __func__, data);
 	}
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
index 3b000ec..0f40c77 100644
--- a/drivers/video/msm/msm_dss_io_8960.c
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -11,6 +11,7 @@
  *
  */
 #include <linux/clk.h>
+#include <mach/clk.h>
 #include "msm_fb.h"
 #include "mdp.h"
 #include "mdp4.h"
@@ -634,6 +635,10 @@
 	hdmi_msm_clk(0);
 	udelay(5);
 	hdmi_msm_clk(1);
+
+	clk_reset(hdmi_msm_state->hdmi_app_clk, CLK_RESET_ASSERT);
+	udelay(20);
+	clk_reset(hdmi_msm_state->hdmi_app_clk, CLK_RESET_DEASSERT);
 }
 
 void hdmi_msm_init_phy(int video_format)
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 593f10b..2962393 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -188,40 +188,14 @@
 };
 #endif
 
-#define PANEL_NAME_MAX_LEN 30
 static struct msm_fb_platform_data *msm_fb_pdata;
-static char prim_panel_name[PANEL_NAME_MAX_LEN];
-static char ext_panel_name[PANEL_NAME_MAX_LEN];
-module_param_string(prim_display, prim_panel_name, sizeof(prim_panel_name) , 0);
-module_param_string(ext_display, ext_panel_name, sizeof(ext_panel_name) , 0);
 
 int msm_fb_detect_client(const char *name)
 {
 	int ret = 0;
-	u32 len;
 #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
 	u32 id;
 #endif
-	len = strnlen(name, PANEL_NAME_MAX_LEN);
-	if (strnlen(prim_panel_name, PANEL_NAME_MAX_LEN)) {
-		MSM_FB_DEBUG("\n name = %s, prim_display = %s",
-			name, prim_panel_name);
-		if (!strncmp((char *)prim_panel_name, name, len))
-			return 0;
-		else
-			ret = -EPERM;
-	}
-	if (strnlen(ext_panel_name, PANEL_NAME_MAX_LEN)) {
-		MSM_FB_DEBUG("\n name = %s, ext_display = %s",
-			name, ext_panel_name);
-		if (!strncmp((char *)ext_panel_name, name, len))
-			return 0;
-		else
-			ret = -EPERM;
-	}
-
-	if (ret)
-		return ret;
 
 	ret = -EPERM;
 	if (msm_fb_pdata && msm_fb_pdata->detect_client) {
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 9837f07..a4b46ea 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -177,6 +177,7 @@
 	u32 mem_hid;
 	u32 mdp_rev;
 	u32 use_ov0_blt, ov0_blt_state;
+	u32 use_ov1_blt, ov1_blt_state;
 	u32 writeback_state;
 };
 
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index bfaac82..f685cd5 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -2024,8 +2024,8 @@
 	}
 
 	client_index = vid_dec_get_empty_client_index();
-	if (client_index == -1) {
-		ERR("%s() : No free clients client_index == -1\n", __func__);
+	if (client_index < 0) {
+		ERR("%s() : No free clients client_index < 0\n", __func__);
 		goto client_failure;
 	}
 	client_ctx = &vid_dec_device_p->vdec_clients[client_index];
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index 500ee6b..3ac41bc 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -37,6 +37,8 @@
 	u8 variant_id;
 	u8 version;
 	u8 build;
+	/* Points to the firmware name to be upgraded to */
+	const char *fw_name;
 };
 
 /* The platform data for the Atmel maXTouch touchscreen driver */
diff --git a/include/linux/ion.h b/include/linux/ion.h
index caed2a2..ca1f198 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -493,6 +493,23 @@
  */
 int msm_ion_unsecure_heap(int heap_id);
 
+/**
+ * msm_ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @vaddr -  virtual address to operate on.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ *		ION_IOC_CLEAN_CACHES
+ *		ION_IOC_INV_CACHES
+ *		ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+			void *vaddr, unsigned long len, unsigned int cmd);
+
 #else
 static inline struct ion_client *ion_client_create(struct ion_device *dev,
 				     unsigned int heap_mask, const char *name)
@@ -604,6 +621,14 @@
 {
 	return -ENODEV;
 }
+
+static inline int msm_ion_do_cache_op(struct ion_client *client,
+			struct ion_handle *handle, void *vaddr,
+			unsigned long len, unsigned int cmd)
+{
+	return -ENODEV;
+}
+
 #endif /* CONFIG_ION */
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/mfd/Kbuild b/include/linux/mfd/Kbuild
index 1acc78f..bba647c 100644
--- a/include/linux/mfd/Kbuild
+++ b/include/linux/mfd/Kbuild
@@ -1,3 +1,3 @@
 header-y += timpani-audio.h
 header-y += msm-adie-codec.h
-header-y += wcd9310/
+header-y += wcd9xxx/
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index e2d4d93..818eeca 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -175,6 +175,16 @@
  *				track of chargecycles
  */
 void pm8921_bms_charging_end(int is_battery_full);
+
+void pm8921_bms_calibrate_hkadc(void);
+/**
+ * pm8921_bms_get_simultaneous_battery_voltage_and_current
+ *		- function to take simultaneous vbat and vsense readings
+ *		  this puts the bms in override mode but keeps coulumb couting
+ *		  on. Useful when ir compensation needs to be implemented
+ */
+int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
+								int *vbat_uv);
 #else
 static inline int pm8921_bms_get_vsense_avg(int *result)
 {
@@ -198,6 +208,14 @@
 static inline void pm8921_bms_charging_end(int is_battery_full)
 {
 }
+static inline void pm8921_bms_calibrate_hkadc(void)
+{
+}
+static inline int pm8921_bms_get_simultaneous_battery_voltage_and_current(
+						int *ibat_ua, int *vbat_uv)
+{
+	return -ENXIO;
+}
 #endif
 
 #endif
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
index 22293fe..bdaee74 100644
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ b/include/linux/mfd/pm8xxx/pm8921.h
@@ -142,6 +142,7 @@
 	struct pm8xxx_led_platform_data		*leds_pdata;
 	struct pm8xxx_vibrator_platform_data	*vibrator_pdata;
 	struct pm8xxx_ccadc_platform_data	*ccadc_pdata;
+	struct pm8xxx_pwm_platform_data		*pwm_pdata;
 };
 
 #endif
diff --git a/include/linux/mfd/pm8xxx/pwm.h b/include/linux/mfd/pm8xxx/pwm.h
index 9169e90..09b165e 100644
--- a/include/linux/mfd/pm8xxx/pwm.h
+++ b/include/linux/mfd/pm8xxx/pwm.h
@@ -19,7 +19,6 @@
 
 #define PM8XXX_PWM_PERIOD_MIN	7 /* usec: 19.2M, n=6, m=0, pre=2 */
 #define PM8XXX_PWM_PERIOD_MAX	(384 * USEC_PER_SEC) /* 1K, n=9, m=7, pre=6 */
-
 #define PM_PWM_LUT_SIZE			64
 #define PM_PWM_LUT_DUTY_TIME_MAX	512	/* ms */
 #define PM_PWM_LUT_PAUSE_MAX		(7000 * PM_PWM_LUT_DUTY_TIME_MAX)
@@ -92,6 +91,14 @@
 };
 
 /**
+ * struct pm8xxx_pwm_platform_data - PWM platform data
+ * dtest_channel - Enable LPG DTEST mode for this LPG channel
+ */
+struct pm8xxx_pwm_platform_data {
+	int dtest_channel;
+};
+
+/**
  * pm8xxx_pwm_config_period - change PWM period
  *
  * @pwm: the PWM device
diff --git a/include/linux/mfd/wcd9310/Kbuild b/include/linux/mfd/wcd9310/Kbuild
deleted file mode 100644
index 2702ec6..0000000
--- a/include/linux/mfd/wcd9310/Kbuild
+++ /dev/null
@@ -1 +0,0 @@
-header-y += registers.h
diff --git a/include/linux/mfd/wcd9310/core.h b/include/linux/mfd/wcd9310/core.h
deleted file mode 100644
index 8605ac6..0000000
--- a/include/linux/mfd/wcd9310/core.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MFD_TABLA_CORE_H__
-#define __MFD_TABLA_CORE_H__
-
-#include <linux/interrupt.h>
-#include <linux/wakelock.h>
-
-#define TABLA_NUM_IRQ_REGS 3
-
-#define TABLA_SLIM_NUM_PORT_REG 3
-
-#define TABLA_INTERFACE_TYPE_SLIMBUS	0x00
-#define TABLA_INTERFACE_TYPE_I2C	0x01
-
-#define TABLA_VERSION_1_0	0
-#define TABLA_VERSION_1_1	1
-#define TABLA_VERSION_2_0	2
-#define TABLA_IS_1_X(ver) \
-	(((ver == TABLA_VERSION_1_0) || (ver == TABLA_VERSION_1_1)) ? 1 : 0)
-#define TABLA_IS_2_0(ver) ((ver == TABLA_VERSION_2_0) ? 1 : 0)
-
-enum {
-	TABLA_IRQ_SLIMBUS = 0,
-	TABLA_IRQ_MBHC_REMOVAL,
-	TABLA_IRQ_MBHC_SHORT_TERM,
-	TABLA_IRQ_MBHC_PRESS,
-	TABLA_IRQ_MBHC_RELEASE,
-	TABLA_IRQ_MBHC_POTENTIAL,
-	TABLA_IRQ_MBHC_INSERTION,
-	TABLA_IRQ_BG_PRECHARGE,
-	TABLA_IRQ_PA1_STARTUP,
-	TABLA_IRQ_PA2_STARTUP,
-	TABLA_IRQ_PA3_STARTUP,
-	TABLA_IRQ_PA4_STARTUP,
-	TABLA_IRQ_PA5_STARTUP,
-	TABLA_IRQ_MICBIAS1_PRECHARGE,
-	TABLA_IRQ_MICBIAS2_PRECHARGE,
-	TABLA_IRQ_MICBIAS3_PRECHARGE,
-	TABLA_IRQ_HPH_PA_OCPL_FAULT,
-	TABLA_IRQ_HPH_PA_OCPR_FAULT,
-	TABLA_IRQ_EAR_PA_OCPL_FAULT,
-	TABLA_IRQ_HPH_L_PA_STARTUP,
-	TABLA_IRQ_HPH_R_PA_STARTUP,
-	TABLA_IRQ_EAR_PA_STARTUP,
-	TABLA_NUM_IRQS,
-};
-
-enum tabla_pm_state {
-	TABLA_PM_SLEEPABLE,
-	TABLA_PM_AWAKE,
-	TABLA_PM_ASLEEP,
-};
-
-struct tabla {
-	struct device *dev;
-	struct slim_device *slim;
-	struct slim_device *slim_slave;
-	struct mutex io_lock;
-	struct mutex xfer_lock;
-	struct mutex irq_lock;
-	u8 version;
-
-	unsigned int irq_base;
-	unsigned int irq;
-	u8 irq_masks_cur[TABLA_NUM_IRQ_REGS];
-	u8 irq_masks_cache[TABLA_NUM_IRQ_REGS];
-	u8 irq_level[TABLA_NUM_IRQ_REGS];
-
-	int reset_gpio;
-
-	int (*read_dev)(struct tabla *tabla, unsigned short reg,
-			int bytes, void *dest, bool interface_reg);
-	int (*write_dev)(struct tabla *tabla, unsigned short reg,
-			 int bytes, void *src, bool interface_reg);
-
-	struct regulator_bulk_data *supplies;
-
-	enum tabla_pm_state pm_state;
-	struct mutex pm_lock;
-	/* pm_wq notifies change of pm_state */
-	wait_queue_head_t pm_wq;
-	struct wake_lock wlock;
-	int wlock_holders;
-};
-
-int tabla_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
-int tabla_interface_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
-int tabla_bulk_read(struct tabla *tabla, unsigned short reg, int count,
-		    u8 *buf);
-int tabla_bulk_write(struct tabla *tabla, unsigned short reg, int count,
-		     u8 *buf);
-int tabla_irq_init(struct tabla *tabla);
-void tabla_irq_exit(struct tabla *tabla);
-int tabla_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
-int tabla_get_intf_type(void);
-
-void tabla_lock_sleep(struct tabla *tabla);
-void tabla_unlock_sleep(struct tabla *tabla);
-enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
-				     enum tabla_pm_state n);
-
-static inline int tabla_request_irq(struct tabla *tabla, int irq,
-				     irq_handler_t handler, const char *name,
-				     void *data)
-{
-	if (!tabla->irq_base)
-		return -EINVAL;
-	return request_threaded_irq(tabla->irq_base + irq, NULL, handler,
-				    IRQF_TRIGGER_RISING, name,
-				    data);
-}
-static inline void tabla_free_irq(struct tabla *tabla, int irq, void *data)
-{
-	if (!tabla->irq_base)
-		return;
-	free_irq(tabla->irq_base + irq, data);
-}
-static inline void tabla_enable_irq(struct tabla *tabla, int irq)
-{
-	if (!tabla->irq_base)
-		return;
-	enable_irq(tabla->irq_base + irq);
-}
-static inline void tabla_disable_irq(struct tabla *tabla, int irq)
-{
-	if (!tabla->irq_base)
-		return;
-	disable_irq_nosync(tabla->irq_base + irq);
-}
-
-#endif
diff --git a/include/linux/mfd/wcd9xxx/Kbuild b/include/linux/mfd/wcd9xxx/Kbuild
new file mode 100644
index 0000000..acfab6e
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/Kbuild
@@ -0,0 +1,2 @@
+header-y += wcd9xxx_registers.h
+header-y += wcd9310_registers.h
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
new file mode 100644
index 0000000..0d99e37
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -0,0 +1,177 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MFD_TABLA_CORE_H__
+#define __MFD_TABLA_CORE_H__
+
+#include <linux/interrupt.h>
+#include <linux/wakelock.h>
+
+#define WCD9XXX_NUM_IRQ_REGS 3
+
+#define WCD9XXX_SLIM_NUM_PORT_REG 3
+
+#define WCD9XXX_INTERFACE_TYPE_SLIMBUS	0x00
+#define WCD9XXX_INTERFACE_TYPE_I2C	0x01
+
+#define TABLA_VERSION_1_0	0
+#define TABLA_VERSION_1_1	1
+#define TABLA_VERSION_2_0	2
+#define TABLA_IS_1_X(ver) \
+	(((ver == TABLA_VERSION_1_0) || (ver == TABLA_VERSION_1_1)) ? 1 : 0)
+#define TABLA_IS_2_0(ver) ((ver == TABLA_VERSION_2_0) ? 1 : 0)
+
+enum {
+	TABLA_IRQ_SLIMBUS = 0,
+	TABLA_IRQ_MBHC_REMOVAL,
+	TABLA_IRQ_MBHC_SHORT_TERM,
+	TABLA_IRQ_MBHC_PRESS,
+	TABLA_IRQ_MBHC_RELEASE,
+	TABLA_IRQ_MBHC_POTENTIAL,
+	TABLA_IRQ_MBHC_INSERTION,
+	TABLA_IRQ_BG_PRECHARGE,
+	TABLA_IRQ_PA1_STARTUP,
+	TABLA_IRQ_PA2_STARTUP,
+	TABLA_IRQ_PA3_STARTUP,
+	TABLA_IRQ_PA4_STARTUP,
+	TABLA_IRQ_PA5_STARTUP,
+	TABLA_IRQ_MICBIAS1_PRECHARGE,
+	TABLA_IRQ_MICBIAS2_PRECHARGE,
+	TABLA_IRQ_MICBIAS3_PRECHARGE,
+	TABLA_IRQ_HPH_PA_OCPL_FAULT,
+	TABLA_IRQ_HPH_PA_OCPR_FAULT,
+	TABLA_IRQ_EAR_PA_OCPL_FAULT,
+	TABLA_IRQ_HPH_L_PA_STARTUP,
+	TABLA_IRQ_HPH_R_PA_STARTUP,
+	TABLA_IRQ_EAR_PA_STARTUP,
+	TABLA_NUM_IRQS,
+};
+
+enum {
+	SITAR_IRQ_SLIMBUS = 0,
+	SITAR_IRQ_MBHC_REMOVAL,
+	SITAR_IRQ_MBHC_SHORT_TERM,
+	SITAR_IRQ_MBHC_PRESS,
+	SITAR_IRQ_MBHC_RELEASE,
+	SITAR_IRQ_MBHC_POTENTIAL,
+	SITAR_IRQ_MBHC_INSERTION,
+	SITAR_IRQ_BG_PRECHARGE,
+	SITAR_IRQ_PA1_STARTUP,
+	SITAR_IRQ_PA2_STARTUP,
+	SITAR_IRQ_PA3_STARTUP,
+	SITAR_IRQ_PA4_STARTUP,
+	SITAR_IRQ_PA5_STARTUP,
+	SITAR_IRQ_MICBIAS1_PRECHARGE,
+	SITAR_IRQ_MICBIAS2_PRECHARGE,
+	SITAR_IRQ_MICBIAS3_PRECHARGE,
+	SITAR_IRQ_HPH_PA_OCPL_FAULT,
+	SITAR_IRQ_HPH_PA_OCPR_FAULT,
+	SITAR_IRQ_EAR_PA_OCPL_FAULT,
+	SITAR_IRQ_HPH_L_PA_STARTUP,
+	SITAR_IRQ_HPH_R_PA_STARTUP,
+	SITAR_IRQ_EAR_PA_STARTUP,
+	SITAR_NUM_IRQS,
+};
+
+
+enum wcd9xxx_pm_state {
+	WCD9XXX_PM_SLEEPABLE,
+	WCD9XXX_PM_AWAKE,
+	WCD9XXX_PM_ASLEEP,
+};
+
+struct wcd9xxx {
+	struct device *dev;
+	struct slim_device *slim;
+	struct slim_device *slim_slave;
+	struct mutex io_lock;
+	struct mutex xfer_lock;
+	struct mutex irq_lock;
+	u8 version;
+
+	unsigned int irq_base;
+	unsigned int irq;
+	u8 irq_masks_cur[WCD9XXX_NUM_IRQ_REGS];
+	u8 irq_masks_cache[WCD9XXX_NUM_IRQ_REGS];
+	u8 irq_level[WCD9XXX_NUM_IRQ_REGS];
+
+	int reset_gpio;
+
+	int (*read_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			int bytes, void *dest, bool interface_reg);
+	int (*write_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			 int bytes, void *src, bool interface_reg);
+
+	struct regulator_bulk_data *supplies;
+
+	enum wcd9xxx_pm_state pm_state;
+	struct mutex pm_lock;
+	/* pm_wq notifies change of pm_state */
+	wait_queue_head_t pm_wq;
+	struct wake_lock wlock;
+	int wlock_holders;
+	int num_rx_port;
+	int num_tx_port;
+};
+
+int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
+int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		u8 val);
+int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
+int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+		u8 val);
+int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			int count, u8 *buf);
+int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+			int count, u8 *buf);
+int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx);
+void wcd9xxx_irq_exit(struct wcd9xxx *wcd9xxx);
+int wcd9xxx_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
+int wcd9xxx_get_intf_type(void);
+
+void wcd9xxx_lock_sleep(struct wcd9xxx *wcd9xxx);
+void wcd9xxx_unlock_sleep(struct wcd9xxx *wcd9xxx);
+enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(struct wcd9xxx *wcd9xxx,
+				enum wcd9xxx_pm_state o,
+				enum wcd9xxx_pm_state n);
+
+static inline int wcd9xxx_request_irq(struct wcd9xxx *wcd9xxx, int irq,
+				     irq_handler_t handler, const char *name,
+				     void *data)
+{
+	if (!wcd9xxx->irq_base)
+		return -EINVAL;
+	return request_threaded_irq(wcd9xxx->irq_base + irq, NULL, handler,
+				    IRQF_TRIGGER_RISING, name,
+				    data);
+}
+static inline void wcd9xxx_free_irq(struct wcd9xxx *wcd9xxx,
+				int irq, void *data)
+{
+	if (!wcd9xxx->irq_base)
+		return;
+	free_irq(wcd9xxx->irq_base + irq, data);
+}
+static inline void wcd9xxx_enable_irq(struct wcd9xxx *wcd9xxx, int irq)
+{
+	if (!wcd9xxx->irq_base)
+		return;
+	enable_irq(wcd9xxx->irq_base + irq);
+}
+static inline void wcd9xxx_disable_irq(struct wcd9xxx *wcd9xxx, int irq)
+{
+	if (!wcd9xxx->irq_base)
+		return;
+	disable_irq_nosync(wcd9xxx->irq_base + irq);
+}
+
+#endif
diff --git a/include/linux/mfd/wcd9310/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
similarity index 71%
rename from include/linux/mfd/wcd9310/pdata.h
rename to include/linux/mfd/wcd9xxx/pdata.h
index af801f0..db76294 100644
--- a/include/linux/mfd/wcd9310/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,15 @@
 
 #include <linux/slimbus/slimbus.h>
 
+#define SITAR_LDOH_1P95_V 0x0
+#define SITAR_LDOH_2P35_V 0x1
+#define SITAR_LDOH_2P75_V 0x2
+#define SITAR_LDOH_2P85_V 0x3
+
+#define SITAR_CFILT1_SEL 0x0
+#define SITAR_CFILT2_SEL 0x1
+#define SITAR_CFILT3_SEL 0x2
+
 #define TABLA_LDOH_1P95_V 0x0
 #define TABLA_LDOH_2P35_V 0x1
 #define TABLA_LDOH_2P75_V 0x2
@@ -51,7 +60,7 @@
 #define TABLA_DCYCLE_3839 0xE
 #define TABLA_DCYCLE_4095 0xF
 
-struct tabla_amic {
+struct wcd9xxx_amic {
 	/*legacy mode, txfe_enable and txfe_buff take 7 input
 	 * each bit represent the channel / TXFE number
 	 * and numbered as below
@@ -75,7 +84,7 @@
  * If ldoh_v = 2.85 250 mv < cfiltx_mv < 2700 mv
  */
 
-struct tabla_micbias_setting {
+struct wcd9xxx_micbias_setting {
 	u8 ldoh_v;
 	u32 cfilt1_mv; /* in mv */
 	u32 cfilt2_mv; /* in mv */
@@ -86,7 +95,7 @@
 	u8 bias4_cfilt_sel;
 };
 
-struct tabla_ocp_setting {
+struct wcd9xxx_ocp_setting {
 	unsigned int	use_pdata:1; /* 0 - use sys default as recommended */
 	unsigned int	num_attempts:4; /* up to 15 attempts */
 	unsigned int	run_time:4; /* in duty cycle */
@@ -94,15 +103,39 @@
 	unsigned int	hph_ocp_limit:3; /* Headphone OCP current limit */
 };
 
-struct tabla_pdata {
+#define MAX_REGULATOR	6
+/*
+ *      format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
+ *
+ *      <POWER_SUPPLY_PIN_NAME> from Tabla objective spec
+*/
+
+#define  WCD9XXX_CDC_VDDA_CP_CUR_MAX      500000
+#define  WCD9XXX_CDC_VDDA_RX_CUR_MAX      20000
+#define  WCD9XXX_CDC_VDDA_TX_CUR_MAX      20000
+#define  WCD9XXX_VDDIO_CDC_CUR_MAX        5000
+
+#define  WCD9XXX_VDDD_CDC_D_CUR_MAX       5000
+#define  WCD9XXX_VDDD_CDC_A_CUR_MAX       5000
+
+struct wcd9xxx_regulator {
+	const char *name;
+	int min_uV;
+	int max_uV;
+	int optimum_uA;
+	struct regulator *regulator;
+};
+
+struct wcd9xxx_pdata {
 	int irq;
 	int irq_base;
 	int num_irqs;
 	int reset_gpio;
-	struct tabla_amic amic_settings;
+	struct wcd9xxx_amic amic_settings;
 	struct slim_device slimbus_slave_device;
-	struct tabla_micbias_setting micbias;
-	struct tabla_ocp_setting ocp;
+	struct wcd9xxx_micbias_setting micbias;
+	struct wcd9xxx_ocp_setting ocp;
+	struct wcd9xxx_regulator regulator[MAX_REGULATOR];
 };
 
 #endif
diff --git a/include/linux/mfd/wcd9xxx/wcd9304_registers.h b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
new file mode 100644
index 0000000..df54e02
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
@@ -0,0 +1,742 @@
+/* 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 SITAR_CODEC_DIGITAL_H
+#define SITAR_CODEC_DIGITAL_H
+
+#define SITAR_A_PIN_CTL_OE0			(0x10)
+#define SITAR_A_PIN_CTL_OE0__POR			(0x00000000)
+#define SITAR_A_PIN_CTL_OE1			(0x11)
+#define SITAR_A_PIN_CTL_OE1__POR			(0x00000000)
+#define SITAR_A_PIN_CTL_DATA0			(0x12)
+#define SITAR_A_PIN_CTL_DATA0__POR			(0x00000000)
+#define SITAR_A_PIN_CTL_DATA1			(0x13)
+#define SITAR_A_PIN_CTL_DATA1__POR			(0x00000000)
+#define SITAR_A_HDRIVE_GENERIC			(0x18)
+#define SITAR_A_HDRIVE_GENERIC__POR			(0x00000000)
+#define SITAR_A_HDRIVE_OVERRIDE			(0x19)
+#define SITAR_A_HDRIVE_OVERRIDE__POR			(0x00000008)
+#define SITAR_A_ANA_CSR_WAIT_STATE			(0x20)
+#define SITAR_A_ANA_CSR_WAIT_STATE__POR			(0x00000044)
+#define SITAR_A_PROCESS_MONITOR_CTL0			(0x40)
+#define SITAR_A_PROCESS_MONITOR_CTL0__POR			(0x00000080)
+#define SITAR_A_PROCESS_MONITOR_CTL1			(0x41)
+#define SITAR_A_PROCESS_MONITOR_CTL1__POR			(0x00000000)
+#define SITAR_A_PROCESS_MONITOR_CTL2			(0x42)
+#define SITAR_A_PROCESS_MONITOR_CTL2__POR			(0x00000000)
+#define SITAR_A_PROCESS_MONITOR_CTL3			(0x43)
+#define SITAR_A_PROCESS_MONITOR_CTL3__POR			(0x00000001)
+#define SITAR_A_QFUSE_CTL			(0x48)
+#define SITAR_A_QFUSE_CTL__POR			(0x00000000)
+#define SITAR_A_QFUSE_STATUS			(0x49)
+#define SITAR_A_QFUSE_STATUS__POR			(0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT0			(0x4A)
+#define SITAR_A_QFUSE_DATA_OUT0__POR			(0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT1			(0x4B)
+#define SITAR_A_QFUSE_DATA_OUT1__POR			(0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT2			(0x4C)
+#define SITAR_A_QFUSE_DATA_OUT2__POR			(0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT3			(0x4D)
+#define SITAR_A_QFUSE_DATA_OUT3__POR			(0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT4			(0x4E)
+#define SITAR_A_QFUSE_DATA_OUT4__POR			(0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT5			(0x4F)
+#define SITAR_A_QFUSE_DATA_OUT5__POR			(0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT6			(0x50)
+#define SITAR_A_QFUSE_DATA_OUT6__POR			(0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT7			(0x51)
+#define SITAR_A_QFUSE_DATA_OUT7__POR			(0x00000000)
+#define SITAR_A_CDC_CTL			(0x80)
+#define SITAR_A_CDC_CTL__POR			(0x00000000)
+#define SITAR_A_LEAKAGE_CTL			(0x88)
+#define SITAR_A_LEAKAGE_CTL__POR			(0x00000004)
+#define SITAR_A_INTR_MODE			(0x90)
+#define SITAR_A_INTR_MODE__POR			(0x00000000)
+#define SITAR_A_INTR_MASK0			(0x94)
+#define SITAR_A_INTR_MASK0__POR			(0x000000ff)
+#define SITAR_A_INTR_MASK1			(0x95)
+#define SITAR_A_INTR_MASK1__POR			(0x000000ff)
+#define SITAR_A_INTR_MASK2			(0x96)
+#define SITAR_A_INTR_MASK2__POR			(0x000000ff)
+#define SITAR_A_INTR_STATUS0			(0x98)
+#define SITAR_A_INTR_STATUS0__POR			(0x00000000)
+#define SITAR_A_INTR_STATUS1			(0x99)
+#define SITAR_A_INTR_STATUS1__POR			(0x00000000)
+#define SITAR_A_INTR_STATUS2			(0x9A)
+#define SITAR_A_INTR_STATUS2__POR			(0x00000000)
+#define SITAR_A_INTR_CLEAR0			(0x9C)
+#define SITAR_A_INTR_CLEAR0__POR			(0x00000000)
+#define SITAR_A_INTR_CLEAR1			(0x9D)
+#define SITAR_A_INTR_CLEAR1__POR			(0x00000000)
+#define SITAR_A_INTR_CLEAR2			(0x9E)
+#define SITAR_A_INTR_CLEAR2__POR			(0x00000000)
+#define SITAR_A_INTR_LEVEL0			(0xA0)
+#define SITAR_A_INTR_LEVEL0__POR			(0x00000001)
+#define SITAR_A_INTR_LEVEL1			(0xA1)
+#define SITAR_A_INTR_LEVEL1__POR			(0x00000000)
+#define SITAR_A_INTR_LEVEL2			(0xA2)
+#define SITAR_A_INTR_LEVEL2__POR			(0x00000000)
+#define SITAR_A_INTR_TEST0			(0xA4)
+#define SITAR_A_INTR_TEST0__POR			(0x00000000)
+#define SITAR_A_INTR_TEST1			(0xA5)
+#define SITAR_A_INTR_TEST1__POR			(0x00000000)
+#define SITAR_A_INTR_TEST2			(0xA6)
+#define SITAR_A_INTR_TEST2__POR			(0x00000000)
+#define SITAR_A_INTR_SET0			(0xA8)
+#define SITAR_A_INTR_SET0__POR			(0x00000000)
+#define SITAR_A_INTR_SET1			(0xA9)
+#define SITAR_A_INTR_SET1__POR			(0x00000000)
+#define SITAR_A_INTR_SET2			(0xAA)
+#define SITAR_A_INTR_SET2__POR			(0x00000000)
+#define SITAR_A_CDC_TX_I2S_SCK_MODE			(0xC0)
+#define SITAR_A_CDC_TX_I2S_SCK_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_TX_I2S_WS_MODE			(0xC1)
+#define SITAR_A_CDC_TX_I2S_WS_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_DMIC_DATA0_MODE			(0xC4)
+#define SITAR_A_CDC_DMIC_DATA0_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_DMIC_CLK0_MODE			(0xC5)
+#define SITAR_A_CDC_DMIC_CLK0_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_DMIC_DATA1_MODE			(0xC6)
+#define SITAR_A_CDC_DMIC_DATA1_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_DMIC_CLK1_MODE			(0xC7)
+#define SITAR_A_CDC_DMIC_CLK1_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_TX_I2S_SD0_MODE			(0xC8)
+#define SITAR_A_CDC_TX_I2S_SD0_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_INTR_MODE			(0xC9)
+#define SITAR_A_CDC_INTR_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_RX_I2S_SD0_MODE			(0xCA)
+#define SITAR_A_CDC_RX_I2S_SD0_MODE__POR			(0x00000000)
+#define SITAR_A_CDC_RX_I2S_SD1_MODE			(0xCB)
+#define SITAR_A_CDC_RX_I2S_SD1_MODE__POR			(0x00000000)
+#define SITAR_A_BIAS_REF_CTL			(0x100)
+#define SITAR_A_BIAS_REF_CTL__POR			(0x0000001c)
+#define SITAR_A_BIAS_CENTRAL_BG_CTL			(0x101)
+#define SITAR_A_BIAS_CENTRAL_BG_CTL__POR			(0x00000050)
+#define SITAR_A_BIAS_PRECHRG_CTL			(0x102)
+#define SITAR_A_BIAS_PRECHRG_CTL__POR			(0x00000007)
+#define SITAR_A_BIAS_CURR_CTL_1			(0x103)
+#define SITAR_A_BIAS_CURR_CTL_1__POR			(0x00000052)
+#define SITAR_A_BIAS_CURR_CTL_2			(0x104)
+#define SITAR_A_BIAS_CURR_CTL_2__POR			(0x00000000)
+#define SITAR_A_BIAS_OSC_BG_CTL			(0x105)
+#define SITAR_A_BIAS_OSC_BG_CTL__POR			(0x00000016)
+#define SITAR_A_CLK_BUFF_EN1			(0x108)
+#define SITAR_A_CLK_BUFF_EN1__POR			(0x00000004)
+#define SITAR_A_CLK_BUFF_EN2			(0x109)
+#define SITAR_A_CLK_BUFF_EN2__POR			(0x00000002)
+#define SITAR_A_LDO_H_MODE_1			(0x110)
+#define SITAR_A_LDO_H_MODE_1__POR			(0x00000065)
+#define SITAR_A_LDO_H_MODE_2			(0x111)
+#define SITAR_A_LDO_H_MODE_2__POR			(0x000000a8)
+#define SITAR_A_LDO_H_LOOP_CTL			(0x112)
+#define SITAR_A_LDO_H_LOOP_CTL__POR			(0x0000006b)
+#define SITAR_A_LDO_H_COMP_1			(0x113)
+#define SITAR_A_LDO_H_COMP_1__POR			(0x00000084)
+#define SITAR_A_LDO_H_COMP_2			(0x114)
+#define SITAR_A_LDO_H_COMP_2__POR			(0x000000e0)
+#define SITAR_A_LDO_H_BIAS_1			(0x115)
+#define SITAR_A_LDO_H_BIAS_1__POR			(0x0000006d)
+#define SITAR_A_LDO_H_BIAS_2			(0x116)
+#define SITAR_A_LDO_H_BIAS_2__POR			(0x000000a5)
+#define SITAR_A_LDO_H_BIAS_3			(0x117)
+#define SITAR_A_LDO_H_BIAS_3__POR			(0x00000060)
+#define SITAR_A_MICB_CFILT_1_CTL			(0x128)
+#define SITAR_A_MICB_CFILT_1_CTL__POR			(0x00000040)
+#define SITAR_A_MICB_CFILT_1_VAL			(0x129)
+#define SITAR_A_MICB_CFILT_1_VAL__POR			(0x00000080)
+#define SITAR_A_MICB_CFILT_1_PRECHRG			(0x12A)
+#define SITAR_A_MICB_CFILT_1_PRECHRG__POR			(0x00000038)
+#define SITAR_A_MICB_1_CTL			(0x12B)
+#define SITAR_A_MICB_1_CTL__POR			(0x00000016)
+#define SITAR_A_MICB_1_INT_RBIAS			(0x12C)
+#define SITAR_A_MICB_1_INT_RBIAS__POR			(0x00000024)
+#define SITAR_A_MICB_1_MBHC			(0x12D)
+#define SITAR_A_MICB_1_MBHC__POR			(0x00000001)
+#define SITAR_A_MICB_CFILT_2_CTL			(0x12E)
+#define SITAR_A_MICB_CFILT_2_CTL__POR			(0x00000040)
+#define SITAR_A_MICB_CFILT_2_VAL			(0x12F)
+#define SITAR_A_MICB_CFILT_2_VAL__POR			(0x00000080)
+#define SITAR_A_MICB_CFILT_2_PRECHRG			(0x130)
+#define SITAR_A_MICB_CFILT_2_PRECHRG__POR			(0x00000038)
+#define SITAR_A_MICB_2_CTL			(0x131)
+#define SITAR_A_MICB_2_CTL__POR			(0x00000016)
+#define SITAR_A_MICB_2_INT_RBIAS			(0x132)
+#define SITAR_A_MICB_2_INT_RBIAS__POR			(0x00000024)
+#define SITAR_A_MICB_2_MBHC			(0x133)
+#define SITAR_A_MICB_2_MBHC__POR			(0x00000002)
+#define SITAR_A_TX_COM_BIAS			(0x14C)
+#define SITAR_A_TX_COM_BIAS__POR			(0x000000e0)
+#define SITAR_A_MBHC_SCALING_MUX_1			(0x14E)
+#define SITAR_A_MBHC_SCALING_MUX_1__POR			(0x00000000)
+#define SITAR_A_MBHC_SCALING_MUX_2			(0x14F)
+#define SITAR_A_MBHC_SCALING_MUX_2__POR			(0x00000080)
+#define SITAR_A_TX_SUP_SWITCH_CTRL_1			(0x151)
+#define SITAR_A_TX_SUP_SWITCH_CTRL_1__POR			(0x00000000)
+#define SITAR_A_TX_SUP_SWITCH_CTRL_2			(0x152)
+#define SITAR_A_TX_SUP_SWITCH_CTRL_2__POR			(0x00000080)
+#define SITAR_A_TX_1_2_EN			(0x153)
+#define SITAR_A_TX_1_2_EN__POR			(0x00000000)
+#define SITAR_A_TX_1_2_TEST_EN			(0x154)
+#define SITAR_A_TX_1_2_TEST_EN__POR			(0x000000cc)
+#define SITAR_A_TX_1_2_ADC_CH1			(0x155)
+#define SITAR_A_TX_1_2_ADC_CH1__POR			(0x00000044)
+#define SITAR_A_TX_1_2_ADC_CH2			(0x156)
+#define SITAR_A_TX_1_2_ADC_CH2__POR			(0x00000044)
+#define SITAR_A_TX_1_2_ATEST_REFCTRL			(0x157)
+#define SITAR_A_TX_1_2_ATEST_REFCTRL__POR			(0x00000000)
+#define SITAR_A_TX_1_2_TEST_CTL			(0x158)
+#define SITAR_A_TX_1_2_TEST_CTL__POR			(0x00000038)
+#define SITAR_A_TX_1_2_TEST_BLOCK_EN			(0x159)
+#define SITAR_A_TX_1_2_TEST_BLOCK_EN__POR			(0x000000fc)
+#define SITAR_A_TX_1_2_TXFE_CLKDIV			(0x15A)
+#define SITAR_A_TX_1_2_TXFE_CLKDIV__POR			(0x000000ee)
+#define SITAR_A_TX_1_2_SAR_ERR_CH1			(0x15B)
+#define SITAR_A_TX_1_2_SAR_ERR_CH1__POR			(0x00000000)
+#define SITAR_A_TX_1_2_SAR_ERR_CH2			(0x15C)
+#define SITAR_A_TX_1_2_SAR_ERR_CH2__POR			(0x00000000)
+#define SITAR_A_TX_3_EN			(0x15D)
+#define SITAR_A_TX_3_EN__POR			(0x00000000)
+#define SITAR_A_TX_3_TEST_EN			(0x15E)
+#define SITAR_A_TX_3_TEST_EN__POR			(0x000000cc)
+#define SITAR_A_TX_3_ADC			(0x15F)
+#define SITAR_A_TX_3_ADC__POR			(0x00000044)
+#define SITAR_A_TX_3_MBHC_ATEST_REFCTRL			(0x161)
+#define SITAR_A_TX_3_MBHC_ATEST_REFCTRL__POR			(0x00000000)
+#define SITAR_A_TX_3_TEST_CTL			(0x162)
+#define SITAR_A_TX_3_TEST_CTL__POR			(0x00000038)
+#define SITAR_A_TX_3_TEST_BLOCK_EN			(0x163)
+#define SITAR_A_TX_3_TEST_BLOCK_EN__POR			(0x000000fc)
+#define SITAR_A_TX_3_TXFE_CKDIV			(0x164)
+#define SITAR_A_TX_3_TXFE_CKDIV__POR			(0x000000ee)
+#define SITAR_A_TX_3_SAR_ERR			(0x165)
+#define SITAR_A_TX_3_SAR_ERR__POR			(0x00000000)
+#define SITAR_A_TX_4_MBHC_EN			(0x171)
+#define SITAR_A_TX_4_MBHC_EN__POR			(0x0000000c)
+#define SITAR_A_TX_4_MBHC_ADC			(0x173)
+#define SITAR_A_TX_4_MBHC_ADC__POR			(0x00000044)
+#define SITAR_A_TX_4_MBHC_TEST_CTL			(0x174)
+#define SITAR_A_TX_4_MBHC_TEST_CTL__POR			(0x00000038)
+#define SITAR_A_TX_4_MBHC_SAR_ERR			(0x175)
+#define SITAR_A_TX_4_MBHC_SAR_ERR__POR			(0x00000000)
+#define SITAR_A_TX_4_TXFE_CLKDIV			(0x176)
+#define SITAR_A_TX_4_TXFE_CLKDIV__POR			(0x0000001c)
+#define SITAR_A_AUX_COM_CTL			(0x180)
+#define SITAR_A_AUX_COM_CTL__POR			(0x00000034)
+#define SITAR_A_AUX_COM_ATEST			(0x181)
+#define SITAR_A_AUX_COM_ATEST__POR			(0x00000000)
+#define SITAR_A_AUX_L_EN			(0x182)
+#define SITAR_A_AUX_L_EN__POR			(0x00000000)
+#define SITAR_A_AUX_L_GAIN			(0x183)
+#define SITAR_A_AUX_L_GAIN__POR			(0x0000001f)
+#define SITAR_A_AUX_L_PA_CONN			(0x184)
+#define SITAR_A_AUX_L_PA_CONN__POR			(0x00000000)
+#define SITAR_A_AUX_L_PA_CONN_INV			(0x185)
+#define SITAR_A_AUX_L_PA_CONN_INV__POR			(0x00000000)
+#define SITAR_A_AUX_R_EN			(0x186)
+#define SITAR_A_AUX_R_EN__POR			(0x00000000)
+#define SITAR_A_AUX_R_GAIN			(0x187)
+#define SITAR_A_AUX_R_GAIN__POR			(0x0000001f)
+#define SITAR_A_AUX_R_PA_CONN			(0x188)
+#define SITAR_A_AUX_R_PA_CONN__POR			(0x00000000)
+#define SITAR_A_AUX_R_PA_CONN_INV			(0x189)
+#define SITAR_A_AUX_R_PA_CONN_INV__POR			(0x00000000)
+#define SITAR_A_CP_EN			(0x192)
+#define SITAR_A_CP_EN__POR			(0x000000e6)
+#define SITAR_A_CP_CLK			(0x193)
+#define SITAR_A_CP_CLK__POR			(0x00000029)
+#define SITAR_A_CP_STATIC			(0x194)
+#define SITAR_A_CP_STATIC__POR			(0x00000010)
+#define SITAR_A_CP_DCC1			(0x195)
+#define SITAR_A_CP_DCC1__POR			(0x00000052)
+#define SITAR_A_CP_DCC3			(0x196)
+#define SITAR_A_CP_DCC3__POR			(0x00000001)
+#define SITAR_A_CP_ATEST			(0x197)
+#define SITAR_A_CP_ATEST__POR			(0x00000000)
+#define SITAR_A_CP_DTEST			(0x198)
+#define SITAR_A_CP_DTEST__POR			(0x00000000)
+#define SITAR_A_RX_COM_TIMER_DIV			(0x19E)
+#define SITAR_A_RX_COM_TIMER_DIV__POR			(0x000000e8)
+#define SITAR_A_RX_COM_OCP_CTL			(0x19F)
+#define SITAR_A_RX_COM_OCP_CTL__POR			(0x0000001f)
+#define SITAR_A_RX_COM_OCP_COUNT			(0x1A0)
+#define SITAR_A_RX_COM_OCP_COUNT__POR			(0x00000077)
+#define SITAR_A_RX_COM_DAC_CTL			(0x1A1)
+#define SITAR_A_RX_COM_DAC_CTL__POR			(0x00000000)
+#define SITAR_A_RX_COM_BIAS			(0x1A2)
+#define SITAR_A_RX_COM_BIAS__POR			(0x00000000)
+#define SITAR_A_RX_HPH_BIAS_PA			(0x1A6)
+#define SITAR_A_RX_HPH_BIAS_PA__POR			(0x00000057)
+#define SITAR_A_RX_HPH_BIAS_LDO			(0x1A7)
+#define SITAR_A_RX_HPH_BIAS_LDO__POR			(0x00000056)
+#define SITAR_A_RX_HPH_BIAS_CNP			(0x1A8)
+#define SITAR_A_RX_HPH_BIAS_CNP__POR			(0x0000008a)
+#define SITAR_A_RX_HPH_BIAS_WG			(0x1A9)
+#define SITAR_A_RX_HPH_BIAS_WG__POR			(0x00000060)
+#define SITAR_A_RX_HPH_OCP_CTL			(0x1AA)
+#define SITAR_A_RX_HPH_OCP_CTL__POR			(0x000000e8)
+#define SITAR_A_RX_HPH_CNP_EN			(0x1AB)
+#define SITAR_A_RX_HPH_CNP_EN__POR			(0x00000080)
+#define SITAR_A_RX_HPH_CNP_WG_CTL			(0x1AC)
+#define SITAR_A_RX_HPH_CNP_WG_CTL__POR			(0x000000dc)
+#define SITAR_A_RX_HPH_CNP_WG_TIME			(0x1AD)
+#define SITAR_A_RX_HPH_CNP_WG_TIME__POR			(0x00000028)
+#define SITAR_A_RX_HPH_L_GAIN			(0x1AE)
+#define SITAR_A_RX_HPH_L_GAIN__POR			(0x00000000)
+#define SITAR_A_RX_HPH_L_TEST			(0x1AF)
+#define SITAR_A_RX_HPH_L_TEST__POR			(0x00000001)
+#define SITAR_A_RX_HPH_L_PA_CTL			(0x1B0)
+#define SITAR_A_RX_HPH_L_PA_CTL__POR			(0x00000040)
+#define SITAR_A_RX_HPH_L_DAC_CTL			(0x1B1)
+#define SITAR_A_RX_HPH_L_DAC_CTL__POR			(0x00000000)
+#define SITAR_A_RX_HPH_L_ATEST			(0x1B2)
+#define SITAR_A_RX_HPH_L_ATEST__POR			(0x00000000)
+#define SITAR_A_RX_HPH_L_STATUS			(0x1B3)
+#define SITAR_A_RX_HPH_L_STATUS__POR			(0x00000004)
+#define SITAR_A_RX_HPH_R_GAIN			(0x1B4)
+#define SITAR_A_RX_HPH_R_GAIN__POR			(0x00000000)
+#define SITAR_A_RX_HPH_R_TEST			(0x1B5)
+#define SITAR_A_RX_HPH_R_TEST__POR			(0x00000001)
+#define SITAR_A_RX_HPH_R_PA_CTL			(0x1B6)
+#define SITAR_A_RX_HPH_R_PA_CTL__POR			(0x00000040)
+#define SITAR_A_RX_HPH_R_DAC_CTL			(0x1B7)
+#define SITAR_A_RX_HPH_R_DAC_CTL__POR			(0x00000000)
+#define SITAR_A_RX_HPH_R_ATEST			(0x1B8)
+#define SITAR_A_RX_HPH_R_ATEST__POR			(0x00000000)
+#define SITAR_A_RX_HPH_R_STATUS			(0x1B9)
+#define SITAR_A_RX_HPH_R_STATUS__POR			(0x00000004)
+#define SITAR_A_RX_EAR_BIAS_PA			(0x1BA)
+#define SITAR_A_RX_EAR_BIAS_PA__POR			(0x000000a6)
+#define SITAR_A_RX_EAR_BIAS_CMBUFF			(0x1BB)
+#define SITAR_A_RX_EAR_BIAS_CMBUFF__POR			(0x000000a0)
+#define SITAR_A_RX_EAR_EN			(0x1BC)
+#define SITAR_A_RX_EAR_EN__POR			(0x00000000)
+#define SITAR_A_RX_EAR_GAIN			(0x1BD)
+#define SITAR_A_RX_EAR_GAIN__POR			(0x00000002)
+#define SITAR_A_RX_EAR_CMBUFF			(0x1BE)
+#define SITAR_A_RX_EAR_CMBUFF__POR			(0x00000004)
+#define SITAR_A_RX_EAR_ICTL			(0x1BF)
+#define SITAR_A_RX_EAR_ICTL__POR			(0x00000040)
+#define SITAR_A_RX_EAR_CCOMP			(0x1C0)
+#define SITAR_A_RX_EAR_CCOMP__POR			(0x00000008)
+#define SITAR_A_RX_EAR_VCM			(0x1C1)
+#define SITAR_A_RX_EAR_VCM__POR			(0x00000003)
+#define SITAR_A_RX_EAR_CNP			(0x1C2)
+#define SITAR_A_RX_EAR_CNP__POR			(0x000000f2)
+#define SITAR_A_RX_EAR_ATEST			(0x1C3)
+#define SITAR_A_RX_EAR_ATEST__POR			(0x00000000)
+#define SITAR_A_RX_EAR_STATUS			(0x1C5)
+#define SITAR_A_RX_EAR_STATUS__POR			(0x00000004)
+#define SITAR_A_RX_LINE_BIAS_PA			(0x1C6)
+#define SITAR_A_RX_LINE_BIAS_PA__POR			(0x000000aa)
+#define SITAR_A_RX_LINE_BIAS_LDO			(0x1C7)
+#define SITAR_A_RX_LINE_BIAS_LDO__POR			(0x00000086)
+#define SITAR_A_RX_LINE_BIAS_CNP1			(0x1C8)
+#define SITAR_A_RX_LINE_BIAS_CNP1__POR			(0x00000060)
+#define SITAR_A_RX_LINE_COM			(0x1C9)
+#define SITAR_A_RX_LINE_COM__POR			(0x00000000)
+#define SITAR_A_RX_LINE_CNP_EN			(0x1CA)
+#define SITAR_A_RX_LINE_CNP_EN__POR			(0x00000080)
+#define SITAR_A_RX_LINE_CNP_WG_CTL			(0x1CB)
+#define SITAR_A_RX_LINE_CNP_WG_CTL__POR			(0x000000dc)
+#define SITAR_A_RX_LINE_CNP_WG_TIME			(0x1CC)
+#define SITAR_A_RX_LINE_CNP_WG_TIME__POR			(0x00000028)
+#define SITAR_A_RX_LINE_1_GAIN			(0x1CD)
+#define SITAR_A_RX_LINE_1_GAIN__POR			(0x00000000)
+#define SITAR_A_RX_LINE_1_TEST			(0x1CE)
+#define SITAR_A_RX_LINE_1_TEST__POR			(0x00000001)
+#define SITAR_A_RX_LINE_1_DAC_CTL			(0x1CF)
+#define SITAR_A_RX_LINE_1_DAC_CTL__POR			(0x00000000)
+#define SITAR_A_RX_LINE_1_STATUS			(0x1D0)
+#define SITAR_A_RX_LINE_1_STATUS__POR			(0x00000004)
+#define SITAR_A_RX_LINE_2_GAIN			(0x1D1)
+#define SITAR_A_RX_LINE_2_GAIN__POR			(0x00000000)
+#define SITAR_A_RX_LINE_2_TEST			(0x1D2)
+#define SITAR_A_RX_LINE_2_TEST__POR			(0x00000001)
+#define SITAR_A_RX_LINE_2_DAC_CTL			(0x1D3)
+#define SITAR_A_RX_LINE_2_DAC_CTL__POR			(0x00000000)
+#define SITAR_A_RX_LINE_2_STATUS			(0x1D4)
+#define SITAR_A_RX_LINE_2_STATUS__POR			(0x00000004)
+#define SITAR_A_RX_LINE_BIAS_CNP2			(0x1E1)
+#define SITAR_A_RX_LINE_BIAS_CNP2__POR			(0x0000008a)
+#define SITAR_A_RX_LINE_OCP_CTL			(0x1E2)
+#define SITAR_A_RX_LINE_OCP_CTL__POR			(0x000000e8)
+#define SITAR_A_RX_LINE_1_PA_CTL			(0x1E3)
+#define SITAR_A_RX_LINE_1_PA_CTL__POR			(0x00000040)
+#define SITAR_A_RX_LINE_2_PA_CTL			(0x1E4)
+#define SITAR_A_RX_LINE_2_PA_CTL__POR			(0x00000040)
+#define SITAR_A_RX_LINE_CNP_DBG			(0x1EC)
+#define SITAR_A_RX_LINE_CNP_DBG__POR			(0x00000000)
+#define SITAR_A_MBHC_HPH			(0x1ED)
+#define SITAR_A_MBHC_HPH__POR			(0x00000048)
+#define SITAR_A_RC_OSC_FREQ			(0x1F7)
+#define SITAR_A_RC_OSC_FREQ__POR			(0x00000046)
+#define SITAR_A_RC_OSC_TEST			(0x1F8)
+#define SITAR_A_RC_OSC_TEST__POR			(0x0000000a)
+#define SITAR_A_RC_OSC_STATUS			(0x1F9)
+#define SITAR_A_RC_OSC_STATUS__POR			(0x0000001c)
+#define SITAR_A_RC_OSC_TUNER			(0x1FA)
+#define SITAR_A_RC_OSC_TUNER__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_CTL			(0x200)
+#define SITAR_A_CDC_ANC1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_SHIFT			(0x201)
+#define SITAR_A_CDC_ANC1_SHIFT__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_IIR_B1_CTL			(0x202)
+#define SITAR_A_CDC_ANC1_IIR_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_IIR_B2_CTL			(0x203)
+#define SITAR_A_CDC_ANC1_IIR_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_IIR_B3_CTL			(0x204)
+#define SITAR_A_CDC_ANC1_IIR_B3_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_IIR_B4_CTL			(0x205)
+#define SITAR_A_CDC_ANC1_IIR_B4_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_LPF_B1_CTL			(0x206)
+#define SITAR_A_CDC_ANC1_LPF_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_LPF_B2_CTL			(0x207)
+#define SITAR_A_CDC_ANC1_LPF_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_LPF_B3_CTL			(0x208)
+#define SITAR_A_CDC_ANC1_LPF_B3_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_SPARE			(0x209)
+#define SITAR_A_CDC_ANC1_SPARE__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_SMLPF_CTL			(0x20A)
+#define SITAR_A_CDC_ANC1_SMLPF_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_ANC1_DCFLT_CTL			(0x20B)
+#define SITAR_A_CDC_ANC1_DCFLT_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_TX1_VOL_CTL_TIMER			(0x220)
+#define SITAR_A_CDC_TX1_VOL_CTL_TIMER__POR			(0x00000000)
+#define SITAR_A_CDC_TX1_VOL_CTL_GAIN			(0x221)
+#define SITAR_A_CDC_TX1_VOL_CTL_GAIN__POR			(0x00000000)
+#define SITAR_A_CDC_TX1_VOL_CTL_CFG			(0x222)
+#define SITAR_A_CDC_TX1_VOL_CTL_CFG__POR			(0x00000000)
+#define SITAR_A_CDC_TX1_MUX_CTL			(0x223)
+#define SITAR_A_CDC_TX1_MUX_CTL__POR			(0x00000008)
+#define SITAR_A_CDC_TX1_CLK_FS_CTL			(0x224)
+#define SITAR_A_CDC_TX1_CLK_FS_CTL__POR			(0x00000003)
+#define SITAR_A_CDC_TX1_DMIC_CTL			(0x225)
+#define SITAR_A_CDC_TX1_DMIC_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_SRC1_PDA_CFG			(0x2A0)
+#define SITAR_A_CDC_SRC1_PDA_CFG__POR			(0x00000000)
+#define SITAR_A_CDC_SRC1_FS_CTL			(0x2A1)
+#define SITAR_A_CDC_SRC1_FS_CTL__POR			(0x0000001b)
+
+#define SITAR_A_CDC_RX1_B1_CTL                  (0x000002B0)
+#define SITAR_A_CDC_RX1_B1_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B1_CTL                  (0x000002B8)
+#define SITAR_A_CDC_RX2_B1_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B1_CTL                  (0x000002C0)
+#define SITAR_A_CDC_RX3_B1_CTL__POR                     (0x00000000)
+
+#define SITAR_A_CDC_RX1_B2_CTL                  (0x000002B1)
+#define SITAR_A_CDC_RX1_B2_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B2_CTL                  (0x000002B9)
+#define SITAR_A_CDC_RX2_B2_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B2_CTL                  (0x000002C1)
+#define SITAR_A_CDC_RX3_B2_CTL__POR                     (0x00000000)
+
+#define SITAR_A_CDC_RX1_B3_CTL                  (0x000002B2)
+#define SITAR_A_CDC_RX1_B3_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B3_CTL                  (0x000002BA)
+#define SITAR_A_CDC_RX2_B3_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B3_CTL                  (0x000002C2)
+#define SITAR_A_CDC_RX3_B3_CTL__POR                     (0x00000000)
+
+#define SITAR_A_CDC_RX1_B4_CTL                  (0x000002B3)
+#define SITAR_A_CDC_RX1_B4_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B4_CTL                  (0x000002BB)
+#define SITAR_A_CDC_RX2_B4_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B4_CTL                  (0x000002C3)
+#define SITAR_A_CDC_RX3_B4_CTL__POR                     (0x00000000)
+
+#define SITAR_A_CDC_RX1_B5_CTL                  (0x000002B4)
+#define SITAR_A_CDC_RX1_B5_CTL__POR                     (0x00000060)
+#define SITAR_A_CDC_RX2_B5_CTL                  (0x000002BC)
+#define SITAR_A_CDC_RX2_B5_CTL__POR                     (0x00000060)
+#define SITAR_A_CDC_RX3_B5_CTL                  (0x000002C4)
+#define SITAR_A_CDC_RX3_B5_CTL__POR                     (0x00000060)
+
+#define SITAR_A_CDC_RX1_B6_CTL                  (0x000002B5)
+#define SITAR_A_CDC_RX1_B6_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B6_CTL                  (0x000002BD)
+#define SITAR_A_CDC_RX2_B6_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B6_CTL                  (0x000002C5)
+#define SITAR_A_CDC_RX3_B6_CTL__POR                     (0x00000000)
+
+
+#define SITAR_A_CDC_RX1_VOL_CTL_B1_CTL			(0x2B6)
+#define SITAR_A_CDC_RX1_VOL_CTL_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_RX1_VOL_CTL_B2_CTL			(0x2B7)
+#define SITAR_A_CDC_RX1_VOL_CTL_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_ANC_RESET_CTL			(0x300)
+#define SITAR_A_CDC_CLK_ANC_RESET_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_RX_RESET_CTL			(0x301)
+#define SITAR_A_CDC_CLK_RX_RESET_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_TX_RESET_B1_CTL			(0x302)
+#define SITAR_A_CDC_CLK_TX_RESET_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_TX_RESET_B2_CTL			(0x303)
+#define SITAR_A_CDC_CLK_TX_RESET_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_DMIC_CTL			(0x304)
+#define SITAR_A_CDC_CLK_DMIC_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_RX_I2S_CTL			(0x305)
+#define SITAR_A_CDC_CLK_RX_I2S_CTL__POR			(0x00000003)
+#define SITAR_A_CDC_CLK_TX_I2S_CTL			(0x306)
+#define SITAR_A_CDC_CLK_TX_I2S_CTL__POR			(0x00000003)
+#define SITAR_A_CDC_CLK_OTHR_RESET_CTL			(0x307)
+#define SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL			(0x308)
+#define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_OTHR_CTL			(0x30A)
+#define SITAR_A_CDC_CLK_OTHR_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL			(0x30B)
+#define SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_ANC_CLK_EN_CTL			(0x30C)
+#define SITAR_A_CDC_CLK_ANC_CLK_EN_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_RX_B1_CTL			(0x30D)
+#define SITAR_A_CDC_CLK_RX_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_RX_B2_CTL			(0x30E)
+#define SITAR_A_CDC_CLK_RX_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_MCLK_CTL			(0x30F)
+#define SITAR_A_CDC_CLK_MCLK_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_PDM_CTL			(0x310)
+#define SITAR_A_CDC_CLK_PDM_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_SD_CTL			(0x311)
+#define SITAR_A_CDC_CLK_SD_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_LP_CTL			(0x312)
+#define SITAR_A_CDC_CLK_LP_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL			(0x320)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL__POR	(0x00000007)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL		(0x321)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL__POR	(0x00000013)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL		(0x322)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL__POR	(0x0000001b)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL		(0x323)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL__POR	(0x0000007f)
+#define SITAR_A_CDC_CLSG_GAIN_THRESH_CTL		(0x324)
+#define SITAR_A_CDC_CLSG_GAIN_THRESH_CTL__POR		(0x00000026)
+#define SITAR_A_CDC_CLSG_TIMER_B1_CFG			(0x325)
+#define SITAR_A_CDC_CLSG_TIMER_B1_CFG__POR		(0x0000000a)
+#define SITAR_A_CDC_CLSG_TIMER_B2_CFG			(0x326)
+#define SITAR_A_CDC_CLSG_TIMER_B2_CFG__POR		(0x00000000)
+#define SITAR_A_CDC_CLSG_CTL			(0x327)
+#define SITAR_A_CDC_CLSG_CTL__POR			(0x00000013)
+#define SITAR_A_CDC_IIR1_GAIN_B1_CTL			(0x340)
+#define SITAR_A_CDC_IIR1_GAIN_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B2_CTL			(0x341)
+#define SITAR_A_CDC_IIR1_GAIN_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B3_CTL			(0x342)
+#define SITAR_A_CDC_IIR1_GAIN_B3_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B4_CTL			(0x343)
+#define SITAR_A_CDC_IIR1_GAIN_B4_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B5_CTL			(0x344)
+#define SITAR_A_CDC_IIR1_GAIN_B5_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B6_CTL			(0x345)
+#define SITAR_A_CDC_IIR1_GAIN_B6_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B7_CTL			(0x346)
+#define SITAR_A_CDC_IIR1_GAIN_B7_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B8_CTL			(0x347)
+#define SITAR_A_CDC_IIR1_GAIN_B8_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_CTL				(0x348)
+#define SITAR_A_CDC_IIR1_CTL__POR			(0x00000040)
+#define SITAR_A_CDC_IIR1_GAIN_TIMER_CTL			(0x349)
+#define SITAR_A_CDC_IIR1_GAIN_TIMER_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B1_CTL			(0x34A)
+#define SITAR_A_CDC_IIR1_COEF_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B2_CTL			(0x34B)
+#define SITAR_A_CDC_IIR1_COEF_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B3_CTL			(0x34C)
+#define SITAR_A_CDC_IIR1_COEF_B3_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B4_CTL			(0x34D)
+#define SITAR_A_CDC_IIR1_COEF_B4_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B5_CTL			(0x34E)
+#define SITAR_A_CDC_IIR1_COEF_B5_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_TOP_GAIN_UPDATE			(0x360)
+#define SITAR_A_CDC_TOP_GAIN_UPDATE__POR		(0x00000000)
+#define SITAR_A_CDC_TOP_RDAC_DOUT_CTL			(0x361)
+#define SITAR_A_CDC_TOP_RDAC_DOUT_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_DEBUG_B1_CTL			(0x368)
+#define SITAR_A_CDC_DEBUG_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_DEBUG_B2_CTL			(0x369)
+#define SITAR_A_CDC_DEBUG_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_DEBUG_B3_CTL			(0x36A)
+#define SITAR_A_CDC_DEBUG_B3_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_DEBUG_B4_CTL			(0x36B)
+#define SITAR_A_CDC_DEBUG_B4_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_DEBUG_B5_CTL			(0x36C)
+#define SITAR_A_CDC_DEBUG_B5_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_DEBUG_B6_CTL			(0x36D)
+#define SITAR_A_CDC_DEBUG_B6_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_DEBUG_B7_CTL			(0x36E)
+#define SITAR_A_CDC_DEBUG_B7_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_COMP1_B1_CTL			(0x370)
+#define SITAR_A_CDC_COMP1_B1_CTL__POR			(0x00000030)
+#define SITAR_A_CDC_COMP1_B2_CTL			(0x371)
+#define SITAR_A_CDC_COMP1_B2_CTL__POR			(0x000000b5)
+#define SITAR_A_CDC_COMP1_B3_CTL			(0x372)
+#define SITAR_A_CDC_COMP1_B3_CTL__POR			(0x00000028)
+#define SITAR_A_CDC_COMP1_B4_CTL			(0x373)
+#define SITAR_A_CDC_COMP1_B4_CTL__POR			(0x0000003c)
+#define SITAR_A_CDC_COMP1_B5_CTL			(0x374)
+#define SITAR_A_CDC_COMP1_B5_CTL__POR			(0x0000001f)
+#define SITAR_A_CDC_COMP1_B6_CTL			(0x375)
+#define SITAR_A_CDC_COMP1_B6_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS		(0x376)
+#define SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS__POR		(0x00000003)
+#define SITAR_A_CDC_COMP1_FS_CFG			(0x377)
+#define SITAR_A_CDC_COMP1_FS_CFG__POR			(0x0000001b)
+#define SITAR_A_CDC_CONN_RX1_B1_CTL			(0x380)
+#define SITAR_A_CDC_CONN_RX1_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX1_B2_CTL			(0x381)
+#define SITAR_A_CDC_CONN_RX1_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX1_B3_CTL			(0x382)
+#define SITAR_A_CDC_CONN_RX1_B3_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX2_B1_CTL			(0x383)
+#define SITAR_A_CDC_CONN_RX2_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX2_B2_CTL			(0x384)
+#define SITAR_A_CDC_CONN_RX2_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX2_B3_CTL			(0x385)
+#define SITAR_A_CDC_CONN_RX2_B3_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX3_B1_CTL			(0x386)
+#define SITAR_A_CDC_CONN_RX3_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX3_B2_CTL			(0x387)
+#define SITAR_A_CDC_CONN_RX3_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX3_B3_CTL			(0x388)
+#define SITAR_A_CDC_CONN_RX3_B3_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_ANC_B1_CTL			(0x391)
+#define SITAR_A_CDC_CONN_ANC_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_ANC_B2_CTL			(0x392)
+#define SITAR_A_CDC_CONN_ANC_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_TX_B1_CTL			(0x393)
+#define SITAR_A_CDC_CONN_TX_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CONN_TX_B2_CTL			(0x394)
+#define SITAR_A_CDC_CONN_TX_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CONN_EQ1_B1_CTL			(0x397)
+#define SITAR_A_CDC_CONN_EQ1_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_EQ1_B2_CTL			(0x398)
+#define SITAR_A_CDC_CONN_EQ1_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_EQ1_B3_CTL			(0x399)
+#define SITAR_A_CDC_CONN_EQ1_B3_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_EQ1_B4_CTL			(0x39A)
+#define SITAR_A_CDC_CONN_EQ1_B4_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_EQ2_B1_CTL			(0x39B)
+#define SITAR_A_CDC_CONN_EQ2_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_EQ2_B2_CTL			(0x39C)
+#define SITAR_A_CDC_CONN_EQ2_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_EQ2_B3_CTL			(0x39D)
+#define SITAR_A_CDC_CONN_EQ2_B3_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_EQ2_B4_CTL			(0x39E)
+#define SITAR_A_CDC_CONN_EQ2_B4_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_SRC1_B1_CTL			(0x39F)
+#define SITAR_A_CDC_CONN_SRC1_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_SRC1_B2_CTL			(0x3A0)
+#define SITAR_A_CDC_CONN_SRC1_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_SRC2_B1_CTL			(0x3A1)
+#define SITAR_A_CDC_CONN_SRC2_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_SRC2_B2_CTL			(0x3A2)
+#define SITAR_A_CDC_CONN_SRC2_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B1_CTL			(0x3A3)
+#define SITAR_A_CDC_CONN_TX_SB_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B2_CTL			(0x3A4)
+#define SITAR_A_CDC_CONN_TX_SB_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B3_CTL			(0x3A5)
+#define SITAR_A_CDC_CONN_TX_SB_B3_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B4_CTL			(0x3A6)
+#define SITAR_A_CDC_CONN_TX_SB_B4_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B5_CTL			(0x3A7)
+#define SITAR_A_CDC_CONN_TX_SB_B5_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX_SB_B1_CTL			(0x3AE)
+#define SITAR_A_CDC_CONN_RX_SB_B1_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_RX_SB_B2_CTL			(0x3AF)
+#define SITAR_A_CDC_CONN_RX_SB_B2_CTL__POR		(0x00000000)
+#define SITAR_A_CDC_CONN_CLSG_CTL			(0x3B0)
+#define SITAR_A_CDC_CONN_CLSG_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CONN_SPARE			(0x3B1)
+#define SITAR_A_CDC_CONN_SPARE__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_EN_CTL			(0x3C0)
+#define SITAR_A_CDC_MBHC_EN_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_FIR_B1_CFG			(0x3C1)
+#define SITAR_A_CDC_MBHC_FIR_B1_CFG__POR		(0x00000000)
+#define SITAR_A_CDC_MBHC_FIR_B2_CFG			(0x3C2)
+#define SITAR_A_CDC_MBHC_FIR_B2_CFG__POR		(0x00000006)
+#define SITAR_A_CDC_MBHC_TIMER_B1_CTL			(0x3C3)
+#define SITAR_A_CDC_MBHC_TIMER_B1_CTL__POR		(0x00000003)
+#define SITAR_A_CDC_MBHC_TIMER_B2_CTL			(0x3C4)
+#define SITAR_A_CDC_MBHC_TIMER_B2_CTL__POR		(0x00000009)
+#define SITAR_A_CDC_MBHC_TIMER_B3_CTL			(0x3C5)
+#define SITAR_A_CDC_MBHC_TIMER_B3_CTL__POR		(0x0000001e)
+#define SITAR_A_CDC_MBHC_TIMER_B4_CTL			(0x3C6)
+#define SITAR_A_CDC_MBHC_TIMER_B4_CTL__POR		(0x00000045)
+#define SITAR_A_CDC_MBHC_TIMER_B5_CTL			(0x3C7)
+#define SITAR_A_CDC_MBHC_TIMER_B5_CTL__POR		(0x00000004)
+#define SITAR_A_CDC_MBHC_TIMER_B6_CTL			(0x3C8)
+#define SITAR_A_CDC_MBHC_TIMER_B6_CTL__POR		(0x00000078)
+#define SITAR_A_CDC_MBHC_B1_STATUS			(0x3C9)
+#define SITAR_A_CDC_MBHC_B1_STATUS__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_B2_STATUS			(0x3CA)
+#define SITAR_A_CDC_MBHC_B2_STATUS__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_B3_STATUS			(0x3CB)
+#define SITAR_A_CDC_MBHC_B3_STATUS__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_B4_STATUS			(0x3CC)
+#define SITAR_A_CDC_MBHC_B4_STATUS__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_B5_STATUS			(0x3CD)
+#define SITAR_A_CDC_MBHC_B5_STATUS__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_B1_CTL			(0x3CE)
+#define SITAR_A_CDC_MBHC_B1_CTL__POR			(0x000000c0)
+#define SITAR_A_CDC_MBHC_B2_CTL			(0x3CF)
+#define SITAR_A_CDC_MBHC_B2_CTL__POR			(0x0000005d)
+#define SITAR_A_CDC_MBHC_VOLT_B1_CTL			(0x3D0)
+#define SITAR_A_CDC_MBHC_VOLT_B1_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B2_CTL			(0x3D1)
+#define SITAR_A_CDC_MBHC_VOLT_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B3_CTL			(0x3D2)
+#define SITAR_A_CDC_MBHC_VOLT_B3_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B4_CTL			(0x3D3)
+#define SITAR_A_CDC_MBHC_VOLT_B4_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B5_CTL			(0x3D4)
+#define SITAR_A_CDC_MBHC_VOLT_B5_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B6_CTL			(0x3D5)
+#define SITAR_A_CDC_MBHC_VOLT_B6_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B7_CTL			(0x3D6)
+#define SITAR_A_CDC_MBHC_VOLT_B7_CTL__POR			(0x000000ff)
+#define SITAR_A_CDC_MBHC_VOLT_B8_CTL			(0x3D7)
+#define SITAR_A_CDC_MBHC_VOLT_B8_CTL__POR			(0x00000007)
+#define SITAR_A_CDC_MBHC_VOLT_B9_CTL			(0x3D8)
+#define SITAR_A_CDC_MBHC_VOLT_B9_CTL__POR			(0x000000ff)
+#define SITAR_A_CDC_MBHC_VOLT_B10_CTL			(0x3D9)
+#define SITAR_A_CDC_MBHC_VOLT_B10_CTL__POR			(0x0000007f)
+#define SITAR_A_CDC_MBHC_VOLT_B11_CTL			(0x3DA)
+#define SITAR_A_CDC_MBHC_VOLT_B11_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B12_CTL			(0x3DB)
+#define SITAR_A_CDC_MBHC_VOLT_B12_CTL__POR			(0x00000080)
+#define SITAR_A_CDC_MBHC_CLK_CTL			(0x3DC)
+#define SITAR_A_CDC_MBHC_CLK_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_INT_CTL			(0x3DD)
+#define SITAR_A_CDC_MBHC_INT_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_DEBUG_CTL			(0x3DE)
+#define SITAR_A_CDC_MBHC_DEBUG_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_MBHC_SPARE			(0x3DF)
+#define SITAR_A_CDC_MBHC_SPARE__POR			(0x00000000)
+/* SLIMBUS Slave Registers */
+#define SITAR_SLIM_PGD_PORT_INT_EN0                     (0x30)
+#define SITAR_SLIM_PGD_PORT_INT_STATUS0                 (0x34)
+#define SITAR_SLIM_PGD_PORT_INT_CLR0                    (0x38)
+#define SITAR_SLIM_PGD_PORT_INT_SOURCE0                 (0x60)
+
+/* Macros for Packing Register Writes into a U32 */
+#define SITAR_PACKED_REG_SIZE sizeof(u32)
+
+#define SITAR_CODEC_PACK_ENTRY(reg, mask, val) ((val & 0xff)|\
+	((mask & 0xff) << 8)|((reg & 0xffff) << 16))
+
+#define SITAR_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/mfd/wcd9310/registers.h b/include/linux/mfd/wcd9xxx/wcd9310_registers.h
similarity index 95%
rename from include/linux/mfd/wcd9310/registers.h
rename to include/linux/mfd/wcd9xxx/wcd9310_registers.h
index ef27c08..d2736ea 100644
--- a/include/linux/mfd/wcd9310/registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9310_registers.h
@@ -1,29 +1,41 @@
+/* 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 TABLA_CODEC_DIGITAL_H
 
 #define TABLA_CODEC_DIGITAL_H
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 
-#define TABLA_A_CHIP_CTL			(0x00)
-#define TABLA_A_CHIP_CTL__POR			(0x00000000)
-#define TABLA_A_CHIP_STATUS			(0x01)
-#define TABLA_A_CHIP_STATUS__POR			(0x00000000)
-#define TABLA_A_CHIP_ID_BYTE_0			(0x04)
-#define TABLA_A_CHIP_ID_BYTE_0__POR			(0x00000000)
-#define TABLA_A_CHIP_ID_BYTE_1			(0x05)
-#define TABLA_A_CHIP_ID_BYTE_1__POR			(0x00000000)
-#define TABLA_A_CHIP_ID_BYTE_2			(0x06)
-#define TABLA_A_CHIP_ID_BYTE_2__POR			(0x00000000)
-#define TABLA_A_CHIP_ID_BYTE_3			(0x07)
-#define TABLA_A_CHIP_ID_BYTE_3__POR			(0x00000001)
-#define TABLA_A_CHIP_VERSION			(0x08)
-#define TABLA_A_CHIP_VERSION__POR			(0x00000020)
-#define TABLA_A_SB_VERSION			(0x09)
-#define TABLA_A_SB_VERSION__POR			(0x00000010)
-#define TABLA_A_SLAVE_ID_1			(0x0C)
-#define TABLA_A_SLAVE_ID_1__POR			(0x00000077)
-#define TABLA_A_SLAVE_ID_2			(0x0D)
-#define TABLA_A_SLAVE_ID_2__POR			(0x00000066)
-#define TABLA_A_SLAVE_ID_3			(0x0E)
-#define TABLA_A_SLAVE_ID_3__POR			(0x00000055)
+#define TABLA_A_CHIP_CTL			WCD9XXX_A_CHIP_CTL
+#define TABLA_A_CHIP_CTL__POR			WCD9XXX_A_CHIP_CTL__POR
+#define TABLA_A_CHIP_STATUS			WCD9XXX_A_CHIP_STATUS
+#define TABLA_A_CHIP_STATUS__POR		WCD9XXX_A_CHIP_STATUS__POR
+#define TABLA_A_CHIP_ID_BYTE_0			WCD9XXX_A_CHIP_ID_BYTE_0
+#define TABLA_A_CHIP_ID_BYTE_0__POR		WCD9XXX_A_CHIP_ID_BYTE_0__POR
+#define TABLA_A_CHIP_ID_BYTE_1			WCD9XXX_A_CHIP_ID_BYTE_1
+#define TABLA_A_CHIP_ID_BYTE_1__POR		WCD9XXX_A_CHIP_ID_BYTE_1__POR
+#define TABLA_A_CHIP_ID_BYTE_2			WCD9XXX_A_CHIP_ID_BYTE_2
+#define TABLA_A_CHIP_ID_BYTE_2__POR		WCD9XXX_A_CHIP_ID_BYTE_2__POR
+#define TABLA_A_CHIP_ID_BYTE_3			WCD9XXX_A_CHIP_ID_BYTE_3
+#define TABLA_A_CHIP_ID_BYTE_3__POR		WCD9XXX_A_CHIP_ID_BYTE_3__POR
+#define TABLA_A_CHIP_VERSION			WCD9XXX_A_CHIP_VERSION
+#define TABLA_A_CHIP_VERSION__POR		WCD9XXX_A_CHIP_VERSION__POR
+#define TABLA_A_SB_VERSION			WCD9XXX_A_SB_VERSION
+#define TABLA_A_SB_VERSION__POR			WCD9XXX_A_SB_VERSION__POR
+#define TABLA_A_SLAVE_ID_1			WCD9XXX_A_SLAVE_ID_1
+#define TABLA_A_SLAVE_ID_1__POR			WCD9XXX_A_SLAVE_ID_1__POR
+#define TABLA_A_SLAVE_ID_2			WCD9XXX_A_SLAVE_ID_2
+#define TABLA_A_SLAVE_ID_2__POR			WCD9XXX_A_SLAVE_ID_2__POR
+#define TABLA_A_SLAVE_ID_3			WCD9XXX_A_SLAVE_ID_3
+#define TABLA_A_SLAVE_ID_3__POR			WCD9XXX_A_SLAVE_ID_3__POR
 #define TABLA_A_PIN_CTL_OE0			(0x10)
 #define TABLA_A_PIN_CTL_OE0__POR			(0x00000000)
 #define TABLA_A_PIN_CTL_OE1			(0x11)
@@ -58,10 +70,10 @@
 #define TABLA_A_QFUSE_DATA_OUT2__POR			(0x00000000)
 #define TABLA_A_QFUSE_DATA_OUT3			(0x4D)
 #define TABLA_A_QFUSE_DATA_OUT3__POR			(0x00000000)
-#define TABLA_A_CDC_CTL			(0x80)
-#define TABLA_A_CDC_CTL__POR			(0x00000000)
-#define TABLA_A_LEAKAGE_CTL			(0x88)
-#define TABLA_A_LEAKAGE_CTL__POR			(0x00000004)
+#define TABLA_A_CDC_CTL				WCD9XXX_A_CDC_CTL
+#define TABLA_A_CDC_CTL__POR			WCD9XXX_A_CDC_CTL__POR
+#define TABLA_A_LEAKAGE_CTL			WCD9XXX_A_LEAKAGE_CTL
+#define TABLA_A_LEAKAGE_CTL__POR		WCD9XXX_A_LEAKAGE_CTL__POR
 #define TABLA_A_INTR_MODE			(0x90)
 #define TABLA_A_INTR_MODE__POR			(0x00000000)
 #define TABLA_A_INTR_MASK0			(0x94)
diff --git a/include/linux/mfd/wcd9310/wcd9310-slimslave.h b/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
similarity index 84%
rename from include/linux/mfd/wcd9310/wcd9310-slimslave.h
rename to include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
index 0bbf96f..fcd3bd3 100644
--- a/include/linux/mfd/wcd9310/wcd9310-slimslave.h
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
@@ -14,7 +14,7 @@
 #define __WCD9310_SLIMSLAVE_H_
 
 #include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
+#include <linux/mfd/wcd9xxx/core.h>
 
 /* Local to the core only */
 #define SLIM_MAX_RX_PORTS 7
@@ -84,19 +84,19 @@
 #define BASE_CH_NUM 128
 
 
-int tabla_init_slimslave(struct tabla *tabla, u8 tabla_pgd_la);
+int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la);
 
-int tabla_deinit_slimslave(struct tabla *tabla);
+int wcd9xxx_deinit_slimslave(struct wcd9xxx *wcd9xxx);
 
-int tabla_cfg_slim_sch_rx(struct tabla *tabla, unsigned int *ch_num,
+int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
 				unsigned int tot_ch, unsigned int rate);
-int tabla_cfg_slim_sch_tx(struct tabla *tabla, unsigned int *ch_num,
+int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
 				unsigned int tot_ch, unsigned int rate);
-int tabla_close_slim_sch_rx(struct tabla *tabla, unsigned int *ch_num,
+int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
 				unsigned int tot_ch);
-int tabla_close_slim_sch_tx(struct tabla *tabla, unsigned int *ch_num,
+int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
 				unsigned int tot_ch);
-int tabla_get_channel(struct tabla *tabla,
+int wcd9xxx_get_channel(struct wcd9xxx *wcd9xxx,
 			unsigned int *rx_ch,
 			unsigned int *tx_ch);
 #endif /* __WCD9310_SLIMSLAVE_H_ */
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
new file mode 100644
index 0000000..c66e953
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef WCD9XXX_CODEC_DIGITAL_H
+
+#define WCD9XXX_CODEC_DIGITAL_H
+
+#define WCD9XXX_A_CHIP_CTL			(0x00)
+#define WCD9XXX_A_CHIP_CTL__POR			(0x00000000)
+#define WCD9XXX_A_CHIP_STATUS			(0x01)
+#define WCD9XXX_A_CHIP_STATUS__POR			(0x00000000)
+#define WCD9XXX_A_CHIP_ID_BYTE_0			(0x04)
+#define WCD9XXX_A_CHIP_ID_BYTE_0__POR			(0x00000000)
+#define WCD9XXX_A_CHIP_ID_BYTE_1			(0x05)
+#define WCD9XXX_A_CHIP_ID_BYTE_1__POR			(0x00000000)
+#define WCD9XXX_A_CHIP_ID_BYTE_2			(0x06)
+#define WCD9XXX_A_CHIP_ID_BYTE_2__POR			(0x00000000)
+#define WCD9XXX_A_CHIP_ID_BYTE_3			(0x07)
+#define WCD9XXX_A_CHIP_ID_BYTE_3__POR			(0x00000001)
+#define WCD9XXX_A_CHIP_VERSION			(0x08)
+#define WCD9XXX_A_CHIP_VERSION__POR			(0x00000020)
+#define WCD9XXX_A_SB_VERSION			(0x09)
+#define WCD9XXX_A_SB_VERSION__POR			(0x00000010)
+#define WCD9XXX_A_SLAVE_ID_1			(0x0C)
+#define WCD9XXX_A_SLAVE_ID_1__POR			(0x00000077)
+#define WCD9XXX_A_SLAVE_ID_2			(0x0D)
+#define WCD9XXX_A_SLAVE_ID_2__POR			(0x00000066)
+#define WCD9XXX_A_SLAVE_ID_3			(0x0E)
+#define WCD9XXX_A_SLAVE_ID_3__POR			(0x00000055)
+#define WCD9XXX_A_CDC_CTL			(0x80)
+#define WCD9XXX_A_CDC_CTL__POR			(0x00000000)
+#define WCD9XXX_A_LEAKAGE_CTL			(0x88)
+#define WCD9XXX_A_LEAKAGE_CTL__POR			(0x00000004)
+#endif
diff --git a/include/linux/msm_audio.h b/include/linux/msm_audio.h
index 30d74ce..8a35ca0 100644
--- a/include/linux/msm_audio.h
+++ b/include/linux/msm_audio.h
@@ -90,6 +90,9 @@
 #define AUDIO_GET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 96,  \
 					struct msm_acdb_cmd_device)
 
+#define AUDIO_REGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 97, unsigned)
+#define AUDIO_DEREGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 98, unsigned)
+
 #define	AUDIO_MAX_COMMON_IOCTL_NUM	100
 
 
@@ -166,6 +169,11 @@
 	uint32_t unused[2];
 };
 
+struct msm_audio_ion_info {
+	int fd;
+	void *vaddr;
+};
+
 struct msm_audio_pmem_info {
 	int fd;
 	void *vaddr;
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 5e39f89..69ff05b 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -34,6 +34,16 @@
 #define KGSL_CLK_MEM_IFACE 0x00000010
 #define KGSL_CLK_AXI	0x00000020
 
+/*
+ * Reset status values for context
+ */
+enum kgsl_ctx_reset_stat {
+	KGSL_CTX_STAT_NO_ERROR				= 0x00000000,
+	KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT		= 0x00000001,
+	KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT	= 0x00000002,
+	KGSL_CTX_STAT_UNKNOWN_CONTEXT_RESET_EXT		= 0x00000003
+};
+
 #define KGSL_MAX_PWRLEVELS 5
 
 #define KGSL_CONVERT_TO_MBPS(val) \
@@ -110,6 +120,7 @@
 	KGSL_PROP_MMU_ENABLE 	  = 0x00000006,
 	KGSL_PROP_INTERRUPT_WAITS = 0x00000007,
 	KGSL_PROP_VERSION         = 0x00000008,
+	KGSL_PROP_GPU_RESET_STAT  = 0x00000009
 };
 
 struct kgsl_shadowprop {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 07d5af6..6442faa 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -140,6 +140,7 @@
 #define MDP_OV_PLAY_NOWAIT		0x00200000
 #define MDP_SOURCE_ROTATED_90		0x00100000
 #define MDP_DPP_HSIC			0x00080000
+#define MDP_BACKEND_COMPOSITION		0x00040000
 #define MDP_BORDERFILL_SUPPORTED	0x00010000
 #define MDP_SECURE_OVERLAY_SESSION      0x00008000
 #define MDP_MEMORY_ID_TYPE_FB		0x00001000
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 867bd8a..6a7f99b 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -342,6 +342,7 @@
 #define MSM_CAM_RESP_MAX               8
 
 #define MSM_CAM_APP_NOTIFY_EVENT  0
+#define MSM_CAM_APP_NOTIFY_ERROR_EVENT  1
 
 /* this one is used to send ctrl/status up to config thread */
 
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index d08f528..0fabc5b 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -15,6 +15,9 @@
 #include <mach/qdsp6v2/apr.h>
 #include <mach/msm_subsystem_map.h>
 #include <sound/apr_audio.h>
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#include <linux/ion.h>
+#endif
 
 #define IN                      0x000
 #define OUT                     0x001
@@ -94,10 +97,15 @@
 struct audio_buffer {
 	dma_addr_t phys;
 	void       *data;
-	struct msm_mapped_buffer *mem_buffer;
 	uint32_t   used;
 	uint32_t   size;/* size of buffer */
 	uint32_t   actual_size; /* actual number of bytes read by DSP */
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	struct ion_handle *handle;
+	struct ion_client *client;
+#else
+	struct msm_mapped_buffer *mem_buffer;
+#endif
 };
 
 struct audio_aio_write_param {
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9662795..a3d5e34 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -569,7 +569,7 @@
 		struct hci_chan *ampchan = l2cap_pi(sk)->ampchan;
 		l2cap_pi(sk)->ampchan = NULL;
 		if (!hci_chan_put(ampchan))
-			l2cap_deaggregate(l2cap_pi(sk)->ampchan, l2cap_pi(sk));
+			l2cap_deaggregate(ampchan, l2cap_pi(sk));
 	}
 
 	sk->sk_state = BT_CLOSED;
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 0d41625..11e1a67 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -8,9 +8,10 @@
 use strict;
 
 use constant BEFORE_SHORTTEXT => 0;
-use constant IN_SHORTTEXT => 1;
-use constant AFTER_SHORTTEXT => 2;
-use constant CHECK_NEXT_SHORTTEXT => 3;
+use constant IN_SHORTTEXT_BLANKLINE => 1;
+use constant IN_SHORTTEXT => 2;
+use constant AFTER_SHORTTEXT => 3;
+use constant CHECK_NEXT_SHORTTEXT => 4;
 use constant SHORTTEXT_LIMIT => 75;
 
 my $P = $0;
@@ -1233,6 +1234,7 @@
 
 	my $shorttext = BEFORE_SHORTTEXT;
 	my $shorttext_exspc = 0;
+	my $commit_text_present = 0;
 
 	sanitise_line_reset();
 	cleanup_continuation_headers();
@@ -1416,8 +1418,24 @@
 		my $hereprev = "$here\n$prevrawline\n$rawline\n";
 
 		if ($shorttext != AFTER_SHORTTEXT) {
+			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);
+				$shorttext = IN_SHORTTEXT;
+				# this non-blank line may or may not be commit text -
+				# a warning has been generated so assume it is commit
+				# text and move on
+				$commit_text_present = 1;
+				# fall through and treat this line as IN_SHORTTEXT
+			}
 			if ($shorttext == IN_SHORTTEXT) {
 				if ($line=~/^---/ || $line=~/^diff.*/) {
+					if ($commit_text_present == 0) {
+						WARN("please add commit text explaining " .
+						     "*why* the change is needed\n" .
+						     $herecurr);
+					}
 					$shorttext = AFTER_SHORTTEXT;
 				} elsif (length($line) > (SHORTTEXT_LIMIT +
 							  $shorttext_exspc)
@@ -1427,7 +1445,22 @@
 					WARN("commit text line over " .
 					     SHORTTEXT_LIMIT .
 					     " characters\n" . $herecurr);
+				} elsif ($line=~/^\s*[\x21-\x39\x3b-\x7e]+:/) {
+					# this is a tag, there must be commit
+					# text by now
+					if ($commit_text_present == 0) {
+						WARN("please add commit text explaining " .
+						     "*why* the change is needed\n" .
+						     $herecurr);
+						# prevent duplicate warnings
+						$commit_text_present = 1;
+					}
+				} elsif ($line=~/\S/) {
+					$commit_text_present = 1;
 				}
+			} elsif ($shorttext == IN_SHORTTEXT_BLANKLINE) {
+				# case of non-blank line in this state handled above
+				$shorttext = IN_SHORTTEXT;
 			} elsif ($shorttext == CHECK_NEXT_SHORTTEXT) {
 # The Subject line doesn't have to be the last header in the patch.
 # Avoid moving to the IN_SHORTTEXT state until clear of all headers.
@@ -1435,16 +1468,25 @@
 # text which looks like a header is definitely a header.
 				if ($line!~/^[\x21-\x39\x3b-\x7e]+:/) {
 					$shorttext = IN_SHORTTEXT;
-# Check for Subject line followed by a blank line.
+					# Check for Subject line followed by a blank line.
 					if (length($line) != 0) {
 						WARN("non-blank line after " .
 						     "summary line\n" .
 						     $sublinenr . $here .
 						     "\n" . $subjectline .
 						     "\n" . $line . "\n");
+						# this non-blank line may or may not
+						# be commit text - a warning has been
+						# generated so assume it is commit
+						# text and move on
+						$commit_text_present = 1;
 					}
 				}
+			# The next two cases are BEFORE_SHORTTEXT.
 			} elsif ($line=~/^Subject: \[[^\]]*\] (.*)/) {
+				# This is the subject line. Go to
+				# CHECK_NEXT_SHORTTEXT to wait for the commit
+				# text to show up.
 				$shorttext = CHECK_NEXT_SHORTTEXT;
 				$subjectline = $line;
 				$sublinenr = "#$linenr & ";
@@ -1455,7 +1497,10 @@
 					     " characters\n" . $herecurr);
 				}
 			} elsif ($line=~/^    (.*)/) {
-				$shorttext = IN_SHORTTEXT;
+				# Indented format, this must be the summary
+				# line (i.e. git show). There will be no more
+				# headers so we are now in the shorttext.
+				$shorttext = IN_SHORTTEXT_BLANKLINE;
 				$shorttext_exspc = 4;
 				if (length($1) > SHORTTEXT_LIMIT) {
 					WARN("summary line over " .
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index 0104f1a..d3d393d 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -44,6 +44,8 @@
     "alignment.c:720",
     "async.c:122",
     "async.c:270",
+    "block.c:835",
+    "block.c:836",
     "dir.c:43",
     "dm.c:1053",
     "dm.c:1080",
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b923a25..88181a6 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -250,6 +250,9 @@
 config SND_SOC_UDA1380
         tristate
 
+config SND_SOC_WCD9304
+	tristate
+
 config SND_SOC_WCD9310
         tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 78740ab..0bd7255 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -38,6 +38,7 @@
 snd-soc-twl6040-objs := twl6040.o
 snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
+snd-soc-wcd9304-objs := wcd9304.o wcd9304-tables.o
 snd-soc-wcd9310-objs := wcd9310.o wcd9310-tables.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
@@ -132,6 +133,7 @@
 obj-$(CONFIG_SND_SOC_TWL6040)	+= snd-soc-twl6040.o
 obj-$(CONFIG_SND_SOC_UDA134X)	+= snd-soc-uda134x.o
 obj-$(CONFIG_SND_SOC_UDA1380)	+= snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_WCD9304)	+= snd-soc-wcd9304.o
 obj-$(CONFIG_SND_SOC_WCD9310)	+= snd-soc-wcd9310.o
 obj-$(CONFIG_SND_SOC_WL1273)	+= snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
diff --git a/sound/soc/codecs/wcd9304-tables.c b/sound/soc/codecs/wcd9304-tables.c
new file mode 100644
index 0000000..823f926
--- /dev/null
+++ b/sound/soc/codecs/wcd9304-tables.c
@@ -0,0 +1,720 @@
+/* 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/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9304_registers.h>
+#include "wcd9304.h"
+
+const u8 sitar_reg_defaults[SITAR_CACHE_SIZE] = {
+	[WCD9XXX_A_CHIP_CTL] = WCD9XXX_A_CHIP_CTL__POR,
+	[WCD9XXX_A_CHIP_STATUS] = WCD9XXX_A_CHIP_STATUS__POR,
+	[WCD9XXX_A_CHIP_ID_BYTE_0] = WCD9XXX_A_CHIP_ID_BYTE_0__POR,
+	[WCD9XXX_A_CHIP_ID_BYTE_1] = WCD9XXX_A_CHIP_ID_BYTE_1__POR,
+	[WCD9XXX_A_CHIP_ID_BYTE_2] = WCD9XXX_A_CHIP_ID_BYTE_2__POR,
+	[WCD9XXX_A_CHIP_ID_BYTE_3] = WCD9XXX_A_CHIP_ID_BYTE_3__POR,
+	[WCD9XXX_A_CHIP_VERSION] = WCD9XXX_A_CHIP_VERSION__POR,
+	[WCD9XXX_A_SB_VERSION] = WCD9XXX_A_SB_VERSION__POR,
+	[WCD9XXX_A_SLAVE_ID_1] = WCD9XXX_A_SLAVE_ID_1__POR,
+	[WCD9XXX_A_SLAVE_ID_2] = WCD9XXX_A_SLAVE_ID_2__POR,
+	[WCD9XXX_A_SLAVE_ID_3] = WCD9XXX_A_SLAVE_ID_3__POR,
+	[SITAR_A_PIN_CTL_OE0] = SITAR_A_PIN_CTL_OE0__POR,
+	[SITAR_A_PIN_CTL_OE1] = SITAR_A_PIN_CTL_OE1__POR,
+	[SITAR_A_PIN_CTL_DATA0] = SITAR_A_PIN_CTL_DATA0__POR,
+	[SITAR_A_PIN_CTL_DATA1] = SITAR_A_PIN_CTL_DATA1__POR,
+	[SITAR_A_HDRIVE_GENERIC] = SITAR_A_HDRIVE_GENERIC__POR,
+	[SITAR_A_HDRIVE_OVERRIDE] = SITAR_A_HDRIVE_OVERRIDE__POR,
+	[SITAR_A_ANA_CSR_WAIT_STATE] = SITAR_A_ANA_CSR_WAIT_STATE__POR,
+	[SITAR_A_PROCESS_MONITOR_CTL0] = SITAR_A_PROCESS_MONITOR_CTL0__POR,
+	[SITAR_A_PROCESS_MONITOR_CTL1] = SITAR_A_PROCESS_MONITOR_CTL1__POR,
+	[SITAR_A_PROCESS_MONITOR_CTL2] = SITAR_A_PROCESS_MONITOR_CTL2__POR,
+	[SITAR_A_PROCESS_MONITOR_CTL3] = SITAR_A_PROCESS_MONITOR_CTL3__POR,
+	[SITAR_A_QFUSE_CTL] = SITAR_A_QFUSE_CTL__POR,
+	[SITAR_A_QFUSE_STATUS] = SITAR_A_QFUSE_STATUS__POR,
+	[SITAR_A_QFUSE_DATA_OUT0] = SITAR_A_QFUSE_DATA_OUT0__POR,
+	[SITAR_A_QFUSE_DATA_OUT1] = SITAR_A_QFUSE_DATA_OUT1__POR,
+	[SITAR_A_QFUSE_DATA_OUT2] = SITAR_A_QFUSE_DATA_OUT2__POR,
+	[SITAR_A_QFUSE_DATA_OUT3] = SITAR_A_QFUSE_DATA_OUT3__POR,
+	[SITAR_A_CDC_CTL] = SITAR_A_CDC_CTL__POR,
+	[SITAR_A_LEAKAGE_CTL] = SITAR_A_LEAKAGE_CTL__POR,
+	[SITAR_A_INTR_MODE] = SITAR_A_INTR_MODE__POR,
+	[SITAR_A_INTR_MASK0] = SITAR_A_INTR_MASK0__POR,
+	[SITAR_A_INTR_MASK1] = SITAR_A_INTR_MASK1__POR,
+	[SITAR_A_INTR_MASK2] = SITAR_A_INTR_MASK2__POR,
+	[SITAR_A_INTR_STATUS0] = SITAR_A_INTR_STATUS0__POR,
+	[SITAR_A_INTR_STATUS1] = SITAR_A_INTR_STATUS1__POR,
+	[SITAR_A_INTR_STATUS2] = SITAR_A_INTR_STATUS2__POR,
+	[SITAR_A_INTR_CLEAR0] = SITAR_A_INTR_CLEAR0__POR,
+	[SITAR_A_INTR_CLEAR1] = SITAR_A_INTR_CLEAR1__POR,
+	[SITAR_A_INTR_CLEAR2] = SITAR_A_INTR_CLEAR2__POR,
+	[SITAR_A_INTR_LEVEL0] = SITAR_A_INTR_LEVEL0__POR,
+	[SITAR_A_INTR_LEVEL1] = SITAR_A_INTR_LEVEL1__POR,
+	[SITAR_A_INTR_LEVEL2] = SITAR_A_INTR_LEVEL2__POR,
+	[SITAR_A_INTR_TEST0] = SITAR_A_INTR_TEST0__POR,
+	[SITAR_A_INTR_TEST1] = SITAR_A_INTR_TEST1__POR,
+	[SITAR_A_INTR_TEST2] = SITAR_A_INTR_TEST2__POR,
+	[SITAR_A_INTR_SET0] = SITAR_A_INTR_SET0__POR,
+	[SITAR_A_INTR_SET1] = SITAR_A_INTR_SET1__POR,
+	[SITAR_A_INTR_SET2] = SITAR_A_INTR_SET2__POR,
+	[SITAR_A_CDC_TX_I2S_SCK_MODE] = SITAR_A_CDC_TX_I2S_SCK_MODE__POR,
+	[SITAR_A_CDC_TX_I2S_WS_MODE] = SITAR_A_CDC_TX_I2S_WS_MODE__POR,
+	[SITAR_A_CDC_DMIC_DATA0_MODE] = SITAR_A_CDC_DMIC_DATA0_MODE__POR,
+	[SITAR_A_CDC_DMIC_CLK0_MODE] = SITAR_A_CDC_DMIC_CLK0_MODE__POR,
+	[SITAR_A_CDC_DMIC_DATA1_MODE] = SITAR_A_CDC_DMIC_DATA1_MODE__POR,
+	[SITAR_A_CDC_DMIC_CLK1_MODE] = SITAR_A_CDC_DMIC_CLK1_MODE__POR,
+	[SITAR_A_CDC_TX_I2S_SD0_MODE] = SITAR_A_CDC_TX_I2S_SD0_MODE__POR,
+	[SITAR_A_CDC_INTR_MODE] = SITAR_A_CDC_INTR_MODE__POR,
+	[SITAR_A_CDC_RX_I2S_SD0_MODE] = SITAR_A_CDC_RX_I2S_SD0_MODE__POR,
+	[SITAR_A_CDC_RX_I2S_SD1_MODE] = SITAR_A_CDC_RX_I2S_SD1_MODE__POR,
+	[SITAR_A_BIAS_REF_CTL] = SITAR_A_BIAS_REF_CTL__POR,
+	[SITAR_A_BIAS_CENTRAL_BG_CTL] = SITAR_A_BIAS_CENTRAL_BG_CTL__POR,
+	[SITAR_A_BIAS_PRECHRG_CTL] = SITAR_A_BIAS_PRECHRG_CTL__POR,
+	[SITAR_A_BIAS_CURR_CTL_1] = SITAR_A_BIAS_CURR_CTL_1__POR,
+	[SITAR_A_BIAS_CURR_CTL_2] = SITAR_A_BIAS_CURR_CTL_2__POR,
+	[SITAR_A_BIAS_OSC_BG_CTL] = SITAR_A_BIAS_OSC_BG_CTL__POR,
+	[SITAR_A_CLK_BUFF_EN1] = SITAR_A_CLK_BUFF_EN1__POR,
+	[SITAR_A_CLK_BUFF_EN2] = SITAR_A_CLK_BUFF_EN2__POR,
+	[SITAR_A_LDO_H_MODE_1] = SITAR_A_LDO_H_MODE_1__POR,
+	[SITAR_A_LDO_H_MODE_2] = SITAR_A_LDO_H_MODE_2__POR,
+	[SITAR_A_LDO_H_LOOP_CTL] = SITAR_A_LDO_H_LOOP_CTL__POR,
+	[SITAR_A_LDO_H_COMP_1] = SITAR_A_LDO_H_COMP_1__POR,
+	[SITAR_A_LDO_H_COMP_2] = SITAR_A_LDO_H_COMP_2__POR,
+	[SITAR_A_LDO_H_BIAS_1] = SITAR_A_LDO_H_BIAS_1__POR,
+	[SITAR_A_LDO_H_BIAS_2] = SITAR_A_LDO_H_BIAS_2__POR,
+	[SITAR_A_LDO_H_BIAS_3] = SITAR_A_LDO_H_BIAS_3__POR,
+	[SITAR_A_MICB_CFILT_1_CTL] = SITAR_A_MICB_CFILT_1_CTL__POR,
+	[SITAR_A_MICB_CFILT_1_VAL] = SITAR_A_MICB_CFILT_1_VAL__POR,
+	[SITAR_A_MICB_CFILT_1_PRECHRG] = SITAR_A_MICB_CFILT_1_PRECHRG__POR,
+	[SITAR_A_MICB_1_CTL] = SITAR_A_MICB_1_CTL__POR,
+	[SITAR_A_MICB_1_INT_RBIAS] = SITAR_A_MICB_1_INT_RBIAS__POR,
+	[SITAR_A_MICB_1_MBHC] = SITAR_A_MICB_1_MBHC__POR,
+	[SITAR_A_MICB_CFILT_2_CTL] = SITAR_A_MICB_CFILT_2_CTL__POR,
+	[SITAR_A_MICB_CFILT_2_VAL] = SITAR_A_MICB_CFILT_2_VAL__POR,
+	[SITAR_A_MICB_CFILT_2_PRECHRG] = SITAR_A_MICB_CFILT_2_PRECHRG__POR,
+	[SITAR_A_MICB_2_CTL] = SITAR_A_MICB_2_CTL__POR,
+	[SITAR_A_MICB_2_INT_RBIAS] = SITAR_A_MICB_2_INT_RBIAS__POR,
+	[SITAR_A_MICB_2_MBHC] = SITAR_A_MICB_2_MBHC__POR,
+	[SITAR_A_TX_COM_BIAS] = SITAR_A_TX_COM_BIAS__POR,
+	[SITAR_A_MBHC_SCALING_MUX_1] = SITAR_A_MBHC_SCALING_MUX_1__POR,
+	[SITAR_A_MBHC_SCALING_MUX_2] = SITAR_A_MBHC_SCALING_MUX_2__POR,
+	[SITAR_A_TX_SUP_SWITCH_CTRL_1] = SITAR_A_TX_SUP_SWITCH_CTRL_1__POR,
+	[SITAR_A_TX_SUP_SWITCH_CTRL_2] = SITAR_A_TX_SUP_SWITCH_CTRL_2__POR,
+	[SITAR_A_TX_1_2_EN] = SITAR_A_TX_1_2_EN__POR,
+	[SITAR_A_TX_1_2_TEST_EN] = SITAR_A_TX_1_2_TEST_EN__POR,
+	[SITAR_A_TX_1_2_ADC_CH1] = SITAR_A_TX_1_2_ADC_CH1__POR,
+	[SITAR_A_TX_1_2_ADC_CH2] = SITAR_A_TX_1_2_ADC_CH2__POR,
+	[SITAR_A_TX_1_2_ATEST_REFCTRL] = SITAR_A_TX_1_2_ATEST_REFCTRL__POR,
+	[SITAR_A_TX_1_2_TEST_CTL] = SITAR_A_TX_1_2_TEST_CTL__POR,
+	[SITAR_A_TX_1_2_TEST_BLOCK_EN] = SITAR_A_TX_1_2_TEST_BLOCK_EN__POR,
+	[SITAR_A_TX_1_2_TXFE_CLKDIV] = SITAR_A_TX_1_2_TXFE_CLKDIV__POR,
+	[SITAR_A_TX_1_2_SAR_ERR_CH1] = SITAR_A_TX_1_2_SAR_ERR_CH1__POR,
+	[SITAR_A_TX_1_2_SAR_ERR_CH2] = SITAR_A_TX_1_2_SAR_ERR_CH2__POR,
+	[SITAR_A_TX_3_EN] = SITAR_A_TX_3_EN__POR,
+	[SITAR_A_TX_3_TEST_EN] = SITAR_A_TX_3_TEST_EN__POR,
+	[SITAR_A_TX_3_ADC] = SITAR_A_TX_3_ADC__POR,
+	[SITAR_A_TX_3_MBHC_ATEST_REFCTRL] =
+		SITAR_A_TX_3_MBHC_ATEST_REFCTRL__POR,
+	[SITAR_A_TX_3_TEST_CTL] = SITAR_A_TX_3_TEST_CTL__POR,
+	[SITAR_A_TX_3_TEST_BLOCK_EN] = SITAR_A_TX_3_TEST_BLOCK_EN__POR,
+	[SITAR_A_TX_3_TXFE_CKDIV] = SITAR_A_TX_3_TXFE_CKDIV__POR,
+	[SITAR_A_TX_3_SAR_ERR] = SITAR_A_TX_3_SAR_ERR__POR,
+	[SITAR_A_TX_4_MBHC_EN] = SITAR_A_TX_4_MBHC_EN__POR,
+	[SITAR_A_TX_4_MBHC_ADC] = SITAR_A_TX_4_MBHC_ADC__POR,
+	[SITAR_A_TX_4_MBHC_TEST_CTL] = SITAR_A_TX_4_MBHC_TEST_CTL__POR,
+	[SITAR_A_TX_4_MBHC_SAR_ERR] = SITAR_A_TX_4_MBHC_SAR_ERR__POR,
+	[SITAR_A_TX_4_TXFE_CLKDIV] = SITAR_A_TX_4_TXFE_CLKDIV__POR,
+	[SITAR_A_AUX_COM_CTL] = SITAR_A_AUX_COM_CTL__POR,
+	[SITAR_A_AUX_COM_ATEST] = SITAR_A_AUX_COM_ATEST__POR,
+	[SITAR_A_AUX_L_EN] = SITAR_A_AUX_L_EN__POR,
+	[SITAR_A_AUX_L_GAIN] = SITAR_A_AUX_L_GAIN__POR,
+	[SITAR_A_AUX_L_PA_CONN] = SITAR_A_AUX_L_PA_CONN__POR,
+	[SITAR_A_AUX_L_PA_CONN_INV] = SITAR_A_AUX_L_PA_CONN_INV__POR,
+	[SITAR_A_AUX_R_EN] = SITAR_A_AUX_R_EN__POR,
+	[SITAR_A_AUX_R_GAIN] = SITAR_A_AUX_R_GAIN__POR,
+	[SITAR_A_AUX_R_PA_CONN] = SITAR_A_AUX_R_PA_CONN__POR,
+	[SITAR_A_AUX_R_PA_CONN_INV] = SITAR_A_AUX_R_PA_CONN_INV__POR,
+	[SITAR_A_CP_EN] = SITAR_A_CP_EN__POR,
+	[SITAR_A_CP_CLK] = SITAR_A_CP_CLK__POR,
+	[SITAR_A_CP_STATIC] = SITAR_A_CP_STATIC__POR,
+	[SITAR_A_CP_DCC1] = SITAR_A_CP_DCC1__POR,
+	[SITAR_A_CP_DCC3] = SITAR_A_CP_DCC3__POR,
+	[SITAR_A_CP_ATEST] = SITAR_A_CP_ATEST__POR,
+	[SITAR_A_CP_DTEST] = SITAR_A_CP_DTEST__POR,
+	[SITAR_A_RX_COM_TIMER_DIV] = SITAR_A_RX_COM_TIMER_DIV__POR,
+	[SITAR_A_RX_COM_OCP_CTL] = SITAR_A_RX_COM_OCP_CTL__POR,
+	[SITAR_A_RX_COM_OCP_COUNT] = SITAR_A_RX_COM_OCP_COUNT__POR,
+	[SITAR_A_RX_COM_DAC_CTL] = SITAR_A_RX_COM_DAC_CTL__POR,
+	[SITAR_A_RX_COM_BIAS] = SITAR_A_RX_COM_BIAS__POR,
+	[SITAR_A_RX_HPH_BIAS_PA] = SITAR_A_RX_HPH_BIAS_PA__POR,
+	[SITAR_A_RX_HPH_BIAS_LDO] = SITAR_A_RX_HPH_BIAS_LDO__POR,
+	[SITAR_A_RX_HPH_BIAS_CNP] = SITAR_A_RX_HPH_BIAS_CNP__POR,
+	[SITAR_A_RX_HPH_BIAS_WG] = SITAR_A_RX_HPH_BIAS_WG__POR,
+	[SITAR_A_RX_HPH_OCP_CTL] = SITAR_A_RX_HPH_OCP_CTL__POR,
+	[SITAR_A_RX_HPH_CNP_EN] = SITAR_A_RX_HPH_CNP_EN__POR,
+	[SITAR_A_RX_HPH_CNP_WG_CTL] = SITAR_A_RX_HPH_CNP_WG_CTL__POR,
+	[SITAR_A_RX_HPH_CNP_WG_TIME] = SITAR_A_RX_HPH_CNP_WG_TIME__POR,
+	[SITAR_A_RX_HPH_L_GAIN] = SITAR_A_RX_HPH_L_GAIN__POR,
+	[SITAR_A_RX_HPH_L_TEST] = SITAR_A_RX_HPH_L_TEST__POR,
+	[SITAR_A_RX_HPH_L_PA_CTL] = SITAR_A_RX_HPH_L_PA_CTL__POR,
+	[SITAR_A_RX_HPH_L_DAC_CTL] = SITAR_A_RX_HPH_L_DAC_CTL__POR,
+	[SITAR_A_RX_HPH_L_ATEST] = SITAR_A_RX_HPH_L_ATEST__POR,
+	[SITAR_A_RX_HPH_L_STATUS] = SITAR_A_RX_HPH_L_STATUS__POR,
+	[SITAR_A_RX_HPH_R_GAIN] = SITAR_A_RX_HPH_R_GAIN__POR,
+	[SITAR_A_RX_HPH_R_TEST] = SITAR_A_RX_HPH_R_TEST__POR,
+	[SITAR_A_RX_HPH_R_PA_CTL] = SITAR_A_RX_HPH_R_PA_CTL__POR,
+	[SITAR_A_RX_HPH_R_DAC_CTL] = SITAR_A_RX_HPH_R_DAC_CTL__POR,
+	[SITAR_A_RX_HPH_R_ATEST] = SITAR_A_RX_HPH_R_ATEST__POR,
+	[SITAR_A_RX_HPH_R_STATUS] = SITAR_A_RX_HPH_R_STATUS__POR,
+	[SITAR_A_RX_EAR_BIAS_PA] = SITAR_A_RX_EAR_BIAS_PA__POR,
+	[SITAR_A_RX_EAR_BIAS_CMBUFF] = SITAR_A_RX_EAR_BIAS_CMBUFF__POR,
+	[SITAR_A_RX_EAR_EN] = SITAR_A_RX_EAR_EN__POR,
+	[SITAR_A_RX_EAR_GAIN] = SITAR_A_RX_EAR_GAIN__POR,
+	[SITAR_A_RX_EAR_CMBUFF] = SITAR_A_RX_EAR_CMBUFF__POR,
+	[SITAR_A_RX_EAR_ICTL] = SITAR_A_RX_EAR_ICTL__POR,
+	[SITAR_A_RX_EAR_CCOMP] = SITAR_A_RX_EAR_CCOMP__POR,
+	[SITAR_A_RX_EAR_VCM] = SITAR_A_RX_EAR_VCM__POR,
+	[SITAR_A_RX_EAR_CNP] = SITAR_A_RX_EAR_CNP__POR,
+	[SITAR_A_RX_EAR_ATEST] = SITAR_A_RX_EAR_ATEST__POR,
+	[SITAR_A_RX_EAR_STATUS] = SITAR_A_RX_EAR_STATUS__POR,
+	[SITAR_A_RX_LINE_BIAS_PA] = SITAR_A_RX_LINE_BIAS_PA__POR,
+	[SITAR_A_RX_LINE_BIAS_LDO] = SITAR_A_RX_LINE_BIAS_LDO__POR,
+	[SITAR_A_RX_LINE_BIAS_CNP1] = SITAR_A_RX_LINE_BIAS_CNP1__POR,
+	[SITAR_A_RX_LINE_COM] = SITAR_A_RX_LINE_COM__POR,
+	[SITAR_A_RX_LINE_CNP_EN] = SITAR_A_RX_LINE_CNP_EN__POR,
+	[SITAR_A_RX_LINE_CNP_WG_CTL] = SITAR_A_RX_LINE_CNP_WG_CTL__POR,
+	[SITAR_A_RX_LINE_CNP_WG_TIME] = SITAR_A_RX_LINE_CNP_WG_TIME__POR,
+	[SITAR_A_RX_LINE_1_GAIN] = SITAR_A_RX_LINE_1_GAIN__POR,
+	[SITAR_A_RX_LINE_1_TEST] = SITAR_A_RX_LINE_1_TEST__POR,
+	[SITAR_A_RX_LINE_1_DAC_CTL] = SITAR_A_RX_LINE_1_DAC_CTL__POR,
+	[SITAR_A_RX_LINE_1_STATUS] = SITAR_A_RX_LINE_1_STATUS__POR,
+	[SITAR_A_RX_LINE_2_GAIN] = SITAR_A_RX_LINE_2_GAIN__POR,
+	[SITAR_A_RX_LINE_2_TEST] = SITAR_A_RX_LINE_2_TEST__POR,
+	[SITAR_A_RX_LINE_2_DAC_CTL] = SITAR_A_RX_LINE_2_DAC_CTL__POR,
+	[SITAR_A_RX_LINE_2_STATUS] = SITAR_A_RX_LINE_2_STATUS__POR,
+	[SITAR_A_RX_LINE_BIAS_CNP2] = SITAR_A_RX_LINE_BIAS_CNP2__POR,
+	[SITAR_A_RX_LINE_OCP_CTL] = SITAR_A_RX_LINE_OCP_CTL__POR,
+	[SITAR_A_RX_LINE_1_PA_CTL] = SITAR_A_RX_LINE_1_PA_CTL__POR,
+	[SITAR_A_RX_LINE_2_PA_CTL] = SITAR_A_RX_LINE_2_PA_CTL__POR,
+	[SITAR_A_RX_LINE_CNP_DBG] = SITAR_A_RX_LINE_CNP_DBG__POR,
+	[SITAR_A_MBHC_HPH] = SITAR_A_MBHC_HPH__POR,
+	[SITAR_A_RC_OSC_FREQ] = SITAR_A_RC_OSC_FREQ__POR,
+	[SITAR_A_RC_OSC_TEST] = SITAR_A_RC_OSC_TEST__POR,
+	[SITAR_A_RC_OSC_STATUS] = SITAR_A_RC_OSC_STATUS__POR,
+	[SITAR_A_RC_OSC_TUNER] = SITAR_A_RC_OSC_TUNER__POR,
+	[SITAR_A_CDC_ANC1_CTL] = SITAR_A_CDC_ANC1_CTL__POR,
+	[SITAR_A_CDC_ANC1_SHIFT] = SITAR_A_CDC_ANC1_SHIFT__POR,
+	[SITAR_A_CDC_ANC1_IIR_B1_CTL] = SITAR_A_CDC_ANC1_IIR_B1_CTL__POR,
+	[SITAR_A_CDC_ANC1_IIR_B2_CTL] = SITAR_A_CDC_ANC1_IIR_B2_CTL__POR,
+	[SITAR_A_CDC_ANC1_IIR_B3_CTL] = SITAR_A_CDC_ANC1_IIR_B3_CTL__POR,
+	[SITAR_A_CDC_ANC1_IIR_B4_CTL] = SITAR_A_CDC_ANC1_IIR_B4_CTL__POR,
+	[SITAR_A_CDC_ANC1_LPF_B1_CTL] = SITAR_A_CDC_ANC1_LPF_B1_CTL__POR,
+	[SITAR_A_CDC_ANC1_LPF_B2_CTL] = SITAR_A_CDC_ANC1_LPF_B2_CTL__POR,
+	[SITAR_A_CDC_ANC1_LPF_B3_CTL] = SITAR_A_CDC_ANC1_LPF_B3_CTL__POR,
+	[SITAR_A_CDC_ANC1_SPARE] = SITAR_A_CDC_ANC1_SPARE__POR,
+	[SITAR_A_CDC_ANC1_SMLPF_CTL] = SITAR_A_CDC_ANC1_SMLPF_CTL__POR,
+	[SITAR_A_CDC_ANC1_DCFLT_CTL] = SITAR_A_CDC_ANC1_DCFLT_CTL__POR,
+	[SITAR_A_CDC_TX1_VOL_CTL_TIMER] = SITAR_A_CDC_TX1_VOL_CTL_TIMER__POR,
+	[SITAR_A_CDC_TX1_VOL_CTL_GAIN] = SITAR_A_CDC_TX1_VOL_CTL_GAIN__POR,
+	[SITAR_A_CDC_TX1_VOL_CTL_CFG] = SITAR_A_CDC_TX1_VOL_CTL_CFG__POR,
+	[SITAR_A_CDC_TX1_MUX_CTL] = SITAR_A_CDC_TX1_MUX_CTL__POR,
+	[SITAR_A_CDC_TX1_CLK_FS_CTL] = SITAR_A_CDC_TX1_CLK_FS_CTL__POR,
+	[SITAR_A_CDC_TX1_DMIC_CTL] = SITAR_A_CDC_TX1_DMIC_CTL__POR,
+	[SITAR_A_CDC_SRC1_PDA_CFG] = SITAR_A_CDC_SRC1_PDA_CFG__POR,
+	[SITAR_A_CDC_SRC1_FS_CTL] = SITAR_A_CDC_SRC1_FS_CTL__POR,
+	[SITAR_A_CDC_RX1_B1_CTL] = SITAR_A_CDC_RX1_B1_CTL__POR,
+	[SITAR_A_CDC_RX1_B2_CTL] = SITAR_A_CDC_RX1_B2_CTL__POR,
+	[SITAR_A_CDC_RX1_B3_CTL] = SITAR_A_CDC_RX1_B3_CTL__POR,
+	[SITAR_A_CDC_RX1_B4_CTL] = SITAR_A_CDC_RX1_B4_CTL__POR,
+	[SITAR_A_CDC_RX1_B5_CTL] = SITAR_A_CDC_RX1_B5_CTL__POR,
+	[SITAR_A_CDC_RX1_B6_CTL] = SITAR_A_CDC_RX1_B6_CTL__POR,
+	[SITAR_A_CDC_RX1_VOL_CTL_B1_CTL] = SITAR_A_CDC_RX1_VOL_CTL_B1_CTL__POR,
+	[SITAR_A_CDC_RX1_VOL_CTL_B2_CTL] = SITAR_A_CDC_RX1_VOL_CTL_B2_CTL__POR,
+	[SITAR_A_CDC_CLK_ANC_RESET_CTL] = SITAR_A_CDC_CLK_ANC_RESET_CTL__POR,
+	[SITAR_A_CDC_CLK_RX_RESET_CTL] = SITAR_A_CDC_CLK_RX_RESET_CTL__POR,
+	[SITAR_A_CDC_CLK_TX_RESET_B1_CTL] =
+		SITAR_A_CDC_CLK_TX_RESET_B1_CTL__POR,
+	[SITAR_A_CDC_CLK_TX_RESET_B2_CTL] =
+		SITAR_A_CDC_CLK_TX_RESET_B2_CTL__POR,
+	[SITAR_A_CDC_CLK_DMIC_CTL] = SITAR_A_CDC_CLK_DMIC_CTL__POR,
+	[SITAR_A_CDC_CLK_RX_I2S_CTL] = SITAR_A_CDC_CLK_RX_I2S_CTL__POR,
+	[SITAR_A_CDC_CLK_TX_I2S_CTL] = SITAR_A_CDC_CLK_TX_I2S_CTL__POR,
+	[SITAR_A_CDC_CLK_OTHR_RESET_CTL] = SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR,
+	[SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL] =
+		SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR,
+	[SITAR_A_CDC_CLK_OTHR_CTL] = SITAR_A_CDC_CLK_OTHR_CTL__POR,
+	[SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL] =
+		SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL__POR,
+	[SITAR_A_CDC_CLK_ANC_CLK_EN_CTL] = SITAR_A_CDC_CLK_ANC_CLK_EN_CTL__POR,
+	[SITAR_A_CDC_CLK_RX_B1_CTL] = SITAR_A_CDC_CLK_RX_B1_CTL__POR,
+	[SITAR_A_CDC_CLK_RX_B2_CTL] = SITAR_A_CDC_CLK_RX_B2_CTL__POR,
+	[SITAR_A_CDC_CLK_MCLK_CTL] = SITAR_A_CDC_CLK_MCLK_CTL__POR,
+	[SITAR_A_CDC_CLK_PDM_CTL] = SITAR_A_CDC_CLK_PDM_CTL__POR,
+	[SITAR_A_CDC_CLK_SD_CTL] = SITAR_A_CDC_CLK_SD_CTL__POR,
+	[SITAR_A_CDC_CLK_LP_CTL] = SITAR_A_CDC_CLK_LP_CTL__POR,
+	[SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL] =
+		SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL__POR,
+	[SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL] =
+		SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL__POR,
+	[SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL] =
+		SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL__POR,
+	[SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL] =
+		SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL__POR,
+	[SITAR_A_CDC_CLSG_GAIN_THRESH_CTL] =
+		SITAR_A_CDC_CLSG_GAIN_THRESH_CTL__POR,
+	[SITAR_A_CDC_CLSG_TIMER_B1_CFG] = SITAR_A_CDC_CLSG_TIMER_B1_CFG__POR,
+	[SITAR_A_CDC_CLSG_TIMER_B2_CFG] = SITAR_A_CDC_CLSG_TIMER_B2_CFG__POR,
+	[SITAR_A_CDC_CLSG_CTL] = SITAR_A_CDC_CLSG_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_B1_CTL] = SITAR_A_CDC_IIR1_GAIN_B1_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_B2_CTL] = SITAR_A_CDC_IIR1_GAIN_B2_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_B3_CTL] = SITAR_A_CDC_IIR1_GAIN_B3_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_B4_CTL] = SITAR_A_CDC_IIR1_GAIN_B4_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_B5_CTL] = SITAR_A_CDC_IIR1_GAIN_B5_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_B6_CTL] = SITAR_A_CDC_IIR1_GAIN_B6_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_B7_CTL] = SITAR_A_CDC_IIR1_GAIN_B7_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_B8_CTL] = SITAR_A_CDC_IIR1_GAIN_B8_CTL__POR,
+	[SITAR_A_CDC_IIR1_CTL] = SITAR_A_CDC_IIR1_CTL__POR,
+	[SITAR_A_CDC_IIR1_GAIN_TIMER_CTL] =
+		SITAR_A_CDC_IIR1_GAIN_TIMER_CTL__POR,
+	[SITAR_A_CDC_IIR1_COEF_B1_CTL] = SITAR_A_CDC_IIR1_COEF_B1_CTL__POR,
+	[SITAR_A_CDC_IIR1_COEF_B2_CTL] = SITAR_A_CDC_IIR1_COEF_B2_CTL__POR,
+	[SITAR_A_CDC_IIR1_COEF_B3_CTL] = SITAR_A_CDC_IIR1_COEF_B3_CTL__POR,
+	[SITAR_A_CDC_IIR1_COEF_B4_CTL] = SITAR_A_CDC_IIR1_COEF_B4_CTL__POR,
+	[SITAR_A_CDC_IIR1_COEF_B5_CTL] = SITAR_A_CDC_IIR1_COEF_B5_CTL__POR,
+	[SITAR_A_CDC_TOP_GAIN_UPDATE] = SITAR_A_CDC_TOP_GAIN_UPDATE__POR,
+	[SITAR_A_CDC_TOP_RDAC_DOUT_CTL] = SITAR_A_CDC_TOP_RDAC_DOUT_CTL__POR,
+	[SITAR_A_CDC_DEBUG_B1_CTL] = SITAR_A_CDC_DEBUG_B1_CTL__POR,
+	[SITAR_A_CDC_DEBUG_B2_CTL] = SITAR_A_CDC_DEBUG_B2_CTL__POR,
+	[SITAR_A_CDC_DEBUG_B3_CTL] = SITAR_A_CDC_DEBUG_B3_CTL__POR,
+	[SITAR_A_CDC_DEBUG_B4_CTL] = SITAR_A_CDC_DEBUG_B4_CTL__POR,
+	[SITAR_A_CDC_DEBUG_B5_CTL] = SITAR_A_CDC_DEBUG_B5_CTL__POR,
+	[SITAR_A_CDC_DEBUG_B6_CTL] = SITAR_A_CDC_DEBUG_B6_CTL__POR,
+	[SITAR_A_CDC_DEBUG_B7_CTL] = SITAR_A_CDC_DEBUG_B7_CTL__POR,
+	[SITAR_A_CDC_COMP1_B1_CTL] = SITAR_A_CDC_COMP1_B1_CTL__POR,
+	[SITAR_A_CDC_COMP1_B2_CTL] = SITAR_A_CDC_COMP1_B2_CTL__POR,
+	[SITAR_A_CDC_COMP1_B3_CTL] = SITAR_A_CDC_COMP1_B3_CTL__POR,
+	[SITAR_A_CDC_COMP1_B4_CTL] = SITAR_A_CDC_COMP1_B4_CTL__POR,
+	[SITAR_A_CDC_COMP1_B5_CTL] = SITAR_A_CDC_COMP1_B5_CTL__POR,
+	[SITAR_A_CDC_COMP1_B6_CTL] = SITAR_A_CDC_COMP1_B6_CTL__POR,
+	[SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS] =
+		SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS__POR,
+	[SITAR_A_CDC_COMP1_FS_CFG] = SITAR_A_CDC_COMP1_FS_CFG__POR,
+	[SITAR_A_CDC_CONN_RX1_B1_CTL] = SITAR_A_CDC_CONN_RX1_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_RX1_B2_CTL] = SITAR_A_CDC_CONN_RX1_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_RX1_B3_CTL] = SITAR_A_CDC_CONN_RX1_B3_CTL__POR,
+	[SITAR_A_CDC_CONN_RX2_B1_CTL] = SITAR_A_CDC_CONN_RX2_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_RX2_B2_CTL] = SITAR_A_CDC_CONN_RX2_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_RX2_B3_CTL] = SITAR_A_CDC_CONN_RX2_B3_CTL__POR,
+	[SITAR_A_CDC_CONN_RX3_B1_CTL] = SITAR_A_CDC_CONN_RX3_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_RX3_B2_CTL] = SITAR_A_CDC_CONN_RX3_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_RX3_B3_CTL] = SITAR_A_CDC_CONN_RX3_B3_CTL__POR,
+	[SITAR_A_CDC_CONN_ANC_B1_CTL] = SITAR_A_CDC_CONN_ANC_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_ANC_B2_CTL] = SITAR_A_CDC_CONN_ANC_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_TX_B1_CTL] = SITAR_A_CDC_CONN_TX_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_TX_B2_CTL] = SITAR_A_CDC_CONN_TX_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_EQ1_B1_CTL] = SITAR_A_CDC_CONN_EQ1_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_EQ1_B2_CTL] = SITAR_A_CDC_CONN_EQ1_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_EQ1_B3_CTL] = SITAR_A_CDC_CONN_EQ1_B3_CTL__POR,
+	[SITAR_A_CDC_CONN_EQ1_B4_CTL] = SITAR_A_CDC_CONN_EQ1_B4_CTL__POR,
+	[SITAR_A_CDC_CONN_EQ2_B1_CTL] = SITAR_A_CDC_CONN_EQ2_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_EQ2_B2_CTL] = SITAR_A_CDC_CONN_EQ2_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_EQ2_B3_CTL] = SITAR_A_CDC_CONN_EQ2_B3_CTL__POR,
+	[SITAR_A_CDC_CONN_EQ2_B4_CTL] = SITAR_A_CDC_CONN_EQ2_B4_CTL__POR,
+	[SITAR_A_CDC_CONN_SRC1_B1_CTL] = SITAR_A_CDC_CONN_SRC1_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_SRC1_B2_CTL] = SITAR_A_CDC_CONN_SRC1_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_SRC2_B1_CTL] = SITAR_A_CDC_CONN_SRC2_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_SRC2_B2_CTL] = SITAR_A_CDC_CONN_SRC2_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_TX_SB_B1_CTL] = SITAR_A_CDC_CONN_TX_SB_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_TX_SB_B2_CTL] = SITAR_A_CDC_CONN_TX_SB_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_TX_SB_B3_CTL] = SITAR_A_CDC_CONN_TX_SB_B3_CTL__POR,
+	[SITAR_A_CDC_CONN_TX_SB_B4_CTL] = SITAR_A_CDC_CONN_TX_SB_B4_CTL__POR,
+	[SITAR_A_CDC_CONN_TX_SB_B5_CTL] = SITAR_A_CDC_CONN_TX_SB_B5_CTL__POR,
+	[SITAR_A_CDC_CONN_RX_SB_B1_CTL] = SITAR_A_CDC_CONN_RX_SB_B1_CTL__POR,
+	[SITAR_A_CDC_CONN_RX_SB_B2_CTL] = SITAR_A_CDC_CONN_RX_SB_B2_CTL__POR,
+	[SITAR_A_CDC_CONN_CLSG_CTL] = SITAR_A_CDC_CONN_CLSG_CTL__POR,
+	[SITAR_A_CDC_CONN_SPARE] = SITAR_A_CDC_CONN_SPARE__POR,
+	[SITAR_A_CDC_MBHC_EN_CTL] = SITAR_A_CDC_MBHC_EN_CTL__POR,
+	[SITAR_A_CDC_MBHC_FIR_B1_CFG] = SITAR_A_CDC_MBHC_FIR_B1_CFG__POR,
+	[SITAR_A_CDC_MBHC_FIR_B2_CFG] = SITAR_A_CDC_MBHC_FIR_B2_CFG__POR,
+	[SITAR_A_CDC_MBHC_TIMER_B1_CTL] = SITAR_A_CDC_MBHC_TIMER_B1_CTL__POR,
+	[SITAR_A_CDC_MBHC_TIMER_B2_CTL] = SITAR_A_CDC_MBHC_TIMER_B2_CTL__POR,
+	[SITAR_A_CDC_MBHC_TIMER_B3_CTL] = SITAR_A_CDC_MBHC_TIMER_B3_CTL__POR,
+	[SITAR_A_CDC_MBHC_TIMER_B4_CTL] = SITAR_A_CDC_MBHC_TIMER_B4_CTL__POR,
+	[SITAR_A_CDC_MBHC_TIMER_B5_CTL] = SITAR_A_CDC_MBHC_TIMER_B5_CTL__POR,
+	[SITAR_A_CDC_MBHC_TIMER_B6_CTL] = SITAR_A_CDC_MBHC_TIMER_B6_CTL__POR,
+	[SITAR_A_CDC_MBHC_B1_STATUS] = SITAR_A_CDC_MBHC_B1_STATUS__POR,
+	[SITAR_A_CDC_MBHC_B2_STATUS] = SITAR_A_CDC_MBHC_B2_STATUS__POR,
+	[SITAR_A_CDC_MBHC_B3_STATUS] = SITAR_A_CDC_MBHC_B3_STATUS__POR,
+	[SITAR_A_CDC_MBHC_B4_STATUS] = SITAR_A_CDC_MBHC_B4_STATUS__POR,
+	[SITAR_A_CDC_MBHC_B5_STATUS] = SITAR_A_CDC_MBHC_B5_STATUS__POR,
+	[SITAR_A_CDC_MBHC_B1_CTL] = SITAR_A_CDC_MBHC_B1_CTL__POR,
+	[SITAR_A_CDC_MBHC_B2_CTL] = SITAR_A_CDC_MBHC_B2_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B1_CTL] = SITAR_A_CDC_MBHC_VOLT_B1_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B2_CTL] = SITAR_A_CDC_MBHC_VOLT_B2_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B3_CTL] = SITAR_A_CDC_MBHC_VOLT_B3_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B4_CTL] = SITAR_A_CDC_MBHC_VOLT_B4_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B5_CTL] = SITAR_A_CDC_MBHC_VOLT_B5_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B6_CTL] = SITAR_A_CDC_MBHC_VOLT_B6_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B7_CTL] = SITAR_A_CDC_MBHC_VOLT_B7_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B8_CTL] = SITAR_A_CDC_MBHC_VOLT_B8_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B9_CTL] = SITAR_A_CDC_MBHC_VOLT_B9_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B10_CTL] = SITAR_A_CDC_MBHC_VOLT_B10_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B11_CTL] = SITAR_A_CDC_MBHC_VOLT_B11_CTL__POR,
+	[SITAR_A_CDC_MBHC_VOLT_B12_CTL] = SITAR_A_CDC_MBHC_VOLT_B12_CTL__POR,
+	[SITAR_A_CDC_MBHC_CLK_CTL] = SITAR_A_CDC_MBHC_CLK_CTL__POR,
+	[SITAR_A_CDC_MBHC_INT_CTL] = SITAR_A_CDC_MBHC_INT_CTL__POR,
+	[SITAR_A_CDC_MBHC_DEBUG_CTL] = SITAR_A_CDC_MBHC_DEBUG_CTL__POR,
+	[SITAR_A_CDC_MBHC_SPARE] = SITAR_A_CDC_MBHC_SPARE__POR,
+};
+
+const u8 sitar_reg_readable[SITAR_CACHE_SIZE] = {
+	[WCD9XXX_A_CHIP_CTL] = 1,
+	[WCD9XXX_A_CHIP_STATUS] = 1,
+	[WCD9XXX_A_CHIP_ID_BYTE_0] = 1,
+	[WCD9XXX_A_CHIP_ID_BYTE_1] = 1,
+	[WCD9XXX_A_CHIP_ID_BYTE_2] = 1,
+	[WCD9XXX_A_CHIP_ID_BYTE_3] = 1,
+	[WCD9XXX_A_CHIP_VERSION] = 1,
+	[WCD9XXX_A_SB_VERSION] = 1,
+	[WCD9XXX_A_SLAVE_ID_1] = 1,
+	[WCD9XXX_A_SLAVE_ID_2] = 1,
+	[WCD9XXX_A_SLAVE_ID_3] = 1,
+	[SITAR_A_PIN_CTL_OE0] = 1,
+	[SITAR_A_PIN_CTL_OE1] = 1,
+	[SITAR_A_PIN_CTL_DATA0] = 1,
+	[SITAR_A_PIN_CTL_DATA1] = 1,
+	[SITAR_A_HDRIVE_GENERIC] = 1,
+	[SITAR_A_HDRIVE_OVERRIDE] = 1,
+	[SITAR_A_ANA_CSR_WAIT_STATE] = 1,
+	[SITAR_A_PROCESS_MONITOR_CTL0] = 1,
+	[SITAR_A_PROCESS_MONITOR_CTL1] = 1,
+	[SITAR_A_PROCESS_MONITOR_CTL2] = 1,
+	[SITAR_A_PROCESS_MONITOR_CTL3] = 1,
+	[SITAR_A_QFUSE_CTL] = 1,
+	[SITAR_A_QFUSE_STATUS] = 1,
+	[SITAR_A_QFUSE_DATA_OUT0] = 1,
+	[SITAR_A_QFUSE_DATA_OUT1] = 1,
+	[SITAR_A_QFUSE_DATA_OUT2] = 1,
+	[SITAR_A_QFUSE_DATA_OUT3] = 1,
+	[SITAR_A_CDC_CTL] = 1,
+	[SITAR_A_LEAKAGE_CTL] = 1,
+	[SITAR_A_INTR_MODE] = 1,
+	[SITAR_A_INTR_MASK0] = 1,
+	[SITAR_A_INTR_MASK1] = 1,
+	[SITAR_A_INTR_MASK2] = 1,
+	[SITAR_A_INTR_STATUS0] = 1,
+	[SITAR_A_INTR_STATUS1] = 1,
+	[SITAR_A_INTR_STATUS2] = 1,
+	[SITAR_A_INTR_LEVEL0] = 1,
+	[SITAR_A_INTR_LEVEL1] = 1,
+	[SITAR_A_INTR_LEVEL2] = 1,
+	[SITAR_A_INTR_TEST0] = 1,
+	[SITAR_A_INTR_TEST1] = 1,
+	[SITAR_A_INTR_TEST2] = 1,
+	[SITAR_A_INTR_SET0] = 1,
+	[SITAR_A_INTR_SET1] = 1,
+	[SITAR_A_INTR_SET2] = 1,
+	[SITAR_A_CDC_TX_I2S_SCK_MODE] = 1,
+	[SITAR_A_CDC_TX_I2S_WS_MODE] = 1,
+	[SITAR_A_CDC_DMIC_DATA0_MODE] = 1,
+	[SITAR_A_CDC_DMIC_CLK0_MODE] = 1,
+	[SITAR_A_CDC_DMIC_DATA1_MODE] = 1,
+	[SITAR_A_CDC_DMIC_CLK1_MODE] = 1,
+	[SITAR_A_CDC_TX_I2S_SD0_MODE] = 1,
+	[SITAR_A_CDC_INTR_MODE] = 1,
+	[SITAR_A_CDC_RX_I2S_SD0_MODE] = 1,
+	[SITAR_A_CDC_RX_I2S_SD1_MODE] = 1,
+	[SITAR_A_BIAS_REF_CTL] = 1,
+	[SITAR_A_BIAS_CENTRAL_BG_CTL] = 1,
+	[SITAR_A_BIAS_PRECHRG_CTL] = 1,
+	[SITAR_A_BIAS_CURR_CTL_1] = 1,
+	[SITAR_A_BIAS_CURR_CTL_2] = 1,
+	[SITAR_A_BIAS_OSC_BG_CTL] = 1,
+	[SITAR_A_CLK_BUFF_EN1] = 1,
+	[SITAR_A_CLK_BUFF_EN2] = 1,
+	[SITAR_A_LDO_H_MODE_1] = 1,
+	[SITAR_A_LDO_H_MODE_2] = 1,
+	[SITAR_A_LDO_H_LOOP_CTL] = 1,
+	[SITAR_A_LDO_H_COMP_1] = 1,
+	[SITAR_A_LDO_H_COMP_2] = 1,
+	[SITAR_A_LDO_H_BIAS_1] = 1,
+	[SITAR_A_LDO_H_BIAS_2] = 1,
+	[SITAR_A_LDO_H_BIAS_3] = 1,
+	[SITAR_A_MICB_CFILT_1_CTL] = 1,
+	[SITAR_A_MICB_CFILT_1_VAL] = 1,
+	[SITAR_A_MICB_CFILT_1_PRECHRG] = 1,
+	[SITAR_A_MICB_1_CTL] = 1,
+	[SITAR_A_MICB_1_INT_RBIAS] = 1,
+	[SITAR_A_MICB_1_MBHC] = 1,
+	[SITAR_A_MICB_CFILT_2_CTL] = 1,
+	[SITAR_A_MICB_CFILT_2_VAL] = 1,
+	[SITAR_A_MICB_CFILT_2_PRECHRG] = 1,
+	[SITAR_A_MICB_2_CTL] = 1,
+	[SITAR_A_MICB_2_INT_RBIAS] = 1,
+	[SITAR_A_MICB_2_MBHC] = 1,
+	[SITAR_A_TX_COM_BIAS] = 1,
+	[SITAR_A_MBHC_SCALING_MUX_1] = 1,
+	[SITAR_A_MBHC_SCALING_MUX_2] = 1,
+	[SITAR_A_TX_SUP_SWITCH_CTRL_1] = 1,
+	[SITAR_A_TX_SUP_SWITCH_CTRL_2] = 1,
+	[SITAR_A_TX_1_2_EN] = 1,
+	[SITAR_A_TX_1_2_TEST_EN] = 1,
+	[SITAR_A_TX_1_2_ADC_CH1] = 1,
+	[SITAR_A_TX_1_2_ADC_CH2] = 1,
+	[SITAR_A_TX_1_2_ATEST_REFCTRL] = 1,
+	[SITAR_A_TX_1_2_TEST_CTL] = 1,
+	[SITAR_A_TX_1_2_TEST_BLOCK_EN] = 1,
+	[SITAR_A_TX_1_2_TXFE_CLKDIV] = 1,
+	[SITAR_A_TX_1_2_SAR_ERR_CH1] = 1,
+	[SITAR_A_TX_1_2_SAR_ERR_CH2] = 1,
+	[SITAR_A_TX_3_EN] = 1,
+	[SITAR_A_TX_3_TEST_EN] = 1,
+	[SITAR_A_TX_3_ADC] = 1,
+	[SITAR_A_TX_3_MBHC_ATEST_REFCTRL] = 1,
+	[SITAR_A_TX_3_TEST_CTL] = 1,
+	[SITAR_A_TX_3_TEST_BLOCK_EN] = 1,
+	[SITAR_A_TX_3_TXFE_CKDIV] = 1,
+	[SITAR_A_TX_3_SAR_ERR] = 1,
+	[SITAR_A_TX_4_MBHC_EN] = 1,
+	[SITAR_A_TX_4_MBHC_ADC] = 1,
+	[SITAR_A_TX_4_MBHC_TEST_CTL] = 1,
+	[SITAR_A_TX_4_MBHC_SAR_ERR] = 1,
+	[SITAR_A_TX_4_TXFE_CLKDIV] = 1,
+	[SITAR_A_AUX_COM_CTL] = 1,
+	[SITAR_A_AUX_COM_ATEST] = 1,
+	[SITAR_A_AUX_L_EN] = 1,
+	[SITAR_A_AUX_L_GAIN] = 1,
+	[SITAR_A_AUX_L_PA_CONN] = 1,
+	[SITAR_A_AUX_L_PA_CONN_INV] = 1,
+	[SITAR_A_AUX_R_EN] = 1,
+	[SITAR_A_AUX_R_GAIN] = 1,
+	[SITAR_A_AUX_R_PA_CONN] = 1,
+	[SITAR_A_AUX_R_PA_CONN_INV] = 1,
+	[SITAR_A_CP_EN] = 1,
+	[SITAR_A_CP_CLK] = 1,
+	[SITAR_A_CP_STATIC] = 1,
+	[SITAR_A_CP_DCC1] = 1,
+	[SITAR_A_CP_DCC3] = 1,
+	[SITAR_A_CP_ATEST] = 1,
+	[SITAR_A_CP_DTEST] = 1,
+	[SITAR_A_RX_COM_TIMER_DIV] = 1,
+	[SITAR_A_RX_COM_OCP_CTL] = 1,
+	[SITAR_A_RX_COM_OCP_COUNT] = 1,
+	[SITAR_A_RX_COM_DAC_CTL] = 1,
+	[SITAR_A_RX_COM_BIAS] = 1,
+	[SITAR_A_RX_HPH_BIAS_PA] = 1,
+	[SITAR_A_RX_HPH_BIAS_LDO] = 1,
+	[SITAR_A_RX_HPH_BIAS_CNP] = 1,
+	[SITAR_A_RX_HPH_BIAS_WG] = 1,
+	[SITAR_A_RX_HPH_OCP_CTL] = 1,
+	[SITAR_A_RX_HPH_CNP_EN] = 1,
+	[SITAR_A_RX_HPH_CNP_WG_CTL] = 1,
+	[SITAR_A_RX_HPH_CNP_WG_TIME] = 1,
+	[SITAR_A_RX_HPH_L_GAIN] = 1,
+	[SITAR_A_RX_HPH_L_TEST] = 1,
+	[SITAR_A_RX_HPH_L_PA_CTL] = 1,
+	[SITAR_A_RX_HPH_L_DAC_CTL] = 1,
+	[SITAR_A_RX_HPH_L_ATEST] = 1,
+	[SITAR_A_RX_HPH_L_STATUS] = 1,
+	[SITAR_A_RX_HPH_R_GAIN] = 1,
+	[SITAR_A_RX_HPH_R_TEST] = 1,
+	[SITAR_A_RX_HPH_R_PA_CTL] = 1,
+	[SITAR_A_RX_HPH_R_DAC_CTL] = 1,
+	[SITAR_A_RX_HPH_R_ATEST] = 1,
+	[SITAR_A_RX_HPH_R_STATUS] = 1,
+	[SITAR_A_RX_EAR_BIAS_PA] = 1,
+	[SITAR_A_RX_EAR_BIAS_CMBUFF] = 1,
+	[SITAR_A_RX_EAR_EN] = 1,
+	[SITAR_A_RX_EAR_GAIN] = 1,
+	[SITAR_A_RX_EAR_CMBUFF] = 1,
+	[SITAR_A_RX_EAR_ICTL] = 1,
+	[SITAR_A_RX_EAR_CCOMP] = 1,
+	[SITAR_A_RX_EAR_VCM] = 1,
+	[SITAR_A_RX_EAR_CNP] = 1,
+	[SITAR_A_RX_EAR_ATEST] = 1,
+	[SITAR_A_RX_EAR_STATUS] = 1,
+	[SITAR_A_RX_LINE_BIAS_PA] = 1,
+	[SITAR_A_RX_LINE_BIAS_LDO] = 1,
+	[SITAR_A_RX_LINE_BIAS_CNP1] = 1,
+	[SITAR_A_RX_LINE_COM] = 1,
+	[SITAR_A_RX_LINE_CNP_EN] = 1,
+	[SITAR_A_RX_LINE_CNP_WG_CTL] = 1,
+	[SITAR_A_RX_LINE_CNP_WG_TIME] = 1,
+	[SITAR_A_RX_LINE_1_GAIN] = 1,
+	[SITAR_A_RX_LINE_1_TEST] = 1,
+	[SITAR_A_RX_LINE_1_DAC_CTL] = 1,
+	[SITAR_A_RX_LINE_1_STATUS] = 1,
+	[SITAR_A_RX_LINE_2_GAIN] = 1,
+	[SITAR_A_RX_LINE_2_TEST] = 1,
+	[SITAR_A_RX_LINE_2_DAC_CTL] = 1,
+	[SITAR_A_RX_LINE_2_STATUS] = 1,
+	[SITAR_A_RX_LINE_BIAS_CNP2] = 1,
+	[SITAR_A_RX_LINE_OCP_CTL] = 1,
+	[SITAR_A_RX_LINE_1_PA_CTL] = 1,
+	[SITAR_A_RX_LINE_2_PA_CTL] = 1,
+	[SITAR_A_RX_LINE_CNP_DBG] = 1,
+	[SITAR_A_MBHC_HPH] = 1,
+	[SITAR_A_RC_OSC_FREQ] = 1,
+	[SITAR_A_RC_OSC_TEST] = 1,
+	[SITAR_A_RC_OSC_STATUS] = 1,
+	[SITAR_A_RC_OSC_TUNER] = 1,
+	[SITAR_A_CDC_ANC1_CTL] = 1,
+	[SITAR_A_CDC_ANC1_SHIFT] = 1,
+	[SITAR_A_CDC_ANC1_IIR_B1_CTL] = 1,
+	[SITAR_A_CDC_ANC1_IIR_B2_CTL] = 1,
+	[SITAR_A_CDC_ANC1_IIR_B3_CTL] = 1,
+	[SITAR_A_CDC_ANC1_IIR_B4_CTL] = 1,
+	[SITAR_A_CDC_ANC1_LPF_B1_CTL] = 1,
+	[SITAR_A_CDC_ANC1_LPF_B2_CTL] = 1,
+	[SITAR_A_CDC_ANC1_LPF_B3_CTL] = 1,
+	[SITAR_A_CDC_ANC1_SPARE] = 1,
+	[SITAR_A_CDC_ANC1_SMLPF_CTL] = 1,
+	[SITAR_A_CDC_ANC1_DCFLT_CTL] = 1,
+	[SITAR_A_CDC_TX1_VOL_CTL_TIMER] = 1,
+	[SITAR_A_CDC_TX1_VOL_CTL_GAIN] = 1,
+	[SITAR_A_CDC_TX1_VOL_CTL_CFG] = 1,
+	[SITAR_A_CDC_TX1_MUX_CTL] = 1,
+	[SITAR_A_CDC_TX1_CLK_FS_CTL] = 1,
+	[SITAR_A_CDC_TX1_DMIC_CTL] = 1,
+	[SITAR_A_CDC_SRC1_PDA_CFG] = 1,
+	[SITAR_A_CDC_SRC1_FS_CTL] = 1,
+	[SITAR_A_CDC_RX1_B1_CTL] = 1,
+	[SITAR_A_CDC_RX1_B2_CTL] = 1,
+	[SITAR_A_CDC_RX1_B3_CTL] = 1,
+	[SITAR_A_CDC_RX1_B4_CTL] = 1,
+	[SITAR_A_CDC_RX1_B5_CTL] = 1,
+	[SITAR_A_CDC_RX1_B6_CTL] = 1,
+	[SITAR_A_CDC_RX1_VOL_CTL_B1_CTL] = 1,
+	[SITAR_A_CDC_RX1_VOL_CTL_B2_CTL] = 1,
+	[SITAR_A_CDC_CLK_ANC_RESET_CTL] = 1,
+	[SITAR_A_CDC_CLK_RX_RESET_CTL] = 1,
+	[SITAR_A_CDC_CLK_TX_RESET_B1_CTL] = 1,
+	[SITAR_A_CDC_CLK_TX_RESET_B2_CTL] = 1,
+	[SITAR_A_CDC_CLK_DMIC_CTL] = 1,
+	[SITAR_A_CDC_CLK_RX_I2S_CTL] = 1,
+	[SITAR_A_CDC_CLK_TX_I2S_CTL] = 1,
+	[SITAR_A_CDC_CLK_OTHR_RESET_CTL] = 1,
+	[SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL] = 1,
+	[SITAR_A_CDC_CLK_OTHR_CTL] = 1,
+	[SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL] = 1,
+	[SITAR_A_CDC_CLK_ANC_CLK_EN_CTL] = 1,
+	[SITAR_A_CDC_CLK_RX_B1_CTL] = 1,
+	[SITAR_A_CDC_CLK_RX_B2_CTL] = 1,
+	[SITAR_A_CDC_CLK_MCLK_CTL] = 1,
+	[SITAR_A_CDC_CLK_PDM_CTL] = 1,
+	[SITAR_A_CDC_CLK_SD_CTL] = 1,
+	[SITAR_A_CDC_CLK_LP_CTL] = 1,
+	[SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL] = 1,
+	[SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL] = 1,
+	[SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL] = 1,
+	[SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL] = 1,
+	[SITAR_A_CDC_CLSG_GAIN_THRESH_CTL] = 1,
+	[SITAR_A_CDC_CLSG_TIMER_B1_CFG] = 1,
+	[SITAR_A_CDC_CLSG_TIMER_B2_CFG] = 1,
+	[SITAR_A_CDC_CLSG_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_B1_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_B2_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_B3_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_B4_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_B5_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_B6_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_B7_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_B8_CTL] = 1,
+	[SITAR_A_CDC_IIR1_CTL] = 1,
+	[SITAR_A_CDC_IIR1_GAIN_TIMER_CTL] = 1,
+	[SITAR_A_CDC_IIR1_COEF_B1_CTL] = 1,
+	[SITAR_A_CDC_IIR1_COEF_B2_CTL] = 1,
+	[SITAR_A_CDC_IIR1_COEF_B3_CTL] = 1,
+	[SITAR_A_CDC_IIR1_COEF_B4_CTL] = 1,
+	[SITAR_A_CDC_IIR1_COEF_B5_CTL] = 1,
+	[SITAR_A_CDC_TOP_GAIN_UPDATE] = 1,
+	[SITAR_A_CDC_TOP_RDAC_DOUT_CTL] = 1,
+	[SITAR_A_CDC_DEBUG_B1_CTL] = 1,
+	[SITAR_A_CDC_DEBUG_B2_CTL] = 1,
+	[SITAR_A_CDC_DEBUG_B3_CTL] = 1,
+	[SITAR_A_CDC_DEBUG_B4_CTL] = 1,
+	[SITAR_A_CDC_DEBUG_B5_CTL] = 1,
+	[SITAR_A_CDC_DEBUG_B6_CTL] = 1,
+	[SITAR_A_CDC_DEBUG_B7_CTL] = 1,
+	[SITAR_A_CDC_COMP1_B1_CTL] = 1,
+	[SITAR_A_CDC_COMP1_B2_CTL] = 1,
+	[SITAR_A_CDC_COMP1_B3_CTL] = 1,
+	[SITAR_A_CDC_COMP1_B4_CTL] = 1,
+	[SITAR_A_CDC_COMP1_B5_CTL] = 1,
+	[SITAR_A_CDC_COMP1_B6_CTL] = 1,
+	[SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS] = 1,
+	[SITAR_A_CDC_COMP1_FS_CFG] = 1,
+	[SITAR_A_CDC_CONN_RX1_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX1_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX1_B3_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX2_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX2_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX2_B3_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX3_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX3_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX3_B3_CTL] = 1,
+	[SITAR_A_CDC_CONN_ANC_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_ANC_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_TX_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_TX_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_EQ1_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_EQ1_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_EQ1_B3_CTL] = 1,
+	[SITAR_A_CDC_CONN_EQ1_B4_CTL] = 1,
+	[SITAR_A_CDC_CONN_EQ2_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_EQ2_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_EQ2_B3_CTL] = 1,
+	[SITAR_A_CDC_CONN_EQ2_B4_CTL] = 1,
+	[SITAR_A_CDC_CONN_SRC1_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_SRC1_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_SRC2_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_SRC2_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_TX_SB_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_TX_SB_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_TX_SB_B3_CTL] = 1,
+	[SITAR_A_CDC_CONN_TX_SB_B4_CTL] = 1,
+	[SITAR_A_CDC_CONN_TX_SB_B5_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX_SB_B1_CTL] = 1,
+	[SITAR_A_CDC_CONN_RX_SB_B2_CTL] = 1,
+	[SITAR_A_CDC_CONN_CLSG_CTL] = 1,
+	[SITAR_A_CDC_CONN_SPARE] = 1,
+	[SITAR_A_CDC_MBHC_EN_CTL] = 1,
+	[SITAR_A_CDC_MBHC_FIR_B1_CFG] = 1,
+	[SITAR_A_CDC_MBHC_FIR_B2_CFG] = 1,
+	[SITAR_A_CDC_MBHC_TIMER_B1_CTL] = 1,
+	[SITAR_A_CDC_MBHC_TIMER_B2_CTL] = 1,
+	[SITAR_A_CDC_MBHC_TIMER_B3_CTL] = 1,
+	[SITAR_A_CDC_MBHC_TIMER_B4_CTL] = 1,
+	[SITAR_A_CDC_MBHC_TIMER_B5_CTL] = 1,
+	[SITAR_A_CDC_MBHC_TIMER_B6_CTL] = 1,
+	[SITAR_A_CDC_MBHC_B1_STATUS] = 1,
+	[SITAR_A_CDC_MBHC_B2_STATUS] = 1,
+	[SITAR_A_CDC_MBHC_B3_STATUS] = 1,
+	[SITAR_A_CDC_MBHC_B4_STATUS] = 1,
+	[SITAR_A_CDC_MBHC_B5_STATUS] = 1,
+	[SITAR_A_CDC_MBHC_B1_CTL] = 1,
+	[SITAR_A_CDC_MBHC_B2_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B1_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B2_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B3_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B4_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B5_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B6_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B7_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B8_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B9_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B10_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B11_CTL] = 1,
+	[SITAR_A_CDC_MBHC_VOLT_B12_CTL] = 1,
+	[SITAR_A_CDC_MBHC_CLK_CTL] = 1,
+	[SITAR_A_CDC_MBHC_INT_CTL] = 1,
+	[SITAR_A_CDC_MBHC_DEBUG_CTL] = 1,
+	[SITAR_A_CDC_MBHC_SPARE] = 1,
+};
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
new file mode 100644
index 0000000..1d93d7a
--- /dev/null
+++ b/sound/soc/codecs/wcd9304.c
@@ -0,0 +1,3593 @@
+/* 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/wcd9304_registers.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include "wcd9304.h"
+
+#define WCD9304_RATES (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\
+			SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_48000)
+
+#define NUM_DECIMATORS 4
+#define NUM_INTERPOLATORS 3
+#define BITS_PER_REG 8
+#define AIF1_PB 1
+#define AIF1_CAP 2
+#define NUM_CODEC_DAIS 2
+
+struct sitar_codec_dai_data {
+	u32 rate;
+	u32 *ch_num;
+	u32 ch_act;
+	u32 ch_tot;
+};
+#define SITAR_CFILT_FAST_MODE 0x00
+#define SITAR_CFILT_SLOW_MODE 0x40
+
+
+#define SITAR_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
+
+#define SITAR_I2S_MASTER_MODE_MASK 0x08
+
+#define SITAR_OCP_ATTEMPT 1
+
+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 sitar_dai[];
+static int sitar_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event);
+static int sitar_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event);
+
+enum sitar_bandgap_type {
+	SITAR_BANDGAP_OFF = 0,
+	SITAR_BANDGAP_AUDIO_MODE,
+	SITAR_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,
+};
+
+/* 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 sitar_priv_ack_flags {
+	SITAR_HPHL_PA_OFF_ACK = 0,
+	SITAR_HPHR_PA_OFF_ACK,
+	SITAR_HPHL_DAC_OFF_ACK,
+	SITAR_HPHR_DAC_OFF_ACK
+};
+
+struct sitar_priv {
+	struct snd_soc_codec *codec;
+	u32 adc_count;
+	u32 cfilt1_cnt;
+	u32 cfilt2_cnt;
+	u32 cfilt3_cnt;
+	u32 rx_bias_count;
+	enum sitar_bandgap_type bandgap_type;
+	bool mclk_enabled;
+	bool clock_active;
+	bool config_mode_active;
+	bool mbhc_polling_active;
+	bool fake_insert_context;
+	int buttons_pressed;
+
+	struct sitar_mbhc_calibration *calibration;
+
+	struct snd_soc_jack *headset_jack;
+	struct snd_soc_jack *button_jack;
+
+	struct wcd9xxx_pdata *pdata;
+	u32 anc_slot;
+
+	bool no_mic_headset_override;
+	/* Delayed work to report long button press */
+	struct delayed_work btn0_dwork;
+
+	struct mbhc_micbias_regs mbhc_bias_regs;
+	u8 cfilt_k_value;
+	bool mbhc_micbias_switched;
+
+	/* track PA/DAC state */
+	unsigned long hph_pa_dac_state;
+
+	/*track sitar 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 */
+
+	/* pm_cnt holds number of sleep lock holders + 1
+	 * so if pm_cnt is 1 system is sleep-able. */
+	atomic_t pm_cnt;
+	wait_queue_head_t pm_wq;
+
+	u8 hphlocp_cnt; /* headphone left ocp retry */
+	u8 hphrocp_cnt; /* headphone right ocp retry */
+	/* num of slim ports required */
+	struct sitar_codec_dai_data dai[NUM_CODEC_DAIS];
+};
+
+#ifdef CONFIG_DEBUG_FS
+struct sitar_priv *debug_sitar_priv;
+#endif
+
+
+static int sitar_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, SITAR_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_err("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+
+	return 0;
+}
+
+static int sitar_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_write(codec, SITAR_A_RX_EAR_GAIN, ear_pa_gain);
+	return 0;
+}
+
+static int sitar_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, (SITAR_A_CDC_IIR1_CTL + 16 * iir_idx)) &
+		(1 << band_idx);
+
+	pr_err("%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int sitar_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, (SITAR_A_CDC_IIR1_CTL + 16 * iir_idx),
+		(1 << band_idx), (value << band_idx));
+
+	pr_err("%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_update_bits(codec,
+		(SITAR_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		0x1F, band_idx * BAND_MAX + coeff_idx);
+
+	/* Mask bits top 2 bits since they are reserved */
+	return ((snd_soc_read(codec,
+		(SITAR_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24) |
+		(snd_soc_read(codec,
+		(SITAR_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx)) << 16) |
+		(snd_soc_read(codec,
+		(SITAR_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx)) << 8) |
+		(snd_soc_read(codec,
+		(SITAR_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx)))) &
+		0x3FFFFFFF;
+}
+
+static int sitar_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_err("%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_update_bits(codec,
+		(SITAR_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		0x1F, band_idx * BAND_MAX + coeff_idx);
+
+	/* Mask top 2 bits, 7-8 are reserved */
+	snd_soc_update_bits(codec,
+		(SITAR_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+		0x3F, (value >> 24) & 0x3F);
+
+	/* Isolate 8bits at a time */
+	snd_soc_update_bits(codec,
+		(SITAR_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx),
+		0xFF, (value >> 16) & 0xFF);
+
+	snd_soc_update_bits(codec,
+		(SITAR_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx),
+		0xFF, (value >> 8) & 0xFF);
+
+	snd_soc_update_bits(codec,
+		(SITAR_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx),
+		0xFF, value & 0xFF);
+}
+
+static int sitar_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_err("%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 const char *sitar_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum sitar_ear_pa_gain_enum[] = {
+		SOC_ENUM_SINGLE_EXT(2, sitar_ear_pa_gain_text),
+};
+
+/*cut of frequency for high pass filter*/
+static const char *cf_text[] = {
+	"MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
+};
+
+static const struct soc_enum cf_dec1_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_rxmix1_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_RX1_B4_CTL, 1, 3, cf_text);
+
+static const struct snd_kcontrol_new sitar_snd_controls[] = {
+
+	SOC_ENUM_EXT("EAR PA Gain", sitar_ear_pa_gain_enum[0],
+		sitar_pa_gain_get, sitar_pa_gain_put),
+
+	SOC_SINGLE_TLV("LINEOUT1 Volume", SITAR_A_RX_LINE_1_GAIN, 0, 12, 1,
+		line_gain),
+	SOC_SINGLE_TLV("LINEOUT2 Volume", SITAR_A_RX_LINE_2_GAIN, 0, 12, 1,
+		line_gain),
+
+	SOC_SINGLE_TLV("HPHL Volume", SITAR_A_RX_HPH_L_GAIN, 0, 12, 1,
+		line_gain),
+	SOC_SINGLE_TLV("HPHR Volume", SITAR_A_RX_HPH_R_GAIN, 0, 12, 1,
+		line_gain),
+
+	SOC_SINGLE_S8_TLV("RX1 Digital Volume", SITAR_A_CDC_RX1_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+
+	SOC_SINGLE_S8_TLV("DEC1 Volume", SITAR_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", SITAR_A_CDC_IIR1_GAIN_B1_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", SITAR_A_CDC_IIR1_GAIN_B2_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", SITAR_A_CDC_IIR1_GAIN_B3_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", SITAR_A_CDC_IIR1_GAIN_B4_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_TLV("ADC1 Volume", SITAR_A_TX_1_2_EN, 5, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC2 Volume", SITAR_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+
+	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_ENUM("TX1 HPF cut off", cf_dec1_enum),
+
+	SOC_SINGLE("TX1 HPF Switch", SITAR_A_CDC_TX1_MUX_CTL, 3, 1, 0),
+
+	SOC_SINGLE("RX1 HPF Switch", SITAR_A_CDC_RX1_B5_CTL, 2, 1, 0),
+
+	SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
+
+	SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+	sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+
+	SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+};
+
+static const char *rx_mix1_text[] = {
+	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
+		"RX5"
+};
+
+static const char *rx_dac1_text[] = {
+	"ZERO", "RX1", "RX2"
+};
+
+static const char *rx_dac2_text[] = {
+	"ZERO", "RX1",
+};
+
+static const char *rx_dac3_text[] = {
+	"ZERO", "RX1", "RX1_INV", "RX2"
+};
+
+static const char *rx_dac4_text[] = {
+	"ZERO", "ON"
+};
+
+static const char *sb_tx1_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC1"
+};
+
+static const char *sb_tx2_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC2"
+};
+
+static const char *sb_tx3_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC3"
+};
+
+static const char *sb_tx5_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC5"
+};
+
+static const char *dec1_mux_text[] = {
+	"ZERO", "DMIC1", "ADC1", "ADC2", "ADC3", "MBADC", "DMIC4", "ANCFB1",
+};
+
+static const char *dec2_mux_text[] = {
+	"ZERO", "DMIC2", "ADC1", "ADC2", "ADC3", "MBADC", "DMIC3", "ANCFB2",
+};
+
+static const char *dec3_mux_text[] = {
+	"ZERO", "DMIC2", "DMIC3", "DMIC4", "ADC1", "ADC2", "ADC3", "MBADC",
+};
+
+static const char *dec4_mux_text[] = {
+	"ZERO", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "ADC1", "ADC2", "ADC3",
+};
+
+static const char *iir1_inp1_text[] = {
+	"ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "ZERO", "ZERO", "ZERO",
+	"ZERO", "ZERO", "ZERO", "RX1", "RX2", "RX3", "RX4", "RX5",
+};
+
+static const struct soc_enum rx_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX1_B1_CTL, 0, 10, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX1_B1_CTL, 4, 10, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX2_B1_CTL, 0, 10, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX2_B1_CTL, 4, 10, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX3_B1_CTL, 0, 10, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX3_B1_CTL, 4, 10, rx_mix1_text);
+
+static const struct soc_enum rx_dac1_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_TOP_RDAC_DOUT_CTL, 6, 3, rx_dac1_text);
+
+static const struct soc_enum rx_dac2_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_TOP_RDAC_DOUT_CTL, 4, 2, rx_dac2_text);
+
+static const struct soc_enum rx_dac3_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_TOP_RDAC_DOUT_CTL, 2, 4, rx_dac3_text);
+
+static const struct soc_enum rx_dac4_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_TOP_RDAC_DOUT_CTL, 0, 2, rx_dac4_text);
+
+static const struct soc_enum sb_tx5_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
+
+static const struct soc_enum sb_tx3_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
+
+static const struct soc_enum sb_tx2_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
+
+static const struct soc_enum sb_tx1_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
+
+static const struct soc_enum dec1_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 0, 8, dec1_mux_text);
+
+static const struct soc_enum dec2_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 2, 8, dec2_mux_text);
+
+static const struct soc_enum dec3_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 4, 8, dec3_mux_text);
+
+static const struct soc_enum dec4_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 6, 8, dec4_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);
+
+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 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 rx_dac1_mux =
+	SOC_DAPM_ENUM("RX1 DAC Mux", rx_dac1_enum);
+
+static const struct snd_kcontrol_new rx_dac2_mux =
+	SOC_DAPM_ENUM("RX2 DAC Mux", rx_dac2_enum);
+
+static const struct snd_kcontrol_new rx_dac3_mux =
+	SOC_DAPM_ENUM("RX3 DAC Mux", rx_dac3_enum);
+
+static const struct snd_kcontrol_new rx_dac4_mux =
+	SOC_DAPM_ENUM("RX4 DAC Mux", rx_dac4_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_tx3_mux =
+	SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_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_tx1_mux =
+	SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
+
+static const struct snd_kcontrol_new dec1_mux =
+	SOC_DAPM_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+
+static const struct snd_kcontrol_new dec2_mux =
+	SOC_DAPM_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+
+static const struct snd_kcontrol_new dec3_mux =
+	SOC_DAPM_ENUM("DEC3 MUX Mux", dec3_mux_enum);
+
+static const struct snd_kcontrol_new dec4_mux =
+	SOC_DAPM_ENUM("DEC4 MUX Mux", dec4_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 dac1_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SITAR_A_RX_EAR_EN, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new hphl_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SITAR_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
+};
+
+static void sitar_codec_enable_adc_block(struct snd_soc_codec *codec,
+	int enable)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	pr_err("%s %d\n", __func__, enable);
+
+	if (enable) {
+		sitar->adc_count++;
+		snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0xE0);
+
+	} else {
+		sitar->adc_count--;
+		if (!sitar->adc_count) {
+			if (!sitar->mbhc_polling_active)
+				snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS,
+					0xE0, 0x0);
+		}
+	}
+}
+
+static int sitar_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;
+
+	pr_err("%s %d\n", __func__, event);
+
+	if (w->reg == SITAR_A_TX_1_2_EN)
+		adc_reg = SITAR_A_TX_1_2_TEST_CTL;
+	else {
+		pr_err("%s: Error, invalid adc register\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		sitar_codec_enable_adc_block(codec, 1);
+		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);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		sitar_codec_enable_adc_block(codec, 0);
+		break;
+	}
+	return 0;
+}
+
+static int sitar_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_err("%s %d %s\n", __func__, event, w->name);
+
+	switch (w->shift) {
+	case 0:
+		lineout_gain_reg = SITAR_A_RX_LINE_1_GAIN;
+		break;
+	case 1:
+		lineout_gain_reg = SITAR_A_RX_LINE_2_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_err("%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 sitar_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	u16 tx_mux_ctl_reg, tx_dmic_ctl_reg;
+	u8 dmic_clk_sel, dmic_clk_en;
+	unsigned int dmic;
+	int ret;
+
+	ret = kstrtouint(strpbrk(w->name, "12"), 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_sel = 0x02;
+		dmic_clk_en = 0x01;
+		break;
+	case 3:
+	case 4:
+		dmic_clk_sel = 0x08;
+		dmic_clk_en = 0x04;
+		break;
+
+		break;
+
+	default:
+		pr_err("%s: Invalid DMIC Selection\n", __func__);
+		return -EINVAL;
+	}
+
+	tx_mux_ctl_reg = SITAR_A_CDC_TX1_MUX_CTL + 8 * (dmic - 1);
+	tx_dmic_ctl_reg = SITAR_A_CDC_TX1_DMIC_CTL + 8 * (dmic - 1);
+
+	pr_err("%s %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, 0x1);
+
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_DMIC_CTL,
+				dmic_clk_sel, dmic_clk_sel);
+
+		snd_soc_update_bits(codec, tx_dmic_ctl_reg, 0x1, 0x1);
+
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_DMIC_CTL,
+				dmic_clk_en, dmic_clk_en);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_DMIC_CTL,
+				dmic_clk_en, 0);
+		break;
+	}
+	return 0;
+}
+
+
+static void sitar_codec_disable_button_presses(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B4_CTL, 0x80);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B3_CTL, 0x00);
+}
+
+static void sitar_codec_start_hs_polling(struct snd_soc_codec *codec)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x84);
+	wcd9xxx_enable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+	if (!sitar->no_mic_headset_override) {
+		wcd9xxx_enable_irq(codec->control_data,
+				SITAR_IRQ_MBHC_POTENTIAL);
+		wcd9xxx_enable_irq(codec->control_data,
+				SITAR_IRQ_MBHC_RELEASE);
+	} else {
+		sitar_codec_disable_button_presses(codec);
+	}
+}
+
+static void sitar_codec_pause_hs_polling(struct snd_soc_codec *codec)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+	if (!sitar->no_mic_headset_override) {
+		wcd9xxx_disable_irq(codec->control_data,
+			SITAR_IRQ_MBHC_POTENTIAL);
+		wcd9xxx_disable_irq(codec->control_data,
+			SITAR_IRQ_MBHC_RELEASE);
+	}
+}
+
+static void sitar_codec_switch_cfilt_mode(struct snd_soc_codec *codec,
+		int mode)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	u8 reg_mode_val, cur_mode_val;
+	bool mbhc_was_polling = false;
+
+	if (mode)
+		reg_mode_val = SITAR_CFILT_FAST_MODE;
+	else
+		reg_mode_val = SITAR_CFILT_SLOW_MODE;
+
+	cur_mode_val = snd_soc_read(codec,
+			sitar->mbhc_bias_regs.cfilt_ctl) & 0x40;
+
+	if (cur_mode_val != reg_mode_val) {
+		if (sitar->mbhc_polling_active) {
+			sitar_codec_pause_hs_polling(codec);
+			mbhc_was_polling = true;
+		}
+		snd_soc_update_bits(codec,
+			sitar->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
+		if (mbhc_was_polling)
+			sitar_codec_start_hs_polling(codec);
+		pr_err("%s: CFILT mode change (%x to %x)\n", __func__,
+			cur_mode_val, reg_mode_val);
+	} else {
+		pr_err("%s: CFILT Value is already %x\n",
+			__func__, cur_mode_val);
+	}
+}
+
+static void sitar_codec_update_cfilt_usage(struct snd_soc_codec *codec,
+					  u8 cfilt_sel, int inc)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	u32 *cfilt_cnt_ptr = NULL;
+	u16 micb_cfilt_reg;
+
+	switch (cfilt_sel) {
+	case SITAR_CFILT1_SEL:
+		cfilt_cnt_ptr = &sitar->cfilt1_cnt;
+		micb_cfilt_reg = SITAR_A_MICB_CFILT_1_CTL;
+		break;
+	case SITAR_CFILT2_SEL:
+		cfilt_cnt_ptr = &sitar->cfilt2_cnt;
+		micb_cfilt_reg = SITAR_A_MICB_CFILT_2_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 == sitar->mbhc_bias_regs.cfilt_sel)
+				sitar_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 == sitar->mbhc_bias_regs.cfilt_sel)
+				sitar_codec_switch_cfilt_mode(codec, 1);
+		}
+	}
+}
+
+static int sitar_find_k_value(unsigned int ldoh_v, unsigned int cfilt_mv)
+{
+	int rc = -EINVAL;
+	unsigned min_mv, max_mv;
+
+	switch (ldoh_v) {
+	case SITAR_LDOH_1P95_V:
+		min_mv = 160;
+		max_mv = 1800;
+		break;
+	case SITAR_LDOH_2P35_V:
+		min_mv = 200;
+		max_mv = 2200;
+		break;
+	case SITAR_LDOH_2P75_V:
+		min_mv = 240;
+		max_mv = 2600;
+		break;
+	case SITAR_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 sitar_is_hph_pa_on(struct snd_soc_codec *codec)
+{
+	u8 hph_reg_val = 0;
+	hph_reg_val = snd_soc_read(codec, SITAR_A_RX_HPH_CNP_EN);
+
+	return (hph_reg_val & 0x30) ? true : false;
+}
+
+static bool sitar_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,
+					  SITAR_A_RX_HPH_L_DAC_CTL);
+	else
+		hph_reg_val = snd_soc_read(codec,
+					  SITAR_A_RX_HPH_R_DAC_CTL);
+
+	return (hph_reg_val & 0xC0) ? true : false;
+}
+
+static void sitar_codec_switch_micbias(struct snd_soc_codec *codec,
+	int vddio_switch)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	int cfilt_k_val;
+	bool mbhc_was_polling =  false;
+
+	switch (vddio_switch) {
+	case 1:
+		if (sitar->mbhc_polling_active) {
+
+			sitar_codec_pause_hs_polling(codec);
+			/* Enable Mic Bias switch to VDDIO */
+			sitar->cfilt_k_value = snd_soc_read(codec,
+					sitar->mbhc_bias_regs.cfilt_val);
+			cfilt_k_val = sitar_find_k_value(
+					sitar->pdata->micbias.ldoh_v, 1800);
+			snd_soc_update_bits(codec,
+				sitar->mbhc_bias_regs.cfilt_val,
+				0xFC, (cfilt_k_val << 2));
+
+			snd_soc_update_bits(codec,
+				sitar->mbhc_bias_regs.mbhc_reg,	0x80, 0x80);
+			snd_soc_update_bits(codec,
+				sitar->mbhc_bias_regs.mbhc_reg,	0x10, 0x00);
+			sitar_codec_start_hs_polling(codec);
+
+			sitar->mbhc_micbias_switched = true;
+			pr_err("%s: Enabled MBHC Mic bias to VDDIO Switch\n",
+				__func__);
+		}
+		break;
+
+	case 0:
+		if (sitar->mbhc_micbias_switched) {
+			if (sitar->mbhc_polling_active) {
+				sitar_codec_pause_hs_polling(codec);
+				mbhc_was_polling = true;
+			}
+			/* Disable Mic Bias switch to VDDIO */
+			if (sitar->cfilt_k_value != 0)
+				snd_soc_update_bits(codec,
+					sitar->mbhc_bias_regs.cfilt_val, 0XFC,
+					sitar->cfilt_k_value);
+			snd_soc_update_bits(codec,
+				sitar->mbhc_bias_regs.mbhc_reg,	0x80, 0x00);
+			snd_soc_update_bits(codec,
+				sitar->mbhc_bias_regs.mbhc_reg,	0x10, 0x00);
+
+			if (mbhc_was_polling)
+				sitar_codec_start_hs_polling(codec);
+
+			sitar->mbhc_micbias_switched = false;
+			pr_err("%s: Disabled MBHC Mic bias to VDDIO Switch\n",
+				__func__);
+		}
+		break;
+	}
+}
+
+static int sitar_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct sitar_priv *sitar = 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";
+
+	pr_err("%s %d\n", __func__, event);
+	switch (w->reg) {
+	case SITAR_A_MICB_1_CTL:
+		micb_int_reg = SITAR_A_MICB_1_INT_RBIAS;
+		cfilt_sel_val = sitar->pdata->micbias.bias1_cfilt_sel;
+		micb_line = SITAR_MICBIAS1;
+		break;
+	case SITAR_A_MICB_2_CTL:
+		micb_int_reg = SITAR_A_MICB_2_INT_RBIAS;
+		cfilt_sel_val = sitar->pdata->micbias.bias2_cfilt_sel;
+		micb_line = SITAR_MICBIAS2;
+		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 == sitar->mbhc_bias_regs.ctl_reg)
+				&& sitar->mbhc_micbias_switched)
+			sitar_codec_switch_micbias(codec, 0);
+
+		snd_soc_update_bits(codec, w->reg, 0x1E, 0x0A);
+		sitar_codec_update_cfilt_usage(codec, cfilt_sel_val, 1);
+
+		if (strnstr(w->name, internal1_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0xFF, 0xA4);
+		else if (strnstr(w->name, internal2_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (sitar->mbhc_polling_active &&
+			(sitar->calibration->bias == micb_line)) {
+			sitar_codec_pause_hs_polling(codec);
+			sitar_codec_start_hs_polling(codec);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+
+		if ((w->reg == sitar->mbhc_bias_regs.ctl_reg)
+				&& sitar_is_hph_pa_on(codec))
+			sitar_codec_switch_micbias(codec, 1);
+
+		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);
+		sitar_codec_update_cfilt_usage(codec, cfilt_sel_val, 0);
+		break;
+	}
+
+	return 0;
+}
+
+static int sitar_codec_enable_dec(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	u16 dec_reset_reg;
+
+	pr_err("%s %d\n", __func__, event);
+
+	if (w->reg == SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL)
+		dec_reset_reg = SITAR_A_CDC_CLK_TX_RESET_B1_CTL;
+	else {
+		pr_err("%s: Error, incorrect dec\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		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);
+		break;
+	}
+	return 0;
+}
+
+static int sitar_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_err("%s %d %s\n", __func__, event, w->name);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_RX_RESET_CTL,
+			1 << w->shift, 1 << w->shift);
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_RX_RESET_CTL,
+			1 << w->shift, 0x0);
+		break;
+	}
+	return 0;
+}
+
+static int sitar_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);
+		pr_debug("LDO_H\n");
+		break;
+	}
+	return 0;
+}
+
+static void sitar_enable_rx_bias(struct snd_soc_codec *codec, u32  enable)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	if (enable) {
+		sitar->rx_bias_count++;
+		if (sitar->rx_bias_count == 1)
+			snd_soc_update_bits(codec, SITAR_A_RX_COM_BIAS,
+				0x80, 0x80);
+	} else {
+		sitar->rx_bias_count--;
+		if (!sitar->rx_bias_count)
+			snd_soc_update_bits(codec, SITAR_A_RX_COM_BIAS,
+				0x80, 0x00);
+	}
+}
+
+static int sitar_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_err("%s %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		sitar_enable_rx_bias(codec, 1);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		sitar_enable_rx_bias(codec, 0);
+		break;
+	}
+	return 0;
+}
+static int sitar_hphr_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_err("%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 sitar_snd_soc_jack_report(struct sitar_priv *sitar,
+				     struct snd_soc_jack *jack, int status,
+				     int mask)
+{
+	/* XXX: wake_lock_timeout()? */
+	snd_soc_jack_report(jack, status, mask);
+}
+
+static void hphocp_off_report(struct sitar_priv *sitar,
+	u32 jack_status, int irq)
+{
+	struct snd_soc_codec *codec;
+
+	if (sitar) {
+		pr_info("%s: clear ocp status %x\n", __func__, jack_status);
+		codec = sitar->codec;
+		sitar->hph_status &= ~jack_status;
+		if (sitar->headset_jack)
+			sitar_snd_soc_jack_report(sitar, sitar->headset_jack,
+						 sitar->hph_status,
+						 SITAR_JACK_MASK);
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+		0x00);
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+		0x10);
+		/* reset retry counter as PA is turned off signifying
+		* start of new OCP detection session
+		*/
+		if (SITAR_IRQ_HPH_PA_OCPL_FAULT)
+			sitar->hphlocp_cnt = 0;
+		else
+			sitar->hphrocp_cnt = 0;
+		wcd9xxx_enable_irq(codec->control_data, irq);
+	} else {
+		pr_err("%s: Bad sitar private data\n", __func__);
+	}
+}
+
+static void hphlocp_off_report(struct work_struct *work)
+{
+	struct sitar_priv *sitar = container_of(work, struct sitar_priv,
+		hphlocp_work);
+	hphocp_off_report(sitar, SND_JACK_OC_HPHL, SITAR_IRQ_HPH_PA_OCPL_FAULT);
+}
+
+static void hphrocp_off_report(struct work_struct *work)
+{
+	struct sitar_priv *sitar = container_of(work, struct sitar_priv,
+		hphrocp_work);
+	hphocp_off_report(sitar, SND_JACK_OC_HPHR, SITAR_IRQ_HPH_PA_OCPR_FAULT);
+}
+
+static int sitar_hph_pa_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	u8 mbhc_micb_ctl_val;
+	pr_err("%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mbhc_micb_ctl_val = snd_soc_read(codec,
+				sitar->mbhc_bias_regs.ctl_reg);
+
+		if (!(mbhc_micb_ctl_val & 0x80)
+				&& !sitar->mbhc_micbias_switched)
+			sitar_codec_switch_micbias(codec, 1);
+
+		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(SITAR_HPHL_PA_OFF_ACK,
+				 &sitar->hph_pa_dac_state);
+			clear_bit(SITAR_HPHL_DAC_OFF_ACK,
+				 &sitar->hph_pa_dac_state);
+			if (sitar->hph_status & SND_JACK_OC_HPHL)
+				schedule_work(&sitar->hphlocp_work);
+		} else if (w->shift == 4) {
+			clear_bit(SITAR_HPHR_PA_OFF_ACK,
+				 &sitar->hph_pa_dac_state);
+			clear_bit(SITAR_HPHR_DAC_OFF_ACK,
+				 &sitar->hph_pa_dac_state);
+			if (sitar->hph_status & SND_JACK_OC_HPHR)
+				schedule_work(&sitar->hphrocp_work);
+		}
+
+		if (sitar->mbhc_micbias_switched)
+			sitar_codec_switch_micbias(codec, 0);
+
+		pr_err("%s: sleep 10 ms after %s PA disable.\n", __func__,
+				w->name);
+		usleep_range(10000, 10000);
+
+		break;
+	}
+	return 0;
+}
+
+static void sitar_get_mbhc_micbias_regs(struct snd_soc_codec *codec,
+		struct mbhc_micbias_regs *micbias_regs)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	struct sitar_mbhc_calibration *calibration = sitar->calibration;
+	unsigned int cfilt;
+
+	switch (calibration->bias) {
+	case SITAR_MICBIAS1:
+		cfilt = sitar->pdata->micbias.bias1_cfilt_sel;
+		micbias_regs->mbhc_reg = SITAR_A_MICB_1_MBHC;
+		micbias_regs->int_rbias = SITAR_A_MICB_1_INT_RBIAS;
+		micbias_regs->ctl_reg = SITAR_A_MICB_1_CTL;
+		break;
+	case SITAR_MICBIAS2:
+		cfilt = sitar->pdata->micbias.bias2_cfilt_sel;
+		micbias_regs->mbhc_reg = SITAR_A_MICB_2_MBHC;
+		micbias_regs->int_rbias = SITAR_A_MICB_2_INT_RBIAS;
+		micbias_regs->ctl_reg = SITAR_A_MICB_2_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 SITAR_CFILT1_SEL:
+		micbias_regs->cfilt_val = SITAR_A_MICB_CFILT_1_VAL;
+		micbias_regs->cfilt_ctl = SITAR_A_MICB_CFILT_1_CTL;
+		break;
+	case SITAR_CFILT2_SEL:
+		micbias_regs->cfilt_val = SITAR_A_MICB_CFILT_2_VAL;
+		micbias_regs->cfilt_ctl = SITAR_A_MICB_CFILT_2_CTL;
+		break;
+	}
+}
+
+static int sitar_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_err("%s %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x01,
+			0x01);
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLSG_CTL, 0x08, 0x08);
+		usleep_range(200, 200);
+		snd_soc_update_bits(codec, SITAR_A_CP_STATIC, 0x10, 0x00);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
+			0x10);
+		usleep_range(20, 20);
+		snd_soc_update_bits(codec, SITAR_A_CP_STATIC, 0x08, 0x08);
+		snd_soc_update_bits(codec, SITAR_A_CP_STATIC, 0x10, 0x10);
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLSG_CTL, 0x08, 0x00);
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x01,
+			0x00);
+		snd_soc_update_bits(codec, SITAR_A_CP_STATIC, 0x08, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget sitar_dapm_i2s_widgets[] = {
+	SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", SITAR_A_CDC_CLK_RX_I2S_CTL,
+	4, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", SITAR_A_CDC_CLK_TX_I2S_CTL, 4,
+	0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_widget sitar_dapm_widgets[] = {
+	/*RX stuff */
+	SND_SOC_DAPM_OUTPUT("EAR"),
+
+	SND_SOC_DAPM_PGA("EAR PA", SITAR_A_RX_EAR_EN, 4, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("DAC1", SITAR_A_RX_EAR_EN, 6, 0, dac1_switch,
+		ARRAY_SIZE(dac1_switch)),
+	SND_SOC_DAPM_SUPPLY("EAR DRIVER", SITAR_A_RX_EAR_EN, 3, 0, NULL, 0),
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+				0, sitar_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, sitar_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SLIM RX5", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+	/* Headphone */
+	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+	SND_SOC_DAPM_PGA_E("HPHL", SITAR_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+		sitar_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER("HPHL DAC", SITAR_A_RX_HPH_L_DAC_CTL, 7, 0,
+		hphl_switch, ARRAY_SIZE(hphl_switch)),
+
+	SND_SOC_DAPM_PGA_E("HPHR", SITAR_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+		sitar_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, SITAR_A_RX_HPH_R_DAC_CTL, 7, 0,
+		sitar_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_PGA_E("LINEOUT1 PA", SITAR_A_RX_LINE_CNP_EN, 0, 0, NULL,
+			0, sitar_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", SITAR_A_RX_LINE_CNP_EN, 1, 0, NULL,
+			0, sitar_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("RX1 MIX1", SITAR_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
+		0, sitar_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER_E("RX2 MIX1", SITAR_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
+		0, sitar_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER_E("RX3 MIX1", SITAR_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+		0, sitar_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX("DAC1 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac1_mux),
+	SND_SOC_DAPM_MUX("DAC2 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac2_mux),
+	SND_SOC_DAPM_MUX("DAC3 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac3_mux),
+	SND_SOC_DAPM_MUX("DAC4 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac4_mux),
+
+	SND_SOC_DAPM_MIXER("RX1 CHAIN", SITAR_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX2 CHAIN", SITAR_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX3 CHAIN", SITAR_A_CDC_RX3_B6_CTL, 5, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp2_mux),
+
+	SND_SOC_DAPM_SUPPLY("CP", SITAR_A_CP_EN, 0, 0,
+		sitar_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,
+		sitar_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY("LDO_H", SITAR_A_LDO_H_MODE_1, 7, 0,
+		sitar_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+	/* TX */
+	SND_SOC_DAPM_SUPPLY("CDC_CONN", SITAR_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+		0),
+	SND_SOC_DAPM_INPUT("AMIC1"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SITAR_A_MICB_1_CTL, 7, 0,
+		sitar_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", SITAR_A_MICB_1_CTL, 7, 0,
+		sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC2"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SITAR_A_MICB_2_CTL, 7, 0,
+		sitar_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", SITAR_A_MICB_2_CTL, 7, 0,
+		sitar_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", SITAR_A_MICB_2_CTL, 7, 0,
+		sitar_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, SITAR_A_TX_1_2_EN, 7, 0,
+		sitar_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC2", NULL, SITAR_A_TX_1_2_EN, 3, 0,
+		sitar_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC1 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+		&dec1_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	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),
+
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX1", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+				0, sitar_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX2", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+				0, sitar_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+				0, sitar_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("DEC2 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+		&dec2_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MUX_E("DEC3 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+		&dec3_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+	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),
+
+	/* Digital Mic Inputs */
+	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		sitar_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,
+		sitar_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,
+		sitar_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,
+		sitar_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", SITAR_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* Earpiece (RX MIX1) */
+	{"EAR", NULL, "EAR PA"},
+	{"EAR PA", "NULL", "DAC1"},
+	{"DAC1", "Switch", "DAC1 MUX"},
+	{"DAC1", NULL, "CP"},
+	{"DAC1", NULL, "EAR DRIVER"},
+
+	{"LINEOUT1", NULL, "CP"},
+	{"LINEOUT2", NULL, "CP"},
+
+	{"LINEOUT2", NULL, "LINEOUT2 PA"},
+	{"LINEOUT2 PA", "NULL", "DAC3 MUX"},
+
+	{"LINEOUT1", NULL, "LINEOUT1 PA"},
+	{"LINEOUT1 PA", "NULL", "DAC2 MUX"},
+
+	/* Headset (RX MIX1 and RX MIX2) */
+	{"HEADPHONE", NULL, "HPHL"},
+	{"HEADPHONE", NULL, "HPHR"},
+
+	{"HPHL", NULL, "HPHL DAC"},
+	{"HPHL DAC", NULL, "DAC4 MUX"},
+	{"HPHR", NULL, "HPHR DAC"},
+	{"HPHL DAC", NULL, "RX3 MIX1"},
+
+	{"DAC1 MUX", "RX1", "RX1 CHAIN"},
+	{"DAC2 MUX", "RX1", "RX1 CHAIN"},
+	{"DAC3 MUX", "RX1", "RX1 CHAIN"},
+	{"DAC3 MUX", "RX1_INV", "RX1 CHAIN"},
+	{"DAC3 MUX", "RX2", "RX2 MIX1"},
+	{"DAC4 MUX", "ON", "RX2 MIX1"},
+
+	{"RX1 CHAIN", NULL, "RX1 MIX1"},
+
+	{"CP", NULL, "RX_BIAS"},
+
+	{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
+	{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
+	{"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
+	{"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
+	{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+	{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+
+	/* SLIMBUS Connections */
+
+	/* Slimbus port 5 is non functional in Sitar 1.0 */
+	{"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", "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", "IIR1", "IIR1"},
+	{"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", "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", "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", "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", "IIR1", "IIR1"},
+
+
+	/* TX */
+	{"SLIM TX1", NULL, "SLIM TX1 MUX"},
+	{"MIC BIAS2 Internal1", NULL, "DEC1 MUX"},
+
+	{"SLIM TX2", NULL, "SLIM TX2 MUX"},
+	{"MIC BIAS2 Internal1", NULL, "DEC1 MUX"},
+
+	{"SLIM TX1", NULL, "SLIM TX1 MUX"},
+	{"SLIM TX2", NULL, "SLIM TX2 MUX"},
+	{"SLIM TX3", NULL, "SLIM TX3 MUX"},
+
+	{"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
+
+	/* Decimator Inputs */
+	{"DEC1 MUX", "DMIC1", "DMIC1"},
+	{"DEC1 MUX", "DMIC4", "DMIC4"},
+	{"DEC1 MUX", "ADC1", "ADC1"},
+	{"DEC1 MUX", "ADC2", "ADC2"},
+
+	{"DEC2 MUX", "DMIC2", "DMIC2"},
+	{"DEC2 MUX", "DMIC3", "DMIC3"},
+	{"DEC2 MUX", "ADC1", "ADC1"},
+	{"DEC2 MUX", "ADC2", "ADC2"},
+
+	{"DEC3 MUX", "DMIC3", "DMIC3"},
+	{"DEC3 MUX", "ADC1", "ADC1"},
+	{"DEC3 MUX", "ADC2", "ADC2"},
+	{"DEC3 MUX", "DMIC2", "DMIC2"},
+	{"DEC3 MUX", "DMIC3", "DMIC4"},
+
+	{"DEC4 MUX", "DMIC4", "DMIC4"},
+	{"DEC4 MUX", "ADC1", "ADC1"},
+	{"DEC4 MUX", "ADC2", "ADC2"},
+	{"DEC4 MUX", "DMIC3", "DMIC3"},
+	{"DEC4 MUX", "DMIC2", "DMIC2"},
+	{"DEC4 MUX", "DMIC1", "DMIC1"},
+
+	/* ADC Connections */
+	{"ADC1", NULL, "AMIC1"},
+	{"ADC2", NULL, "AMIC2"},
+
+	/* IIR */
+	{"IIR1", NULL, "IIR1 INP1 MUX"},
+	{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
+	{"MIC BIAS1 Internal1", NULL, "LDO_H"},
+	{"MIC BIAS1 External", NULL, "LDO_H"},
+	{"MIC BIAS2 Internal1", NULL, "LDO_H"},
+	{"MIC BIAS2 External", NULL, "LDO_H"},
+};
+
+static int sitar_readable(struct snd_soc_codec *ssc, unsigned int reg)
+{
+	return sitar_reg_readable[reg];
+}
+
+static int sitar_volatile(struct snd_soc_codec *ssc, unsigned int reg)
+{
+	/* Registers lower than 0x100 are top level registers which can be
+	* written by the Sitar core driver.
+	*/
+
+	if ((reg >= SITAR_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
+		return 1;
+
+	/* IIR Coeff registers are not cacheable */
+	if ((reg >= SITAR_A_CDC_IIR1_COEF_B1_CTL) &&
+		(reg <= SITAR_A_CDC_IIR1_COEF_B5_CTL))
+		return 1;
+
+	return 0;
+}
+
+#define SITAR_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+static int sitar_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int value)
+{
+	int ret;
+
+	BUG_ON(reg > SITAR_MAX_REGISTER);
+
+	if (!sitar_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 sitar_read(struct snd_soc_codec *codec,
+				unsigned int reg)
+{
+	unsigned int val;
+	int ret;
+
+	BUG_ON(reg > SITAR_MAX_REGISTER);
+
+	if (!sitar_volatile(codec, reg) && sitar_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 void sitar_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
+{
+
+	snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x0C, 0x61);
+	snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x80);
+	usleep_range(1000, 1000);
+	snd_soc_write(codec, SITAR_A_BIAS_REF_CTL, 0x1C);
+	snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
+		0x80);
+	snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x04,
+		0x04);
+	snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x01,
+		0x01);
+	usleep_range(1000, 1000);
+	snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
+		0x00);
+}
+
+static void sitar_codec_enable_bandgap(struct snd_soc_codec *codec,
+	enum sitar_bandgap_type choice)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	/* TODO lock resources accessed by audio streams and threaded
+	* interrupt handlers
+	*/
+
+	pr_err("%s, choice is %d, current is %d\n", __func__, choice,
+		sitar->bandgap_type);
+
+	if (sitar->bandgap_type == choice)
+		return;
+
+	if ((sitar->bandgap_type == SITAR_BANDGAP_OFF) &&
+		(choice == SITAR_BANDGAP_AUDIO_MODE)) {
+		sitar_codec_enable_audio_mode_bandgap(codec);
+	} else if (choice == SITAR_BANDGAP_MBHC_MODE) {
+		snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x2,
+			0x2);
+		snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
+			0x80);
+		snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x4,
+			0x4);
+		snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x01,
+			0x1);
+		usleep_range(1000, 1000);
+		snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
+			0x00);
+	} else if ((sitar->bandgap_type == SITAR_BANDGAP_MBHC_MODE) &&
+		(choice == SITAR_BANDGAP_AUDIO_MODE)) {
+		snd_soc_write(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x50);
+		usleep_range(100, 100);
+		sitar_codec_enable_audio_mode_bandgap(codec);
+	} else if (choice == SITAR_BANDGAP_OFF) {
+		snd_soc_write(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x50);
+	} else {
+		pr_err("%s: Error, Invalid bandgap settings\n", __func__);
+	}
+	sitar->bandgap_type = choice;
+}
+
+
+static int sitar_codec_enable_clock_block(struct snd_soc_codec *codec,
+	int config_mode)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	pr_err("%s\n", __func__);
+
+	if (config_mode) {
+		snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x00);
+		snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x02);
+		snd_soc_write(codec, SITAR_A_CLK_BUFF_EN1, 0x0D);
+		usleep_range(1000, 1000);
+	} else
+		snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x08, 0x00);
+
+
+	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x05);
+	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x00);
+	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x04);
+	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
+	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x04, 0x04);
+	usleep_range(50, 50);
+	sitar->clock_active = true;
+	return 0;
+}
+static void sitar_codec_disable_clock_block(struct snd_soc_codec *codec)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	pr_err("%s\n", __func__);
+	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x04, 0x04);
+	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
+	ndelay(160);
+	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
+	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x00);
+	sitar->clock_active = false;
+}
+
+static void sitar_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
+{
+	/* TODO store register values in calibration */
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B5_CTL, 0x20);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B6_CTL, 0xFF);
+
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B10_CTL, 0xFF);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B9_CTL, 0x20);
+
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B4_CTL, 0xF8);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B3_CTL, 0xEE);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B2_CTL, 0xFC);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B1_CTL, 0xCE);
+
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B1_CTL, 3);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B2_CTL, 9);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B3_CTL, 30);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B6_CTL, 120);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_TIMER_B1_CTL, 0x78, 0x58);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_B2_CTL, 11);
+}
+
+static int sitar_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	pr_err("%s(): substream = %s  stream = %d\n" , __func__,
+		substream->name, substream->stream);
+
+	return 0;
+}
+
+static void sitar_shutdown(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	pr_err("%s(): substream = %s  stream = %d\n" , __func__,
+		substream->name, substream->stream);
+}
+
+int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	pr_err("%s() mclk_enable = %u\n", __func__, mclk_enable);
+
+	if (mclk_enable) {
+		sitar->mclk_enabled = true;
+
+		if (sitar->mbhc_polling_active && (sitar->mclk_enabled)) {
+			sitar_codec_pause_hs_polling(codec);
+			sitar_codec_enable_bandgap(codec,
+					SITAR_BANDGAP_AUDIO_MODE);
+			sitar_codec_enable_clock_block(codec, 0);
+			sitar_codec_calibrate_hs_polling(codec);
+			sitar_codec_start_hs_polling(codec);
+		} else {
+			sitar_codec_enable_bandgap(codec,
+					SITAR_BANDGAP_AUDIO_MODE);
+			sitar_codec_enable_clock_block(codec, 0);
+		}
+	} else {
+
+		if (!sitar->mclk_enabled) {
+			pr_err("Error, MCLK already diabled\n");
+			return -EINVAL;
+		}
+		sitar->mclk_enabled = false;
+
+		if (sitar->mbhc_polling_active) {
+			if (!sitar->mclk_enabled) {
+				sitar_codec_pause_hs_polling(codec);
+				sitar_codec_enable_bandgap(codec,
+					SITAR_BANDGAP_MBHC_MODE);
+				sitar_enable_rx_bias(codec, 1);
+				sitar_codec_enable_clock_block(codec, 1);
+				sitar_codec_calibrate_hs_polling(codec);
+				sitar_codec_start_hs_polling(codec);
+			}
+			snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1,
+					0x05, 0x01);
+		} else {
+			sitar_codec_disable_clock_block(codec);
+			sitar_codec_enable_bandgap(codec,
+				SITAR_BANDGAP_OFF);
+		}
+	}
+	return 0;
+}
+
+static int sitar_set_dai_sysclk(struct snd_soc_dai *dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	pr_err("%s\n", __func__);
+	return 0;
+}
+
+static int sitar_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	u8 val = 0;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
+
+	pr_err("%s\n", __func__);
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		/* CPU is master */
+		if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			if (dai->id == AIF1_CAP)
+				snd_soc_update_bits(dai->codec,
+					SITAR_A_CDC_CLK_TX_I2S_CTL,
+					SITAR_I2S_MASTER_MODE_MASK, 0);
+			else if (dai->id == AIF1_PB)
+				snd_soc_update_bits(dai->codec,
+					SITAR_A_CDC_CLK_RX_I2S_CTL,
+					SITAR_I2S_MASTER_MODE_MASK, 0);
+		}
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+	/* CPU is slave */
+		if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			val = SITAR_I2S_MASTER_MODE_MASK;
+			if (dai->id == AIF1_CAP)
+				snd_soc_update_bits(dai->codec,
+					SITAR_A_CDC_CLK_TX_I2S_CTL, val, val);
+			else if (dai->id == AIF1_PB)
+				snd_soc_update_bits(dai->codec,
+					SITAR_A_CDC_CLK_RX_I2S_CTL, val, val);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+static int sitar_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 sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
+	u32 i = 0;
+	if (!tx_slot && !rx_slot) {
+		pr_err("%s: Invalid\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s: DAI-ID %x %d %d\n", __func__, dai->id, tx_num, rx_num);
+
+	if (dai->id == AIF1_PB) {
+		for (i = 0; i < rx_num; i++) {
+			sitar->dai[dai->id - 1].ch_num[i]  = rx_slot[i];
+			sitar->dai[dai->id - 1].ch_act = 0;
+			sitar->dai[dai->id - 1].ch_tot = rx_num;
+		}
+	} else if (dai->id == AIF1_CAP) {
+		for (i = 0; i < tx_num; i++) {
+			sitar->dai[dai->id - 1].ch_num[i]  = tx_slot[i];
+			sitar->dai[dai->id - 1].ch_act = 0;
+			sitar->dai[dai->id - 1].ch_tot = tx_num;
+		}
+	}
+	return 0;
+}
+
+static int sitar_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 *sitar = dev_get_drvdata(dai->codec->control_data);
+
+	u32 cnt = 0;
+	u32 tx_ch[SLIM_MAX_TX_PORTS];
+	u32 rx_ch[SLIM_MAX_RX_PORTS];
+
+	if (!rx_slot && !tx_slot) {
+		pr_err("%s: Invalid\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
+	/* for virtual port, codec driver needs to do
+	* housekeeping, for now should be ok
+	*/
+	wcd9xxx_get_channel(sitar, rx_ch, tx_ch);
+	if (dai->id == AIF1_PB) {
+		*rx_num = sitar_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 = sitar_dai[dai->id - 1].capture.channels_max;
+		while (cnt < *tx_num) {
+			tx_slot[cnt] = tx_ch[6 + cnt];
+			cnt++;
+		}
+	}
+	return 0;
+}
+
+static int sitar_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 sitar_priv *sitar = 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;
+
+	pr_err("%s: DAI-ID %x\n", __func__, dai->id);
+
+	switch (params_rate(params)) {
+	case 8000:
+		tx_fs_rate = 0x00;
+		rx_fs_rate = 0x00;
+		break;
+	case 16000:
+		tx_fs_rate = 0x01;
+		rx_fs_rate = 0x20;
+		break;
+	case 32000:
+		tx_fs_rate = 0x02;
+		rx_fs_rate = 0x40;
+		break;
+	case 48000:
+		tx_fs_rate = 0x03;
+		rx_fs_rate = 0x60;
+		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) {
+
+		tx_state = snd_soc_read(codec,
+				SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL);
+
+		for (path = 1, shift = 0;
+				path <= NUM_DECIMATORS; path++, shift++) {
+
+			if (!(tx_state & (1 << shift))) {
+				tx_fs_reg = SITAR_A_CDC_TX1_CLK_FS_CTL
+						+ (BITS_PER_REG*(path-1));
+				snd_soc_update_bits(codec, tx_fs_reg,
+							0x03, tx_fs_rate);
+			}
+		}
+		if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					SITAR_A_CDC_CLK_TX_I2S_CTL,
+					0x20, 0x20);
+				break;
+			case SNDRV_PCM_FORMAT_S32_LE:
+				snd_soc_update_bits(codec,
+					SITAR_A_CDC_CLK_TX_I2S_CTL,
+					0x20, 0x00);
+				break;
+			default:
+				pr_err("invalid format\n");
+				break;
+			}
+			snd_soc_update_bits(codec, SITAR_A_CDC_CLK_TX_I2S_CTL,
+						0x03, tx_fs_rate);
+		}
+	} else {
+		sitar->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) {
+
+		rx_state = snd_soc_read(codec,
+			SITAR_A_CDC_CLK_RX_B1_CTL);
+
+		for (path = 1, shift = 0;
+				path <= NUM_INTERPOLATORS; path++, shift++) {
+
+			if (!(rx_state & (1 << shift))) {
+				rx_fs_reg = SITAR_A_CDC_RX1_B5_CTL
+						+ (BITS_PER_REG*(path-1));
+				snd_soc_update_bits(codec, rx_fs_reg,
+						0xE0, rx_fs_rate);
+			}
+		}
+		if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					SITAR_A_CDC_CLK_RX_I2S_CTL,
+					0x20, 0x20);
+				break;
+			case SNDRV_PCM_FORMAT_S32_LE:
+				snd_soc_update_bits(codec,
+					SITAR_A_CDC_CLK_RX_I2S_CTL,
+					0x20, 0x00);
+				break;
+			default:
+				pr_err("invalid format\n");
+				break;
+			}
+			snd_soc_update_bits(codec, SITAR_A_CDC_CLK_RX_I2S_CTL,
+						0x03, (rx_fs_rate >> 0x05));
+		}
+	} else {
+		sitar->dai[dai->id - 1].rate   = params_rate(params);
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops sitar_dai_ops = {
+	.startup = sitar_startup,
+	.shutdown = sitar_shutdown,
+	.hw_params = sitar_hw_params,
+	.set_sysclk = sitar_set_dai_sysclk,
+	.set_fmt = sitar_set_dai_fmt,
+	.set_channel_map = sitar_set_channel_map,
+	.get_channel_map = sitar_get_channel_map,
+};
+
+static struct snd_soc_dai_driver sitar_dai[] = {
+	{
+		.name = "sitar_rx1",
+		.id = AIF1_PB,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.rates = WCD9304_RATES,
+			.formats = SITAR_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &sitar_dai_ops,
+	},
+	{
+		.name = "sitar_tx1",
+		.id = AIF1_CAP,
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.rates = WCD9304_RATES,
+			.formats = SITAR_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &sitar_dai_ops,
+	},
+};
+
+static int sitar_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct wcd9xxx *sitar;
+	struct snd_soc_codec *codec = w->codec;
+	struct sitar_priv *sitar_p = snd_soc_codec_get_drvdata(codec);
+	u32  j = 0;
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	sitar = codec->control_data;
+	/* Execute the callback only if interface type is slimbus */
+	if (sitar_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		return 0;
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
+			if (sitar_dai[j].id == AIF1_CAP)
+				continue;
+			if (!strncmp(w->sname,
+				sitar_dai[j].playback.stream_name, 13)) {
+				++sitar_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (sitar_p->dai[j].ch_act == sitar_p->dai[j].ch_tot)
+			wcd9xxx_cfg_slim_sch_rx(sitar,
+					sitar_p->dai[j].ch_num,
+					sitar_p->dai[j].ch_tot,
+					sitar_p->dai[j].rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
+			if (sitar_dai[j].id == AIF1_CAP)
+				continue;
+			if (!strncmp(w->sname,
+				sitar_dai[j].playback.stream_name, 13)) {
+				--sitar_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (!sitar_p->dai[j].ch_act) {
+			wcd9xxx_close_slim_sch_rx(sitar,
+					sitar_p->dai[j].ch_num,
+					sitar_p->dai[j].ch_tot);
+			sitar_p->dai[j].rate = 0;
+			memset(sitar_p->dai[j].ch_num, 0, (sizeof(u32)*
+					sitar_p->dai[j].ch_tot));
+			sitar_p->dai[j].ch_tot = 0;
+		}
+	}
+	return 0;
+}
+
+static int sitar_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct wcd9xxx *sitar;
+	struct snd_soc_codec *codec = w->codec;
+	struct sitar_priv *sitar_p = snd_soc_codec_get_drvdata(codec);
+	/* index to the DAI ID, for now hardcoding */
+	u32  j = 0;
+
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	sitar = codec->control_data;
+
+	/* Execute the callback only if interface type is slimbus */
+	if (sitar_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		return 0;
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
+			if (sitar_dai[j].id == AIF1_PB)
+				continue;
+			if (!strncmp(w->sname,
+				sitar_dai[j].capture.stream_name, 13)) {
+				++sitar_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (sitar_p->dai[j].ch_act == sitar_p->dai[j].ch_tot)
+			wcd9xxx_cfg_slim_sch_tx(sitar,
+					sitar_p->dai[j].ch_num,
+					sitar_p->dai[j].ch_tot,
+					sitar_p->dai[j].rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
+			if (sitar_dai[j].id == AIF1_PB)
+				continue;
+			if (!strncmp(w->sname,
+				sitar_dai[j].capture.stream_name, 13)) {
+				--sitar_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (!sitar_p->dai[j].ch_act) {
+			wcd9xxx_close_slim_sch_tx(sitar,
+					sitar_p->dai[j].ch_num,
+					sitar_p->dai[j].ch_tot);
+			sitar_p->dai[j].rate = 0;
+			memset(sitar_p->dai[j].ch_num, 0, (sizeof(u32)*
+					sitar_p->dai[j].ch_tot));
+			sitar_p->dai[j].ch_tot = 0;
+		}
+	}
+	return 0;
+}
+
+
+static short sitar_codec_read_sta_result(struct snd_soc_codec *codec)
+{
+	u8 bias_msb, bias_lsb;
+	short bias_value;
+
+	bias_msb = snd_soc_read(codec, SITAR_A_CDC_MBHC_B3_STATUS);
+	bias_lsb = snd_soc_read(codec, SITAR_A_CDC_MBHC_B2_STATUS);
+	bias_value = (bias_msb << 8) | bias_lsb;
+	return bias_value;
+}
+
+static short sitar_codec_read_dce_result(struct snd_soc_codec *codec)
+{
+	u8 bias_msb, bias_lsb;
+	short bias_value;
+
+	bias_msb = snd_soc_read(codec, SITAR_A_CDC_MBHC_B5_STATUS);
+	bias_lsb = snd_soc_read(codec, SITAR_A_CDC_MBHC_B4_STATUS);
+	bias_value = (bias_msb << 8) | bias_lsb;
+	return bias_value;
+}
+
+static short sitar_codec_measure_micbias_voltage(struct snd_soc_codec *codec,
+	int dce)
+{
+	short bias_value;
+
+	if (dce) {
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x4);
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x4);
+		usleep_range(60000, 60000);
+		bias_value = sitar_codec_read_dce_result(codec);
+	} else {
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x2);
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+		usleep_range(5000, 5000);
+		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x2);
+		usleep_range(50, 50);
+		bias_value = sitar_codec_read_sta_result(codec);
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x0);
+	}
+
+	pr_err("read microphone bias value %x\n", bias_value);
+	return bias_value;
+}
+
+static short sitar_codec_setup_hs_polling(struct snd_soc_codec *codec)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	struct sitar_mbhc_calibration *calibration = sitar->calibration;
+	short bias_value;
+	u8 cfilt_mode;
+
+	if (!calibration) {
+		pr_err("Error, no sitar calibration\n");
+		return -ENODEV;
+	}
+
+	sitar->mbhc_polling_active = true;
+
+	if (!sitar->mclk_enabled) {
+		sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_MBHC_MODE);
+		sitar_enable_rx_bias(codec, 1);
+		sitar_codec_enable_clock_block(codec, 1);
+	}
+
+	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x01);
+
+	snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0xE0);
+
+	/* Make sure CFILT is in fast mode, save current mode */
+	cfilt_mode = snd_soc_read(codec,
+		sitar->mbhc_bias_regs.cfilt_ctl);
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl,
+		0x70, 0x00);
+
+	snd_soc_update_bits(codec,
+		sitar->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x84);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x6, 0x6);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+
+	sitar_codec_calibrate_hs_polling(codec);
+
+	bias_value = sitar_codec_measure_micbias_voltage(codec, 0);
+	snd_soc_update_bits(codec,
+		sitar->mbhc_bias_regs.cfilt_ctl, 0x40, cfilt_mode);
+	snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x13, 0x00);
+
+	return bias_value;
+}
+
+static int sitar_codec_enable_hs_detect(struct snd_soc_codec *codec,
+		int insertion)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	struct sitar_mbhc_calibration *calibration = sitar->calibration;
+	int central_bias_enabled = 0;
+	u8 wg_time;
+
+	if (!calibration) {
+		pr_err("Error, no sitar calibration\n");
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x1, 0);
+
+	if (insertion) {
+		/* Make sure mic bias and Mic line schmitt trigger
+		* are turned OFF
+		*/
+		snd_soc_update_bits(codec, sitar->mbhc_bias_regs.ctl_reg,
+			0x81, 0x01);
+		snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg,
+			0x90, 0x00);
+		wg_time = snd_soc_read(codec, SITAR_A_RX_HPH_CNP_WG_TIME) ;
+		wg_time += 1;
+
+		/* Enable HPH Schmitt Trigger */
+		snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x11, 0x11);
+		snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x0C,
+			calibration->hph_current << 2);
+
+		/* Turn off HPH PAs and DAC's during insertion detection to
+		* avoid false insertion interrupts
+		*/
+		if (sitar->mbhc_micbias_switched)
+			sitar_codec_switch_micbias(codec, 0);
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_CNP_EN, 0x30, 0x00);
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_L_DAC_CTL,
+			0xC0, 0x00);
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_R_DAC_CTL,
+			0xC0, 0x00);
+		usleep_range(wg_time * 1000, wg_time * 1000);
+
+		/* setup for insetion detection */
+		snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x02, 0x02);
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x2, 0);
+	} else {
+		/* Make sure the HPH schmitt trigger is OFF */
+		snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x12, 0x00);
+
+		/* enable the mic line schmitt trigger */
+		snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg, 0x60,
+			calibration->mic_current << 5);
+		snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg,
+			0x80, 0x80);
+		usleep_range(calibration->mic_pid, calibration->mic_pid);
+		snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg,
+			0x10, 0x10);
+
+		/* Setup for low power removal detection */
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x2, 0x2);
+	}
+
+	if (snd_soc_read(codec, SITAR_A_CDC_MBHC_B1_CTL) & 0x4) {
+		if (!(sitar->clock_active)) {
+			snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL,
+				0x06, 0);
+			usleep_range(calibration->shutdown_plug_removal,
+				calibration->shutdown_plug_removal);
+		} else
+			snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL,
+				0x06, 0);
+	}
+
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.int_rbias, 0x80, 0);
+
+	/* If central bandgap disabled */
+	if (!(snd_soc_read(codec, SITAR_A_PIN_CTL_OE1) & 1)) {
+		snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE1, 0x3, 0x3);
+		usleep_range(calibration->bg_fast_settle,
+			calibration->bg_fast_settle);
+		central_bias_enabled = 1;
+	}
+
+	/* If LDO_H disabled */
+	if (snd_soc_read(codec, SITAR_A_PIN_CTL_OE0) & 0x80) {
+		snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x10, 0);
+		snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x80, 0x80);
+		usleep_range(calibration->tldoh, calibration->tldoh);
+		snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x80, 0);
+
+		if (central_bias_enabled)
+			snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE1, 0x1, 0);
+	}
+
+	wcd9xxx_enable_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+	return 0;
+}
+
+
+static void sitar_lock_sleep(struct sitar_priv *sitar)
+{
+	int ret;
+	while (!(ret = wait_event_timeout(sitar->pm_wq,
+					 atomic_inc_not_zero(&sitar->pm_cnt),
+					 2 * HZ))) {
+		pr_err("%s: didn't wake up for 2000ms (%d), pm_cnt %d\n",
+			__func__, ret, atomic_read(&sitar->pm_cnt));
+		WARN_ON_ONCE(1);
+	}
+}
+
+static void sitar_unlock_sleep(struct sitar_priv *sitar)
+{
+	atomic_dec(&sitar->pm_cnt);
+	wake_up(&sitar->pm_wq);
+}
+
+
+static void btn0_lpress_fn(struct work_struct *work)
+{
+	struct delayed_work *delayed_work;
+	struct sitar_priv *sitar;
+
+	pr_err("%s:\n", __func__);
+
+	delayed_work = to_delayed_work(work);
+	sitar = container_of(delayed_work, struct sitar_priv, btn0_dwork);
+
+	if (sitar) {
+		if (sitar->button_jack) {
+			pr_err("%s: Reporting long button press event\n",
+					__func__);
+			sitar_snd_soc_jack_report(sitar, sitar->button_jack,
+						 SND_JACK_BTN_0,
+						 SND_JACK_BTN_0);
+		}
+	} else {
+		pr_err("%s: Bad sitar private data\n", __func__);
+	}
+
+	sitar_unlock_sleep(sitar);
+}
+
+int sitar_hs_detect(struct snd_soc_codec *codec,
+	struct snd_soc_jack *headset_jack, struct snd_soc_jack *button_jack,
+	struct sitar_mbhc_calibration *calibration)
+{
+	struct sitar_priv *sitar;
+	int rc;
+
+	if (!codec || !calibration) {
+		pr_err("Error: no codec or calibration\n");
+		return -EINVAL;
+	}
+	sitar = snd_soc_codec_get_drvdata(codec);
+	sitar->headset_jack = headset_jack;
+	sitar->button_jack = button_jack;
+	sitar->calibration = calibration;
+	sitar_get_mbhc_micbias_regs(codec, &sitar->mbhc_bias_regs);
+
+	/* Put CFILT in fast mode by default */
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl,
+		0x40, SITAR_CFILT_FAST_MODE);
+
+	INIT_DELAYED_WORK(&sitar->btn0_dwork, btn0_lpress_fn);
+	INIT_WORK(&sitar->hphlocp_work, hphlocp_off_report);
+	INIT_WORK(&sitar->hphrocp_work, hphrocp_off_report);
+	rc =  sitar_codec_enable_hs_detect(codec, 1);
+
+	if (!IS_ERR_VALUE(rc)) {
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+			0x10);
+		wcd9xxx_enable_irq(codec->control_data,
+			SITAR_IRQ_HPH_PA_OCPL_FAULT);
+		wcd9xxx_enable_irq(codec->control_data,
+			SITAR_IRQ_HPH_PA_OCPR_FAULT);
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(sitar_hs_detect);
+
+static irqreturn_t sitar_dce_handler(int irq, void *data)
+{
+	struct sitar_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+	short bias_value;
+
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL);
+	sitar_lock_sleep(priv);
+
+	bias_value = sitar_codec_read_dce_result(codec);
+	pr_err("%s: button press interrupt, bias value(DCE Read)=%d\n",
+			__func__, bias_value);
+
+	bias_value = sitar_codec_read_sta_result(codec);
+	pr_err("%s: button press interrupt, bias value(STA Read)=%d\n",
+			__func__, bias_value);
+	/*
+	* TODO: If button pressed is not button 0,
+	* report the button press event immediately.
+	*/
+	priv->buttons_pressed |= SND_JACK_BTN_0;
+
+	msleep(100);
+
+	if (schedule_delayed_work(&priv->btn0_dwork,
+				 msecs_to_jiffies(400)) == 0) {
+		WARN(1, "Button pressed twice without release event\n");
+		sitar_unlock_sleep(priv);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sitar_release_handler(int irq, void *data)
+{
+	struct sitar_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+	int ret, mic_voltage;
+
+	pr_err("%s\n", __func__);
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE);
+	sitar_lock_sleep(priv);
+
+	mic_voltage = sitar_codec_read_dce_result(codec);
+	pr_err("%s: Microphone Voltage on release(DCE Read) = %d\n",
+		__func__, mic_voltage);
+
+	if (priv->buttons_pressed & SND_JACK_BTN_0) {
+		ret = cancel_delayed_work(&priv->btn0_dwork);
+
+		if (ret == 0) {
+
+			pr_err("%s: Reporting long button release event\n",
+					__func__);
+			if (priv->button_jack) {
+				sitar_snd_soc_jack_report(priv,
+							 priv->button_jack, 0,
+							 SND_JACK_BTN_0);
+			}
+
+		} else {
+			/* if scheduled btn0_dwork is canceled from here,
+			* we have to unlock from here instead btn0_work */
+			sitar_unlock_sleep(priv);
+			mic_voltage =
+				sitar_codec_measure_micbias_voltage(codec, 0);
+			pr_err("%s: Mic Voltage on release(new STA) = %d\n",
+						__func__, mic_voltage);
+
+			if (mic_voltage < -2000 || mic_voltage > -670) {
+				pr_err("%s: Fake buttton press interrupt\n",
+						__func__);
+			} else {
+
+				if (priv->button_jack) {
+					pr_err("%s:reporting short button press and release\n",
+							__func__);
+
+					sitar_snd_soc_jack_report(priv,
+							     priv->button_jack,
+						SND_JACK_BTN_0, SND_JACK_BTN_0);
+					sitar_snd_soc_jack_report(priv,
+							    priv->button_jack,
+							    0, SND_JACK_BTN_0);
+				}
+			}
+		}
+
+		priv->buttons_pressed &= ~SND_JACK_BTN_0;
+	}
+
+	sitar_codec_start_hs_polling(codec);
+	sitar_unlock_sleep(priv);
+	return IRQ_HANDLED;
+}
+
+static void sitar_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	struct sitar_mbhc_calibration *calibration = sitar->calibration;
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
+
+	snd_soc_update_bits(codec,
+		sitar->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
+	usleep_range(calibration->shutdown_plug_removal,
+		calibration->shutdown_plug_removal);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
+
+	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x00);
+}
+
+static void sitar_codec_shutdown_hs_polling(struct snd_soc_codec *codec)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	sitar_codec_shutdown_hs_removal_detect(codec);
+
+	if (!sitar->mclk_enabled) {
+		snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0x00);
+		sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_AUDIO_MODE);
+		sitar_codec_enable_clock_block(codec, 0);
+	}
+
+	sitar->mbhc_polling_active = false;
+}
+
+static irqreturn_t sitar_hphl_ocp_irq(int irq, void *data)
+{
+	struct sitar_priv *sitar = data;
+	struct snd_soc_codec *codec;
+
+	pr_info("%s: received HPHL OCP irq\n", __func__);
+
+	if (sitar) {
+		codec = sitar->codec;
+		if (sitar->hphlocp_cnt++ < SITAR_OCP_ATTEMPT) {
+			pr_info("%s: retry\n", __func__);
+			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+					   0x00);
+			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+					   0x10);
+		} else {
+			wcd9xxx_disable_irq(codec->control_data,
+					 SITAR_IRQ_HPH_PA_OCPL_FAULT);
+			sitar->hphlocp_cnt = 0;
+			sitar->hph_status |= SND_JACK_OC_HPHL;
+			if (sitar->headset_jack)
+				sitar_snd_soc_jack_report(sitar,
+							 sitar->headset_jack,
+							 sitar->hph_status,
+							 SITAR_JACK_MASK);
+		}
+	} else {
+		pr_err("%s: Bad sitar private data\n", __func__);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sitar_hphr_ocp_irq(int irq, void *data)
+{
+	struct sitar_priv *sitar = data;
+	struct snd_soc_codec *codec;
+
+	pr_info("%s: received HPHR OCP irq\n", __func__);
+
+	if (sitar) {
+		codec = sitar->codec;
+		if (sitar->hphrocp_cnt++ < SITAR_OCP_ATTEMPT) {
+			pr_info("%s: retry\n", __func__);
+			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+					   0x00);
+			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+					   0x10);
+		} else {
+			wcd9xxx_disable_irq(codec->control_data,
+					 SITAR_IRQ_HPH_PA_OCPR_FAULT);
+			sitar->hphrocp_cnt = 0;
+			sitar->hph_status |= SND_JACK_OC_HPHR;
+			if (sitar->headset_jack)
+				sitar_snd_soc_jack_report(sitar,
+							 sitar->headset_jack,
+							 sitar->hph_status,
+							 SITAR_JACK_MASK);
+		}
+	} else {
+		pr_err("%s: Bad sitar private data\n", __func__);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void sitar_sync_hph_state(struct sitar_priv *sitar)
+{
+	if (test_and_clear_bit(SITAR_HPHR_PA_OFF_ACK,
+				&sitar->hph_pa_dac_state)) {
+		pr_err("%s: HPHR clear flag and enable PA\n", __func__);
+		snd_soc_update_bits(sitar->codec, SITAR_A_RX_HPH_CNP_EN, 0x10,
+				   1 << 4);
+	}
+	if (test_and_clear_bit(SITAR_HPHL_PA_OFF_ACK,
+				&sitar->hph_pa_dac_state)) {
+		pr_err("%s: HPHL clear flag and enable PA\n", __func__);
+		snd_soc_update_bits(sitar->codec, SITAR_A_RX_HPH_CNP_EN, 0x20,
+				   1 << 5);
+	}
+
+	if (test_and_clear_bit(SITAR_HPHR_DAC_OFF_ACK,
+				&sitar->hph_pa_dac_state)) {
+		pr_err("%s: HPHR clear flag and enable DAC\n", __func__);
+		snd_soc_update_bits(sitar->codec, SITAR_A_RX_HPH_R_DAC_CTL,
+				   0xC0, 0xC0);
+	}
+	if (test_and_clear_bit(SITAR_HPHL_DAC_OFF_ACK,
+				&sitar->hph_pa_dac_state)) {
+		pr_err("%s: HPHL clear flag and enable DAC\n", __func__);
+		snd_soc_update_bits(sitar->codec, SITAR_A_RX_HPH_L_DAC_CTL,
+				   0xC0, 0xC0);
+	}
+}
+
+static irqreturn_t sitar_hs_insert_irq(int irq, void *data)
+{
+	struct sitar_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+	int ldo_h_on, micb_cfilt_on;
+	short mic_voltage;
+	short threshold_no_mic = 0xF7F6;
+	short threshold_fake_insert = 0xFD30;
+	u8 is_removal;
+
+	pr_err("%s\n", __func__);
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION);
+	sitar_lock_sleep(priv);
+
+	is_removal = snd_soc_read(codec, SITAR_A_CDC_MBHC_INT_CTL) & 0x02;
+	snd_soc_update_bits(codec, SITAR_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, SITAR_A_MBHC_HPH, 0x13, 0x00);
+
+	if (priv->fake_insert_context) {
+		pr_err("%s: fake context interrupt, reset insertion\n",
+			__func__);
+		priv->fake_insert_context = false;
+		sitar_codec_shutdown_hs_polling(codec);
+		sitar_codec_enable_hs_detect(codec, 1);
+		return IRQ_HANDLED;
+	}
+
+
+	ldo_h_on = snd_soc_read(codec, SITAR_A_LDO_H_MODE_1) & 0x80;
+	micb_cfilt_on = snd_soc_read(codec,
+					priv->mbhc_bias_regs.cfilt_ctl) & 0x80;
+
+	if (!ldo_h_on)
+		snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x80);
+	if (!micb_cfilt_on)
+		snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
+							0x80, 0x80);
+
+	usleep_range(priv->calibration->setup_plug_removal_delay,
+		priv->calibration->setup_plug_removal_delay);
+
+	if (!ldo_h_on)
+		snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x0);
+	if (!micb_cfilt_on)
+		snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
+							0x80, 0x0);
+
+	if (is_removal) {
+		/*
+		* If headphone is removed while playback is in progress,
+		* it is possible that micbias will be switched to VDDIO.
+		*/
+		if (priv->mbhc_micbias_switched)
+			sitar_codec_switch_micbias(codec, 0);
+		priv->hph_status &= ~SND_JACK_HEADPHONE;
+
+		/* If headphone PA is on, check if userspace receives
+		* removal event to sync-up PA's state */
+		if (sitar_is_hph_pa_on(codec)) {
+			set_bit(SITAR_HPHL_PA_OFF_ACK, &priv->hph_pa_dac_state);
+			set_bit(SITAR_HPHR_PA_OFF_ACK, &priv->hph_pa_dac_state);
+		}
+
+		if (sitar_is_hph_dac_on(codec, 1))
+			set_bit(SITAR_HPHL_DAC_OFF_ACK,
+				&priv->hph_pa_dac_state);
+		if (sitar_is_hph_dac_on(codec, 0))
+			set_bit(SITAR_HPHR_DAC_OFF_ACK,
+				&priv->hph_pa_dac_state);
+
+		if (priv->headset_jack) {
+			pr_err("%s: Reporting removal\n", __func__);
+			sitar_snd_soc_jack_report(priv, priv->headset_jack,
+						 priv->hph_status,
+						 SITAR_JACK_MASK);
+		}
+		sitar_codec_shutdown_hs_removal_detect(codec);
+		sitar_codec_enable_hs_detect(codec, 1);
+		sitar_unlock_sleep(priv);
+		return IRQ_HANDLED;
+	}
+
+	mic_voltage = sitar_codec_setup_hs_polling(codec);
+
+	if (mic_voltage > threshold_fake_insert) {
+		pr_err("%s: Fake insertion interrupt, mic_voltage = %x\n",
+			__func__, mic_voltage);
+
+		/* Disable HPH trigger and enable MIC line trigger */
+		snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x12, 0x00);
+
+		snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x60,
+			priv->calibration->mic_current << 5);
+		snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
+			0x80, 0x80);
+		usleep_range(priv->calibration->mic_pid,
+			priv->calibration->mic_pid);
+		snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
+			0x10, 0x10);
+
+		/* Setup for insertion detection */
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x2, 0);
+		priv->fake_insert_context = true;
+		wcd9xxx_enable_irq(codec->control_data,
+				SITAR_IRQ_MBHC_INSERTION);
+		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+
+	} else if (mic_voltage < threshold_no_mic) {
+		pr_err("%s: Headphone Detected, mic_voltage = %x\n",
+			__func__, mic_voltage);
+		priv->hph_status |= SND_JACK_HEADPHONE;
+		if (priv->headset_jack) {
+			pr_err("%s: Reporting insertion %d\n", __func__,
+				SND_JACK_HEADPHONE);
+			sitar_snd_soc_jack_report(priv, priv->headset_jack,
+						 priv->hph_status,
+						 SITAR_JACK_MASK);
+		}
+		sitar_codec_shutdown_hs_polling(codec);
+		sitar_codec_enable_hs_detect(codec, 0);
+		sitar_sync_hph_state(priv);
+	} else {
+		pr_err("%s: Headset detected, mic_voltage = %x\n",
+			__func__, mic_voltage);
+		priv->hph_status |= SND_JACK_HEADSET;
+		if (priv->headset_jack) {
+			pr_err("%s: Reporting insertion %d\n", __func__,
+				SND_JACK_HEADSET);
+			sitar_snd_soc_jack_report(priv, priv->headset_jack,
+						 priv->hph_status,
+						 SITAR_JACK_MASK);
+		}
+		sitar_codec_start_hs_polling(codec);
+		sitar_sync_hph_state(priv);
+	}
+
+	sitar_unlock_sleep(priv);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sitar_hs_remove_irq(int irq, void *data)
+{
+	struct sitar_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+	short bias_value;
+
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE);
+	sitar_lock_sleep(priv);
+
+	usleep_range(priv->calibration->shutdown_plug_removal,
+		priv->calibration->shutdown_plug_removal);
+
+	bias_value = sitar_codec_measure_micbias_voltage(codec, 1);
+	pr_err("removal interrupt, bias value is %d\n", bias_value);
+
+	if (bias_value < -90) {
+		pr_err("False alarm, headset not actually removed\n");
+		sitar_codec_start_hs_polling(codec);
+	} else {
+		/*
+		* If this removal is not false, first check the micbias
+		* switch status and switch it to LDOH if it is already
+		* switched to VDDIO.
+		*/
+		if (priv->mbhc_micbias_switched)
+			sitar_codec_switch_micbias(codec, 0);
+		priv->hph_status &= ~SND_JACK_HEADSET;
+		if (priv->headset_jack) {
+			pr_err("%s: Reporting removal\n", __func__);
+			sitar_snd_soc_jack_report(priv, priv->headset_jack, 0,
+						 SITAR_JACK_MASK);
+		}
+		sitar_codec_shutdown_hs_polling(codec);
+
+		sitar_codec_enable_hs_detect(codec, 1);
+	}
+
+	sitar_unlock_sleep(priv);
+	return IRQ_HANDLED;
+}
+
+
+static unsigned long slimbus_value;
+
+static irqreturn_t sitar_slimbus_irq(int irq, void *data)
+{
+	struct sitar_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+	int i, j;
+	u8 val;
+
+	sitar_lock_sleep(priv);
+
+	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
+		slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
+			SITAR_SLIM_PGD_PORT_INT_STATUS0 + i);
+		for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
+			val = wcd9xxx_interface_reg_read(codec->control_data,
+				SITAR_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,
+			SITAR_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+	}
+
+	sitar_unlock_sleep(priv);
+	return IRQ_HANDLED;
+}
+
+
+static int sitar_handle_pdata(struct sitar_priv *sitar)
+{
+	struct snd_soc_codec *codec = sitar->codec;
+	struct wcd9xxx_pdata *pdata = sitar->pdata;
+	int k1, k2, 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 > SITAR_LDOH_2P85_V) ||
+	   (pdata->micbias.bias1_cfilt_sel > SITAR_CFILT2_SEL) ||
+	   (pdata->micbias.bias2_cfilt_sel > SITAR_CFILT2_SEL)) {
+		rc = -EINVAL;
+		goto done;
+	}
+
+	/* figure out k value */
+	k1 = sitar_find_k_value(pdata->micbias.ldoh_v,
+		pdata->micbias.cfilt1_mv);
+	k2 = sitar_find_k_value(pdata->micbias.ldoh_v,
+		pdata->micbias.cfilt2_mv);
+
+	if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2)) {
+		rc = -EINVAL;
+		goto done;
+	}
+
+	/* Set voltage level and always use LDO */
+
+	snd_soc_update_bits(codec, SITAR_A_MICB_CFILT_1_VAL, 0xFC,
+		(k1 << 2));
+	snd_soc_update_bits(codec, SITAR_A_MICB_CFILT_2_VAL, 0xFC,
+		(k2 << 2));
+
+	snd_soc_update_bits(codec, SITAR_A_MICB_1_CTL, 0x60,
+		(pdata->micbias.bias1_cfilt_sel << 5));
+	snd_soc_update_bits(codec, SITAR_A_MICB_2_CTL, 0x60,
+		(pdata->micbias.bias2_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, SITAR_A_TX_1_2_EN + j * 10,
+				0x10, value);
+			snd_soc_update_bits(codec,
+				SITAR_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, SITAR_A_TX_1_2_EN + j * 10,
+				0x01, value);
+			snd_soc_update_bits(codec,
+				SITAR_A_TX_1_2_TEST_EN + j * 10,
+				0x03, val_txfe);
+		}
+	}
+
+	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, SITAR_A_RX_COM_OCP_CTL,
+			0x0F, pdata->ocp.num_attempts);
+		snd_soc_write(codec, SITAR_A_RX_COM_OCP_COUNT,
+			((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL,
+			0xE0, (pdata->ocp.hph_ocp_limit << 5));
+	}
+done:
+	return rc;
+}
+
+static const struct sitar_reg_mask_val sitar_1_1_reg_defaults[] = {
+
+	/* Sitar 1.1 MICBIAS changes */
+	SITAR_REG_VAL(SITAR_A_MICB_1_INT_RBIAS, 0x24),
+	SITAR_REG_VAL(SITAR_A_MICB_2_INT_RBIAS, 0x24),
+
+	/* Sitar 1.1 HPH changes */
+	SITAR_REG_VAL(SITAR_A_RX_HPH_BIAS_PA, 0x57),
+	SITAR_REG_VAL(SITAR_A_RX_HPH_BIAS_LDO, 0x56),
+
+	/* Sitar 1.1 EAR PA changes */
+	SITAR_REG_VAL(SITAR_A_RX_EAR_BIAS_PA, 0xA6),
+	SITAR_REG_VAL(SITAR_A_RX_EAR_GAIN, 0x02),
+	SITAR_REG_VAL(SITAR_A_RX_EAR_VCM, 0x03),
+
+	/* Sitar 1.1 RX Changes */
+	SITAR_REG_VAL(SITAR_A_CDC_RX1_B5_CTL, 0x78),
+
+	/* Sitar 1.1 RX1 and RX2 Changes */
+	SITAR_REG_VAL(SITAR_A_CDC_RX1_B6_CTL, 0x80),
+
+	SITAR_REG_VAL(SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL, 0x1B),
+
+};
+
+static void sitar_update_reg_defaults(struct snd_soc_codec *codec)
+{
+	u32 i;
+	for (i = 0; i < ARRAY_SIZE(sitar_1_1_reg_defaults); i++)
+		snd_soc_write(codec, sitar_1_1_reg_defaults[i].reg,
+				sitar_1_1_reg_defaults[i].val);
+
+}
+static const struct sitar_reg_mask_val sitar_codec_reg_init_val[] = {
+	/* Initialize current threshold to 350MA
+	* number of wait and run cycles to 4096
+	*/
+	{SITAR_A_RX_HPH_OCP_CTL, 0xF8, 0x60},
+	{SITAR_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+
+	{SITAR_A_QFUSE_CTL, 0xFF, 0x03},
+
+	/* Initialize gain registers to use register gain */
+	{SITAR_A_RX_HPH_L_GAIN, 0x10, 0x10},
+	{SITAR_A_RX_HPH_R_GAIN, 0x10, 0x10},
+	{SITAR_A_RX_LINE_1_GAIN, 0x10, 0x10},
+	{SITAR_A_RX_LINE_2_GAIN, 0x10, 0x10},
+
+	/* Initialize mic biases to differential mode */
+	{SITAR_A_MICB_1_INT_RBIAS, 0x24, 0x24},
+	{SITAR_A_MICB_2_INT_RBIAS, 0x24, 0x24},
+
+	{SITAR_A_CDC_CONN_CLSG_CTL, 0x3C, 0x14},
+
+	/* Use 16 bit sample size for TX1 to TX6 */
+	{SITAR_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x28},
+	{SITAR_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
+	{SITAR_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
+	{SITAR_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
+	{SITAR_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
+
+	/* Use 16 bit sample size for RX */
+	{SITAR_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
+	{SITAR_A_CDC_CONN_RX_SB_B2_CTL, 0x02, 0x02},
+
+	/*enable HPF filter for TX paths */
+	{SITAR_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
+};
+
+static void sitar_codec_init_reg(struct snd_soc_codec *codec)
+{
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(sitar_codec_reg_init_val); i++)
+		snd_soc_update_bits(codec, sitar_codec_reg_init_val[i].reg,
+			sitar_codec_reg_init_val[i].mask,
+			sitar_codec_reg_init_val[i].val);
+}
+
+static int sitar_codec_probe(struct snd_soc_codec *codec)
+{
+	struct sitar *control;
+	struct sitar_priv *sitar;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret = 0;
+	int i;
+	u8 sitar_version;
+	int ch_cnt;
+
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	control = codec->control_data;
+
+	sitar = kzalloc(sizeof(struct sitar_priv), GFP_KERNEL);
+	if (!sitar) {
+		dev_err(codec->dev, "Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+
+	/* Make sure mbhc micbias register addresses are zeroed out */
+	memset(&sitar->mbhc_bias_regs, 0,
+		sizeof(struct mbhc_micbias_regs));
+	sitar->cfilt_k_value = 0;
+	sitar->mbhc_micbias_switched = false;
+
+	snd_soc_codec_set_drvdata(codec, sitar);
+
+	sitar->mclk_enabled = false;
+	sitar->bandgap_type = SITAR_BANDGAP_OFF;
+	sitar->clock_active = false;
+	sitar->config_mode_active = false;
+	sitar->mbhc_polling_active = false;
+	sitar->fake_insert_context = false;
+	sitar->no_mic_headset_override = false;
+	sitar->codec = codec;
+	sitar->pdata = dev_get_platdata(codec->dev->parent);
+	atomic_set(&sitar->pm_cnt, 1);
+	init_waitqueue_head(&sitar->pm_wq);
+
+	sitar_update_reg_defaults(codec);
+	sitar_codec_init_reg(codec);
+
+	ret = sitar_handle_pdata(sitar);
+	if (IS_ERR_VALUE(ret)) {
+		pr_err("%s: bad pdata\n", __func__);
+		goto err_pdata;
+	}
+
+	snd_soc_add_controls(codec, sitar_snd_controls,
+		ARRAY_SIZE(sitar_snd_controls));
+	snd_soc_dapm_new_controls(dapm, sitar_dapm_widgets,
+		ARRAY_SIZE(sitar_dapm_widgets));
+	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+
+	sitar_version = snd_soc_read(codec, WCD9XXX_A_CHIP_VERSION);
+	pr_info("%s : Sitar version reg 0x%2x\n", __func__, (u32)sitar_version);
+
+	sitar_version &=  0x1F;
+	pr_info("%s : Sitar version %u\n", __func__, (u32)sitar_version);
+
+	snd_soc_dapm_sync(dapm);
+
+
+	ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION,
+		sitar_hs_insert_irq, "Headset insert detect", sitar);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			SITAR_IRQ_MBHC_INSERTION);
+		goto err_insert_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION);
+
+	ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL,
+		sitar_hs_remove_irq, "Headset remove detect", sitar);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			SITAR_IRQ_MBHC_REMOVAL);
+		goto err_remove_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+
+	ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL,
+		sitar_dce_handler, "DC Estimation detect", sitar);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			SITAR_IRQ_MBHC_POTENTIAL);
+		goto err_potential_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL);
+
+	ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE,
+		sitar_release_handler, "Button Release detect", sitar);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			SITAR_IRQ_MBHC_RELEASE);
+		goto err_release_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE);
+
+	ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_SLIMBUS,
+		sitar_slimbus_irq, "SLIMBUS Slave", sitar);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			SITAR_IRQ_SLIMBUS);
+		goto err_slimbus_irq;
+	}
+
+	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
+		wcd9xxx_interface_reg_write(codec->control_data,
+			SITAR_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
+
+
+	ret = wcd9xxx_request_irq(codec->control_data,
+		SITAR_IRQ_HPH_PA_OCPL_FAULT, sitar_hphl_ocp_irq,
+		"HPH_L OCP detect", sitar);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			SITAR_IRQ_HPH_PA_OCPL_FAULT);
+		goto err_hphl_ocp_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_HPH_PA_OCPL_FAULT);
+
+	ret = wcd9xxx_request_irq(codec->control_data,
+		SITAR_IRQ_HPH_PA_OCPR_FAULT, sitar_hphr_ocp_irq,
+		"HPH_R OCP detect", sitar);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			SITAR_IRQ_HPH_PA_OCPR_FAULT);
+		goto err_hphr_ocp_irq;
+	}
+	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_HPH_PA_OCPR_FAULT);
+
+	for (i = 0; i < ARRAY_SIZE(sitar_dai); i++) {
+		switch (sitar_dai[i].id) {
+		case AIF1_PB:
+			ch_cnt = sitar_dai[i].playback.channels_max;
+			break;
+		case AIF1_CAP:
+			ch_cnt = sitar_dai[i].capture.channels_max;
+			break;
+		default:
+			continue;
+		}
+		sitar->dai[i].ch_num = kzalloc((sizeof(unsigned int)*
+					ch_cnt), GFP_KERNEL);
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	debug_sitar_priv = sitar;
+#endif
+
+	return ret;
+
+err_hphr_ocp_irq:
+	wcd9xxx_free_irq(codec->control_data,
+			SITAR_IRQ_HPH_PA_OCPL_FAULT, sitar);
+err_hphl_ocp_irq:
+	wcd9xxx_free_irq(codec->control_data,
+			SITAR_IRQ_SLIMBUS, sitar);
+err_slimbus_irq:
+	wcd9xxx_free_irq(codec->control_data,
+			SITAR_IRQ_MBHC_RELEASE, sitar);
+err_release_irq:
+	wcd9xxx_free_irq(codec->control_data,
+			SITAR_IRQ_MBHC_POTENTIAL, sitar);
+err_potential_irq:
+	wcd9xxx_free_irq(codec->control_data,
+			SITAR_IRQ_MBHC_REMOVAL, sitar);
+err_remove_irq:
+	wcd9xxx_free_irq(codec->control_data,
+			SITAR_IRQ_MBHC_INSERTION, sitar);
+err_insert_irq:
+err_pdata:
+	kfree(sitar);
+	return ret;
+}
+static int sitar_codec_remove(struct snd_soc_codec *codec)
+{
+	int i;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_SLIMBUS, sitar);
+	wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE, sitar);
+	wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL, sitar);
+	wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL, sitar);
+	wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION, sitar);
+	sitar_codec_disable_clock_block(codec);
+	sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_OFF);
+	for (i = 0; i < ARRAY_SIZE(sitar_dai); i++)
+		kfree(sitar->dai[i].ch_num);
+	kfree(sitar);
+	return 0;
+}
+static struct snd_soc_codec_driver soc_codec_dev_sitar = {
+	.probe	= sitar_codec_probe,
+	.remove	= sitar_codec_remove,
+	.read = sitar_read,
+	.write = sitar_write,
+
+	.readable_register = sitar_readable,
+	.volatile_register = sitar_volatile,
+
+	.reg_cache_size = SITAR_CACHE_SIZE,
+	.reg_cache_default = sitar_reg_defaults,
+	.reg_word_size = 1,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *debugfs_poke;
+
+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;
+
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+	buf = (char *)lbuf;
+	debug_sitar_priv->no_mic_headset_override = (*strsep(&buf, " ") == '0')
+		? false : true;
+
+	return rc;
+}
+
+static const struct file_operations codec_debug_ops = {
+	.open = codec_debug_open,
+	.write = codec_debug_write,
+};
+#endif
+
+#ifdef CONFIG_PM
+static int sitar_suspend(struct device *dev)
+{
+	int ret = 0, cnt;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sitar_priv *sitar = platform_get_drvdata(pdev);
+
+	cnt = atomic_read(&sitar->pm_cnt);
+	if (cnt > 0) {
+		if (wait_event_timeout(sitar->pm_wq,
+					(atomic_cmpxchg(&sitar->pm_cnt, 1, 0)
+						== 1), 5 * HZ)) {
+			dev_dbg(dev, "system suspend pm_cnt %d\n",
+				atomic_read(&sitar->pm_cnt));
+		} else {
+			dev_err(dev, "%s timed out pm_cnt = %d\n",
+				__func__, atomic_read(&sitar->pm_cnt));
+			WARN_ON_ONCE(1);
+			ret = -EBUSY;
+		}
+	} else if (cnt == 0)
+		dev_warn(dev, "system is already in suspend, pm_cnt %d\n",
+			atomic_read(&sitar->pm_cnt));
+	else {
+		WARN(1, "unexpected pm_cnt %d\n", cnt);
+		ret = -EFAULT;
+	}
+
+	return ret;
+}
+
+static int sitar_resume(struct device *dev)
+{
+	int ret = 0, cnt;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sitar_priv *sitar = platform_get_drvdata(pdev);
+
+	cnt = atomic_cmpxchg(&sitar->pm_cnt, 0, 1);
+	if (cnt == 0) {
+		dev_dbg(dev, "system resume, pm_cnt %d\n",
+			atomic_read(&sitar->pm_cnt));
+		wake_up_all(&sitar->pm_wq);
+	} else if (cnt > 0)
+		dev_warn(dev, "system is already awake, pm_cnt %d\n", cnt);
+	else {
+		WARN(1, "unexpected pm_cnt %d\n", cnt);
+		ret = -EFAULT;
+	}
+
+	return ret;
+}
+
+static const struct dev_pm_ops sitar_pm_ops = {
+	.suspend	= sitar_suspend,
+	.resume		= sitar_resume,
+};
+#endif
+
+static int __devinit sitar_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	pr_err("%s\n", __func__);
+#ifdef CONFIG_DEBUG_FS
+	debugfs_poke = debugfs_create_file("TRRS",
+		S_IFREG | S_IRUGO, NULL, (void *) "TRRS", &codec_debug_ops);
+
+#endif
+	ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_sitar,
+			sitar_dai, ARRAY_SIZE(sitar_dai));
+	return ret;
+}
+static int __devexit sitar_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove(debugfs_poke);
+#endif
+	return 0;
+}
+static struct platform_driver sitar_codec_driver = {
+	.probe = sitar_probe,
+	.remove = sitar_remove,
+	.driver = {
+		.name = "sitar_codec",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &sitar_pm_ops,
+#endif
+	},
+};
+
+static int __init sitar_codec_init(void)
+{
+	return platform_driver_register(&sitar_codec_driver);
+}
+
+static void __exit sitar_codec_exit(void)
+{
+	platform_driver_unregister(&sitar_codec_driver);
+}
+
+module_init(sitar_codec_init);
+module_exit(sitar_codec_exit);
+
+MODULE_DESCRIPTION("Sitar codec driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wcd9304.h b/sound/soc/codecs/wcd9304.h
new file mode 100644
index 0000000..07a1ca0
--- /dev/null
+++ b/sound/soc/codecs/wcd9304.h
@@ -0,0 +1,72 @@
+/* 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 <sound/soc.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+
+#define SITAR_VERSION_1_0	0x00
+
+#define SITAR_NUM_REGISTERS 0x3E0
+#define SITAR_MAX_REGISTER (SITAR_NUM_REGISTERS-1)
+#define SITAR_CACHE_SIZE SITAR_NUM_REGISTERS
+
+#define SITAR_REG_VAL(reg, val)		{reg, 0, val}
+
+/* Local to the core only */
+#define SITAR_SLIM_MAX_RX_PORTS 5
+#define SITAR_SLIM_MAX_TX_PORTS 5
+
+extern const u8 sitar_reg_readable[SITAR_CACHE_SIZE];
+extern const u8 sitar_reg_defaults[SITAR_CACHE_SIZE];
+
+enum sitar_micbias_num {
+	SITAR_MICBIAS1,
+	SITAR_MICBIAS2,
+};
+
+enum sitar_pid_current {
+	SITAR_PID_MIC_2P5_UA,
+	SITAR_PID_MIC_5_UA,
+	SITAR_PID_MIC_10_UA,
+	SITAR_PID_MIC_20_UA,
+};
+
+struct sitar_mbhc_calibration {
+	enum sitar_micbias_num bias;
+	int tldoh;
+	int bg_fast_settle;
+	enum sitar_pid_current mic_current;
+	int mic_pid;
+	enum sitar_pid_current hph_current;
+	int setup_plug_removal_delay;
+	int shutdown_plug_removal;
+};
+
+struct sitar_reg_mask_val {
+	u16	reg;
+	u8	mask;
+	u8	val;
+};
+
+extern int sitar_hs_detect(struct snd_soc_codec *codec,
+	struct snd_soc_jack *headset_jack, struct snd_soc_jack *button_jack,
+	struct sitar_mbhc_calibration *calibration);
+
+#ifndef anc_header_dec
+struct anc_header {
+	u32 reserved[3];
+	u32 num_anc_slots;
+};
+#define anc_header_dec
+#endif
+
+extern int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable);
diff --git a/sound/soc/codecs/wcd9310-tables.c b/sound/soc/codecs/wcd9310-tables.c
index c681771..e0ad541 100644
--- a/sound/soc/codecs/wcd9310-tables.c
+++ b/sound/soc/codecs/wcd9310-tables.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mfd/wcd9310/registers.h>
+#include <linux/mfd/wcd9xxx/wcd9310_registers.h>
 #include "wcd9310.h"
 
 const u8 tabla_reg_readable[TABLA_CACHE_SIZE] = {
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 46f6461..082b29e 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -18,9 +18,10 @@
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
 #include <linux/debugfs.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/registers.h>
-#include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9310_registers.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -28,6 +29,7 @@
 #include <sound/tlv.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
+#include <linux/pm_runtime.h>
 #include "wcd9310.h"
 
 #define WCD9310_RATES (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\
@@ -171,7 +173,7 @@
 	struct snd_soc_jack *headset_jack;
 	struct snd_soc_jack *button_jack;
 
-	struct tabla_pdata *pdata;
+	struct wcd9xxx_pdata *pdata;
 	u32 anc_slot;
 
 	bool no_mic_headset_override;
@@ -1319,10 +1321,12 @@
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
 	snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
-	tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+	wcd9xxx_enable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
 	if (!tabla->no_mic_headset_override) {
-		tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
-		tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+		wcd9xxx_enable_irq(codec->control_data,
+				TABLA_IRQ_MBHC_POTENTIAL);
+		wcd9xxx_enable_irq(codec->control_data,
+				TABLA_IRQ_MBHC_RELEASE);
 	} else {
 		tabla_codec_disable_button_presses(codec);
 	}
@@ -1336,11 +1340,12 @@
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
 	if (!tabla->no_mic_headset_override) {
-		tabla_disable_irq(codec->control_data,
+		wcd9xxx_disable_irq(codec->control_data,
 			TABLA_IRQ_MBHC_POTENTIAL);
-		tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+		wcd9xxx_disable_irq(codec->control_data,
+			TABLA_IRQ_MBHC_RELEASE);
 	}
 }
 
@@ -1767,7 +1772,7 @@
 			tabla->hphlocp_cnt = 0;
 		else
 			tabla->hphrocp_cnt = 0;
-		tabla_enable_irq(codec->control_data, irq);
+		wcd9xxx_enable_irq(codec->control_data, irq);
 	} else {
 		pr_err("%s: Bad tabla private data\n", __func__);
 	}
@@ -1925,16 +1930,16 @@
 
 static const struct snd_soc_dapm_widget tabla_1_x_dapm_widgets[] = {
 	SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_1_A_MICB_4_CTL, 7,
-			       0, tabla_codec_enable_micbias,
-			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-			       SND_SOC_DAPM_POST_PMD),
+				0, tabla_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_widget tabla_2_higher_dapm_widgets[] = {
 	SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_2_A_MICB_4_CTL, 7,
-			       0, tabla_codec_enable_micbias,
-			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-			       SND_SOC_DAPM_POST_PMD),
+				0, tabla_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_route audio_i2s_map[] = {
@@ -2284,7 +2289,7 @@
 static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg)
 {
 	int i;
-	struct tabla *tabla_core = dev_get_drvdata(ssc->dev->parent);
+	struct wcd9xxx *tabla_core = dev_get_drvdata(ssc->dev->parent);
 
 	if (TABLA_IS_1_X(tabla_core->version)) {
 		for (i = 0; i < ARRAY_SIZE(tabla_1_reg_readable); i++) {
@@ -2333,7 +2338,7 @@
 				reg, ret);
 	}
 
-	return tabla_reg_write(codec->control_data, reg, value);
+	return wcd9xxx_reg_write(codec->control_data, reg, value);
 }
 static unsigned int tabla_read(struct snd_soc_codec *codec,
 				unsigned int reg)
@@ -2353,7 +2358,7 @@
 				reg, ret);
 	}
 
-	val = tabla_reg_read(codec->control_data, reg);
+	val = wcd9xxx_reg_read(codec->control_data, reg);
 	return val;
 }
 
@@ -2543,8 +2548,13 @@
 static int tabla_startup(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
+	struct wcd9xxx *tabla_core = dev_get_drvdata(dai->codec->dev->parent);
 	pr_debug("%s(): substream = %s  stream = %d\n" , __func__,
 		 substream->name, substream->stream);
+	if ((tabla_core != NULL) &&
+	    (tabla_core->dev != NULL) &&
+	    (tabla_core->dev->parent != NULL))
+		pm_runtime_get_sync(tabla_core->dev->parent);
 
 	return 0;
 }
@@ -2552,8 +2562,15 @@
 static void tabla_shutdown(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
+	struct wcd9xxx *tabla_core = dev_get_drvdata(dai->codec->dev->parent);
 	pr_debug("%s(): substream = %s  stream = %d\n" , __func__,
 		 substream->name, substream->stream);
+	if ((tabla_core != NULL) &&
+	    (tabla_core->dev != NULL) &&
+	    (tabla_core->dev->parent != NULL)) {
+		pm_runtime_mark_last_busy(tabla_core->dev->parent);
+		pm_runtime_put(tabla_core->dev->parent);
+	}
 }
 
 int tabla_mclk_enable(struct snd_soc_codec *codec, int mclk_enable)
@@ -2622,7 +2639,7 @@
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBS_CFS:
 		/* CPU is master */
-		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+		if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
 			if (dai->id == AIF1_CAP)
 				snd_soc_update_bits(dai->codec,
 					TABLA_A_CDC_CLK_TX_I2S_CTL,
@@ -2635,7 +2652,7 @@
 		break;
 	case SND_SOC_DAIFMT_CBM_CFM:
 	/* CPU is slave */
-		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+		if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
 			val = TABLA_I2S_MASTER_MODE_MASK;
 			if (dai->id == AIF1_CAP)
 				snd_soc_update_bits(dai->codec,
@@ -2685,7 +2702,7 @@
 				unsigned int *rx_num, unsigned int *rx_slot)
 
 {
-	struct tabla *tabla = dev_get_drvdata(dai->codec->control_data);
+	struct wcd9xxx *tabla = dev_get_drvdata(dai->codec->control_data);
 
 	u32 cnt = 0;
 	u32 tx_ch[SLIM_MAX_TX_PORTS];
@@ -2699,7 +2716,7 @@
 	/* for virtual port, codec driver needs to do
 	 * housekeeping, for now should be ok
 	 */
-	tabla_get_channel(tabla, rx_ch, tx_ch);
+	wcd9xxx_get_channel(tabla, rx_ch, tx_ch);
 	if (dai->id == AIF1_PB) {
 		*rx_num = tabla_dai[dai->id - 1].playback.channels_max;
 		while (cnt < *rx_num) {
@@ -2784,7 +2801,7 @@
 							0x03, tx_fs_rate);
 			}
 		}
-		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+		if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
 			switch (params_format(params)) {
 			case SNDRV_PCM_FORMAT_S16_LE:
 				snd_soc_update_bits(codec,
@@ -2830,7 +2847,7 @@
 						0xE0, rx_fs_rate);
 			}
 		}
-		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+		if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
 			switch (params_format(params)) {
 			case SNDRV_PCM_FORMAT_S16_LE:
 				snd_soc_update_bits(codec,
@@ -2945,7 +2962,7 @@
 static int tabla_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
-	struct tabla *tabla;
+	struct wcd9xxx *tabla;
 	struct snd_soc_codec *codec = w->codec;
 	struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
 	u32  j = 0;
@@ -2953,7 +2970,7 @@
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	tabla = codec->control_data;
 	/* Execute the callback only if interface type is slimbus */
-	if (tabla_p->intf_type != TABLA_INTERFACE_TYPE_SLIMBUS)
+	if (tabla_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
 		return 0;
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
@@ -2967,10 +2984,10 @@
 			}
 		}
 		if (tabla_p->dai[j].ch_act == tabla_p->dai[j].ch_tot)
-			ret = tabla_cfg_slim_sch_rx(tabla,
-						tabla_p->dai[j].ch_num,
-						tabla_p->dai[j].ch_tot,
-						tabla_p->dai[j].rate);
+			ret = wcd9xxx_cfg_slim_sch_rx(tabla,
+					tabla_p->dai[j].ch_num,
+					tabla_p->dai[j].ch_tot,
+					tabla_p->dai[j].rate);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
@@ -2983,12 +3000,12 @@
 			}
 		}
 		if (!tabla_p->dai[j].ch_act) {
-			ret = tabla_close_slim_sch_rx(tabla,
+			ret = wcd9xxx_close_slim_sch_rx(tabla,
 						tabla_p->dai[j].ch_num,
 						tabla_p->dai[j].ch_tot);
 			tabla_p->dai[j].rate = 0;
 			memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
-						tabla_p->dai[j].ch_tot));
+					tabla_p->dai[j].ch_tot));
 			tabla_p->dai[j].ch_tot = 0;
 		}
 	}
@@ -2998,7 +3015,7 @@
 static int tabla_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
-	struct tabla *tabla;
+	struct wcd9xxx *tabla;
 	struct snd_soc_codec *codec = w->codec;
 	struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
 	/* index to the DAI ID, for now hardcoding */
@@ -3009,7 +3026,7 @@
 	tabla = codec->control_data;
 
 	/* Execute the callback only if interface type is slimbus */
-	if (tabla_p->intf_type != TABLA_INTERFACE_TYPE_SLIMBUS)
+	if (tabla_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
 		return 0;
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
@@ -3024,7 +3041,7 @@
 			}
 		}
 		if (tabla_p->dai[j].ch_act == tabla_p->dai[j].ch_tot)
-			ret = tabla_cfg_slim_sch_tx(tabla,
+			ret = wcd9xxx_cfg_slim_sch_tx(tabla,
 						tabla_p->dai[j].ch_num,
 						tabla_p->dai[j].ch_tot,
 						tabla_p->dai[j].rate);
@@ -3041,12 +3058,12 @@
 			}
 		}
 		if (!tabla_p->dai[j].ch_act) {
-			ret = tabla_close_slim_sch_tx(tabla,
+			ret = wcd9xxx_close_slim_sch_tx(tabla,
 						tabla_p->dai[j].ch_num,
 						tabla_p->dai[j].ch_tot);
 			tabla_p->dai[j].rate = 0;
 			memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
-						tabla_p->dai[j].ch_tot));
+					tabla_p->dai[j].ch_tot));
 			tabla_p->dai[j].ch_tot = 0;
 		}
 	}
@@ -3584,7 +3601,7 @@
 	snd_soc_update_bits(codec, tabla->reg_addr.micb_4_mbhc, 0x3,
 			    tabla->micbias);
 
-	tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+	wcd9xxx_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
 	return 0;
 }
@@ -3655,10 +3672,10 @@
 		if (tabla->button_jack) {
 			bias_value = tabla_codec_read_sta_result(tabla->codec);
 			sta_mv = tabla_codec_sta_dce_v(tabla->codec, 0,
-						       bias_value);
+						bias_value);
 			bias_value = tabla_codec_read_dce_result(tabla->codec);
 			dce_mv = tabla_codec_sta_dce_v(tabla->codec, 1,
-						       bias_value);
+						bias_value);
 			pr_debug("%s: Reporting long button press event"
 				 " STA: %d, DCE: %d\n", __func__,
 				 sta_mv, dce_mv);
@@ -3670,7 +3687,6 @@
 		pr_err("%s: Bad tabla private data\n", __func__);
 	}
 
-	tabla_unlock_sleep(core);
 }
 
 void tabla_mbhc_cal(struct snd_soc_codec *codec)
@@ -3850,7 +3866,7 @@
 	struct tabla_mbhc_btn_detect_cfg *btn_det;
 	int n;
 	u8 *n_cic, *gain;
-	struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
+	struct wcd9xxx *tabla_core = dev_get_drvdata(codec->dev->parent);
 
 	tabla = snd_soc_codec_get_drvdata(codec);
 	generic = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
@@ -3998,7 +4014,7 @@
 	if (mclk_rate != TABLA_MCLK_RATE_12288KHZ) {
 		if (mclk_rate == TABLA_MCLK_RATE_9600KHZ)
 			pr_err("Error: clock rate %dHz is not yet supported\n",
-			       mclk_rate);
+				mclk_rate);
 		else
 			pr_err("Error: unsupported clock rate %d\n", mclk_rate);
 		return -EINVAL;
@@ -4037,9 +4053,9 @@
 	if (!IS_ERR_VALUE(rc)) {
 		snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
 			0x10);
-		tabla_enable_irq(codec->control_data,
+		wcd9xxx_enable_irq(codec->control_data,
 			TABLA_IRQ_HPH_PA_OCPL_FAULT);
-		tabla_enable_irq(codec->control_data,
+		wcd9xxx_enable_irq(codec->control_data,
 			TABLA_IRQ_HPH_PA_OCPR_FAULT);
 	}
 
@@ -4057,7 +4073,7 @@
 	btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
 	v_btn_low = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_V_BTN_LOW);
 	v_btn_high = tabla_mbhc_cal_btn_det_mp(btn_det,
-					       TABLA_BTN_DET_V_BTN_HIGH);
+				TABLA_BTN_DET_V_BTN_HIGH);
 	for (i = 0; i < btn_det->num_btn; i++) {
 		if ((v_btn_low[i] <= bias_mv) && (v_btn_high[i] >= bias_mv)) {
 			btn = i;
@@ -4115,10 +4131,10 @@
 	    TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
 	short btnmeas[d->n_btn_meas + 1];
 	struct snd_soc_codec *codec = priv->codec;
-	struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
+	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
 
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
 
 	bias_value_dce = tabla_codec_read_dce_result(codec);
 	bias_mv_dce = tabla_codec_sta_dce_v(codec, 1, bias_value_dce);
@@ -4164,12 +4180,12 @@
 
 		/* XXX: assuming button 0 has the lowest micbias voltage */
 		if (btn == 0) {
-			tabla_lock_sleep(core);
+			wcd9xxx_lock_sleep(core);
 			if (schedule_delayed_work(&priv->btn0_dwork,
 						  msecs_to_jiffies(400)) == 0) {
 				WARN(1, "Button pressed twice without release"
 				     "event\n");
-				tabla_unlock_sleep(core);
+				wcd9xxx_unlock_sleep(core);
 			}
 		} else {
 			pr_debug("%s: Reporting short button %d(0x%x) press\n",
@@ -4191,10 +4207,10 @@
 	short mb_v;
 	struct tabla_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
-	struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
+	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
 
 	pr_debug("%s: enter\n", __func__);
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
 
 	if (priv->buttons_pressed & SND_JACK_BTN_0) {
 		ret = cancel_delayed_work(&priv->btn0_dwork);
@@ -4208,7 +4224,7 @@
 		} else {
 			/* if scheduled btn0_dwork is canceled from here,
 			 * we have to unlock from here instead btn0_work */
-			tabla_unlock_sleep(core);
+			wcd9xxx_unlock_sleep(core);
 			mb_v = tabla_codec_sta_dce(codec, 0);
 			pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
 				 __func__, mb_v,
@@ -4304,7 +4320,7 @@
 			snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
 					    0x10);
 		} else {
-			tabla_disable_irq(codec->control_data,
+			wcd9xxx_disable_irq(codec->control_data,
 					  TABLA_IRQ_HPH_PA_OCPL_FAULT);
 			tabla->hphlocp_cnt = 0;
 			tabla->hph_status |= SND_JACK_OC_HPHL;
@@ -4337,7 +4353,7 @@
 			snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
 					    0x10);
 		} else {
-			tabla_disable_irq(codec->control_data,
+			wcd9xxx_disable_irq(codec->control_data,
 					  TABLA_IRQ_HPH_PA_OCPR_FAULT);
 			tabla->hphrocp_cnt = 0;
 			tabla->hph_status |= SND_JACK_OC_HPHR;
@@ -4357,26 +4373,26 @@
 static void tabla_sync_hph_state(struct tabla_priv *tabla)
 {
 	if (test_and_clear_bit(TABLA_HPHR_PA_OFF_ACK,
-			       &tabla->hph_pa_dac_state)) {
+				&tabla->hph_pa_dac_state)) {
 		pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
 		snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x10,
 				    1 << 4);
 	}
 	if (test_and_clear_bit(TABLA_HPHL_PA_OFF_ACK,
-			       &tabla->hph_pa_dac_state)) {
+				&tabla->hph_pa_dac_state)) {
 		pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
 		snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x20,
 				    1 << 5);
 	}
 
 	if (test_and_clear_bit(TABLA_HPHR_DAC_OFF_ACK,
-			       &tabla->hph_pa_dac_state)) {
+				&tabla->hph_pa_dac_state)) {
 		pr_debug("%s: HPHR clear flag and enable DAC\n", __func__);
 		snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_R_DAC_CTL,
 				    0xC0, 0xC0);
 	}
 	if (test_and_clear_bit(TABLA_HPHL_DAC_OFF_ACK,
-			       &tabla->hph_pa_dac_state)) {
+				&tabla->hph_pa_dac_state)) {
 		pr_debug("%s: HPHL clear flag and enable DAC\n", __func__);
 		snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_L_DAC_CTL,
 				    0xC0, 0xC0);
@@ -4395,7 +4411,7 @@
 	int mic_mv;
 
 	pr_debug("%s: enter\n", __func__);
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
 
 	is_removal = snd_soc_read(codec, TABLA_A_CDC_MBHC_INT_CTL) & 0x02;
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
@@ -4406,7 +4422,7 @@
 
 	if (priv->mbhc_fake_ins_start &&
 	    time_after(jiffies, priv->mbhc_fake_ins_start +
-		       msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
+			msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
 		pr_debug("%s: fake context interrupt, reset insertion\n",
 			 __func__);
 		priv->mbhc_fake_ins_start = 0;
@@ -4482,8 +4498,8 @@
 			     0),
 			 mb_v, mic_mv);
 		if (time_after(jiffies,
-			       priv->mbhc_fake_ins_start +
-			       msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
+			priv->mbhc_fake_ins_start +
+			msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
 			/* Disable HPH trigger and enable MIC line trigger */
 			snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12,
 					    0x00);
@@ -4509,7 +4525,8 @@
 		}
 		/* Setup for insertion detection */
 		snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
-		tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+		wcd9xxx_enable_irq(codec->control_data,
+					TABLA_IRQ_MBHC_INSERTION);
 		snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
 
 	} else if (mb_v < (short) priv->mbhc_data.v_no_mic) {
@@ -4559,9 +4576,9 @@
 	int min_us = TABLA_FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
 
 	pr_debug("%s: enter, removal interrupt\n", __func__);
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
 
 	usleep_range(generic->t_shutdown_plug_rem,
 		     generic->t_shutdown_plug_rem);
@@ -4611,11 +4628,11 @@
 	int i, j;
 	u8 val;
 
-	for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
-		slimbus_value = tabla_interface_reg_read(codec->control_data,
+	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
+		slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
 			TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
 		for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
-			val = tabla_interface_reg_read(codec->control_data,
+			val = wcd9xxx_interface_reg_read(codec->control_data,
 				TABLA_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
 			if (val & 0x1)
 				pr_err_ratelimited("overflow error on port %x,"
@@ -4624,7 +4641,7 @@
 				pr_err_ratelimited("underflow error on port %x,"
 					" value %x\n", i*8 + j, val);
 		}
-		tabla_interface_reg_write(codec->control_data,
+		wcd9xxx_interface_reg_write(codec->control_data,
 			TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
 	}
 
@@ -4635,7 +4652,7 @@
 static int tabla_handle_pdata(struct tabla_priv *tabla)
 {
 	struct snd_soc_codec *codec = tabla->codec;
-	struct tabla_pdata *pdata = tabla->pdata;
+	struct wcd9xxx_pdata *pdata = tabla->pdata;
 	int k1, k2, k3, rc = 0;
 	u8 leg_mode = pdata->amic_settings.legacy_mode;
 	u8 txfe_bypass = pdata->amic_settings.txfe_enable;
@@ -4802,7 +4819,7 @@
 static void tabla_update_reg_defaults(struct snd_soc_codec *codec)
 {
 	u32 i;
-	struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
+	struct wcd9xxx *tabla_core = dev_get_drvdata(codec->dev->parent);
 
 	for (i = 0; i < ARRAY_SIZE(tabla_1_1_reg_defaults); i++)
 		snd_soc_write(codec, tabla_1_1_reg_defaults[i].reg,
@@ -4894,7 +4911,7 @@
 static void tabla_codec_init_reg(struct snd_soc_codec *codec)
 {
 	u32 i;
-	struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
+	struct wcd9xxx *tabla_core = dev_get_drvdata(codec->dev->parent);
 
 	for (i = 0; i < ARRAY_SIZE(tabla_codec_reg_init_val); i++)
 		snd_soc_update_bits(codec, tabla_codec_reg_init_val[i].reg,
@@ -4918,7 +4935,7 @@
 
 static void tabla_update_reg_address(struct tabla_priv *priv)
 {
-	struct tabla *tabla_core = dev_get_drvdata(priv->codec->dev->parent);
+	struct wcd9xxx *tabla_core = dev_get_drvdata(priv->codec->dev->parent);
 	struct tabla_reg_address *reg_addr = &priv->reg_addr;
 
 	if (TABLA_IS_1_X(tabla_core->version)) {
@@ -4934,7 +4951,7 @@
 
 static int tabla_codec_probe(struct snd_soc_codec *codec)
 {
-	struct tabla *control;
+	struct wcd9xxx *control;
 	struct tabla_priv *tabla;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret = 0;
@@ -4973,7 +4990,7 @@
 	tabla->no_mic_headset_override = false;
 	tabla->codec = codec;
 	tabla->pdata = dev_get_platdata(codec->dev->parent);
-	tabla->intf_type = tabla_get_intf_type();
+	tabla->intf_type = wcd9xxx_get_intf_type();
 
 	tabla_update_reg_address(tabla);
 	tabla_update_reg_defaults(codec);
@@ -5002,7 +5019,7 @@
 		snd_soc_dapm_new_controls(dapm, tabla_2_higher_dapm_widgets,
 				    ARRAY_SIZE(tabla_2_higher_dapm_widgets));
 
-	if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+	if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
 		snd_soc_dapm_new_controls(dapm, tabla_dapm_i2s_widgets,
 			ARRAY_SIZE(tabla_dapm_i2s_widgets));
 		snd_soc_dapm_add_routes(dapm, audio_i2s_map,
@@ -5018,49 +5035,49 @@
 				      ARRAY_SIZE(tabla_2_x_lineout_2_to_4_map));
 	} else  {
 		pr_err("%s : ERROR.  Unsupported Tabla version 0x%2x\n",
-		       __func__, control->version);
+			__func__, control->version);
 		goto err_pdata;
 	}
 
 	snd_soc_dapm_sync(dapm);
 
-	ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
+	ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
 		tabla_hs_insert_irq, "Headset insert detect", tabla);
 	if (ret) {
 		pr_err("%s: Failed to request irq %d\n", __func__,
 			TABLA_IRQ_MBHC_INSERTION);
 		goto err_insert_irq;
 	}
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
 
-	ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL,
+	ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL,
 		tabla_hs_remove_irq, "Headset remove detect", tabla);
 	if (ret) {
 		pr_err("%s: Failed to request irq %d\n", __func__,
 			TABLA_IRQ_MBHC_REMOVAL);
 		goto err_remove_irq;
 	}
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
 
-	ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL,
+	ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL,
 		tabla_dce_handler, "DC Estimation detect", tabla);
 	if (ret) {
 		pr_err("%s: Failed to request irq %d\n", __func__,
 			TABLA_IRQ_MBHC_POTENTIAL);
 		goto err_potential_irq;
 	}
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
 
-	ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE,
+	ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE,
 		tabla_release_handler, "Button Release detect", tabla);
 	if (ret) {
 		pr_err("%s: Failed to request irq %d\n", __func__,
 			TABLA_IRQ_MBHC_RELEASE);
 		goto err_release_irq;
 	}
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
 
-	ret = tabla_request_irq(codec->control_data, TABLA_IRQ_SLIMBUS,
+	ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_SLIMBUS,
 		tabla_slimbus_irq, "SLIMBUS Slave", tabla);
 	if (ret) {
 		pr_err("%s: Failed to request irq %d\n", __func__,
@@ -5068,11 +5085,11 @@
 		goto err_slimbus_irq;
 	}
 
-	for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++)
-		tabla_interface_reg_write(codec->control_data,
+	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
+		wcd9xxx_interface_reg_write(codec->control_data,
 			TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
 
-	ret = tabla_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(codec->control_data,
 		TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla_hphl_ocp_irq,
 		"HPH_L OCP detect", tabla);
 	if (ret) {
@@ -5080,9 +5097,9 @@
 			TABLA_IRQ_HPH_PA_OCPL_FAULT);
 		goto err_hphl_ocp_irq;
 	}
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT);
 
-	ret = tabla_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(codec->control_data,
 		TABLA_IRQ_HPH_PA_OCPR_FAULT, tabla_hphr_ocp_irq,
 		"HPH_R OCP detect", tabla);
 	if (ret) {
@@ -5090,7 +5107,7 @@
 			TABLA_IRQ_HPH_PA_OCPR_FAULT);
 		goto err_hphr_ocp_irq;
 	}
-	tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
+	wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
 	for (i = 0; i < ARRAY_SIZE(tabla_dai); i++) {
 		switch (tabla_dai[i].id) {
 		case AIF1_PB:
@@ -5116,17 +5133,18 @@
 	return ret;
 
 err_hphr_ocp_irq:
-	tabla_free_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla);
+	wcd9xxx_free_irq(codec->control_data,
+			TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla);
 err_hphl_ocp_irq:
-	tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
 err_slimbus_irq:
-	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
 err_release_irq:
-	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
 err_potential_irq:
-	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
 err_remove_irq:
-	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
 err_insert_irq:
 err_pdata:
 	kfree(tabla);
@@ -5136,11 +5154,11 @@
 {
 	int i;
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-	tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
-	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
-	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
-	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
-	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
+	wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
 	tabla_codec_disable_clock_block(codec);
 	tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
 	if (tabla->mbhc_fw)
@@ -5227,10 +5245,10 @@
 		S_IFREG | S_IRUGO, NULL, (void *) "TRRS", &codec_debug_ops);
 
 #endif
-	if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_SLIMBUS)
+	if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
 		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
 			tabla_dai, ARRAY_SIZE(tabla_dai));
-	else if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_I2C)
+	else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
 		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
 			tabla_i2s_dai, ARRAY_SIZE(tabla_i2s_dai));
 	return ret;
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 9c430b9..d1d0c17 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -11,7 +11,7 @@
  */
 #include <sound/soc.h>
 #include <sound/jack.h>
-#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
 
 #define TABLA_NUM_REGISTERS 0x400
 #define TABLA_MAX_REGISTER (TABLA_NUM_REGISTERS-1)
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 1ed5f74..3a2687e 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -126,6 +126,7 @@
 	select SND_SOC_QDSP6
 	select SND_SOC_MSM_STUB
 	select SND_SOC_WCD9310
+	select SND_SOC_WCD9304
 	select SND_SOC_MSM_HOSTLESS_PCM
 	select SND_SOC_MSM_QDSP6_HDMI_AUDIO
 	default n
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 6f2d651..2aef4bd 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -62,7 +62,7 @@
 snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
 obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
 
-snd-soc-msm8960-objs := msm8960.o apq8064.o
+snd-soc-msm8960-objs := msm8960.o apq8064.o msm8930.o
 obj-$(CONFIG_SND_SOC_MSM8960) += snd-soc-msm8960.o
 
 # Generic MSM drivers
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index bcf6784..ff50ba6 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -727,6 +727,13 @@
 	return ret;
 }
 
+static int msm_stubrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+	rtd->pmdown_time = 0;
+
+	return 0;
+}
+
 static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err;
@@ -1253,6 +1260,7 @@
 		.no_pcm = 1,
 		/* .be_id = do not care */
 		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.init = &msm_stubrx_init,
 		.ops = &msm_be_ops,
 	},
 	{
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index f0f17a9..7d99322 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.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
@@ -179,6 +179,7 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct compr_audio *compr = runtime->private_data;
 	struct msm_audio *prtd = &compr->prtd;
+	struct asm_aac_cfg aac_cfg;
 	int ret;
 
 	pr_debug("%s\n", __func__);
@@ -189,14 +190,33 @@
 	prtd->samp_rate = runtime->rate;
 	prtd->channel_mode = runtime->channels;
 	prtd->out_head = 0;
+	atomic_set(&prtd->out_count, runtime->periods);
+
 	if (prtd->enabled)
 		return 0;
 
-	ret = q6asm_media_format_block(prtd->audio_client, compr->codec);
-	if (ret < 0)
-		pr_info("%s: CMD Format block failed\n", __func__);
-
-	atomic_set(&prtd->out_count, runtime->periods);
+	switch (compr->info.codec_param.codec.id) {
+	case SND_AUDIOCODEC_MP3:
+		ret = q6asm_media_format_block(prtd->audio_client,
+				compr->codec);
+		if (ret < 0)
+			pr_info("%s: CMD Format block failed\n", __func__);
+		break;
+	case SND_AUDIOCODEC_AAC:
+		pr_debug("SND_AUDIOCODEC_AAC\n");
+		memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
+		aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
+		aac_cfg.format = 0x03;
+		aac_cfg.ch_cfg = runtime->channels;
+		aac_cfg.sample_rate =  runtime->rate;
+		ret = q6asm_media_format_block_aac(prtd->audio_client,
+					&aac_cfg);
+		if (ret < 0)
+			pr_err("%s: CMD Format block failed\n", __func__);
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	prtd->enabled = 1;
 	prtd->cmd_ack = 0;
@@ -250,6 +270,7 @@
 	compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
 	compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
 	compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
+	compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
 	/* Add new codecs here */
 }
 
@@ -504,6 +525,10 @@
 			pr_debug("SND_AUDIOCODEC_MP3\n");
 			compr->codec = FORMAT_MP3;
 			break;
+		case SND_AUDIOCODEC_AAC:
+			pr_debug("SND_AUDIOCODEC_AAC\n");
+			compr->codec = FORMAT_MPEG4_AAC;
+			break;
 		default:
 			pr_debug("FORMAT_LINEAR_PCM\n");
 			compr->codec = FORMAT_LINEAR_PCM;
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
index 6907ded..3333344 100644
--- a/sound/soc/msm/msm-dai-q6-hdmi.c
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -14,10 +14,8 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/wcd9310/core.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
@@ -25,7 +23,6 @@
 #include <sound/q6afe.h>
 #include <sound/q6adm.h>
 #include <sound/msm-dai-q6.h>
-#include <mach/clk.h>
 #include <mach/msm_hdmi_audio.h>
 
 
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 070dc7b..0430f7b 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -14,7 +14,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/wcd9310/core.h>
+#include <linux/mfd/wcd9xxx/core.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index b01c22c..14da1ba 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -254,6 +254,23 @@
 	mutex_unlock(&routing_lock);
 }
 
+/* Check if FE/BE route is set */
+static bool msm_pcm_routing_route_is_set(u16 be_id, u16 fe_id)
+{
+	bool rc = false;
+
+	if (be_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
+		/* recheck FE ID in the mixer control defined in this file */
+		pr_err("%s: bad MM ID\n", __func__);
+		return rc;
+	}
+
+	if (test_bit(fe_id, &msm_bedais[be_id].fe_sessions))
+		rc = true;
+
+	return rc;
+}
+
 static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
 {
 	int session_type, path_type;
@@ -350,10 +367,12 @@
 		(struct soc_mixer_control *)kcontrol->private_value;
 
 
-	if (ucontrol->value.integer.value[0]) {
+	if (ucontrol->value.integer.value[0] &&
+	    msm_pcm_routing_route_is_set(mc->reg, mc->shift) == false) {
 		msm_pcm_routing_process_audio(mc->reg, mc->shift, 1);
 		snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
-	} else {
+	} else if (!ucontrol->value.integer.value[0] &&
+		   msm_pcm_routing_route_is_set(mc->reg, mc->shift) == true) {
 		msm_pcm_routing_process_audio(mc->reg, mc->shift, 0);
 		snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
 	}
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index 471284b..5a0f27a 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -217,6 +217,26 @@
 	return 0;
 }
 
+static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] =
+		voc_get_rx_device_mute(voc_get_session_id(VOICE_SESSION_NAME));
+	return 0;
+}
+
+static int msm_voice_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_rx_device_mute(voc_get_session_id(VOICE_SESSION_NAME), mute);
+
+	return 0;
+}
+
 static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
 static const struct soc_enum msm_tty_mode_enum[] = {
 		SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -308,6 +328,9 @@
 }
 
 static struct snd_kcontrol_new msm_voice_controls[] = {
+	SOC_SINGLE_EXT("Voice Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+				msm_voice_rx_device_mute_get,
+				msm_voice_rx_device_mute_put),
 	SOC_SINGLE_EXT("Voice Tx Mute", SND_SOC_NOPM, 0, 1, 0,
 				msm_voice_mute_get, msm_voice_mute_put),
 	SOC_SINGLE_EXT("Voice Rx Volume", SND_SOC_NOPM, 0, 5, 0,
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 56b4cf5..2301472 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -108,6 +108,7 @@
 	uint32_t mode;
 	uint32_t rate_type;
 	uint32_t rate;
+	uint32_t dtx_mode;
 
 	uint8_t capture_start;
 	uint8_t playback_start;
@@ -200,6 +201,31 @@
 	return 0;
 }
 
+static int msm_voip_dtx_mode_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	mutex_lock(&voip_info.lock);
+
+	voip_info.dtx_mode  = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: dtx: %d\n", __func__, voip_info.dtx_mode);
+
+	mutex_unlock(&voip_info.lock);
+
+	return 0;
+}
+static int msm_voip_dtx_mode_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	mutex_lock(&voip_info.lock);
+
+	ucontrol->value.integer.value[0] = voip_info.dtx_mode;
+
+	mutex_unlock(&voip_info.lock);
+
+	return 0;
+}
+
 static struct snd_kcontrol_new msm_voip_controls[] = {
 	SOC_SINGLE_EXT("Voip Tx Mute", SND_SOC_NOPM, 0, 1, 0,
 				msm_voip_mute_get, msm_voip_mute_put),
@@ -208,6 +234,8 @@
 	SOC_SINGLE_MULTI_EXT("Voip Mode Rate Config", SND_SOC_NOPM, 0, 23850,
 				0, 2, msm_voip_mode_rate_config_get,
 				msm_voip_mode_rate_config_put),
+	SOC_SINGLE_EXT("Voip Dtx Mode", SND_SOC_NOPM, 0, 1, 0,
+				msm_voip_dtx_mode_get, msm_voip_dtx_mode_put),
 };
 
 static int msm_pcm_voip_probe(struct snd_soc_platform *platform)
@@ -713,11 +741,13 @@
 		if ((prtd->play_samp_rate == 8000) &&
 					(prtd->cap_samp_rate == 8000))
 			voc_config_vocoder(media_type, rate_type,
-					VSS_NETWORK_ID_VOIP_NB);
+					VSS_NETWORK_ID_VOIP_NB,
+					voip_info.dtx_mode);
 		else if ((prtd->play_samp_rate == 16000) &&
 					(prtd->cap_samp_rate == 16000))
 			voc_config_vocoder(media_type, rate_type,
-					VSS_NETWORK_ID_VOIP_WB);
+					VSS_NETWORK_ID_VOIP_WB,
+					voip_info.dtx_mode);
 		else {
 			pr_debug("%s: Invalid rate playback %d, capture %d\n",
 				 __func__, prtd->play_samp_rate,
diff --git a/sound/soc/msm/msm-pcm.c b/sound/soc/msm/msm-pcm.c
index bea528f..ea31985 100644
--- a/sound/soc/msm/msm-pcm.c
+++ b/sound/soc/msm/msm-pcm.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -45,8 +45,6 @@
 	msm_adsp_write(prtd->audrec, QDSP_uPAudRecCmdQueue, cmd, len)
 
 int intcnt;
-static int audio_dsp_send_buffer(struct msm_audio *prtd,
-			unsigned idx, unsigned len);
 
 struct audio_frame {
 	uint16_t count_low;
@@ -139,12 +137,15 @@
 			if (prtd->ops->playback)
 				prtd->ops->playback(prtd);
 
+			if (prtd->mmap_flag)
+				break;
+
 			spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
 			if (prtd->running) {
 				prtd->out[idx].used = 0;
 				frame = prtd->out + prtd->out_tail;
 				if (frame->used) {
-					audio_dsp_send_buffer(prtd,
+					alsa_dsp_send_buffer(prtd,
 							      prtd->out_tail,
 							      frame->used);
 					prtd->out_tail ^= 1;
@@ -414,7 +415,7 @@
 		spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
 		frame = prtd->out + prtd->out_tail;
 		if (frame->used && prtd->out_needed) {
-			audio_dsp_send_buffer(prtd, prtd->out_tail,
+			alsa_dsp_send_buffer(prtd, prtd->out_tail,
 					      frame->used);
 			prtd->out_tail ^= 1;
 			prtd->out_needed--;
@@ -583,7 +584,7 @@
 }
 EXPORT_SYMBOL(alsa_buffer_read);
 
-static int audio_dsp_send_buffer(struct msm_audio *prtd,
+int alsa_dsp_send_buffer(struct msm_audio *prtd,
 					unsigned idx, unsigned len)
 {
 	audpp_cmd_pcm_intf_send_buffer cmd;
diff --git a/sound/soc/msm/msm-pcm.h b/sound/soc/msm/msm-pcm.h
index e7ddd30..6e1325b 100644
--- a/sound/soc/msm/msm-pcm.h
+++ b/sound/soc/msm/msm-pcm.h
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -173,11 +173,15 @@
 	int running;
 	int stopped; /* set when stopped, cleared on flush */
 	int eos_ack;
+	int mmap_flag;
+	int period;
 };
 
 
 
 /* platform data */
+extern int alsa_dsp_send_buffer(struct msm_audio *prtd,
+			unsigned idx, unsigned len);
 extern int audio_dsp_out_enable(struct msm_audio *prtd, int yes);
 extern struct snd_soc_platform_driver msm_soc_platform;
 
diff --git a/sound/soc/msm/msm7k-pcm.c b/sound/soc/msm/msm7k-pcm.c
index 1f36e3b..6ef924f 100644
--- a/sound/soc/msm/msm7k-pcm.c
+++ b/sound/soc/msm/msm7k-pcm.c
@@ -1,6 +1,6 @@
 /* linux/sound/soc/msm/msm7k-pcm.c
  *
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * All source code in this file is licensed under the following license except
  * where indicated.
@@ -109,18 +109,20 @@
 }
 
 static struct snd_pcm_hardware msm_pcm_playback_hardware = {
-	.info =                 SNDRV_PCM_INFO_INTERLEAVED,
+	.info =                 SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_MMAP_VALID |
+				SNDRV_PCM_INFO_INTERLEAVED,
 	.formats =              USE_FORMATS,
 	.rates =                USE_RATE,
 	.rate_min =             USE_RATE_MIN,
 	.rate_max =             USE_RATE_MAX,
 	.channels_min =         USE_CHANNELS_MIN,
 	.channels_max =         USE_CHANNELS_MAX,
-	.buffer_bytes_max =     MAX_BUFFER_PLAYBACK_SIZE,
-	.period_bytes_min =     64,
-	.period_bytes_max =     MAX_PERIOD_SIZE,
-	.periods_min =          USE_PERIODS_MIN,
-	.periods_max =          USE_PERIODS_MAX,
+	.buffer_bytes_max =     4800 * 2,
+	.period_bytes_min =     4800,
+	.period_bytes_max =     4800,
+	.periods_min =          2,
+	.periods_max =          2,
 	.fifo_size =            0,
 };
 
@@ -151,10 +153,36 @@
 	.mask = 0,
 };
 
+static void msm_pcm_enqueue_data(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+	unsigned int period_size;
+
+	pr_debug("prtd->out_tail =%d mmap_flag=%d\n",
+			prtd->out_tail, prtd->mmap_flag);
+	period_size = snd_pcm_lib_period_bytes(substream);
+	alsa_dsp_send_buffer(prtd, prtd->out_tail, period_size);
+	prtd->out_tail ^= 1;
+	++copy_count;
+	prtd->period++;
+	if (unlikely(prtd->period >= runtime->periods))
+		prtd->period = 0;
+
+}
+
 static void playback_event_handler(void *data)
 {
 	struct msm_audio *prtd = data;
 	snd_pcm_period_elapsed(prtd->playback_substream);
+	if (prtd->mmap_flag) {
+		if (prtd->dir == SNDRV_PCM_STREAM_CAPTURE)
+			return;
+		if (!prtd->stopped)
+			msm_pcm_enqueue_data(prtd->playback_substream);
+		else
+			prtd->out_needed++;
+	}
 }
 
 static void capture_event_handler(void *data)
@@ -177,6 +205,26 @@
 	prtd->out_sample_rate = runtime->rate;
 	prtd->out_channel_mode = runtime->channels;
 
+	if (prtd->enabled | !(prtd->mmap_flag))
+		return 0;
+
+	prtd->data = substream->dma_buffer.area;
+	prtd->phys = substream->dma_buffer.addr;
+	prtd->out[0].data = prtd->data + 0;
+	prtd->out[0].addr = prtd->phys + 0;
+	prtd->out[0].size = BUFSZ;
+	prtd->out[1].data = prtd->data + BUFSZ;
+	prtd->out[1].addr = prtd->phys + BUFSZ;
+	prtd->out[1].size = BUFSZ;
+
+	prtd->out[0].used = prtd->pcm_count;
+	prtd->out[1].used = prtd->pcm_count;
+
+	mutex_lock(&the_locks.lock);
+	alsa_audio_configure(prtd);
+	mutex_unlock(&the_locks.lock);
+
+
 	return 0;
 }
 
@@ -231,16 +279,55 @@
 
 static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+	unsigned long flag = 0;
 	int ret = 0;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+			|| !prtd->mmap_flag)
+			break;
+		if (!prtd->out_needed) {
+			prtd->stopped = 0;
+			break;
+		}
+		spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
+		if (prtd->running == 1) {
+			if (prtd->stopped == 1) {
+				prtd->stopped = 0;
+				prtd->period = 0;
+				if (prtd->pcm_irq_pos == 0) {
+					prtd->out_tail = 0;
+					msm_pcm_enqueue_data(
+						prtd->playback_substream);
+					prtd->out_needed--;
+				} else {
+					prtd->out_tail = 1;
+					msm_pcm_enqueue_data(
+						prtd->playback_substream);
+					prtd->out_needed--;
+				}
+				if (prtd->out_needed) {
+					prtd->out_tail ^= 1;
+					msm_pcm_enqueue_data(
+						prtd->playback_substream);
+					prtd->out_needed--;
+				}
+			}
+		}
+		spin_unlock_irqrestore(&the_locks.write_dsp_lock, flag);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+			|| !prtd->mmap_flag)
+			break;
+		prtd->stopped = 1;
 		break;
 	default:
 		ret = -EINVAL;
@@ -376,7 +463,6 @@
 	fbytes = frames_to_bytes(runtime, frames);
 	rc = alsa_send_buffer(prtd, buf, fbytes, NULL);
 	++copy_count;
-	prtd->pcm_buf_pos += fbytes;
 	if (copy_count == 1) {
 		mutex_lock(&the_locks.lock);
 		alsa_audio_configure(prtd);
@@ -469,10 +555,27 @@
 		runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
 		runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
 	}
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 	return 0;
 
 }
 
+int msm_pcm_mmap(struct snd_pcm_substream *substream,
+				struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+
+	prtd->out_head = 0; /* point to First buffer on startup */
+	prtd->mmap_flag = 1;
+	runtime->dma_bytes = snd_pcm_lib_period_bytes(substream)*2;
+	dma_mmap_coherent(substream->pcm->card->dev, vma,
+				     runtime->dma_area,
+				     runtime->dma_addr,
+				     runtime->dma_bytes);
+	return 0;
+}
+
 static struct snd_pcm_ops msm_pcm_ops = {
 	.open           = msm_pcm_open,
 	.copy		= msm_pcm_copy,
@@ -482,6 +585,7 @@
 	.prepare        = msm_pcm_prepare,
 	.trigger        = msm_pcm_trigger,
 	.pointer        = msm_pcm_pointer,
+	.mmap		= msm_pcm_mmap,
 };
 
 static int pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
new file mode 100644
index 0000000..a081253
--- /dev/null
+++ b/sound/soc/msm/msm8930.c
@@ -0,0 +1,1083 @@
+/* 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/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc-dsp.h>
+#include <sound/pcm.h>
+#include <sound/jack.h>
+#include <asm/mach-types.h>
+#include <mach/socinfo.h>
+#include "msm-pcm-routing.h"
+#include "../codecs/wcd9304.h"
+
+/* 8930 machine driver */
+
+#define PM8921_GPIO_BASE		NR_GPIO_IRQS
+#define PM8921_GPIO_PM_TO_SYS(pm_gpio)  (pm_gpio - 1 + PM8921_GPIO_BASE)
+
+#define MSM8930_SPK_ON 1
+#define MSM8930_SPK_OFF 0
+
+#define msm8930_SLIM_0_RX_MAX_CHANNELS		2
+#define msm8930_SLIM_0_TX_MAX_CHANNELS		4
+
+#define BTSCO_RATE_8KHZ 8000
+#define BTSCO_RATE_16KHZ 16000
+
+#define BOTTOM_SPK_AMP_POS	0x1
+#define BOTTOM_SPK_AMP_NEG	0x2
+#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 SITAR_EXT_CLK_RATE 12288000
+
+#define SITAR_MBHC_DEF_BUTTONS 3
+#define SITAR_MBHC_DEF_RLOADS 5
+
+static int msm8930_spk_control;
+static int msm8930_slim_0_rx_ch = 1;
+static int msm8930_slim_0_tx_ch = 1;
+
+static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
+static int msm8930_btsco_ch = 1;
+
+static struct clk *codec_clk;
+static int clk_users;
+
+static int msm8930_headset_gpios_configured;
+
+static struct snd_soc_jack hs_jack;
+static struct snd_soc_jack button_jack;
+
+struct sitar_mbhc_calibration sitar_calib = {
+	.bias = SITAR_MICBIAS2,
+	.tldoh = 100,
+	.bg_fast_settle = 100,
+	.mic_current = SITAR_PID_MIC_5_UA,
+	.mic_pid = 100,
+	.hph_current = SITAR_PID_MIC_5_UA,
+	.setup_plug_removal_delay = 1000000,
+	.shutdown_plug_removal = 100000,
+};
+
+static void msm8930_ext_control(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
+	if (msm8930_spk_control == MSM8930_SPK_ON) {
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk Right Pos");
+	} else {
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Right Pos");
+	}
+
+	snd_soc_dapm_sync(dapm);
+}
+
+static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
+	ucontrol->value.integer.value[0] = msm8930_spk_control;
+	return 0;
+}
+static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	pr_debug("%s()\n", __func__);
+	if (msm8930_spk_control == ucontrol->value.integer.value[0])
+		return 0;
+
+	msm8930_spk_control = ucontrol->value.integer.value[0];
+	msm8930_ext_control(codec);
+	return 1;
+}
+
+static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *k, int event)
+{
+	pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
+	/* TODO: add external speaker power amps support */
+	return 0;
+}
+int msm8930_enable_codec_ext_clk(
+		struct snd_soc_codec *codec, int enable)
+{
+	pr_debug("%s: enable = %d\n", __func__, enable);
+	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, SITAR_EXT_CLK_RATE);
+			clk_enable(codec_clk);
+			sitar_mclk_enable(codec, 1);
+		} else {
+			pr_err("%s: Error setting Tabla MCLK\n", __func__);
+			clk_users--;
+			return -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",
+					 __func__, clk_users);
+			clk_disable(codec_clk);
+			sitar_mclk_enable(codec, 0);
+		}
+	}
+	return 0;
+}
+
+static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	pr_debug("%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		return msm8930_enable_codec_ext_clk(w->codec, 1);
+	case SND_SOC_DAPM_POST_PMD:
+		return msm8930_enable_codec_ext_clk(w->codec, 0);
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
+
+	SND_SOC_DAPM_SUPPLY("MCLK",  SND_SOC_NOPM, 0, 0,
+	msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
+	SND_SOC_DAPM_SPK("Ext Spk Right Pos", msm8930_spkramp_event),
+
+	SND_SOC_DAPM_MIC("Handset Mic", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic1", NULL),
+	SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
+
+	SND_SOC_DAPM_MIC("Digital Mic1", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic2", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic3", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic4", NULL),
+
+};
+
+static const struct snd_soc_dapm_route common_audio_map[] = {
+
+	{"RX_BIAS", NULL, "MCLK"},
+	{"LDO_H", NULL, "MCLK"},
+
+	{"MIC BIAS1 Internal1", NULL, "MCLK"},
+	{"MIC BIAS2 Internal1", NULL, "MCLK"},
+
+	/* Speaker path */
+	{"Ext Spk Left Pos", NULL, "LINEOUT1"},
+	{"Ext Spk Right Pos", NULL, "LINEOUT2"},
+
+
+	{"AMIC2", NULL, "MIC BIAS2 Internal1"},
+	{"MIC BIAS2 Internal1", NULL, "Headset Mic"},
+
+	/* Microphone path */
+	{"AMIC1", NULL, "MIC BIAS1 Internal1"},
+	{"MIC BIAS1 Internal1", NULL, "Handset Mic"},
+
+	{"HEADPHONE", NULL, "LDO_H"},
+
+	/**
+	 * The digital Mic routes are setup considering
+	 * fluid as default device.
+	 */
+
+	/**
+	 * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
+	 * Digital Mic GM5 on CDP mainboard.
+	 * Conncted to DMIC2 Input on Tabla codec.
+	 */
+	{"DMIC1", NULL, "MIC BIAS1 External"},
+	{"MIC BIAS1 External", NULL, "Digital Mic1"},
+
+	/**
+	 * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
+	 * Digital Mic GM6 on CDP mainboard.
+	 * Conncted to DMIC1 Input on Tabla codec.
+	 */
+	{"DMIC2", NULL, "MIC BIAS1 External"},
+	{"MIC BIAS1 External", NULL, "Digital Mic2"},
+	/**
+	 * Digital Mic3. Back Bottom Digital Mic on Fluid.
+	 * Digital Mic GM1 on CDP mainboard.
+	 * Conncted to DMIC4 Input on Tabla codec.
+	 */
+	{"DMIC3", NULL, "MIC BIAS2 External"},
+	{"MIC BIAS2 External", NULL, "Digital Mic3"},
+
+	/**
+	 * Digital Mic4. Back top Digital Mic on Fluid.
+	 * Digital Mic GM2 on CDP mainboard.
+	 * Conncted to DMIC3 Input on Tabla codec.
+	 */
+	{"DMIC4", NULL, "MIC BIAS2 External"},
+	{"MIC BIAS2 External", NULL, "Digital Mic4"},
+
+
+};
+
+static const char *spk_function[] = {"Off", "On"};
+static const char *slim0_rx_ch_text[] = {"One", "Two"};
+static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+
+static const struct soc_enum msm8930_enum[] = {
+	SOC_ENUM_SINGLE_EXT(2, spk_function),
+	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+};
+
+static const char *btsco_rate_text[] = {"8000", "16000"};
+static const struct soc_enum msm8930_btsco_enum[] = {
+		SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
+};
+
+static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm8930_slim_0_rx_ch  = %d\n", __func__,
+		 msm8930_slim_0_rx_ch);
+	ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
+	return 0;
+}
+
+static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
+		 msm8930_slim_0_rx_ch);
+	return 1;
+}
+
+static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm8930_slim_0_tx_ch  = %d\n", __func__,
+		 msm8930_slim_0_tx_ch);
+	ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
+	return 0;
+}
+
+static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
+		 msm8930_slim_0_tx_ch);
+	return 1;
+}
+
+static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm8930_btsco_rate  = %d", __func__, msm8930_btsco_rate);
+	ucontrol->value.integer.value[0] = msm8930_btsco_rate;
+	return 0;
+}
+
+static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		msm8930_btsco_rate = BTSCO_RATE_8KHZ;
+		break;
+	case 1:
+		msm8930_btsco_rate = BTSCO_RATE_16KHZ;
+		break;
+	default:
+		msm8930_btsco_rate = BTSCO_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
+	return 0;
+}
+
+static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
+	SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
+		msm8930_set_spk),
+	SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
+		msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
+	SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
+		msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
+};
+
+static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
+	SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
+		msm8930_btsco_rate_get, msm8930_btsco_rate_put),
+};
+
+static int msm8930_btsco_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int err = 0;
+	struct snd_soc_platform *platform = rtd->platform;
+
+	err = snd_soc_add_platform_controls(platform,
+			int_btsco_rate_mixer_controls,
+		ARRAY_SIZE(int_btsco_rate_mixer_controls));
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static int msm8930_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+
+	pr_debug("%s: ch=%d\n", __func__,
+					msm8930_slim_0_rx_ch);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+				msm8930_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+				msm8930_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+							       __func__);
+			goto end;
+		}
+	} else {
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+				msm8930_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,
+				msm8930_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 msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int err;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+
+	pr_debug("%s()\n", __func__);
+
+
+	rtd->pmdown_time = 0;
+
+	err = snd_soc_add_controls(codec, sitar_msm8930_controls,
+				ARRAY_SIZE(sitar_msm8930_controls));
+	if (err < 0)
+		return err;
+
+	snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
+				ARRAY_SIZE(msm8930_dapm_widgets));
+
+	snd_soc_dapm_add_routes(dapm, common_audio_map,
+		ARRAY_SIZE(common_audio_map));
+
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Right Pos");
+
+	snd_soc_dapm_sync(dapm);
+
+	err = snd_soc_jack_new(codec, "Headset Jack",
+		(SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
+		&hs_jack);
+	if (err) {
+		pr_err("failed to create new jack\n");
+		return err;
+	}
+
+	err = snd_soc_jack_new(codec, "Button Jack",
+				SND_JACK_BTN_0, &button_jack);
+	if (err) {
+		pr_err("failed to create new jack\n");
+		return err;
+	}
+	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+	sitar_hs_detect(codec, &hs_jack, &button_jack, &sitar_calib);
+	return 0;
+}
+
+static struct snd_soc_dsp_link lpa_fe_media = {
+	.playback = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static struct snd_soc_dsp_link fe_media = {
+	.playback = true,
+	.capture = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static struct snd_soc_dsp_link slimbus0_hl_media = {
+	.playback = true,
+	.capture = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static struct snd_soc_dsp_link int_fm_hl_media = {
+	.playback = true,
+	.capture = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+/* bi-directional media definition for hostless PCM device */
+static struct snd_soc_dsp_link bidir_hl_media = {
+	.playback = true,
+	.capture = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static struct snd_soc_dsp_link hdmi_rx_hl = {
+	.playback = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static int msm8930_slim_0_rx_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 = msm8930_slim_0_rx_ch;
+
+	return 0;
+}
+
+static int msm8930_slim_0_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 = msm8930_slim_0_tx_ch;
+
+	return 0;
+}
+
+static int msm8930_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);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
+static int msm8930_hdmi_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);
+
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = 2;
+
+	return 0;
+}
+
+static int msm8930_btsco_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);
+
+	rate->min = rate->max = msm8930_btsco_rate;
+	channels->min = channels->max = msm8930_btsco_ch;
+
+	return 0;
+}
+static int msm8930_auxpcm_be_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);
+
+	/* PCM only supports mono output with 8khz sample rate */
+	rate->min = rate->max = 8000;
+	channels->min = channels->max = 1;
+
+	return 0;
+}
+static int msm8930_aux_pcm_get_gpios(void)
+{
+	int ret = 0;
+
+	pr_debug("%s\n", __func__);
+
+	ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
+				__func__, GPIO_AUX_PCM_DOUT);
+		goto fail_dout;
+	}
+
+	ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
+				__func__, GPIO_AUX_PCM_DIN);
+		goto fail_din;
+	}
+
+	ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
+				__func__, GPIO_AUX_PCM_SYNC);
+		goto fail_sync;
+	}
+	ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
+				__func__, GPIO_AUX_PCM_CLK);
+		goto fail_clk;
+	}
+
+	return 0;
+
+fail_clk:
+	gpio_free(GPIO_AUX_PCM_SYNC);
+fail_sync:
+	gpio_free(GPIO_AUX_PCM_DIN);
+fail_din:
+	gpio_free(GPIO_AUX_PCM_DOUT);
+fail_dout:
+
+	return ret;
+}
+
+static int msm8930_aux_pcm_free_gpios(void)
+{
+	gpio_free(GPIO_AUX_PCM_DIN);
+	gpio_free(GPIO_AUX_PCM_DOUT);
+	gpio_free(GPIO_AUX_PCM_SYNC);
+	gpio_free(GPIO_AUX_PCM_CLK);
+
+	return 0;
+}
+static int msm8930_startup(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	return 0;
+}
+
+static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+
+	pr_debug("%s(): substream = %s\n", __func__, substream->name);
+	ret = msm8930_aux_pcm_get_gpios();
+	if (ret < 0) {
+		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+
+	pr_debug("%s(): substream = %s\n", __func__, substream->name);
+	msm8930_aux_pcm_free_gpios();
+}
+
+static void msm8930_shutdown(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+}
+
+static struct snd_soc_ops msm8930_be_ops = {
+	.startup = msm8930_startup,
+	.hw_params = msm8930_hw_params,
+	.shutdown = msm8930_shutdown,
+};
+
+static struct snd_soc_ops msm8930_auxpcm_be_ops = {
+	.startup = msm8930_auxpcm_startup,
+	.shutdown = msm8930_auxpcm_shutdown,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm8930_dai[] = {
+	/* FrontEnd DAI Links */
+	{
+		.name = "MSM8930 Media1",
+		.stream_name = "MultiMedia1",
+		.cpu_dai_name	= "MultiMedia1",
+		.platform_name  = "msm-pcm-dsp",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+	},
+	{
+		.name = "MSM8930 Media2",
+		.stream_name = "MultiMedia2",
+		.cpu_dai_name	= "MultiMedia2",
+		.platform_name  = "msm-pcm-dsp",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+	},
+	{
+		.name = "Circuit-Switch Voice",
+		.stream_name = "CS-Voice",
+		.cpu_dai_name   = "CS-VOICE",
+		.platform_name  = "msm-pcm-voice",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_CS_VOICE,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = "MSM VoIP",
+		.stream_name = "VoIP",
+		.cpu_dai_name	= "VoIP",
+		.platform_name  = "msm-voip-dsp",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_VOIP,
+	},
+	{
+		.name = "MSM8930 LPA",
+		.stream_name = "LPA",
+		.cpu_dai_name	= "MultiMedia3",
+		.platform_name  = "msm-pcm-lpa",
+		.dynamic = 1,
+		.dsp_link = &lpa_fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+	},
+	/* Hostless PMC purpose */
+	{
+		.name = "SLIMBUS_0 Hostless",
+		.stream_name = "SLIMBUS_0 Hostless",
+		.cpu_dai_name	= "SLIMBUS0_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &slimbus0_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* .be_id = do not care */
+	},
+	{
+		.name = "INT_FM Hostless",
+		.stream_name = "INT_FM Hostless",
+		.cpu_dai_name	= "INT_FM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &int_fm_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* .be_id = do not care */
+	},
+	{
+		.name = "MSM AFE-PCM RX",
+		.stream_name = "AFE-PROXY RX",
+		.cpu_dai_name = "msm-dai-q6.241",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+	},
+	{
+		.name = "MSM AFE-PCM TX",
+		.stream_name = "AFE-PROXY TX",
+		.cpu_dai_name = "msm-dai-q6.240",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+	},
+	{
+		.name = "MSM8930 Compr",
+		.stream_name = "COMPR",
+		.cpu_dai_name	= "MultiMedia4",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.dsp_link = &lpa_fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+	},
+	 {
+		.name = "AUXPCM Hostless",
+		.stream_name = "AUXPCM Hostless",
+		.cpu_dai_name   = "AUXPCM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &bidir_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+	},
+	/* HDMI Hostless */
+	{
+		.name = "HDMI_RX_HOSTLESS",
+		.stream_name = "HDMI_RX_HOSTLESS",
+		.cpu_dai_name = "HDMI_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &hdmi_rx_hl,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.no_codec = 1,
+		.ignore_suspend = 1,
+	},
+	/* Backend DAI Links */
+	{
+		.name = LPASS_BE_SLIMBUS_0_RX,
+		.stream_name = "Slimbus Playback",
+		.cpu_dai_name = "msm-dai-q6.16384",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "sitar_codec",
+		.codec_dai_name	= "sitar_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+		.init = &msm8930_audrx_init,
+		.be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8930_be_ops,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_0_TX,
+		.stream_name = "Slimbus Capture",
+		.cpu_dai_name = "msm-dai-q6.16385",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "sitar_codec",
+		.codec_dai_name	= "sitar_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+		.be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8930_be_ops,
+	},
+	/* Backend BT/FM DAI Links */
+	{
+		.name = LPASS_BE_INT_BT_SCO_RX,
+		.stream_name = "Internal BT-SCO Playback",
+		.cpu_dai_name = "msm-dai-q6.12288",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name	= "msm-stub-rx",
+		.init = &msm8930_btsco_init,
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
+		.be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
+	},
+	{
+		.name = LPASS_BE_INT_BT_SCO_TX,
+		.stream_name = "Internal BT-SCO Capture",
+		.cpu_dai_name = "msm-dai-q6.12289",
+		.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_INT_BT_SCO_TX,
+		.be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
+	},
+	{
+		.name = LPASS_BE_INT_FM_RX,
+		.stream_name = "Internal FM Playback",
+		.cpu_dai_name = "msm-dai-q6.12292",
+		.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_INT_FM_RX,
+		.be_hw_params_fixup = msm8930_be_hw_params_fixup,
+	},
+	{
+		.name = LPASS_BE_INT_FM_TX,
+		.stream_name = "Internal FM Capture",
+		.cpu_dai_name = "msm-dai-q6.12293",
+		.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_INT_FM_TX,
+		.be_hw_params_fixup = msm8930_be_hw_params_fixup,
+	},
+	/* HDMI BACK END DAI Link */
+	{
+		.name = LPASS_BE_HDMI,
+		.stream_name = "HDMI Playback",
+		.cpu_dai_name = "msm-dai-q6-hdmi.8",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.no_codec = 1,
+		.be_id = MSM_BACKEND_DAI_HDMI_RX,
+		.be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
+	},
+	/* Backend AFE DAI Links */
+	{
+		.name = LPASS_BE_AFE_PCM_RX,
+		.stream_name = "AFE Playback",
+		.cpu_dai_name = "msm-dai-q6.224",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_codec = 1,
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+	},
+	{
+		.name = LPASS_BE_AFE_PCM_TX,
+		.stream_name = "AFE Capture",
+		.cpu_dai_name = "msm-dai-q6.225",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_codec = 1,
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+	},
+	/* AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_AUXPCM_RX,
+		.stream_name = "AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6.2",
+		.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_AUXPCM_RX,
+		.be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
+		.ops = &msm8930_auxpcm_be_ops,
+	},
+	{
+		.name = LPASS_BE_AUXPCM_TX,
+		.stream_name = "AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6.3",
+		.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_AUXPCM_TX,
+		.be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
+	},
+	/* Incall Music BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE_PLAYBACK_TX,
+		.stream_name = "Voice Farend Playback",
+		.cpu_dai_name = "msm-dai-q6.32773",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.no_codec = 1,
+		.be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+		.be_hw_params_fixup = msm8930_be_hw_params_fixup,
+	},
+	/* Incall Record Uplink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_TX,
+		.stream_name = "Voice Uplink Capture",
+		.cpu_dai_name = "msm-dai-q6.32772",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.no_codec = 1,
+		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+		.be_hw_params_fixup = msm8930_be_hw_params_fixup,
+	},
+	/* Incall Record Downlink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_RX,
+		.stream_name = "Voice Downlink Capture",
+		.cpu_dai_name = "msm-dai-q6.32771",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.no_codec = 1,
+		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+		.be_hw_params_fixup = msm8930_be_hw_params_fixup,
+	},
+};
+
+struct snd_soc_card snd_soc_card_msm8930 = {
+	.name		= "msm8930-sitar-snd-card",
+	.dai_link	= msm8930_dai,
+	.num_links	= ARRAY_SIZE(msm8930_dai),
+};
+
+static struct platform_device *msm8930_snd_device;
+
+static int msm8930_configure_headset_mic_gpios(void)
+{
+	int ret;
+	ret = gpio_request(80, "US_EURO_SWITCH");
+	if (ret) {
+		pr_err("%s: Failed to request gpio 80\n", __func__);
+		return ret;
+	}
+	ret = gpio_direction_output(80, 0);
+	if (ret) {
+		pr_err("%s: Unable to set direction\n", __func__);
+		gpio_free(80);
+	}
+	msm8930_headset_gpios_configured = 0;
+	return 0;
+}
+static void msm8930_free_headset_mic_gpios(void)
+{
+	if (msm8930_headset_gpios_configured)
+		gpio_free(80);
+}
+
+static int __init msm8930_audio_init(void)
+{
+	int ret;
+
+	if (!cpu_is_msm8930()) {
+		pr_err("%s: Not the right machine type\n", __func__);
+		return -ENODEV ;
+	}
+
+	msm8930_snd_device = platform_device_alloc("soc-audio", 0);
+	if (!msm8930_snd_device) {
+		pr_err("Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
+	ret = platform_device_add(msm8930_snd_device);
+	if (ret) {
+		platform_device_put(msm8930_snd_device);
+		return ret;
+	}
+
+	if (msm8930_configure_headset_mic_gpios()) {
+		pr_err("%s Fail to configure headset mic gpios\n", __func__);
+		msm8930_headset_gpios_configured = 0;
+	} else
+		msm8930_headset_gpios_configured = 1;
+
+	return ret;
+
+}
+module_init(msm8930_audio_init);
+
+static void __exit msm8930_audio_exit(void)
+{
+	if (!cpu_is_msm8930()) {
+		pr_err("%s: Not the right machine type\n", __func__);
+		return ;
+	}
+	msm8930_free_headset_mic_gpios();
+	platform_device_unregister(msm8930_snd_device);
+}
+module_exit(msm8930_audio_exit);
+
+MODULE_DESCRIPTION("ALSA SoC MSM8930");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index eb363e7..0854dff 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1391,7 +1391,7 @@
 {
 	int ret;
 
-	if (!cpu_is_msm8960() && !cpu_is_msm8930()) {
+	if (!cpu_is_msm8960()) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return -ENODEV ;
 	}
@@ -1455,7 +1455,7 @@
 
 static void __exit msm8960_audio_exit(void)
 {
-	if (!cpu_is_msm8960() && !cpu_is_msm8930()) {
+	if (!cpu_is_msm8960()) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return ;
 	}
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 2710fbb..7a16a10 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -205,8 +205,10 @@
 	get_audproc_cal(acdb_path, &aud_cal);
 
 	/* map & cache buffers used */
-	if ((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr)  &&
-		(aud_cal.cal_size > 0)) {
+	if (((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr)  &&
+		(aud_cal.cal_size > 0)) ||
+		(aud_cal.cal_size > mem_addr_audproc[acdb_path].cal_size)) {
+
 		if (mem_addr_audproc[acdb_path].cal_paddr != 0)
 			adm_memory_unmap_regions(
 				&mem_addr_audproc[acdb_path].cal_paddr,
@@ -233,8 +235,9 @@
 	get_audvol_cal(acdb_path, &aud_cal);
 
 	/* map & cache buffers used */
-	if ((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr)  &&
-		(aud_cal.cal_size > 0)) {
+	if (((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr)  &&
+		(aud_cal.cal_size > 0))  ||
+		(aud_cal.cal_size > mem_addr_audvol[acdb_path].cal_size)) {
 		if (mem_addr_audvol[acdb_path].cal_paddr != 0)
 			adm_memory_unmap_regions(
 				&mem_addr_audvol[acdb_path].cal_paddr,
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 59506f1..be08e25 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -37,7 +37,7 @@
 
 static struct afe_ctl this_afe;
 
-static uint32_t afe_cal_addr[MAX_AUDPROC_TYPES];
+static struct acdb_cal_block afe_cal_addr[MAX_AUDPROC_TYPES];
 
 #define TIMEOUT_MS 1000
 #define Q6AFE_MAX_VOLUME 0x3FFF
@@ -332,12 +332,16 @@
 		goto done;
 	}
 
-	if (afe_cal_addr[path] != cal_block.cal_paddr) {
-		if (afe_cal_addr[path] != 0)
-			afe_cmd_memory_unmap_nowait(afe_cal_addr[path]);
+	if ((afe_cal_addr[path].cal_paddr != cal_block.cal_paddr) ||
+		(cal_block.cal_size > afe_cal_addr[path].cal_size)) {
+		if (afe_cal_addr[path].cal_paddr != 0)
+			afe_cmd_memory_unmap_nowait(
+				afe_cal_addr[path].cal_paddr);
+
 		afe_cmd_memory_map_nowait(cal_block.cal_paddr,
 						cal_block.cal_size);
-		afe_cal_addr[path] = cal_block.cal_paddr;
+		afe_cal_addr[path].cal_paddr = cal_block.cal_paddr;
+		afe_cal_addr[path].cal_size = cal_block.cal_size;
 	}
 
 	afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1565,8 +1569,9 @@
 		debugfs_remove(debugfs_afelb_gain);
 #endif
 	for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
-		if (afe_cal_addr[i] != 0)
-			afe_cmd_memory_unmap_nowait(afe_cal_addr[i]);
+		if (afe_cal_addr[i].cal_paddr != 0)
+			afe_cmd_memory_unmap_nowait(
+				afe_cal_addr[i].cal_paddr);
 	}
 }
 
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index d822af5..fe31b27 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -240,6 +240,13 @@
 
 		while (cnt >= 0) {
 			if (port->buf[cnt].data) {
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+				ion_unmap_kernel(port->buf[cnt].client,
+						port->buf[cnt].handle);
+				ion_free(port->buf[cnt].client,
+						port->buf[cnt].handle);
+				ion_client_destroy(port->buf[cnt].client);
+#else
 				pr_debug("%s:data[%p]phys[%p][%p] cnt[%d]"
 					 "mem_buffer[%p]\n",
 					__func__, (void *)port->buf[cnt].data,
@@ -259,6 +266,7 @@
 				free_contiguous_memory_by_paddr(
 					port->buf[cnt].phys);
 
+#endif
 				port->buf[cnt].data = NULL;
 				port->buf[cnt].phys = 0;
 				--(port->max_buf_cnt);
@@ -295,6 +303,19 @@
 	}
 
 	if (port->buf[0].data) {
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
+		ion_free(port->buf[0].client, port->buf[0].handle);
+		ion_client_destroy(port->buf[0].client);
+		pr_debug("%s:data[%p]phys[%p][%p]"
+			", client[%p] handle[%p]\n",
+			__func__,
+			(void *)port->buf[0].data,
+			(void *)port->buf[0].phys,
+			(void *)&port->buf[0].phys,
+			(void *)port->buf[0].client,
+			(void *)port->buf[0].handle);
+#else
 		pr_debug("%s:data[%p]phys[%p][%p]"
 			"mem_buffer[%p]\n",
 			__func__,
@@ -313,6 +334,7 @@
 					" failed\n", __func__);
 		}
 		free_contiguous_memory_by_paddr(port->buf[0].phys);
+#endif
 	}
 
 	while (cnt >= 0) {
@@ -465,6 +487,9 @@
 	int cnt = 0;
 	int rc = 0;
 	struct audio_buffer *buf;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	int len;
+#endif
 
 	if (!(ac) || ((dir != IN) && (dir != OUT)))
 		return -EINVAL;
@@ -494,6 +519,50 @@
 		while (cnt < bufcnt) {
 			if (bufsz > 0) {
 				if (!buf[cnt].data) {
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+					buf[cnt].client = msm_ion_client_create
+						(UINT_MAX, "audio_client");
+					if (IS_ERR_OR_NULL((void *)
+						buf[cnt].client)) {
+						pr_err("%s: ION create client"
+						" for AUDIO failed\n",
+						__func__);
+						goto fail;
+					}
+					buf[cnt].handle = ion_alloc
+						(buf[cnt].client, bufsz, SZ_4K,
+						(0x1 << ION_AUDIO_HEAP_ID));
+					if (IS_ERR_OR_NULL((void *)
+						buf[cnt].handle)) {
+						pr_err("%s: ION memory"
+					" allocation for AUDIO failed\n",
+							__func__);
+						goto fail;
+					}
+
+					rc = ion_phys(buf[cnt].client,
+						buf[cnt].handle,
+						(ion_phys_addr_t *)
+						&buf[cnt].phys,
+						(size_t *)&len);
+					if (rc) {
+						pr_err("%s: ION Get Physical"
+						" for AUDIO failed, rc = %d\n",
+							__func__, rc);
+						goto fail;
+					}
+
+					buf[cnt].data = ion_map_kernel
+					(buf[cnt].client, buf[cnt].handle,
+							 0);
+					if (IS_ERR_OR_NULL((void *)
+						buf[cnt].data)) {
+						pr_err("%s: ION memory"
+				" mapping for AUDIO failed\n", __func__);
+						goto fail;
+					}
+					memset((void *)buf[cnt].data, 0, bufsz);
+#else
 					unsigned int flags = 0;
 					buf[cnt].phys =
 					allocate_contiguous_ebi_nomap(bufsz,
@@ -526,16 +595,15 @@
 						mutex_unlock(&ac->cmd_lock);
 						goto fail;
 					}
+#endif
 					buf[cnt].used = 1;
 					buf[cnt].size = bufsz;
 					buf[cnt].actual_size = bufsz;
-					pr_debug("%s data[%p]phys[%p][%p]"
-						 "mem_buffer[%p]\n",
+					pr_debug("%s data[%p]phys[%p][%p]\n",
 						__func__,
 					   (void *)buf[cnt].data,
 					   (void *)buf[cnt].phys,
-					   (void *)&buf[cnt].phys,
-					   (void *)buf[cnt].mem_buffer);
+					   (void *)&buf[cnt].phys);
 					cnt++;
 				}
 			}
@@ -562,9 +630,12 @@
 {
 	int cnt = 0;
 	int rc = 0;
-	int flags = 0;
 	struct audio_buffer *buf;
-
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	int len;
+#else
+	int flags = 0;
+#endif
 	if (!(ac) || ((dir != IN) && (dir != OUT)))
 		return -EINVAL;
 
@@ -590,6 +661,35 @@
 
 	ac->port[dir].buf = buf;
 
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
+	if (IS_ERR_OR_NULL((void *)buf[0].client)) {
+		pr_err("%s: ION create client for AUDIO failed\n", __func__);
+		goto fail;
+	}
+	buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
+				  (0x1 << ION_AUDIO_HEAP_ID));
+	if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
+		pr_err("%s: ION memory allocation for AUDIO failed\n",
+			__func__);
+		goto fail;
+	}
+
+	rc = ion_phys(buf[0].client, buf[0].handle,
+		  (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+			__func__, rc);
+		goto fail;
+	}
+
+	buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle, 0);
+	if (IS_ERR_OR_NULL((void *) buf[0].data)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		goto fail;
+	}
+	memset((void *)buf[0].data, 0, (bufsz * bufcnt));
+#else
 	buf[0].phys = allocate_contiguous_ebi_nomap(bufsz * bufcnt,
 						SZ_4K);
 	if (!buf[0].phys) {
@@ -612,6 +712,7 @@
 		goto fail;
 	}
 	buf[0].data = buf[0].mem_buffer->vaddr;
+#endif
 	if (!buf[0].data) {
 		pr_err("%s:invalid vaddr,"
 			" iomap failed\n", __func__);
@@ -726,6 +827,9 @@
 	if (data->opcode == RESET_EVENTS) {
 		pr_debug("q6asm_callback: Reset event is received: %d %d apr[%p]\n",
 				data->reset_event, data->reset_proc, ac->apr);
+			if (ac->cb)
+				ac->cb(data->opcode, data->token,
+					(uint32_t *)data->payload, ac->priv);
 		apr_reset(ac->apr);
 		return 0;
 	}
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 532d92b..0376f34 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -662,6 +662,59 @@
 	return -EINVAL;
 }
 
+static int voice_set_dtx(struct voice_data *v)
+{
+	int ret = 0;
+	void *apr_cvs;
+	u16 cvs_handle;
+	struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_cvs = common.apr_q6_cvs;
+
+	if (!apr_cvs) {
+		pr_err("%s: apr_cvs is NULL.\n", __func__);
+		return -EINVAL;
+	}
+
+	cvs_handle = voice_get_cvs_handle(v);
+
+	/* Set DTX */
+	cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+					      APR_HDR_LEN(APR_HDR_SIZE),
+					      APR_PKT_VER);
+	cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+					sizeof(cvs_set_dtx) - APR_HDR_SIZE);
+	cvs_set_dtx.hdr.src_port = v->session_id;
+	cvs_set_dtx.hdr.dest_port = cvs_handle;
+	cvs_set_dtx.hdr.token = 0;
+	cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
+	cvs_set_dtx.dtx_mode.enable = common.mvs_info.dtx_mode;
+
+	pr_debug("%s: Setting DTX %d\n", __func__, common.mvs_info.dtx_mode);
+
+	v->cvs_state = CMD_STATUS_FAIL;
+
+	ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
+	if (ret < 0) {
+		pr_err("%s: Error %d sending SET_DTX\n", __func__, ret);
+		return -EINVAL;
+	}
+
+	ret = wait_event_timeout(v->cvs_wait,
+				 (v->cvs_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int voice_config_cvs_vocoder(struct voice_data *v)
 {
 	int ret = 0;
@@ -753,7 +806,6 @@
 	}
 	case VSS_MEDIA_ID_AMR_NB_MODEM: {
 		struct cvs_set_amr_enc_rate_cmd cvs_set_amr_rate;
-		struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
 
 		pr_debug("Setting AMR rate\n");
 
@@ -785,40 +837,15 @@
 			pr_err("%s: wait_event timeout\n", __func__);
 			goto fail;
 		}
-		/* Disable DTX */
-		pr_debug("Disabling DTX\n");
 
-		cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-						      APR_HDR_LEN(APR_HDR_SIZE),
-						      APR_PKT_VER);
-		cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-					sizeof(cvs_set_dtx) - APR_HDR_SIZE);
-		cvs_set_dtx.hdr.src_port = v->session_id;
-		cvs_set_dtx.hdr.dest_port = cvs_handle;
-		cvs_set_dtx.hdr.token = 0;
-		cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
-		cvs_set_dtx.dtx_mode.enable = 0;
-
-		v->cvs_state = CMD_STATUS_FAIL;
-
-		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
-		if (ret < 0) {
-			pr_err("%s: Error %d sending SET_DTX\n",
-			       __func__, ret);
+		ret = voice_set_dtx(v);
+		if (ret < 0)
 			goto fail;
-		}
-		ret = wait_event_timeout(v->cvs_wait,
-					 (v->cvs_state == CMD_STATUS_SUCCESS),
-					 msecs_to_jiffies(TIMEOUT_MS));
-		if (!ret) {
-			pr_err("%s: wait_event timeout\n", __func__);
-			goto fail;
-		}
+
 		break;
 	}
 	case VSS_MEDIA_ID_AMR_WB_MODEM: {
 		struct cvs_set_amrwb_enc_rate_cmd cvs_set_amrwb_rate;
-		struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
 
 		pr_debug("Setting AMR WB rate\n");
 
@@ -851,70 +878,18 @@
 			pr_err("%s: wait_event timeout\n", __func__);
 			goto fail;
 		}
-		/* Disable DTX */
-		pr_debug("Disabling DTX\n");
 
-		cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-						      APR_HDR_LEN(APR_HDR_SIZE),
-						      APR_PKT_VER);
-		cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-				       sizeof(cvs_set_dtx) - APR_HDR_SIZE);
-		cvs_set_dtx.hdr.src_port = v->session_id;
-		cvs_set_dtx.hdr.dest_port = cvs_handle;
-		cvs_set_dtx.hdr.token = 0;
-		cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
-		cvs_set_dtx.dtx_mode.enable = 0;
-
-		v->cvs_state = CMD_STATUS_FAIL;
-
-		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
-		if (ret < 0) {
-			pr_err("%s: Error %d sending SET_DTX\n",
-			       __func__, ret);
+		ret = voice_set_dtx(v);
+		if (ret < 0)
 			goto fail;
-		}
-		ret = wait_event_timeout(v->cvs_wait,
-					 (v->cvs_state == CMD_STATUS_SUCCESS),
-					 msecs_to_jiffies(TIMEOUT_MS));
-		if (!ret) {
-			pr_err("%s: wait_event timeout\n", __func__);
-			goto fail;
-		}
+
 		break;
 	}
 	case VSS_MEDIA_ID_G729:
 	case VSS_MEDIA_ID_G711_ALAW:
 	case VSS_MEDIA_ID_G711_MULAW: {
-		struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
-		/* Disable DTX */
-		pr_debug("Disabling DTX\n");
+		ret = voice_set_dtx(v);
 
-		cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-						      APR_HDR_LEN(APR_HDR_SIZE),
-						      APR_PKT_VER);
-		cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-					    sizeof(cvs_set_dtx) - APR_HDR_SIZE);
-		cvs_set_dtx.hdr.src_port = v->session_id;
-		cvs_set_dtx.hdr.dest_port = cvs_handle;
-		cvs_set_dtx.hdr.token = 0;
-		cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
-		cvs_set_dtx.dtx_mode.enable = 0;
-
-		v->cvs_state = CMD_STATUS_FAIL;
-
-		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
-		if (ret < 0) {
-			pr_err("%s: Error %d sending SET_DTX\n",
-			       __func__, ret);
-			goto fail;
-		}
-		ret = wait_event_timeout(v->cvs_wait,
-					 (v->cvs_state == CMD_STATUS_SUCCESS),
-					 msecs_to_jiffies(TIMEOUT_MS));
-		if (!ret) {
-			pr_err("%s: wait_event timeout\n", __func__);
-			goto fail;
-		}
 		break;
 	}
 	default:
@@ -2307,6 +2282,51 @@
 	return -EINVAL;
 }
 
+static int voice_send_rx_device_mute_cmd(struct voice_data *v)
+{
+	struct cvp_set_mute_cmd cvp_mute_cmd;
+	int ret = 0;
+	void *apr_cvp;
+	u16 cvp_handle;
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_cvp = common.apr_q6_cvp;
+
+	if (!apr_cvp) {
+		pr_err("%s: apr_cvp is NULL.\n", __func__);
+		return -EINVAL;
+	}
+	cvp_handle = voice_get_cvp_handle(v);
+
+	cvp_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+						APR_HDR_LEN(APR_HDR_SIZE),
+						APR_PKT_VER);
+	cvp_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+					sizeof(cvp_mute_cmd) - APR_HDR_SIZE);
+	cvp_mute_cmd.hdr.src_port = v->session_id;
+	cvp_mute_cmd.hdr.dest_port = cvp_handle;
+	cvp_mute_cmd.hdr.token = 0;
+	cvp_mute_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_MUTE;
+	cvp_mute_cmd.cvp_set_mute.direction = 1;
+	cvp_mute_cmd.cvp_set_mute.mute_flag = v->dev_rx.mute;
+	v->cvp_state = CMD_STATUS_FAIL;
+	ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_mute_cmd);
+	if (ret < 0) {
+		pr_err("Fail in sending RX device mute cmd\n");
+		return -EINVAL;
+	}
+	ret = wait_event_timeout(v->cvp_wait,
+				 (v->cvp_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int voice_send_vol_index_cmd(struct voice_data *v)
 {
 	struct cvp_set_rx_volume_index_cmd cvp_vol_cmd;
@@ -2908,6 +2928,49 @@
 	return ret;
 }
 
+int voc_set_rx_device_mute(uint16_t session_id, uint32_t mute)
+{
+	struct voice_data *v = voice_get_session(session_id);
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+
+		return -EINVAL;
+	}
+
+	mutex_lock(&v->lock);
+
+	v->dev_rx.mute = mute;
+
+	if (v->voc_state == VOC_RUN)
+		ret = voice_send_rx_device_mute_cmd(v);
+
+	mutex_unlock(&v->lock);
+
+	return ret;
+}
+
+int voc_get_rx_device_mute(uint16_t session_id)
+{
+	struct voice_data *v = voice_get_session(session_id);
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+
+		return -EINVAL;
+	}
+
+	mutex_lock(&v->lock);
+
+	ret = v->dev_rx.mute;
+
+	mutex_unlock(&v->lock);
+
+	return ret;
+}
+
 int voc_set_tty_mode(uint16_t session_id, uint8_t tty_mode)
 {
 	struct voice_data *v = voice_get_session(session_id);
@@ -3236,11 +3299,13 @@
 
 void voc_config_vocoder(uint32_t media_type,
 			  uint32_t rate,
-			  uint32_t network_type)
+			  uint32_t network_type,
+			  uint32_t dtx_mode)
 {
 	common.mvs_info.media_type = media_type;
 	common.mvs_info.rate = rate;
 	common.mvs_info.network_type = network_type;
+	common.mvs_info.dtx_mode = dtx_mode;
 }
 
 static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
@@ -3594,6 +3659,7 @@
 
 		/* initialize dev_rx and dev_tx */
 		common.voice[i].dev_rx.volume = common.default_vol_val;
+		common.voice[i].dev_rx.mute =  0;
 		common.voice[i].dev_tx.mute = common.default_mute_val;
 
 		common.voice[i].dev_tx.port_id = 1;
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 2dc08d6..0edf1c9 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -637,6 +637,8 @@
 #define VSS_MEDIA_ID_G729		0x00010FD0
 /* G.729AB (contains two 10ms vocoder frames. */
 
+#define VSS_IVOCPROC_CMD_SET_MUTE			0x000110EF
+
 #define VOICE_CMD_SET_PARAM				0x00011006
 #define VOICE_CMD_GET_PARAM				0x00011007
 #define VOICE_EVT_GET_PARAM_ACK				0x00011008
@@ -729,6 +731,22 @@
 	/* Size of the volume calibration table in bytes. */
 } __packed;
 
+struct vss_ivocproc_cmd_set_mute_t {
+	uint16_t direction;
+	/*
+	* 0 : TX only.
+	* 1 : RX only.
+	* 2 : TX and Rx.
+	*/
+	uint16_t mute_flag;
+	/*
+	* Mute, un-mute.
+	*
+	* 0 : Disable.
+	* 1 : Enable.
+	*/
+} __packed;
+
 struct cvp_create_full_ctl_session_cmd {
 	struct apr_hdr hdr;
 	struct vss_ivocproc_cmd_create_full_control_session_t cvp_session;
@@ -770,6 +788,11 @@
 	struct apr_hdr hdr;
 } __packed;
 
+struct cvp_set_mute_cmd {
+	struct apr_hdr hdr;
+	struct vss_ivocproc_cmd_set_mute_t cvp_set_mute;
+} __packed;
+
 /* CB for up-link packets. */
 typedef void (*ul_cb_fn)(uint8_t *voc_pkt,
 			 uint32_t pkt_len,
@@ -785,6 +808,7 @@
 	uint32_t media_type;
 	uint32_t rate;
 	uint32_t network_type;
+	uint32_t dtx_mode;
 	ul_cb_fn ul_cb;
 	dl_cb_fn dl_cb;
 	void *private_data;
@@ -876,7 +900,8 @@
 
 void voc_config_vocoder(uint32_t media_type,
 			uint32_t rate,
-			uint32_t network_type);
+			uint32_t network_type,
+			uint32_t dtx_mode);
 
 enum {
 	DEV_RX = 0,
@@ -902,6 +927,8 @@
 		      uint32_t dev_type);
 int voc_set_rx_vol_index(uint16_t session_id, uint32_t dir, uint32_t voc_idx);
 int voc_set_tx_mute(uint16_t session_id, uint32_t dir, uint32_t mute);
+int voc_set_rx_device_mute(uint16_t session_id, uint32_t mute);
+int voc_get_rx_device_mute(uint16_t session_id);
 int voc_disable_cvp(uint16_t session_id);
 int voc_enable_cvp(uint16_t session_id);
 int voc_set_route_flag(uint16_t session_id, uint8_t path_dir, uint8_t set);