Merge "Merge remote-tracking branch 'kdorfman/emmc_base' into merge/kdorfman" into msm-3.0
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index 50db52c..cc94b69 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -17,7 +17,7 @@
 ifeq "$(KERNEL_USE_OF)" "y"
 KERNEL_ZIMG = $(KERNEL_OUT)/arch/arm/boot/zImage
 DTB_FILE = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH).dtb
-DTS_FILE = $(KERNEL_OUT)/../../../../../../kernel/arch/arm/boot/dts/$(MSM_ARCH).dts
+DTS_FILE = $(TOP)/kernel/arch/arm/boot/dts/$(MSM_ARCH).dts
 FULL_KERNEL = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH)-zImage
 DTC = $(KERNEL_OUT)/scripts/dtc/dtc
 
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index 4fb653e..084050e 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -24,13 +24,13 @@
 
 Example:
 
-	qcom,sdcc@F9600000 {
+	qcom,sdcc@f9600000 {
 	/* SDC1 used as eMMC slot */
 	cell-index = <1>;
 	compatible = "qcom,msm-sdcc";
-	reg = <0xF9600000 0x800   // SDCC register interface
-		0xF9600800 0x1800  // DML register interface
-		0xF9602000 0x2000> // BAM register interface
+	reg = <0xf9600000 0x800   // SDCC register interface
+		0xf9600800 0x1800  // DML register interface
+		0xf9602000 0x2000> // BAM register interface
 
 	interrupts = <123>;
 	qcom,sdcc-clk-rates = <400000 24000000 48000000>;
diff --git a/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt b/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
new file mode 100644
index 0000000..8cc3c54
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
@@ -0,0 +1,32 @@
+Qualcomm SPMI Controller (PMIC Arbiter)
+
+Required properties:
+- cell-index : the bus identifier.
+- compatible : should be "qcom,spmi-pmic-arb".
+- reg : offset and length of the PMIC Arbiter Core register map.
+- reg : offset and length of the PMIC Arbiter Interrupt controller register map.
+- interrupts : the PMIC Arbiter interrupt.
+- qcom,pmic-arb-ee : the execution environment (EE) identifier.
+- qcom,pmic-arb-channel : the assigned channel number for channel registers.
+- qcom,pmic-arb-ppid-map : an array used to map a 12-bit PPID to 8-bit APID.
+
+Peripherals on the SPMI bus are identified with a 12-bit identifier (PPID)
+which is composed of a 4-bit slave address and an 8-bit peripheral identifier.
+The PMIC Arbiter hardware uses an 8-bit APID (Arbiter Peripheral Identifier)
+internally.  Software needs the mapping between the APID and the PPID.
+Up to a maximum of 256 peripherals are supported and the mapping is target
+specific.
+
+Example:
+
+	qcom,spmi@fc4c0000 {
+		cell-index = <0>;
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0xfc4cf000 0x1000>,
+		      <0Xfc4cb000 0x1000>;
+		interrupts = <0>;
+		qcom,pmic-arb-ee = <0>;
+		qcom,pmic-arb-channel = <0>;
+		qcom,pmic-arb-ppid-map = <0x130 0x00>, /* PPID 0x130, APID 0 */
+					 <0x131 0x01>; /* PPID 0x131, APID 1 */
+	};
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index c1399ae..95ddf34 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -35,16 +35,16 @@
 - qcom,hsusb-otg-pmic-id-irq: ID, routed to PMIC IRQ number
 
 Example HSUSB OTG controller device node :
-	usb@F9690000 {
+	usb@f9690000 {
 		compatible = "qcom,hsusb-otg";
-		reg = <0xF9690000 0x400>;
+		reg = <0xf9690000 0x400>;
 		interrupts = <134>;
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <1>;
 		qcom,hsusb-otg-default-mode = <2>;
-		qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xFFFFFFFF>;
+		qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xffffffff>;
 		qcom,hsusb-otg-power-budget = <500>;
 		qcom,hsusb-otg-pclk-src-name = "dfab_usb_clk";
 		qcom,hsusb-otg-pmic-id-irq = <47>
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index 57ad77a..725971d 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -27,15 +27,15 @@
 		interrupts = <1 2 0>;
 	};
 
-	serial@F991F000 {
+	serial@f991f000 {
 		compatible = "qcom,msm-lsuart-v14";
-		reg = <0xF991F000 0x1000>;
+		reg = <0xf991f000 0x1000>;
 		interrupts = <0 109 0>;
 	};
 
-	usb@F9A55000 {
+	usb@f9a55000 {
 		compatible = "qcom,hsusb-otg";
-		reg = <0xF9A55000 0x400>;
+		reg = <0xf9a55000 0x400>;
 		interrupts = <0 134 0>;
 
 		qcom,hsusb-otg-phy-type = <2>;
@@ -43,10 +43,10 @@
 		qcom,hsusb-otg-otg-control = <1>;
 	};
 
-	qcom,sdcc@F980B000 {
+	qcom,sdcc@f980b000 {
 		cell-index = <1>;
 		compatible = "qcom,msm-sdcc";
-		reg = <0xF980B000 0x1000>;
+		reg = <0xf980b000 0x1000>;
 		interrupts = <0 123 0>;
 
 		qcom,sdcc-clk-rates = <400000 24000000 48000000>;
@@ -56,10 +56,10 @@
 		qcom,sdcc-disable_cmd23;
 	};
 
-	qcom,sdcc@F984B000 {
+	qcom,sdcc@f984b000 {
 		cell-index = <3>;
 		compatible = "qcom,msm-sdcc";
-		reg = <0xF984B000 0x1000>;
+		reg = <0xf984b000 0x1000>;
 		interrupts = <0 127 0>;
 
 		qcom,sdcc-clk-rates = <400000 24000000 48000000>;
@@ -68,10 +68,10 @@
 		qcom,sdcc-disable_cmd23;
 	};
 
-	qcom,sps@F9980000 {
+	qcom,sps@f9980000 {
 		compatible = "qcom,msm_sps";
-		reg = <0xF9984000 0x15000>,
-		      <0xF9999000 0xB000>;
+		reg = <0xf9984000 0x15000>,
+		      <0xf9999000 0xb000>;
 		interrupts = <0 94 0>;
 
 		qcom,bam-dma-res-pipes = <6>;
@@ -83,4 +83,104 @@
 		interrupts = <96>;
 		spi-max-frequency = <24000000>;
 	};
+
+	qcom,spmi@fc4c0000 {
+		cell-index = <0>;
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0xfc4cf000 0x1000>,
+		      <0Xfc4cb000 0x1000>;
+		/* 190,ee0_krait_hlos_spmi_periph_irq */
+		/* 187,channel_0_krait_hlos_trans_done_irq */
+		interrupts = <0 190 0 0 187 0>;
+		qcom,pmic-arb-ee = <0>;
+		qcom,pmic-arb-channel = <0>;
+		qcom,pmic-arb-ppid-map = <0x130 0x00>, /* PM8941_LDO1 */
+					 <0x131 0x01>, /* PM8941_LDO2 */
+					 <0x132 0x02>, /* PM8941_LDO3 */
+					 <0x133 0x03>, /* PM8941_LDO4 */
+					 <0x134 0x04>, /* PM8941_LDO5 */
+					 <0x135 0x05>, /* PM8941_LDO6 */
+					 <0x136 0x06>, /* PM8941_LDO7 */
+					 <0x137 0x07>, /* PM8941_LDO8 */
+					 <0x138 0x08>, /* PM8941_LDO9 */
+					 <0x139 0x09>, /* PM8941_LDO10 */
+					 <0x13a 0x0a>, /* PM8941_LDO11 */
+					 <0x13b 0x0b>, /* PM8941_LDO12 */
+					 <0x13c 0x0c>, /* PM8941_LDO13 */
+					 <0x13d 0x0d>, /* PM8941_LDO14 */
+					 <0x13e 0x0e>, /* PM8941_LDO15 */
+					 <0x13f 0x0f>, /* PM8941_LDO16 */
+					 <0x140 0x10>, /* PM8941_LDO17 */
+					 <0x141 0x11>, /* PM8941_LDO18 */
+					 <0x142 0x12>, /* PM8941_LDO19 */
+					 <0x143 0x13>, /* PM8941_LDO20 */
+					 <0x144 0x14>, /* PM8941_LDO21 */
+					 <0x145 0x15>, /* PM8941_LDO22 */
+					 <0x146 0x16>, /* PM8941_LDO23 */
+					 <0x147 0x17>, /* PM8941_LDO24 */
+					 <0x148 0x18>, /* PM8941_LDO25 */
+					 <0x149 0x19>, /* PM8941_LDO26 */
+					 <0x0c0 0x1a>, /* PM8941_GPIO1 */
+					 <0x0c1 0x1b>, /* PM8941_GPIO2 */
+					 <0x0c2 0x1c>, /* PM8941_GPIO3 */
+					 <0x0c3 0x1d>, /* PM8941_GPIO4 */
+					 <0x0c4 0x1e>, /* PM8941_GPIO5 */
+					 <0x0c5 0x1f>, /* PM8941_GPIO6 */
+					 <0x0c6 0x20>, /* PM8941_GPIO7 */
+					 <0x0c7 0x21>, /* PM8941_GPIO8 */
+					 <0x0c8 0x22>, /* PM8941_GPIO9 */
+					 <0x0c9 0x23>, /* PM8941_GPIO10 */
+					 <0x0ca 0x24>, /* PM8941_GPIO11 */
+					 <0x0cb 0x25>, /* PM8941_GPIO12 */
+					 <0x0cc 0x26>, /* PM8941_GPIO13 */
+					 <0x0cd 0x27>, /* PM8941_GPIO14 */
+					 <0x0ce 0x28>, /* PM8941_GPIO15 */
+					 <0x0cf 0x29>, /* PM8941_GPIO16 */
+					 <0x0d0 0x2a>, /* PM8941_GPIO17 */
+					 <0x0d1 0x2b>, /* PM8941_GPIO18 */
+					 <0x0d2 0x2c>, /* PM8941_GPIO19 */
+					 <0x0d3 0x2d>, /* PM8941_GPIO20 */
+					 <0x0d4 0x2e>, /* PM8941_GPIO21 */
+					 <0x0d5 0x2f>, /* PM8941_GPIO22 */
+					 <0x0d6 0x30>, /* PM8941_GPIO23 */
+					 <0x0d7 0x31>, /* PM8941_GPIO24 */
+					 <0x0d8 0x32>, /* PM8941_GPIO25 */
+					 <0x0d9 0x33>, /* PM8941_GPIO26 */
+					 <0x0da 0x34>, /* PM8941_GPIO27 */
+					 <0x0db 0x35>, /* PM8941_GPIO28 */
+					 <0x0dc 0x36>, /* PM8941_GPIO29 */
+					 <0x0dd 0x37>, /* PM8941_GPIO30 */
+					 <0x0de 0x38>, /* PM8941_GPIO31 */
+					 <0x0df 0x39>, /* PM8941_GPIO32 */
+					 <0x0e0 0x3a>, /* PM8941_GPIO33 */
+					 <0x0e1 0x3b>, /* PM8941_GPIO34 */
+					 <0x0e2 0x3c>, /* PM8941_GPIO35 */
+					 <0x0e3 0x3d>, /* PM8941_GPIO36 */
+					 <0x028 0x3e>, /* COINCELL */
+					 <0x005 0x3f>, /* INTERRUPT */
+					 <0x001 0x40>, /* PM8941_0 */
+					 <0x201 0x41>, /* PM8841_0 */
+					 <0x101 0x42>, /* PM8941_1 */
+					 <0x301 0x43>, /* PM8841_1 */
+					 <0x008 0x44>, /* PON0 */
+					 <0x208 0x45>, /* PON1 */
+					 <0x110 0x46>, /* PM8941_SMPS1 */
+					 <0x111 0x47>, /* PM8941_SMPS2 */
+					 <0x112 0x48>, /* PM8941_SMPS3 */
+					 <0x310 0x49>, /* PM8841_SMPS1 */
+					 <0x311 0x4a>, /* PM8841_SMPS2 */
+					 <0x312 0x4b>, /* PM8841_SMPS3 */
+					 <0x313 0x4c>, /* PM8841_SMPS4 */
+					 <0x314 0x4d>, /* PM8841_SMPS5 */
+					 <0x315 0x4e>, /* PM8841_SMPS6 */
+					 <0x316 0x4f>, /* PM8841_SMPS7 */
+					 <0x317 0x50>, /* PM8841_SMPS8 */
+					 <0x050 0x51>, /* SHARED_XO */
+					 <0x051 0x52>, /* BB_CLK1 */
+					 <0x052 0x53>, /* BB_CLK2 */
+					 <0x059 0x54>, /* SLEEP_CLK */
+					 <0x010 0x55>, /* SMBC_OVP */
+					 <0x011 0x56>, /* SMBC_CHG */
+					 <0x012 0x57>; /* SMBC_BIF */
+	};
 };
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index a708fbc..9672d2c 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -37,10 +37,8 @@
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
-# CONFIG_MSM_DALRPC is not set
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
@@ -94,6 +92,8 @@
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DCC_TTY=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_SUPPLY=y
@@ -168,3 +168,11 @@
 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
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 3c87f8d..446423d 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -26,6 +26,7 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM7X27=y
+CONFIG_ARCH_MSM8625=y
 CONFIG_MSM_SOC_REV_A=y
 # CONFIG_MACH_MSM7X27_SURF is not set
 # CONFIG_MACH_MSM7X27_FFA is not set
@@ -44,14 +45,15 @@
 # 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
 CONFIG_PM8XXX_RPC_VIBRATOR=y
+CONFIG_MSM_SPM_V2=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
@@ -231,6 +233,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
@@ -254,6 +257,7 @@
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
+CONFIG_SND_MSM_SOC=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
 CONFIG_HID_MICROSOFT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index cc33b8f..642d843 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -26,6 +26,7 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM7X27=y
+CONFIG_ARCH_MSM8625=y
 CONFIG_MSM_SOC_REV_A=y
 # CONFIG_MACH_MSM7X27_SURF is not set
 # CONFIG_MACH_MSM7X27_FFA is not set
@@ -49,9 +50,11 @@
 CONFIG_BT_MSM_PINTEST=y
 CONFIG_MSM_RPC_VIBRATOR=y
 CONFIG_PM8XXX_RPC_VIBRATOR=y
+CONFIG_MSM_SPM_V2=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
@@ -349,3 +352,4 @@
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRC_CCITT=y
+CONFIG_OV5647=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index b71df28..b3a45d2 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -326,6 +326,7 @@
 CONFIG_USB_VIDEO_CLASS=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 9fd7e71..1f511bb 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -326,6 +326,7 @@
 CONFIG_USB_VIDEO_CLASS=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 95dd09c..f1b1fa5 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -1,4 +1,5 @@
 CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-perf"
 CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -52,6 +53,8 @@
 CONFIG_MACH_APQ8064_CDP=y
 CONFIG_MACH_APQ8064_MTP=y
 CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_HRD=y
+CONFIG_MACH_MPQ8064_DTV=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_KERNEL_PMEM_EBI_REGION=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -311,6 +314,9 @@
 CONFIG_MSM_CAMERA_FLASH_SC628A=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_RADIO_IRIS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 3a70b22..e58b94b 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -52,6 +52,8 @@
 CONFIG_MACH_APQ8064_CDP=y
 CONFIG_MACH_APQ8064_MTP=y
 CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_HRD=y
+CONFIG_MACH_MPQ8064_DTV=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_KERNEL_PMEM_EBI_REGION=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -82,6 +84,8 @@
 CONFIG_MSM_QDSS=y
 CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE=y
 CONFIG_MSM_SLEEP_STATS=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -312,6 +316,9 @@
 CONFIG_MSM_CAMERA_FLASH_SC628A=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_RADIO_IRIS=y
@@ -433,13 +440,13 @@
 CONFIG_LOCKUP_DETECTOR=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
-CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DEBUG_LIST=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 543a4f9f..7ba17e6 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -142,7 +142,6 @@
 CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
 CONFIG_IP6_NF_MANGLE=y
 CONFIG_IP6_NF_RAW=y
-CONFIG_CFG80211=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -162,7 +161,7 @@
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_NETDEVICES=y
-CONFIG_HOSTAP=y
+CONFIG_ATH6K_LEGACY=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
 # CONFIG_INPUT_MOUSEDEV is not set
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index c3b841a..d2434e6 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -54,79 +54,46 @@
  * consider why they can't support the logging.
  */
 
+#define __raw_write_logged(v, a, _t)	({ \
+	int _ret; \
+	void *_addr = (void *)(a); \
+	_ret = uncached_logk(LOGK_WRITEL, _addr); \
+	ETB_WAYPOINT; \
+	__raw_write##_t##_no_log((v), _addr); \
+	if (_ret) \
+		LOG_BARRIER; \
+	})
+
+
 #define __raw_writeb_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v))
 #define __raw_writew_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
 #define __raw_writel_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))
 
-#define __raw_writeb(v, a)	({ \
-	int _ret; \
-	void *_addr = (void *)(a); \
-	_ret = uncached_logk(LOGK_WRITEL, _addr); \
-	ETB_WAYPOINT; \
-	__raw_writeb_no_log(v, _addr); \
-	if (_ret) \
-		LOG_BARRIER; \
-	})
 
-#define __raw_writew(v, a)	({ \
-	int _ret; \
-	void *_addr = (void *)(a); \
-	_ret = uncached_logk(LOGK_WRITEL, _addr); \
-	ETB_WAYPOINT; \
-	__raw_writew_no_log(v, _addr); \
-	if (_ret) \
-		LOG_BARRIER; \
-	})
-
-#define __raw_writel(v, a)	({ \
-	int _ret; \
-	void *_addr = (void *)(a); \
-	_ret = uncached_logk(LOGK_WRITEL, _addr); \
-	ETB_WAYPOINT; \
-	__raw_writel_no_log(v, _addr); \
-	if (_ret) \
-		LOG_BARRIER; \
-	})
+#define __raw_writeb(v, a)	__raw_write_logged((v), (a), b)
+#define __raw_writew(v, a)	__raw_write_logged((v), (a), w)
+#define __raw_writel(v, a)	__raw_write_logged((v), (a), l)
 
 #define __raw_readb_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
 #define __raw_readw_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
 #define __raw_readl_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned int __force *)(a))
 
-#define __raw_readb(a)		({ \
-	unsigned char __a; \
+#define __raw_read_logged(a, _l, _t)		({ \
+	unsigned _t __a; \
 	void *_addr = (void *)(a); \
 	int _ret; \
 	_ret = uncached_logk(LOGK_READL, _addr); \
 	ETB_WAYPOINT; \
-	__a = __raw_readb_no_log(_addr);\
+	__a = __raw_read##_l##_no_log(_addr);\
 	if (_ret) \
 		LOG_BARRIER; \
 	__a; \
 	})
 
-#define __raw_readw(a)		({ \
-	unsigned short __a; \
-	void *_addr = (void *)(a); \
-	int _ret; \
-	_ret = uncached_logk(LOGK_READL, _addr); \
-	ETB_WAYPOINT; \
-	__a = __raw_readw_no_log(_addr);\
-	if (_ret) \
-		LOG_BARRIER; \
-	__a; \
-	})
 
-#define __raw_readl(a)		({ \
-	unsigned int __a; \
-	void *_addr = (void *)(a); \
-	int _ret; \
-	_ret = uncached_logk(LOGK_READL, _addr); \
-	ETB_WAYPOINT; \
-	__a = __raw_readl_no_log(_addr);\
-	if (_ret) \
-		LOG_BARRIER; \
-	__a; \
-	})
+#define __raw_readb(a)		__raw_read_logged((a), b, char)
+#define __raw_readw(a)		__raw_read_logged((a), w, short)
+#define __raw_readl(a)		__raw_read_logged((a), l, int)
 
 /*
  * Architecture ioremap implementation.
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0b0f733..18fbcf6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -747,6 +747,18 @@
 	help
 	  Support for the Qualcomm APQ8064 LIQUID device.
 
+config MACH_MPQ8064_HRD
+	depends on ARCH_APQ8064
+	bool "MPQ8064 HRD"
+	help
+	  Support for the Qualcomm MPQ8064 HRD device.
+
+config MACH_MPQ8064_DTV
+	depends on ARCH_APQ8064
+	bool "MPQ8064 DTV"
+	help
+	  Support for the Qualcomm MPQ8064 DTV device.
+
 config MACH_FSM9XXX_SURF
 	depends on ARCH_FSM9XXX
 	depends on !MSM_STACKED_MEMORY
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index b2f7c84d..8347a25 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -38,7 +38,12 @@
 	obj-$(CONFIG_MSM_SOC_REV_NONE) += acpuclock-8x50.o
 endif
 
-obj-$(CONFIG_SMP) += headsmp.o platsmp.o
+obj-$(CONFIG_SMP) += headsmp.o
+ifdef CONFIG_ARCH_MSM8625
+	obj-$(CONFIG_SMP) += platsmp-8625.o
+else
+	obj-$(CONFIG_SMP) += platsmp.o
+endif
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 
 obj-$(CONFIG_MSM_CPU_AVS) += avs.o
@@ -88,12 +93,14 @@
 ifndef CONFIG_ARCH_APQ8064
 ifndef CONFIG_ARCH_MSM8960
 ifndef CONFIG_ARCH_MSM8X60
+ifndef CONFIG_ARCH_MSMCOPPER
 	obj-$(CONFIG_MSM_SMD) += pmic.o
 	obj-$(CONFIG_MSM_ONCRPCROUTER) += rpc_hsusb.o rpc_pmapp.o rpc_fsusb.o
 endif
 endif
 endif
 endif
+endif
 ifndef CONFIG_ARCH_MSM8960
 ifndef CONFIG_ARCH_MSM8X60
 ifndef CONFIG_ARCH_APQ8064
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 6140559..5a21407 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -187,7 +187,7 @@
 	{ 0, 61440, ACPU_PLL_1, 1, 3,  7680, 3, 1,  61440 },
 	{ 1, 122880, ACPU_PLL_1, 1, 1,  15360, 3, 2,  61440 },
 	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3,  61440 },
-	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
 	{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
@@ -217,7 +217,7 @@
 	{ 0, 61440, ACPU_PLL_1, 1, 3,  7680, 3, 1, 61440 },
 	{ 1, 122880, ACPU_PLL_1, 1, 1,  15360, 3, 2, 61440 },
 	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3, 61440 },
-	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
 	{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
@@ -232,7 +232,7 @@
 	{ 0, 65536, ACPU_PLL_1, 1, 3,  8192, 3, 1, 49152 },
 	{ 1, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 2, 49152 },
 	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 3, 98304 },
-	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
 	{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
@@ -247,7 +247,7 @@
 	{ 0, 61440, ACPU_PLL_1, 1, 3,  7680, 3, 1,  61440 },
 	{ 1, 122880, ACPU_PLL_1, 1, 1,  15360, 3, 2,  61440 },
 	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3,  61440 },
-	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
 	{ 0, 400000, ACPU_PLL_2, 2, 2, 50000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
@@ -261,7 +261,7 @@
 	{ 0, 61440, ACPU_PLL_1, 1, 11,  7680, 3, 1,  61440 },
 	{ 1, 122880, ACPU_PLL_1, 1, 5,  15360, 3, 2,  61440 },
 	{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3,  61440 },
-	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
 	{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
@@ -291,7 +291,7 @@
 	{ 0, 61440, ACPU_PLL_1, 1, 11,  7680, 3, 1, 61440 },
 	{ 1, 122880, ACPU_PLL_1, 1, 5,  15360, 3, 2, 61440 },
 	{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3, 61440 },
-	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
 	{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
@@ -300,13 +300,13 @@
 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
-/* 7x27aa PLL4 @ 1008MHz with CDMA capable modem */
+/* 7627aa PLL4 @ 1008MHz with CDMA capable modem */
 static struct clkctl_acpu_speed pll0_960_pll1_589_pll2_1200_pll4_1008[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
 	{ 0, 65536, ACPU_PLL_1, 1, 8,  8192, 3, 1, 49152 },
 	{ 1, 98304, ACPU_PLL_1, 1, 5,  12288, 3, 2, 49152 },
 	{ 1, 196608, ACPU_PLL_1, 1, 2, 24576, 3, 3, 98304 },
-	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
 	{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
@@ -315,13 +315,13 @@
 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
-/* 7x25a PLL2 @ 1200MHz with GSM capable modem */
+/* 7625a PLL2 @ 1200MHz with GSM capable modem */
 static struct clkctl_acpu_speed pll0_960_pll1_737_pll2_1200_25a[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
 	{ 0, 61440, ACPU_PLL_1, 1, 11,  7680, 3, 1,  61440 },
 	{ 1, 122880, ACPU_PLL_1, 1, 5,  15360, 3, 2,  61440 },
 	{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3,  61440 },
-	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
 	{ 0, 400000, ACPU_PLL_2, 2, 2, 50000, 3, 4, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
@@ -757,7 +757,7 @@
 	res = clk_set_rate(drv_state.ebi1_clk, speed->axiclk_khz * 1000);
 	if (res < 0)
 		pr_warning("Setting AXI min rate failed (%d)\n", res);
-	res = clk_enable(drv_state.ebi1_clk);
+	res = clk_prepare_enable(drv_state.ebi1_clk);
 	if (res < 0)
 		pr_warning("Enabling AXI clock failed (%d)\n", res);
 
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 470e836..99c3d78 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -148,10 +148,10 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+			.vreg[VREG_HFPLL_A] = { "hfpll0_s8", 2100000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll0_l23", 1800000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_L23 },
 		},
@@ -160,16 +160,16 @@
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait1",     1300000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+			.vreg[VREG_HFPLL_A] = { "hfpll1_s8", 2100000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll1_l23", 1800000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_L23 },
 		},
@@ -177,10 +177,10 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+			.vreg[VREG_HFPLL_A] = { "hfpll_l2_s8", 2100000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll_l2_l23", 1800000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8921_L23 },
 		},
@@ -201,7 +201,7 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -210,13 +210,13 @@
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait1",     1150000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -225,13 +225,13 @@
 			.aux_clk_sel     = MSM_ACC2_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait2",     1150000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait2_mem", 1150000,
 					     RPM_VREG_VOTER4,
 					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait2_dig", 1150000,
 					     RPM_VREG_VOTER4,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll2", 1800000,
 					     RPM_VREG_VOTER4,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -240,13 +240,13 @@
 			.aux_clk_sel     = MSM_ACC3_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait3",     1150000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait3_mem", 1150000,
 					     RPM_VREG_VOTER5,
 					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait3_dig", 1150000,
 					     RPM_VREG_VOTER5,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll3", 1800000,
 					     RPM_VREG_VOTER5,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -254,7 +254,7 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x300,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -272,7 +272,7 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8038_S1 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -281,13 +281,13 @@
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait1",     1300000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_S1 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -295,7 +295,7 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -314,7 +314,7 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8038_S1 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -323,13 +323,13 @@
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait1",     1300000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_S1 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -337,7 +337,7 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -922,8 +922,8 @@
 				sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
 				sc->vreg[VREG_MEM].max_vdd, 0);
 		if (rc) {
-			pr_err("%s: vdd_mem (cpu%d) increase failed (%d)\n",
-				__func__, cpu, rc);
+			pr_err("%s increase failed (%d)\n",
+				sc->vreg[VREG_MEM].name, rc);
 			return rc;
 		}
 		 sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
@@ -935,8 +935,8 @@
 				sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
 				sc->vreg[VREG_DIG].max_vdd, 0);
 		if (rc) {
-			pr_err("%s: vdd_dig (cpu%d) increase failed (%d)\n",
-				__func__, cpu, rc);
+			pr_err("%s increase failed (%d)\n",
+				sc->vreg[VREG_DIG].name, rc);
 			return rc;
 		}
 		sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
@@ -953,8 +953,8 @@
 		rc = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
 					   sc->vreg[VREG_CORE].max_vdd);
 		if (rc) {
-			pr_err("%s: vdd_core (cpu%d) increase failed (%d)\n",
-				__func__, cpu, rc);
+			pr_err("%s increase failed (%d)\n",
+				sc->vreg[VREG_CORE].name, rc);
 			return rc;
 		}
 		sc->vreg[VREG_CORE].cur_vdd = vdd_core;
@@ -980,8 +980,8 @@
 		ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
 					    sc->vreg[VREG_CORE].max_vdd);
 		if (ret) {
-			pr_err("%s: vdd_core (cpu%d) decrease failed (%d)\n",
-			       __func__, cpu, ret);
+			pr_err("%s decrease failed (%d)\n",
+			       sc->vreg[VREG_CORE].name, ret);
 			return;
 		}
 		sc->vreg[VREG_CORE].cur_vdd = vdd_core;
@@ -993,8 +993,8 @@
 				sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
 				sc->vreg[VREG_DIG].max_vdd, 0);
 		if (ret) {
-			pr_err("%s: vdd_dig (cpu%d) decrease failed (%d)\n",
-				__func__, cpu, ret);
+			pr_err("%s decrease failed (%d)\n",
+				sc->vreg[VREG_DIG].name, ret);
 			return;
 		}
 		sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
@@ -1009,8 +1009,8 @@
 				sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
 				sc->vreg[VREG_MEM].max_vdd, 0);
 		if (ret) {
-			pr_err("%s: vdd_mem (cpu%d) decrease failed (%d)\n",
-				__func__, cpu, ret);
+			pr_err("%s decrease failed (%d)\n",
+				sc->vreg[VREG_MEM].name, ret);
 			return;
 		}
 		 sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
@@ -1147,7 +1147,7 @@
 	pr_debug("Initializing HFPLL%d\n", sc - scalable);
 
 	/* Disable the PLL for re-programming. */
-	hfpll_disable(sc, 0);
+	hfpll_disable(sc, 1);
 
 	/* Configure PLL parameters for integer mode. */
 	writel_relaxed(0x7845C665, sc->hfpll_base + HFPLL_CONFIG_CTL);
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index f1abde4..7e5e2f8 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -208,7 +208,7 @@
 static struct delayed_work ul_timeout_work;
 static int ul_packet_written;
 static atomic_t ul_ondemand_vote = ATOMIC_INIT(0);
-static struct clk *dfab_clk;
+static struct clk *dfab_clk, *xo_clk;
 static DEFINE_RWLOCK(ul_wakeup_lock);
 static DECLARE_WORK(kickoff_ul_wakeup, kickoff_ul_wakeup_func);
 static int bam_connection_is_active;
@@ -671,7 +671,7 @@
 	skb = info->skb;
 	kfree(info);
 	hdr = (struct bam_mux_hdr *)skb->data;
-	DBG_INC_WRITE_CNT(skb->data_len);
+	DBG_INC_WRITE_CNT(skb->len);
 	event_data = (unsigned long)(skb);
 	spin_lock_irqsave(&bam_ch[hdr->ch_id].lock, flags);
 	bam_ch[hdr->ch_id].num_tx_pkts--;
@@ -1194,11 +1194,15 @@
 	int i = 0;
 
 	i += scnprintf(buf + i, max - i,
+			"skb read cnt:    %u\n"
+			"skb write cnt:   %u\n"
 			"skb copy cnt:    %u\n"
 			"skb copy bytes:  %u\n"
 			"sps tx failures: %u\n"
 			"sps tx stalls:   %u\n"
 			"rx queue len:    %d\n",
+			bam_dmux_read_cnt,
+			bam_dmux_write_cnt,
 			bam_dmux_write_cpy_cnt,
 			bam_dmux_write_cpy_bytes,
 			bam_dmux_tx_sps_failure_cnt,
@@ -1686,6 +1690,9 @@
 	rc = clk_prepare_enable(dfab_clk);
 	if (rc)
 		DMUX_LOG_KERR("bam_dmux vote for dfab failed rc = %d\n", rc);
+	rc = clk_prepare_enable(xo_clk);
+	if (rc)
+		DMUX_LOG_KERR("bam_dmux vote for xo failed rc = %d\n", rc);
 	dfab_is_on = 1;
 	mutex_unlock(&dfab_status_lock);
 }
@@ -1701,6 +1708,7 @@
 		return;
 	}
 	clk_disable_unprepare(dfab_clk);
+	clk_disable_unprepare(xo_clk);
 	dfab_is_on = 0;
 	mutex_unlock(&dfab_status_lock);
 }
@@ -2095,6 +2103,11 @@
 	if (bam_mux_initialized)
 		return 0;
 
+	xo_clk = clk_get(&pdev->dev, "xo");
+	if (IS_ERR(xo_clk)) {
+		pr_err("%s: did not get xo clock\n", __func__);
+		return PTR_ERR(xo_clk);
+	}
 	dfab_clk = clk_get(&pdev->dev, "bus_clk");
 	if (IS_ERR(dfab_clk)) {
 		pr_err("%s: did not get dfab clock\n", __func__);
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index cd84722..73221b5 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -41,8 +41,8 @@
 	},
 
 	{
-		.func = GPIOMUX_FUNC_1, /*active 3*/
-		.drv = GPIOMUX_DRV_8MA,
+		.func = GPIOMUX_FUNC_2, /*active 3*/
+		.drv = GPIOMUX_DRV_2MA,
 		.pull = GPIOMUX_PULL_NONE,
 	},
 
@@ -76,6 +76,27 @@
 		.pull = GPIOMUX_PULL_KEEPER,
 	},
 
+	{
+		.func = GPIOMUX_FUNC_9, /*active 9*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+	{
+		.func = GPIOMUX_FUNC_A, /*active 10*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+	{
+		.func = GPIOMUX_FUNC_6, /*active 11*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+	{
+		.func = GPIOMUX_FUNC_4, /*active 12*/
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+
 };
 
 
@@ -83,7 +104,7 @@
 	{
 		.gpio = 2,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[2],
+			[GPIOMUX_ACTIVE]    = &cam_settings[12],
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
 		},
 	},
@@ -97,7 +118,7 @@
 	{
 		.gpio = 4,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[1],
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
 		},
 	},
@@ -109,7 +130,7 @@
 		},
 	},
 	{
-		.gpio = 76,
+		.gpio = 34,
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[2],
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
@@ -122,39 +143,39 @@
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
 		},
 	},
-};
-
-static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
 	{
 		.gpio = 10,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_ACTIVE]    = &cam_settings[9],
 			[GPIOMUX_SUSPENDED] = &cam_settings[8],
 		},
 	},
 	{
 		.gpio = 11,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_ACTIVE]    = &cam_settings[10],
 			[GPIOMUX_SUSPENDED] = &cam_settings[8],
 		},
 	},
 	{
 		.gpio = 12,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_ACTIVE]    = &cam_settings[11],
 			[GPIOMUX_SUSPENDED] = &cam_settings[8],
 		},
 	},
 	{
 		.gpio = 13,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_ACTIVE]    = &cam_settings[11],
 			[GPIOMUX_SUSPENDED] = &cam_settings[8],
 		},
 	},
 };
 
+static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
+};
+
 #ifdef CONFIG_MSM_CAMERA
 
 static struct msm_bus_vectors cam_init_vectors[] = {
@@ -310,27 +331,34 @@
 	},
 };
 
-static struct camera_vreg_t msm_8064_back_cam_vreg[] = {
-	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+static struct camera_vreg_t apq_8064_back_cam_vreg[] = {
 	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vio", REG_VS, 0, 0, 0},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
 };
 
+static struct camera_vreg_t apq_8064_front_cam_vreg[] = {
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
+#define CAML_RSTN PM8921_GPIO_PM_TO_SYS(28)
+#define CAMR_RSTN 34
+
 static struct gpio apq8064_common_cam_gpio[] = {
-	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
-	{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
-	{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
 };
 
 static struct gpio apq8064_back_cam_gpio[] = {
-	{107, GPIOF_DIR_OUT, "CAM_RESET"},
+	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
+	{CAML_RSTN, GPIOF_DIR_OUT, "CAM_RESET"},
 };
 
 static struct msm_gpio_set_tbl apq8064_back_cam_gpio_set_tbl[] = {
-	{107, GPIOF_OUT_INIT_LOW, 1000},
-	{107, GPIOF_OUT_INIT_HIGH, 4000},
+	{CAML_RSTN, GPIOF_OUT_INIT_LOW, 10000},
+	{CAML_RSTN, GPIOF_OUT_INIT_HIGH, 10000},
 };
 
 static struct msm_camera_gpio_conf apq8064_back_cam_gpio_conf = {
@@ -344,6 +372,52 @@
 	.cam_gpio_set_tbl_size = ARRAY_SIZE(apq8064_back_cam_gpio_set_tbl),
 };
 
+static struct gpio apq8064_front_cam_gpio[] = {
+	{4, GPIOF_DIR_IN, "CAMIF_MCLK"},
+	{12, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
+	{13, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
+	{CAMR_RSTN, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl apq8064_front_cam_gpio_set_tbl[] = {
+	{CAMR_RSTN, GPIOF_OUT_INIT_LOW, 10000},
+	{CAMR_RSTN, GPIOF_OUT_INIT_HIGH, 10000},
+};
+
+static struct msm_camera_gpio_conf apq8064_front_cam_gpio_conf = {
+	.cam_gpiomux_conf_tbl = apq8064_cam_2d_configs,
+	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(apq8064_cam_2d_configs),
+	.cam_gpio_common_tbl = apq8064_common_cam_gpio,
+	.cam_gpio_common_tbl_size = ARRAY_SIZE(apq8064_common_cam_gpio),
+	.cam_gpio_req_tbl = apq8064_front_cam_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(apq8064_front_cam_gpio),
+	.cam_gpio_set_tbl = apq8064_front_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(apq8064_front_cam_gpio_set_tbl),
+};
+
+static struct msm_camera_i2c_conf apq8064_back_cam_i2c_conf = {
+	.use_i2c_mux = 1,
+	.mux_dev = &msm8960_device_i2c_mux_gsbi4,
+	.i2c_mux_mode = MODE_L,
+};
+
+static struct i2c_board_info imx074_actuator_i2c_info = {
+	I2C_BOARD_INFO("imx074_act", 0x11),
+};
+
+static struct msm_actuator_info imx074_actuator_info = {
+	.board_info     = &imx074_actuator_i2c_info,
+	.bus_id         = APQ_8064_GSBI4_QUP_I2C_BUS_ID,
+	.vcm_pwd        = 0,
+	.vcm_enable     = 1,
+};
+
+static struct msm_camera_i2c_conf apq8064_front_cam_i2c_conf = {
+	.use_i2c_mux = 1,
+	.mux_dev = &msm8960_device_i2c_mux_gsbi4,
+	.i2c_mux_mode = MODE_L,
+};
+
 #ifdef CONFIG_IMX074
 static struct msm_camera_sensor_flash_data flash_imx074 = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
@@ -351,9 +425,10 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
 	.mount_angle	= 90,
-	.cam_vreg = msm_8064_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8064_back_cam_vreg),
+	.cam_vreg = apq_8064_back_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_back_cam_vreg),
 	.gpio_conf = &apq8064_back_cam_gpio_conf,
+	.i2c_conf = &apq8064_back_cam_i2c_conf,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
@@ -363,14 +438,40 @@
 	.sensor_platform_info = &sensor_board_info_imx074,
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
+	.actuator_info = &imx074_actuator_info
 };
 #endif
 
+#ifdef CONFIG_OV2720
+static struct msm_camera_sensor_flash_data flash_ov2720 = {
+	.flash_type	= MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
+	.mount_angle	= 0,
+	.cam_vreg = apq_8064_front_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_front_cam_vreg),
+	.gpio_conf = &apq8064_front_cam_gpio_conf,
+	.i2c_conf = &apq8064_front_cam_i2c_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov2720_data = {
+	.sensor_name	= "ov2720",
+	.pdata	= &msm_camera_csi_device_data[1],
+	.flash_data	= &flash_ov2720,
+	.sensor_platform_info = &sensor_board_info_ov2720,
+	.csi_if	= 1,
+	.camera_type = FRONT_CAMERA_2D,
+};
+#endif
+
+
 void __init apq8064_init_cam(void)
 {
 	msm_gpiomux_install(apq8064_cam_common_configs,
 			ARRAY_SIZE(apq8064_cam_common_configs));
 
+	platform_device_register(&msm8960_device_i2c_mux_gsbi4);
 	platform_device_register(&msm8960_device_csiphy0);
 	platform_device_register(&msm8960_device_csiphy1);
 	platform_device_register(&msm8960_device_csid0);
@@ -388,6 +489,12 @@
 	.platform_data = &msm_camera_sensor_imx074_data,
 	},
 #endif
+#ifdef CONFIG_OV2720
+	{
+	I2C_BOARD_INFO("ov2720", 0x6C),
+	.platform_data = &msm_camera_sensor_ov2720_data,
+	},
+#endif
 };
 
 struct msm_camera_board_info apq8064_camera_board_info = {
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index c3cc9eb..206bebd 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -64,6 +64,18 @@
 };
 #endif
 
+static struct gpiomux_setting gpio_i2c_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gpio_i2c_config_sus = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_KEEPER,
+};
+
 static struct gpiomux_setting cdc_mclk = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
@@ -347,6 +359,20 @@
 			[GPIOMUX_SUSPENDED] = &gsbi7_func1_cfg,
 		},
 	},
+	{
+		.gpio      = 21,		/* GSBI1 QUP I2C_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config_sus,
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
+		},
+	},
+	{
+		.gpio      = 20,		/* GSBI1 QUP I2C_DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config_sus,
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config apq8064_slimbus_config[] __initdata = {
@@ -473,7 +499,29 @@
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &ap2mdm_pon_reset_n_cfg,
 		}
-	}
+	},
+};
+
+static struct gpiomux_setting gpio_rotate_key_act_config = {
+	.pull = GPIOMUX_PULL_UP,
+	.drv = GPIOMUX_DRV_8MA,
+	.func = GPIOMUX_FUNC_GPIO,
+};
+
+static struct gpiomux_setting gpio_rotate_key_sus_config = {
+	.pull = GPIOMUX_PULL_NONE,
+	.drv = GPIOMUX_DRV_2MA,
+	.func = GPIOMUX_FUNC_GPIO,
+};
+
+struct msm_gpiomux_config apq8064_rotate_key_config[] = {
+	{
+		.gpio = 46,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_rotate_key_sus_config,
+			[GPIOMUX_ACTIVE] = &gpio_rotate_key_act_config,
+		}
+	},
 };
 
 static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
@@ -573,11 +621,16 @@
 				ARRAY_SIZE(cyts_gpio_configs));
 
 #ifdef CONFIG_USB_EHCI_MSM_HSIC
-	msm_gpiomux_install(apq8064_hsic_configs,
-			ARRAY_SIZE(apq8064_hsic_configs));
+	if (machine_is_apq8064_mtp())
+		msm_gpiomux_install(apq8064_hsic_configs,
+				ARRAY_SIZE(apq8064_hsic_configs));
 #endif
 
 	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
 		msm_gpiomux_install(apq8064_mxt_configs,
 			ARRAY_SIZE(apq8064_mxt_configs));
+
+	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+		msm_gpiomux_install(apq8064_rotate_key_config,
+				ARRAY_SIZE(apq8064_rotate_key_config));
 }
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 0357c40..213215e 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -122,6 +122,31 @@
 	},
 };
 
+static const char *kgsl_3d0_iommu0_ctx_names[] = {
+	"gfx3d_user",
+	/* priv_ctx goes here */
+};
+
+static const char *kgsl_3d0_iommu1_ctx_names[] = {
+	"gfx3d1_user",
+	/* priv_ctx goes here */
+};
+
+static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = {
+	{
+		.iommu_ctx_names = kgsl_3d0_iommu0_ctx_names,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu0_ctx_names),
+		.physstart = 0x07C00000,
+		.physend = 0x07C00000 + SZ_1M - 1,
+	},
+	{
+		.iommu_ctx_names = kgsl_3d0_iommu1_ctx_names,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu1_ctx_names),
+		.physstart = 0x07D00000,
+		.physend = 0x07D00000 + SZ_1M - 1,
+	},
+};
+
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
 	.pwrlevel = {
 		{
@@ -154,8 +179,8 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	.bus_scale_table = &grp3d_bus_scale_pdata,
 #endif
-	.iommu_user_ctx_name = "gfx3d_user",
-	.iommu_priv_ctx_name = NULL,
+	.iommu_data = kgsl_3d0_iommu_data,
+	.iommu_count = ARRAY_SIZE(kgsl_3d0_iommu_data),
 };
 
 struct platform_device device_kgsl_3d0 = {
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 02dfc5e..364df81 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -117,6 +117,22 @@
 	PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
 	PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
 	PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
+	PM8921_GPIO_OUTPUT_FUNC(44, 0, PM_GPIO_FUNC_2),
+	PM8921_GPIO_OUTPUT(33, 0, HIGH),
+	PM8921_GPIO_OUTPUT(20, 0, HIGH),
+	PM8921_GPIO_INPUT(35, PM_GPIO_PULL_UP_1P5),
+	PM8921_GPIO_INPUT(38, PM_GPIO_PULL_UP_1P5),
+	/* TABLA CODEC RESET */
+	PM8921_GPIO_OUTPUT(34, 1, MED),
+};
+
+static struct pm8xxx_gpio_init pm8921_mtp_kp_gpios[] __initdata = {
+	PM8921_GPIO_INPUT(3, PM_GPIO_PULL_UP_1P5),
+	PM8921_GPIO_INPUT(4, PM_GPIO_PULL_UP_1P5),
+};
+
+static struct pm8xxx_gpio_init pm8921_cdp_kp_gpios[] __initdata = {
+	PM8921_GPIO_INPUT(37, PM_GPIO_PULL_UP_1P5),
 };
 
 /* Initial PM8XXX MPP configurations */
@@ -140,6 +156,28 @@
 		}
 	}
 
+	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+		for (i = 0; i < ARRAY_SIZE(pm8921_cdp_kp_gpios); i++) {
+			rc = pm8xxx_gpio_config(pm8921_cdp_kp_gpios[i].gpio,
+						&pm8921_cdp_kp_gpios[i].config);
+			if (rc) {
+				pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
+					__func__, rc);
+				break;
+			}
+		}
+
+	if (machine_is_apq8064_mtp())
+		for (i = 0; i < ARRAY_SIZE(pm8921_mtp_kp_gpios); i++) {
+			rc = pm8xxx_gpio_config(pm8921_mtp_kp_gpios[i].gpio,
+						&pm8921_mtp_kp_gpios[i].config);
+			if (rc) {
+				pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
+					__func__, rc);
+				break;
+			}
+		}
+
 	for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
 		rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
 					&pm8xxx_mpps[i].config);
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 4e29feb..0d12bb5 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -27,8 +27,9 @@
 };
 VREG_CONSUMERS(L2) = {
 	REGULATOR_SUPPLY("8921_l2",		NULL),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.0"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.1"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.2"),
 	REGULATOR_SUPPLY("lvds_pll_vdda",	"lvds.0"),
 	REGULATOR_SUPPLY("dsi1_pll_vdda",	"mipi_dsi.1"),
 };
@@ -41,8 +42,6 @@
 VREG_CONSUMERS(L4) = {
 	REGULATOR_SUPPLY("8921_l4",		NULL),
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_otg"),
-	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.0"),
-	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.1"),
 	REGULATOR_SUPPLY("iris_vddxo",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(L5) = {
@@ -103,7 +102,8 @@
 	REGULATOR_SUPPLY("8921_l23",		NULL),
 	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.1"),
 	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.2"),
-
+	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.0"),
+	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.1"),
 };
 VREG_CONSUMERS(L24) = {
 	REGULATOR_SUPPLY("8921_l24",		NULL),
@@ -157,6 +157,7 @@
 	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-005b"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-0024"),
+	REGULATOR_SUPPLY("vddp",		"0-0048"),
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
@@ -217,6 +218,7 @@
 };
 VREG_CONSUMERS(EXT_5V) = {
 	REGULATOR_SUPPLY("ext_5v",		NULL),
+	REGULATOR_SUPPLY("vbus",		"msm_ehci_host.0"),
 };
 VREG_CONSUMERS(EXT_MPP8) = {
 	REGULATOR_SUPPLY("ext_mpp8",		NULL),
@@ -506,7 +508,7 @@
 	RPM_LDO(L6,  0, 1, 0, 2950000, 2950000, NULL,          0,     0),
 	RPM_LDO(L7,  0, 1, 0, 1850000, 2950000, NULL,          0,     0),
 	RPM_LDO(L8,  0, 1, 0, 2800000, 2800000, NULL,          0,     0),
-	RPM_LDO(L9,  0, 1, 0, 2850000, 2850000, NULL,          0,     0),
+	RPM_LDO(L9,  0, 1, 0, 3000000, 3000000, NULL,          0,     0),
 	RPM_LDO(L10, 0, 1, 0, 2900000, 2900000, NULL,          0,     0),
 	RPM_LDO(L11, 0, 1, 0, 3000000, 3000000, NULL,          0,     0),
 	RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8921_s4",     0,     0),
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 0d187a9..41be3e7 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -51,7 +51,7 @@
 		.name = "sdc_vdd",
 		.high_vol_level = 2950000,
 		.low_vol_level = 2950000,
-		.hpm_uA = 600000, /* 600mA */
+		.hpm_uA = 800000, /* 800mA */
 	}
 };
 
@@ -121,8 +121,8 @@
 
 static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
 	{TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
-	{TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
-	{TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+	{TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+	{TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
 };
 
 /* SDC3 pad data */
@@ -146,8 +146,8 @@
 
 static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
 	{TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
-	{TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_DOWN},
-	{TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_DOWN}
+	{TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+	{TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
 };
 
 static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
@@ -220,7 +220,7 @@
 
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 static unsigned int sdc3_sup_clk_rates[] = {
-	400000, 24000000, 48000000, 96000000
+	400000, 24000000, 48000000, 96000000, 192000000
 };
 
 static struct mmc_platform_data sdc3_data = {
@@ -234,6 +234,10 @@
 	.status_irq	= MSM_GPIO_TO_INT(26),
 	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 	.is_status_gpio_active_low = 1,
+	.xpc_cap	= 1,
+	.uhs_caps	= (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+			MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
+			MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_800),
 };
 static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
 #else
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index c07f497b..8e7fb1a 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -18,6 +18,7 @@
 #include <linux/slimbus/slimbus.h>
 #include <linux/mfd/wcd9310/core.h>
 #include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/pm8xxx/misc.h>
 #include <linux/msm_ssbi.h>
 #include <linux/spi/spi.h>
 #include <linux/dma-mapping.h>
@@ -26,6 +27,8 @@
 #include <linux/memory.h>
 #include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/cyttsp.h>
+#include <linux/i2c/isa1200.h>
+#include <linux/gpio_keys.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -54,6 +57,7 @@
 #include <mach/msm_bus_board.h>
 #include <mach/cpuidle.h>
 #include <mach/mdm2.h>
+#include <linux/msm_tsens.h>
 
 #include "msm_watchdog.h"
 #include "board-8064.h"
@@ -78,7 +82,7 @@
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE	0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE	0x300000 /* (3MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 #define MSM_ION_HEAP_NUM	8
@@ -233,6 +237,18 @@
 	.align = SZ_128K,
 };
 #endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -243,14 +259,6 @@
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -275,6 +283,14 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
@@ -459,6 +475,19 @@
 	.power_budget		= 750,
 };
 
+static struct msm_usb_host_platform_data msm_ehci_host_pdata = {
+	.power_budget = 500,
+};
+
+static void __init apq8064_ehci_host_init(void)
+{
+	if (machine_is_apq8064_liquid()) {
+		apq8064_device_ehci_host3.dev.platform_data =
+				&msm_ehci_host_pdata;
+		platform_device_register(&apq8064_device_ehci_host3);
+	}
+}
+
 #define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
 
 /* Micbias setting is based on 8660 CDP/MTP/FLUID requirement
@@ -528,6 +557,86 @@
 	},
 };
 
+#define HAP_SHIFT_LVL_OE_GPIO		PM8921_MPP_PM_TO_SYS(8)
+#define ISA1200_HAP_EN_GPIO		PM8921_GPIO_PM_TO_SYS(33)
+#define ISA1200_HAP_LEN_GPIO		PM8921_GPIO_PM_TO_SYS(20)
+#define ISA1200_HAP_CLK			PM8921_GPIO_PM_TO_SYS(44)
+
+static int isa1200_power(int on)
+{
+	gpio_set_value_cansleep(ISA1200_HAP_CLK, !!on);
+
+	return 0;
+}
+
+static int isa1200_dev_setup(bool enable)
+{
+	int rc = 0;
+
+	rc = pm8xxx_aux_clk_control(CLK_MP3_2, XO_DIV_1, enable);
+	if (rc) {
+		pr_err("%s: unable to write aux clock register(%d)\n",
+			__func__, rc);
+		return rc;
+	}
+
+	if (!enable)
+		goto free_gpio;
+
+	rc = gpio_request(ISA1200_HAP_CLK, "haptics_clk");
+	if (rc) {
+		pr_err("%s: unable to request gpio %d config(%d)\n",
+			__func__, ISA1200_HAP_CLK, rc);
+		return rc;
+	}
+
+	rc = gpio_direction_output(ISA1200_HAP_CLK, 0);
+	if (rc) {
+		pr_err("%s: unable to set direction\n", __func__);
+		goto free_gpio;
+	}
+
+	return 0;
+
+free_gpio:
+	gpio_free(ISA1200_HAP_CLK);
+	return rc;
+}
+
+static struct isa1200_regulator isa1200_reg_data[] = {
+	{
+		.name = "vddp",
+		.min_uV = ISA_I2C_VTG_MIN_UV,
+		.max_uV = ISA_I2C_VTG_MAX_UV,
+		.load_uA = ISA_I2C_CURR_UA,
+	},
+};
+
+static struct isa1200_platform_data isa1200_1_pdata = {
+	.name = "vibrator",
+	.dev_setup = isa1200_dev_setup,
+	.power_on = isa1200_power,
+	.hap_en_gpio = ISA1200_HAP_EN_GPIO,
+	.hap_len_gpio = ISA1200_HAP_LEN_GPIO,
+	.max_timeout = 15000,
+	.mode_ctrl = PWM_GEN_MODE,
+	.pwm_fd = {
+		.pwm_div = 256,
+	},
+	.is_erm = false,
+	.smart_en = true,
+	.ext_clk_en = true,
+	.chip_en = 1,
+	.regulator_info = isa1200_reg_data,
+	.num_regulators = ARRAY_SIZE(isa1200_reg_data),
+};
+
+static struct i2c_board_info isa1200_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("isa1200_1", 0x90>>1),
+		.platform_data = &isa1200_1_pdata,
+	},
+};
 /* configuration data for mxt1386e using V2.1 firmware */
 static const u8 mxt1386e_config_data_v2_1[] = {
 	/* T6 Object */
@@ -890,6 +999,14 @@
 	.peripheral_platform_device = &apq8064_device_hsic_host,
 };
 
+static struct tsens_platform_data apq_tsens_pdata  = {
+		.tsens_factor		= 1000,
+		.hw_type		= APQ_8064,
+		.tsens_num_sensor	= 11,
+		.slope = {1176, 1176, 1154, 1176, 1111,
+			1132, 1132, 1199, 1132, 1199, 1132},
+};
+
 #define MSM_SHARED_RAM_PHYS 0x80000000
 static void __init apq8064_map_io(void)
 {
@@ -1225,7 +1342,6 @@
 static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW_L2_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1238,9 +1354,7 @@
 static struct msm_spm_platform_data msm_spm_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW0_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1255,9 +1369,7 @@
 	},
 	[1] = {
 		.reg_base_addr = MSM_SAW1_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1272,9 +1384,7 @@
 	},
 	[2] = {
 		.reg_base_addr = MSM_SAW2_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1289,9 +1399,7 @@
 	},
 	[3] = {
 		.reg_base_addr = MSM_SAW3_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1368,6 +1476,7 @@
 
 static struct platform_device *common_devices[] __initdata = {
 	&apq8064_device_dmov,
+	&apq8064_device_qup_i2c_gsbi1,
 	&apq8064_device_qup_i2c_gsbi3,
 	&apq8064_device_qup_i2c_gsbi4,
 	&apq8064_device_qup_spi_gsbi5,
@@ -1381,7 +1490,6 @@
 	&apq8064_device_otg,
 	&apq8064_device_gadget_peripheral,
 	&apq8064_device_hsusb_host,
-	&apq8064_device_hsic_host,
 	&android_usb_device,
 	&msm_device_wcnss_wlan,
 #ifdef CONFIG_ANDROID_PMEM
@@ -1434,6 +1542,7 @@
 	&apq_pcm_afe,
 	&apq_cpudai_auxpcm_rx,
 	&apq_cpudai_auxpcm_tx,
+	&apq_cpudai_stub,
 	&apq8064_rpm_device,
 	&apq8064_rpm_log_device,
 	&apq8064_rpm_stat_device,
@@ -1496,6 +1605,11 @@
 	/* add more slimbus slaves as needed */
 };
 
+static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi1_pdata = {
+	.clk_freq = 100000,
+	.src_clk_rate = 24000000,
+};
+
 static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
 	.clk_freq = 100000,
 	.src_clk_rate = 24000000,
@@ -1506,8 +1620,20 @@
 	.src_clk_rate = 24000000,
 };
 
+#define GSBI_DUAL_MODE_CODE 0x60
+#define MSM_GSBI1_PHYS		0x12440000
 static void __init apq8064_i2c_init(void)
 {
+	void __iomem *gsbi_mem;
+
+	apq8064_device_qup_i2c_gsbi1.dev.platform_data =
+					&apq8064_i2c_qup_gsbi1_pdata;
+	gsbi_mem = ioremap_nocache(MSM_GSBI1_PHYS, 4);
+	writel_relaxed(GSBI_DUAL_MODE_CODE, gsbi_mem);
+	/* Ensure protocol code is written before proceeding */
+	wmb();
+	iounmap(gsbi_mem);
+	apq8064_i2c_qup_gsbi1_pdata.use_gsbi_shared_mode = 1;
 	apq8064_device_qup_i2c_gsbi3.dev.platform_data =
 					&apq8064_i2c_qup_gsbi3_pdata;
 	apq8064_device_qup_i2c_gsbi4.dev.platform_data =
@@ -1535,6 +1661,116 @@
 }
 #endif
 
+#define GPIO_KEY_HOME		PM8921_GPIO_PM_TO_SYS(27)
+#define GPIO_KEY_VOLUME_UP	PM8921_GPIO_PM_TO_SYS(35)
+#define GPIO_KEY_VOLUME_DOWN	PM8921_GPIO_PM_TO_SYS(38)
+#define GPIO_KEY_CAM_FOCUS	PM8921_GPIO_PM_TO_SYS(3)
+#define GPIO_KEY_CAM_SNAP	PM8921_GPIO_PM_TO_SYS(4)
+#define GPIO_KEY_ROTATION	46
+
+static struct gpio_keys_button cdp_keys[] = {
+	{
+		.code           = KEY_HOME,
+		.gpio           = GPIO_KEY_HOME,
+		.desc           = "home_key",
+		.active_low     = 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code           = KEY_VOLUMEUP,
+		.gpio           = GPIO_KEY_VOLUME_UP,
+		.desc           = "volume_up_key",
+		.active_low     = 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code           = KEY_VOLUMEDOWN,
+		.gpio           = GPIO_KEY_VOLUME_DOWN,
+		.desc           = "volume_down_key",
+		.active_low     = 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code           = SW_ROTATE_LOCK,
+		.gpio           = GPIO_KEY_ROTATION,
+		.desc           = "rotate_key",
+		.active_low     = 1,
+		.type		= EV_SW,
+		.debounce_interval = 15,
+	},
+};
+
+static struct gpio_keys_platform_data cdp_keys_data = {
+	.buttons        = cdp_keys,
+	.nbuttons       = ARRAY_SIZE(cdp_keys),
+};
+
+static struct platform_device cdp_kp_pdev = {
+	.name           = "gpio-keys",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &cdp_keys_data,
+	},
+};
+
+static struct gpio_keys_button mtp_keys[] = {
+	{
+		.code           = KEY_CAMERA_FOCUS,
+		.gpio           = GPIO_KEY_CAM_FOCUS,
+		.desc           = "cam_focus_key",
+		.active_low     = 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code           = KEY_VOLUMEUP,
+		.gpio           = GPIO_KEY_VOLUME_UP,
+		.desc           = "volume_up_key",
+		.active_low     = 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code           = KEY_VOLUMEDOWN,
+		.gpio           = GPIO_KEY_VOLUME_DOWN,
+		.desc           = "volume_down_key",
+		.active_low     = 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code           = KEY_CAMERA_SNAPSHOT,
+		.gpio           = GPIO_KEY_CAM_SNAP,
+		.desc           = "cam_snap_key",
+		.active_low     = 1,
+		.type		= EV_KEY,
+		.debounce_interval = 15,
+	},
+};
+
+static struct gpio_keys_platform_data mtp_keys_data = {
+	.buttons        = mtp_keys,
+	.nbuttons       = ARRAY_SIZE(mtp_keys),
+};
+
+static struct platform_device mtp_kp_pdev = {
+	.name           = "gpio-keys",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &mtp_keys_data,
+	},
+};
+
+
 static void __init apq8064_clock_init(void)
 {
 	if (machine_is_apq8064_rumi3())
@@ -1569,6 +1805,12 @@
 		cyttsp_info,
 		ARRAY_SIZE(cyttsp_info),
 	},
+	{
+		I2C_FFA | I2C_LIQUID,
+		APQ_8064_GSBI1_QUP_I2C_BUS_ID,
+		isa1200_board_info,
+		ARRAY_SIZE(isa1200_board_info),
+	},
 };
 
 static void __init register_i2c_devices(void)
@@ -1576,6 +1818,14 @@
 	u8 mach_mask = 0;
 	int i;
 
+#ifdef CONFIG_MSM_CAMERA
+	struct i2c_registry apq8064_camera_i2c_devices = {
+		I2C_SURF | I2C_FFA | I2C_LIQUID | I2C_RUMI,
+		APQ_8064_GSBI4_QUP_I2C_BUS_ID,
+		apq8064_camera_board_info.board_info,
+		apq8064_camera_board_info.num_i2c_board_info,
+	};
+#endif
 	/* Build the matching 'supported_machs' bitmask */
 	if (machine_is_apq8064_cdp())
 		mach_mask = I2C_SURF;
@@ -1597,6 +1847,12 @@
 						apq8064_i2c_devices[i].info,
 						apq8064_i2c_devices[i].len);
 	}
+#ifdef CONFIG_MSM_CAMERA
+	if (apq8064_camera_i2c_devices.machs & mach_mask)
+		i2c_register_board_info(apq8064_camera_i2c_devices.bus,
+			apq8064_camera_i2c_devices.info,
+			apq8064_camera_i2c_devices.len);
+#endif
 }
 
 static void __init apq8064_common_init(void)
@@ -1618,9 +1874,13 @@
 	if (machine_is_apq8064_liquid())
 		msm_otg_pdata.mhl_enable = true;
 	apq8064_device_otg.dev.platform_data = &msm_otg_pdata;
-	apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
+	apq8064_ehci_host_init();
 	apq8064_init_buses();
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+	if (machine_is_apq8064_mtp()) {
+		apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
+		device_initialize(&apq8064_device_hsic_host.dev);
+	}
 	apq8064_pm8xxx_gpio_mpp_init();
 	apq8064_init_mmc();
 
@@ -1652,12 +1912,14 @@
 		&msm8064_device_watchdog.dev.platform_data;
 
 	wdog_pdata->bark_time = 15000;
+	msm_tsens_early_init(&apq_tsens_pdata);
 	apq8064_common_init();
 	platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
 }
 
 static void __init apq8064_rumi3_init(void)
 {
+	msm_tsens_early_init(&apq_tsens_pdata);
 	apq8064_common_init();
 	ethernet_init();
 	platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
@@ -1668,14 +1930,21 @@
 
 static void __init apq8064_cdp_init(void)
 {
+	msm_tsens_early_init(&apq_tsens_pdata);
 	apq8064_common_init();
 	ethernet_init();
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 	apq8064_init_fb();
 	apq8064_init_gpu();
-	platform_add_devices(msm_footswitch_devices,
-			     msm_num_footswitch_devices);
+	platform_add_devices(apq8064_fs_devices, apq8064_num_fs_devices);
+	apq8064_init_cam();
+
+	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+		platform_device_register(&cdp_kp_pdev);
+
+	if (machine_is_apq8064_mtp())
+		platform_device_register(&mtp_kp_pdev);
 }
 
 MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
@@ -1727,3 +1996,21 @@
 	.init_early = apq8064_allocate_memory_regions,
 MACHINE_END
 
+MACHINE_START(MPQ8064_HRD, "QCT MPQ8064 HRD")
+	.map_io = apq8064_map_io,
+	.reserve = apq8064_reserve,
+	.init_irq = apq8064_init_irq,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_timer,
+	.init_machine = apq8064_cdp_init,
+MACHINE_END
+
+MACHINE_START(MPQ8064_DTV, "QCT MPQ8064 DTV")
+	.map_io = apq8064_map_io,
+	.reserve = apq8064_reserve,
+	.init_irq = apq8064_init_irq,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_timer,
+	.init_machine = apq8064_cdp_init,
+MACHINE_END
+
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index d401f4c..e8c8144 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -64,6 +64,8 @@
 
 extern struct msm_camera_board_info apq8064_camera_board_info;
 void apq8064_init_cam(void);
+
+#define APQ_8064_GSBI1_QUP_I2C_BUS_ID 0
 #define APQ_8064_GSBI3_QUP_I2C_BUS_ID 3
 #define APQ_8064_GSBI4_QUP_I2C_BUS_ID 4
 
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index e0bc723..f82c43c 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -349,17 +349,15 @@
 };
 
 static struct camera_vreg_t msm_8930_back_cam_vreg[] = {
-	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
 };
 
 static struct camera_vreg_t msm_8930_front_cam_vreg[] = {
-	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 };
 
@@ -409,7 +407,6 @@
 	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8930_back_cam_gpio_set_tbl),
 };
 
-#ifdef CONFIG_IMX074_ACT
 static struct i2c_board_info imx074_actuator_i2c_info = {
 	I2C_BOARD_INFO("imx074_act", 0x11),
 };
@@ -420,9 +417,7 @@
 	.vcm_pwd        = 0,
 	.vcm_enable     = 1,
 };
-#endif
 
-#ifdef CONFIG_IMX074
 static struct msm_camera_sensor_flash_data flash_imx074 = {
 	.flash_type	= MSM_CAMERA_FLASH_LED,
 #ifdef CONFIG_MSM_CAMERA_FLASH
@@ -445,21 +440,24 @@
 	.sensor_platform_info = &sensor_board_info_imx074,
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
-#ifdef CONFIG_IMX074_ACT
 	.actuator_info = &imx074_actuator_info
-#endif
 };
-#endif
 
-#ifdef CONFIG_MT9M114
+static struct camera_vreg_t msm_8930_mt9m114_vreg[] = {
+	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
 static struct msm_camera_sensor_flash_data flash_mt9m114 = {
 	.flash_type = MSM_CAMERA_FLASH_NONE
 };
 
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.cam_vreg = msm_8930_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8930_back_cam_vreg),
+	.cam_vreg = msm_8930_mt9m114_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_mt9m114_vreg),
 	.gpio_conf = &msm_8930_back_cam_gpio_conf,
 };
 
@@ -471,9 +469,7 @@
 	.csi_if = 1,
 	.camera_type = BACK_CAMERA_2D,
 };
-#endif
 
-#ifdef CONFIG_OV2720
 static struct msm_camera_sensor_flash_data flash_ov2720 = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
 };
@@ -493,10 +489,8 @@
 	.csi_if	= 1,
 	.camera_type = FRONT_CAMERA_2D,
 };
-#endif
 
 static struct camera_vreg_t msm_8930_s5k3l1yx_vreg[] = {
-	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
@@ -539,18 +533,14 @@
 
 #ifdef CONFIG_I2C
 struct i2c_board_info msm8930_camera_i2c_boardinfo[] = {
-#ifdef CONFIG_IMX074
 	{
 	I2C_BOARD_INFO("imx074", 0x1A),
 	.platform_data = &msm_camera_sensor_imx074_data,
 	},
-#endif
-#ifdef CONFIG_OV2720
 	{
 	I2C_BOARD_INFO("ov2720", 0x6C),
 	.platform_data = &msm_camera_sensor_ov2720_data,
 	},
-#endif
 	{
 	I2C_BOARD_INFO("mt9m114", 0x48),
 	.platform_data = &msm_camera_sensor_mt9m114_data,
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 9175c75..a840877 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -29,15 +29,19 @@
 #include "board-8930.h"
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1376 * 768 * 4), 4096) * 3) /* 4 bpp x 3 pages */
 #else
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1376 * 768 * 4), 4096) * 2) /* 4 bpp x 2 pages */
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE	(1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+		(roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
 #elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+		(roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
 #else
 #define MSM_FB_EXT_BUF_SIZE	0
 #endif
@@ -87,7 +91,8 @@
 				PANEL_NAME_MAX_LEN)))
 		return 0;
 
-#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+	!defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
 	if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
 			strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
 				PANEL_NAME_MAX_LEN)))
@@ -618,9 +623,15 @@
 	if (on == prev_on)
 		return 0;
 
-	if (!reg_ext_5v)
-		reg_ext_5v = regulator_get(&hdmi_msm_device.dev,
-			"hdmi_mvs");
+	if (!reg_ext_5v) {
+		reg_ext_5v = regulator_get(&hdmi_msm_device.dev, "hdmi_mvs");
+		if (IS_ERR(reg_ext_5v)) {
+			pr_err("'%s' regulator not found, rc=%ld\n",
+				"hdmi_mvs", IS_ERR(reg_ext_5v));
+			reg_ext_5v = NULL;
+			return -ENODEV;
+		}
+	}
 
 	if (on) {
 		rc = regulator_enable(reg_ext_5v);
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 2f9fdcd..3a6a30d 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -30,10 +30,9 @@
 	REGULATOR_SUPPLY("8038_l2",		NULL),
 	REGULATOR_SUPPLY("iris_vdddig",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("dsi_vdda",		"mipi_dsi.1"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0048"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",        "4-0020"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.0"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.1"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.2"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8038_l3",		NULL),
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 90cc3c5..ad71007 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -77,6 +77,7 @@
 #include <linux/ion.h>
 #include <mach/ion.h>
 #include <mach/mdm2.h>
+#include <mach/msm_rtb.h>
 
 #include "timer.h"
 #include "devices.h"
@@ -130,7 +131,7 @@
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE	0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE	0x300000 /* (3MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 #define MSM_ION_HEAP_NUM	8
@@ -250,6 +251,38 @@
 	},
 };
 
+#if defined(CONFIG_MSM_RTB)
+static struct msm_rtb_platform_data msm_rtb_pdata = {
+	.size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+	int s;
+
+	s = memparse(p, NULL);
+	msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+	return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+
+static struct platform_device msm_rtb_device = {
+	.name           = "msm_rtb",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &msm_rtb_pdata,
+	},
+};
+#endif
+
+static void __init reserve_rtb_memory(void)
+{
+#if defined(CONFIG_MSM_RTB)
+	msm8930_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+#endif
+}
+
 static void __init size_pmem_devices(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
@@ -303,6 +336,18 @@
 	.align = SZ_128K,
 };
 #endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -313,14 +358,6 @@
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -345,6 +382,14 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
@@ -399,6 +444,7 @@
 	reserve_pmem_memory();
 	reserve_ion_memory();
 	reserve_mdp_memory();
+	reserve_rtb_memory();
 }
 
 static struct reserve_info msm8930_reserve_info __initdata = {
@@ -925,12 +971,54 @@
 #ifdef CONFIG_USB_MSM_OTG_72K
 static struct msm_otg_platform_data msm_otg_pdata;
 #else
+#ifdef CONFIG_MSM_BUS_SCALING
+/* Bandwidth requests (zero) if no vote placed */
+static struct msm_bus_vectors usb_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+/* Bus bandwidth requests in Bytes/sec */
+static struct msm_bus_vectors usb_max_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 60000000,		/* At least 480Mbps on bus. */
+		.ib = 960000000,	/* MAX bursts rate */
+	},
+};
+
+static struct msm_bus_paths usb_bus_scale_usecases[] = {
+	{
+		ARRAY_SIZE(usb_init_vectors),
+		usb_init_vectors,
+	},
+	{
+		ARRAY_SIZE(usb_max_vectors),
+		usb_max_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata usb_bus_scale_pdata = {
+	usb_bus_scale_usecases,
+	ARRAY_SIZE(usb_bus_scale_usecases),
+	.name = "usb",
+};
+#endif
+
 static struct msm_otg_platform_data msm_otg_pdata = {
 	.mode			= USB_OTG,
 	.otg_control		= OTG_PMIC_CONTROL,
 	.phy_type		= SNPS_28NM_INTEGRATED_PHY,
 	.pmic_id_irq		= PM8038_USB_ID_IN_IRQ(PM8038_IRQ_BASE),
 	.power_budget		= 750,
+#ifdef CONFIG_MSM_BUS_SCALING
+	.bus_scale_table	= &usb_bus_scale_pdata,
+#endif
 };
 #endif
 
@@ -1047,9 +1135,7 @@
 static struct msm_spm_platform_data msm_spm_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW0_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1064,9 +1150,7 @@
 	},
 	[1] = {
 		.reg_base_addr = MSM_SAW1_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1120,7 +1204,6 @@
 static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW_L2_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1577,7 +1660,7 @@
 };
 
 static struct tsens_platform_data msm_tsens_pdata  = {
-	.slope			= 910,
+	.slope		= {872, 872, 872, 872, 872},
 	.tsens_factor		= 1000,
 	.hw_type		= MSM_8960,
 	.tsens_num_sensor	= 5,
@@ -1719,6 +1802,9 @@
 #ifdef MSM8930_PHASE_2
 	&gpio_keys_8930,
 #endif
+#ifdef CONFIG_MSM_RTB
+	&msm_rtb_device,
+#endif
 };
 
 static struct platform_device *cdp_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 23c4928..42c09fb 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -411,20 +411,24 @@
 		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 	},
+	{
+		.ioclk.mclk_clk_rate = 24000000,
+		.ioclk.vfe_clk_rate  = 228570000,
+		.csid_core = 2,
+		.cam_bus_scale_table = &cam_bus_client_pdata,
+	},
 };
 
 static struct camera_vreg_t msm_8960_back_cam_vreg[] = {
-	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_VS, 0, 0, 0},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
 };
 
 static struct camera_vreg_t msm_8960_front_cam_vreg[] = {
-	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 };
 
@@ -474,7 +478,6 @@
 	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8960_back_cam_gpio_set_tbl),
 };
 
-#ifdef CONFIG_IMX074_ACT
 static struct i2c_board_info imx074_actuator_i2c_info = {
 	I2C_BOARD_INFO("imx074_act", 0x11),
 };
@@ -485,9 +488,7 @@
 	.vcm_pwd        = 0,
 	.vcm_enable     = 1,
 };
-#endif
 
-#ifdef CONFIG_IMX074
 static struct msm_camera_sensor_flash_data flash_imx074 = {
 	.flash_type	= MSM_CAMERA_FLASH_LED,
 #ifdef CONFIG_MSM_CAMERA_FLASH
@@ -510,21 +511,24 @@
 	.sensor_platform_info = &sensor_board_info_imx074,
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
-#ifdef CONFIG_IMX074_ACT
 	.actuator_info = &imx074_actuator_info
-#endif
 };
-#endif
 
-#ifdef CONFIG_MT9M114
+static struct camera_vreg_t msm_8960_mt9m114_vreg[] = {
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
+};
+
 static struct msm_camera_sensor_flash_data flash_mt9m114 = {
 	.flash_type = MSM_CAMERA_FLASH_NONE
 };
 
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.cam_vreg = msm_8960_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8960_back_cam_vreg),
+	.cam_vreg = msm_8960_mt9m114_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_mt9m114_vreg),
 	.gpio_conf = &msm_8960_back_cam_gpio_conf,
 };
 
@@ -536,9 +540,7 @@
 	.csi_if = 1,
 	.camera_type = BACK_CAMERA_2D,
 };
-#endif
 
-#ifdef CONFIG_OV2720
 static struct msm_camera_sensor_flash_data flash_ov2720 = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
 };
@@ -558,10 +560,8 @@
 	.csi_if	= 1,
 	.camera_type = FRONT_CAMERA_2D,
 };
-#endif
 
 static struct camera_vreg_t msm_8960_s5k3l1yx_vreg[] = {
-	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vio", REG_VS, 0, 0, 0},
@@ -643,8 +643,10 @@
 
 	platform_device_register(&msm8960_device_csiphy0);
 	platform_device_register(&msm8960_device_csiphy1);
+	platform_device_register(&msm8960_device_csiphy2);
 	platform_device_register(&msm8960_device_csid0);
 	platform_device_register(&msm8960_device_csid1);
+	platform_device_register(&msm8960_device_csid2);
 	platform_device_register(&msm8960_device_ispif);
 	platform_device_register(&msm8960_device_vfe);
 	platform_device_register(&msm8960_device_vpe);
@@ -652,18 +654,14 @@
 
 #ifdef CONFIG_I2C
 static struct i2c_board_info msm8960_camera_i2c_boardinfo[] = {
-#ifdef CONFIG_IMX074
 	{
 	I2C_BOARD_INFO("imx074", 0x1A),
 	.platform_data = &msm_camera_sensor_imx074_data,
 	},
-#endif
-#ifdef CONFIG_OV2720
 	{
 	I2C_BOARD_INFO("ov2720", 0x6C),
 	.platform_data = &msm_camera_sensor_ov2720_data,
 	},
-#endif
 	{
 	I2C_BOARD_INFO("mt9m114", 0x48),
 	.platform_data = &msm_camera_sensor_mt9m114_data,
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index aa8477e..37a988a 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -29,15 +29,19 @@
 #include "board-8960.h"
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1920 * 1200 * 4), 4096) * 3) /* 4 bpp x 3 pages */
 #else
-#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1920 * 1200 * 4), 4096) * 2) /* 4 bpp x 2 pages */
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE	(1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+		(roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
 #elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+		(roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
 #else
 #define MSM_FB_EXT_BUF_SIZE	0
 #endif
@@ -68,6 +72,7 @@
 #define MIPI_CMD_NOVATEK_QHD_PANEL_NAME	"mipi_cmd_novatek_qhd"
 #define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME	"mipi_video_novatek_qhd"
 #define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME	"mipi_video_toshiba_wsvga"
+#define MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME	"mipi_video_toshiba_wuxga"
 #define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME	"mipi_video_chimei_wxga"
 #define MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME	"mipi_video_chimei_wuxga"
 #define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME	"mipi_video_simulator_vga"
@@ -81,7 +86,7 @@
 	}
 };
 
-static void set_mdp_clocks_for_liquid_wuxga(void);
+static void set_mdp_clocks_for_wuxga(void);
 
 static int msm_fb_detect_panel(const char *name)
 {
@@ -91,7 +96,7 @@
 			if (!strncmp(name, MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
 				     strnlen(MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
 						PANEL_NAME_MAX_LEN))) {
-				set_mdp_clocks_for_liquid_wuxga();
+				set_mdp_clocks_for_wuxga();
 				return 0;
 			}
 		} else {
@@ -106,7 +111,8 @@
 					PANEL_NAME_MAX_LEN)))
 			return 0;
 
-#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+	!defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
 		if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
 				strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
 					PANEL_NAME_MAX_LEN)))
@@ -126,6 +132,13 @@
 				strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
 					PANEL_NAME_MAX_LEN)))
 			return 0;
+
+		if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME,
+				strnlen(MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME,
+					PANEL_NAME_MAX_LEN))) {
+			set_mdp_clocks_for_wuxga();
+			return 0;
+		}
 #endif
 	}
 
@@ -649,9 +662,9 @@
 
 /**
  * Set MDP clocks to high frequency to avoid DSI underflow
- * when using high resolution 1200x1920 WUXGA panel.
+ * when using high resolution 1200x1920 WUXGA panels
  */
-static void set_mdp_clocks_for_liquid_wuxga(void)
+static void set_mdp_clocks_for_wuxga(void)
 {
 	int i;
 
@@ -866,9 +879,16 @@
 	if (on == prev_on)
 		return 0;
 
-	if (!reg_8921_hdmi_mvs)
+	if (!reg_8921_hdmi_mvs) {
 		reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
-			"hdmi_mvs");
+					"hdmi_mvs");
+		if (IS_ERR(reg_8921_hdmi_mvs)) {
+			pr_err("'%s' regulator not found, rc=%ld\n",
+				"hdmi_mvs", IS_ERR(reg_8921_hdmi_mvs));
+			reg_8921_hdmi_mvs = NULL;
+			return -ENODEV;
+		}
+	}
 
 	if (on) {
 		rc = regulator_enable(reg_8921_hdmi_mvs);
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 744709c..5f8f90b 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -88,6 +88,12 @@
 			PM_GPIO_STRENGTH_HIGH, \
 			PM_GPIO_FUNC_NORMAL, 0, 0)
 
+#define PM8XXX_GPIO_OUTPUT_STRENGTH(_gpio, _val, _out_strength) \
+	PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+			PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+			_out_strength, \
+			PM_GPIO_FUNC_NORMAL, 0, 0)
+
 /* Initial PM8921 GPIO configurations */
 static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
 	PM8XXX_GPIO_OUTPUT_VIN(6, 1, PM_GPIO_VIN_VPH),	 /* MHL power EN_N */
@@ -104,6 +110,8 @@
 	PM8XXX_GPIO_INPUT(26,	    PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
 	PM8XXX_GPIO_OUTPUT(43,	    PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
 	PM8XXX_GPIO_OUTPUT(42, 0),                      /* USB 5V reg enable */
+	/* TABLA CODEC RESET */
+	PM8XXX_GPIO_OUTPUT_STRENGTH(34, 1, PM_GPIO_STRENGTH_MED)
 };
 
 /* Initial PM8921 MPP configurations */
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 0f05af5..d98ae56 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -30,10 +30,9 @@
 VREG_CONSUMERS(L2) = {
 	REGULATOR_SUPPLY("8921_l2",		NULL),
 	REGULATOR_SUPPLY("dsi_vdda",		"mipi_dsi.1"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0048"),
-	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0020"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.0"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.1"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.2"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8921_l3",		NULL),
@@ -527,7 +526,7 @@
 	RPM_LDO(L6,	 0, 1, 0, 2950000, 2950000, NULL,      0, 0),
 	RPM_LDO(L7,	 1, 1, 0, 1850000, 2950000, NULL,      10000, 10000),
 	RPM_LDO(L8,	 0, 1, 0, 2800000, 3000000, NULL,      0, 0),
-	RPM_LDO(L9,	 0, 1, 0, 2850000, 2850000, NULL,      0, 0),
+	RPM_LDO(L9,	 0, 1, 0, 3000000, 3000000, NULL,      0, 0),
 	RPM_LDO(L10,	 0, 1, 0, 3000000, 3000000, NULL,      0, 0),
 	RPM_LDO(L11,	 0, 1, 0, 2850000, 2850000, NULL,      0, 0),
 	RPM_LDO(L12,	 0, 1, 0, 1200000, 1200000, "8921_s4", 0, 0),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 76a27ff..e843a39 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -79,6 +79,7 @@
 #include <mach/ion.h>
 #include <mach/mdm2.h>
 #include <mach/mdm-peripheral.h>
+#include <mach/msm_rtb.h>
 
 #include <linux/fmem.h>
 
@@ -143,7 +144,7 @@
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE	0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE	0x300000 /* (3MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 #define MSM_ION_HEAP_NUM	8
@@ -270,6 +271,38 @@
 	},
 };
 
+#if defined(CONFIG_MSM_RTB)
+static struct msm_rtb_platform_data msm_rtb_pdata = {
+	.size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+	int s;
+
+	s = memparse(p, NULL);
+	msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+	return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+
+static struct platform_device msm_rtb_device = {
+	.name           = "msm_rtb",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &msm_rtb_pdata,
+	},
+};
+#endif
+
+static void __init reserve_rtb_memory(void)
+{
+#if defined(CONFIG_MSM_RTB)
+	msm8960_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+#endif
+}
+
 static void __init size_pmem_devices(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
@@ -306,30 +339,48 @@
 	return MEMTYPE_EBI1;
 }
 
+#define FMEM_ENABLED 1
+
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
-	.reusable = 1,
+	.reusable = FMEM_ENABLED,
+	.mem_is_fmem = FMEM_ENABLED,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
 	.reusable = 0,
+	.mem_is_fmem = FMEM_ENABLED,
 };
 
 static struct ion_co_heap_pdata co_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
+	.mem_is_fmem = 0,
 };
 
 static struct ion_co_heap_pdata fw_co_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
+	.mem_is_fmem = FMEM_ENABLED,
 };
 #endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -340,14 +391,6 @@
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -372,6 +415,14 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
@@ -432,23 +483,17 @@
 	msm8960_reserve_table[mem_type].size += size;
 }
 
-static __init const struct ion_platform_heap *find_ion_heap(int heap_id)
-{
-	unsigned int i;
-	for (i = 0; i < ion_pdata.nr; ++i) {
-		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
-		if (heap->id == heap_id)
-			return (const struct ion_platform_heap *) heap;
-	}
-	return 0;
-}
-
 /**
  * Reserve memory for ION and calculate amount of reusable memory for fmem.
  * We only reserve memory for heaps that are not reusable. However, we only
  * support one reusable heap at the moment so we ignore the reusable flag for
  * other than the first heap with reusable flag set. Also handle special case
- * for adjacent heap when the adjacent heap is adjacent to a reusable heap.
+ * for video heaps (MM,FW, and MFC). Video requires heaps MM and MFC to be
+ * at a higher address than FW in addition to not more than 256MB away from the
+ * base address of the firmware. This means that if MM is reusable the other
+ * two heaps must be allocated in the same region as FW. This is handled by the
+ * mem_is_fmem flag in the platform data. In addition the MM heap must be
+ * adjacent to the FW heap for content protection purposes.
  */
 static void __init reserve_ion_memory(void)
 {
@@ -458,7 +503,8 @@
 
 	adjust_mem_for_liquid();
 	fmem_pdata.size = 0;
-	fmem_pdata.reserved_size = 0;
+	fmem_pdata.reserved_size_low = 0;
+	fmem_pdata.reserved_size_high = 0;
 
 	/* We only support 1 reusable heap. Check if more than one heap
 	 * is specified as reusable and set as non-reusable if found.
@@ -483,7 +529,7 @@
 	for (i = 0; i < ion_pdata.nr; ++i) {
 		int reusable = 0;
 		int adjacent_heap_id = INVALID_HEAP_ID;
-		int adj_reusable = 0;
+		int mem_is_fmem = 0;
 		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
 
 		if (heap->extra_data) {
@@ -491,31 +537,30 @@
 			case ION_HEAP_TYPE_CP:
 				reusable = ((struct ion_cp_heap_pdata *)
 						heap->extra_data)->reusable;
+				mem_is_fmem = ((struct ion_cp_heap_pdata *)
+						heap->extra_data)->mem_is_fmem;
 				break;
 			case ION_HEAP_TYPE_CARVEOUT:
 				adjacent_heap_id = ((struct ion_co_heap_pdata *)
 					heap->extra_data)->adjacent_mem_id;
+				mem_is_fmem = ((struct ion_co_heap_pdata *)
+						heap->extra_data)->mem_is_fmem;
 				break;
 			default:
 				break;
 			}
 		}
 
-		if (adjacent_heap_id != INVALID_HEAP_ID) {
-			const struct ion_platform_heap *adj_heap =
-						find_ion_heap(adjacent_heap_id);
-			if (adj_heap) {
-				adj_reusable = ((struct ion_cp_heap_pdata *)
-						adj_heap->extra_data)->reusable;
-				if (adj_reusable)
-					fmem_pdata.reserved_size += heap->size;
-			}
+		if (mem_is_fmem && !reusable) {
+			if (adjacent_heap_id != INVALID_HEAP_ID)
+				fmem_pdata.reserved_size_low += heap->size;
+			else
+				fmem_pdata.reserved_size_high += heap->size;
 		}
-
-		if (!reusable && !adj_reusable)
-			reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
-		else
+		if (mem_is_fmem)
 			fmem_pdata.size += heap->size;
+		else
+			reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
 	}
 #endif
 }
@@ -531,6 +576,7 @@
 	reserve_pmem_memory();
 	reserve_ion_memory();
 	reserve_mdp_memory();
+	reserve_rtb_memory();
 }
 
 static struct reserve_info msm8960_reserve_info __initdata = {
@@ -1186,9 +1232,7 @@
 static struct msm_spm_platform_data msm_spm_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW0_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0xB0,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1203,9 +1247,7 @@
 	},
 	[1] = {
 		.reg_base_addr = MSM_SAW1_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0xB0,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1259,7 +1301,6 @@
 static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW_L2_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1675,6 +1716,63 @@
 	255,
 };
 
+/* configuration data for mxt1386e on 3D SKU using V2.1 firmware */
+static const u8 mxt1386e_config_data_3d[] = {
+	/* T6 Object */
+	0, 0, 0, 0, 0, 0,
+	/* T38 Object */
+	13, 0, 0, 6, 2, 12, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T7 Object */
+	100, 16, 50,
+	/* T8 Object */
+	25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
+	/* T9 Object */
+	131, 0, 0, 26, 42, 0, 32, 80, 2, 5,
+	0, 5, 5, 0, 10, 30, 10, 10, 175, 4,
+	127, 7, 10, 10, 10, 10, 135, 55, 70, 40,
+	10, 5, 0, 0, 0,
+	/* T18 Object */
+	0, 0,
+	/* T24 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0,
+	/* T25 Object */
+	3, 0, 60, 115, 156, 99,
+	/* T27 Object */
+	0, 0, 0, 0, 0, 0, 0,
+	/* T40 Object */
+	0, 0, 0, 0, 0,
+	/* T42 Object */
+	2, 0, 255, 0, 255, 0, 0, 0, 0, 0,
+	/* T43 Object */
+	0, 0, 0, 0, 0, 0, 0, 64, 0, 8,
+	16,
+	/* T46 Object */
+	64, 0, 20, 20, 0, 0, 0, 0, 0,
+	/* T47 Object */
+	0, 0, 0, 0, 0, 0, 3, 64, 66, 0,
+	/* T48 Object */
+	31, 64, 64, 0, 0, 0, 0, 0, 0, 0,
+	48, 40, 0, 10, 10, 0, 0, 100, 10, 80,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+	52, 0, 12, 0, 17, 0, 1, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T56 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	2, 99, 33, 0, 149, 24, 193, 255, 255, 255,
+	255,
+};
+
 #define MXT_TS_GPIO_IRQ			11
 #define MXT_TS_LDO_EN_GPIO		50
 #define MXT_TS_RESET_GPIO		52
@@ -1703,7 +1801,7 @@
 	gpio_free(MXT_TS_LDO_EN_GPIO);
 }
 
-static struct mxt_config_info mxt_config_array[] = {
+static struct mxt_config_info mxt_config_array_2d[] = {
 	{
 		.config		= mxt1386_config_data,
 		.config_length	= ARRAY_SIZE(mxt1386_config_data),
@@ -1730,9 +1828,9 @@
 	},
 };
 
-static struct mxt_platform_data mxt_platform_data = {
-	.config_array		= mxt_config_array,
-	.config_array_size	= ARRAY_SIZE(mxt_config_array),
+static struct mxt_platform_data mxt_platform_data_2d = {
+	.config_array		= mxt_config_array_2d,
+	.config_array_size	= ARRAY_SIZE(mxt_config_array_2d),
 	.x_size			= 1365,
 	.y_size			= 767,
 	.irqflags		= IRQF_TRIGGER_FALLING,
@@ -1741,10 +1839,31 @@
 	.irq_gpio		= MXT_TS_GPIO_IRQ,
 };
 
+static struct mxt_config_info mxt_config_array_3d[] = {
+	{
+		.config		= mxt1386e_config_data_3d,
+		.config_length	= ARRAY_SIZE(mxt1386e_config_data_3d),
+		.family_id	= 0xA0,
+		.variant_id	= 0x7,
+		.version	= 0x21,
+		.build		= 0xAA,
+	},
+};
+
+static struct mxt_platform_data mxt_platform_data_3d = {
+	.config_array		= mxt_config_array_3d,
+	.config_array_size	= ARRAY_SIZE(mxt_config_array_3d),
+	.x_size			= 1919,
+	.y_size			= 1199,
+	.irqflags		= IRQF_TRIGGER_FALLING,
+	.i2c_pull_up		= true,
+	.reset_gpio		= MXT_TS_RESET_GPIO,
+	.irq_gpio		= MXT_TS_GPIO_IRQ,
+};
+
 static struct i2c_board_info mxt_device_info[] __initdata = {
 	{
 		I2C_BOARD_INFO("atmel_mxt_ts", 0x5b),
-		.platform_data = &mxt_platform_data,
 		.irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
 	},
 };
@@ -1824,7 +1943,7 @@
 };
 
 static struct tsens_platform_data msm_tsens_pdata  = {
-		.slope			= 910,
+		.slope			= {910, 910, 910, 910, 910},
 		.tsens_factor		= 1000,
 		.hw_type		= MSM_8960,
 		.tsens_num_sensor	= 5,
@@ -1943,6 +2062,9 @@
 #endif
 	&msm_device_dspcrashd_8960,
 	&msm8960_device_watchdog,
+#ifdef CONFIG_MSM_RTB
+	&msm_rtb_device,
+#endif
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -2419,6 +2541,15 @@
 	else
 		pr_err("unmatched machine ID in register_i2c_devices\n");
 
+	if (machine_is_msm8960_liquid()) {
+		if (SOCINFO_VERSION_MAJOR(socinfo_get_platform_version()) == 3)
+			mxt_device_info[0].platform_data =
+						&mxt_platform_data_3d;
+		else
+			mxt_device_info[0].platform_data =
+						&mxt_platform_data_2d;
+	}
+
 	/* Run the array and install devices as appropriate */
 	for (i = 0; i < ARRAY_SIZE(msm8960_i2c_devices); ++i) {
 		if (msm8960_i2c_devices[i].machs & mach_mask)
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index 95a1347..58e40db 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -70,6 +70,7 @@
 	REGULATOR_SUPPLY("8018_s1",		NULL),
 	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_otg"),
 	REGULATOR_SUPPLY("HSIC_VDDCX",		"msm_hsic_peripheral"),
+	REGULATOR_SUPPLY("HSIC_VDDCX",		"msm_hsic_host"),
 };
 VREG_CONSUMERS(S2) = {
 	REGULATOR_SUPPLY("8018_s2",		NULL),
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 1f19bf6..74471dd 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -518,6 +518,7 @@
 	&msm_device_hsic_peripheral,
 	&msm_device_gadget_peripheral,
 	&msm_device_hsusb_host,
+	&msm_device_hsic_host,
 	&msm_device_usb_bam,
 	&android_usb_device,
 	&msm9615_device_uart_gsbi4,
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index b4b0b9a..dc26d72 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -36,6 +36,7 @@
 #include <mach/ion.h>
 #endif
 #include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
 #include "clock.h"
 
 #define MSM_KERNEL_EBI1_MEM_SIZE	0x280000
@@ -98,6 +99,17 @@
 	.align = SZ_128K,
 };
 
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -107,14 +119,6 @@
 			.name	= ION_VMALLOC_HEAP_NAME,
 		},
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -139,6 +143,14 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
@@ -182,6 +194,126 @@
 }
 #endif
 
+static struct resource smd_resource[] = {
+	{
+		.name	= "modem_smd_in",
+		.start	= 32 + 17,		/* mss_sw_to_kpss_ipc_irq0  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "modem_smsm_in",
+		.start	= 32 + 18,		/* mss_sw_to_kpss_ipc_irq1  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "adsp_smd_in",
+		.start	= 32 + 156,		/* lpass_to_kpss_ipc_irq0  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "adsp_smsm_in",
+		.start	= 32 + 157,		/* lpass_to_kpss_ipc_irq1  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "wcnss_smd_in",
+		.start	= 32 + 142,		/* WcnssAppsSmdMedIrq  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "wcnss_smsm_in",
+		.start	= 32 + 144,		/* RicaAppsWlanSmsmIrq  */
+		.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 = "modem_smd_in",
+		.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 << 12,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "modem_smsm_in",
+		.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 << 13,
+		.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_smd_in",
+		.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 << 8,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "adsp_smsm_in",
+		.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 << 9,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+	{
+		.irq_config_id = SMD_WCNSS,
+		.subsys_name = "wcnss",
+		.edge = SMD_APPS_WCNSS,
+
+		.smd_int.irq_name = "wcnss_smd_in",
+		.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 << 17,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "wcnss_smsm_in",
+		.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 << 19,
+		.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_copper = {
+	.name	= "msm_smd",
+	.id	= -1,
+	.resource = smd_resource,
+	.num_resources = ARRAY_SIZE(smd_resource),
+	.dev = {
+		.platform_data = &smd_platform_data,
+	}
+};
+
 static void __init msm_copper_calculate_reserve_sizes(void)
 {
 #ifdef CONFIG_ION_MSM
@@ -223,6 +355,7 @@
 #ifdef CONFIG_ION_MSM
 	platform_device_register(&ion_dev);
 #endif
+	platform_device_register(&msm_device_smd_copper);
 }
 
 static struct of_device_id irq_match[] __initdata  = {
@@ -247,6 +380,7 @@
 	CLK_DUMMY("core_clk", NULL, "msm_otg", OFF),
 	CLK_DUMMY("alt_core_clk", NULL, "msm_otg", OFF),
 	CLK_DUMMY("iface_clk", NULL, "msm_otg", OFF),
+	CLK_DUMMY("xo", NULL, "msm_otg", OFF),
 	CLK_DUMMY("dfab_clk",	DFAB_CLK,	NULL, 0),
 	CLK_DUMMY("dma_bam_pclk",	DMA_BAM_P_CLK,	NULL, 0),
 	CLK_DUMMY("mem_clk",	NULL,	NULL, 0),
@@ -266,6 +400,8 @@
 			"msm_otg", NULL),
 	OF_DEV_AUXDATA("qcom,spi-qup-v2", 0xF9924000, \
 			"spi_qsd.1", NULL),
+	OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
+			"spmi-pmic-arb.0", NULL),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index c0b1d16..06fbb7b 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -22,6 +22,7 @@
 #include <mach/irqs-7xxx.h>
 #include "devices-msm7x2xa.h"
 #include "board-msm7627a.h"
+#include <mach/vreg.h>
 
 #ifdef CONFIG_MSM_CAMERA_V4L2
 static uint32_t camera_off_gpio_table[] = {
@@ -177,6 +178,7 @@
 static struct msm_camera_sensor_info msm_camera_sensor_s5k4e1_data = {
 	.sensor_name    = "s5k4e1",
 	.sensor_reset_enable = 1,
+	.pmic_gpio_enable    = 0,
 	.pdata                  = &msm_camera_device_data_csi1,
 	.flash_data             = &flash_s5k4e1,
 	.sensor_platform_info   = &sensor_board_info_s5k4e1,
@@ -205,6 +207,7 @@
 static struct msm_camera_sensor_info msm_camera_sensor_mt9e013_data = {
 	.sensor_name    = "mt9e013",
 	.sensor_reset_enable = 1,
+	.pmic_gpio_enable    = 0,
 	.pdata                  = &msm_camera_device_data_csi1,
 	.flash_data             = &flash_mt9e013,
 	.sensor_platform_info   = &sensor_board_info_mt9e013,
@@ -227,6 +230,7 @@
 	.sensor_name    = "imx072",
 	.sensor_reset_enable = 1,
 	.sensor_reset   = GPIO_CAM_GP_CAMIF_RESET_N, /* TODO 106,*/
+	.pmic_gpio_enable  = 0,
 	.sensor_pwd             = 85,
 	.vcm_pwd                = GPIO_CAM_GP_CAM_PWDN,
 	.vcm_enable             = 1,
@@ -261,6 +265,7 @@
 static struct msm_camera_sensor_info msm_camera_sensor_ov9726_data = {
 	.sensor_name    = "ov9726",
 	.sensor_reset_enable = 0,
+	.pmic_gpio_enable  = 0,
 	.pdata                  = &msm_camera_device_data_csi0,
 	.flash_data             = &flash_ov9726,
 	.sensor_platform_info   = &sensor_board_info_ov9726,
@@ -385,6 +390,85 @@
 	gpio_direction_output(QRD_GPIO_CAM_3MP_PWDN, 1);
 }
 
+#define GPIO_SKU3_CAM_5MP_SHDN_N   5         /* PWDN */
+#define GPIO_SKU3_CAM_5MP_CAMIF_RESET   6    /* (board_is(EVT))?123:121 RESET */
+#define GPIO_SKU3_CAM_5MP_CAM_DRIVER_PWDN 30
+
+#define GPIO_SKU1_CAM_VGA_SHDN    18
+#define GPIO_SKU1_CAM_VGA_RESET_N 29
+
+static void evb_camera_gpio_cfg(void)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_SKU3_CAM_5MP_SHDN_N, "ov5647");
+	if (rc < 0)
+		pr_err("%s: gpio_request GPIO_SKU3_CAM_5MP_SHDN_N failed!",
+			 __func__);
+
+	pr_debug("gpio_tlmm_config %d\r\n", GPIO_SKU3_CAM_5MP_SHDN_N);
+	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU3_CAM_5MP_SHDN_N, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s:unable to enable Powr Dwn gpio for main camera!\n",
+			 __func__);
+		gpio_free(GPIO_SKU3_CAM_5MP_SHDN_N);
+	}
+
+	gpio_direction_output(GPIO_SKU3_CAM_5MP_SHDN_N, 1);
+
+	rc = gpio_request(GPIO_SKU3_CAM_5MP_CAMIF_RESET, "ov5647");
+	if (rc < 0)
+		pr_err("%s: gpio_request GPIO_SKU3_CAM_5MP_CAMIF_RESET failed!",
+			 __func__);
+
+	pr_debug("gpio_tlmm_config %d\r\n", GPIO_SKU3_CAM_5MP_CAMIF_RESET);
+	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU3_CAM_5MP_CAMIF_RESET, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s: unable to enable reset gpio for main camera!\n",
+			 __func__);
+		gpio_free(GPIO_SKU3_CAM_5MP_CAMIF_RESET);
+	}
+
+	gpio_direction_output(GPIO_SKU3_CAM_5MP_CAMIF_RESET, 1);
+
+	rc = gpio_request(GPIO_SKU1_CAM_VGA_SHDN, "ov7692");
+	if (rc < 0)
+		pr_err("%s: gpio_request---GPIO_SKU1_CAM_VGA_SHDN failed!",
+			 __func__);
+
+	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU1_CAM_VGA_SHDN, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s:unable to enable Powr Dwn gpio for frnt camera!\n",
+			 __func__);
+		gpio_free(GPIO_SKU1_CAM_VGA_SHDN);
+	}
+
+	gpio_direction_output(GPIO_SKU1_CAM_VGA_SHDN, 1);
+
+	rc = gpio_request(GPIO_SKU1_CAM_VGA_RESET_N, "ov7692");
+	if (rc < 0)
+		pr_err("%s: gpio_request---GPIO_SKU1_CAM_VGA_RESET_N failed!",
+			 __func__);
+
+	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU1_CAM_VGA_RESET_N, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+
+	if (rc < 0) {
+		pr_err("%s: unable to enable reset gpio for front camera!\n",
+			 __func__);
+		gpio_free(GPIO_SKU1_CAM_VGA_RESET_N);
+	}
+	gpio_direction_output(GPIO_SKU1_CAM_VGA_RESET_N, 1);
+
+}
+
 static void msm_camera_vreg_config(int vreg_en)
 {
 	int rc = vreg_en ?
@@ -495,6 +579,45 @@
 	.ioext.appsz		= MSM7XXX_CLK_CTL_SIZE,
 };
 
+#ifdef CONFIG_OV5647
+
+static struct msm_camera_sensor_platform_info ov5647_sensor_7627a_info = {
+	.mount_angle = 90
+};
+
+static struct msm_camera_sensor_flash_src msm_flash_src_ov5647 = {
+	.flash_sr_type = MSM_CAMERA_FLASH_SRC_LED,
+	._fsrc.led_src.led_name = "flashlight",
+	._fsrc.led_src.led_name_len = 10,
+};
+
+static struct msm_camera_sensor_flash_data flash_ov5647 = {
+	.flash_type             = MSM_CAMERA_FLASH_LED,
+	.flash_src              = &msm_flash_src_ov5647,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov5647_data = {
+	.sensor_name    = "ov5647",
+	.sensor_reset_enable = 1,
+	.sensor_reset   = GPIO_SKU3_CAM_5MP_CAMIF_RESET,
+	.pmic_gpio_enable  = 1,
+	.sensor_pwd     = GPIO_SKU3_CAM_5MP_SHDN_N,
+	.vcm_pwd        = GPIO_SKU3_CAM_5MP_CAM_DRIVER_PWDN,
+	.vcm_enable     = 1,
+	.pdata          = &msm_camera_device_data_rear,
+	.flash_data     = &flash_ov5647,
+	.sensor_platform_info   = &ov5647_sensor_7627a_info,
+	.csi_if                 = 1
+};
+
+static struct platform_device msm_camera_sensor_ov5647 = {
+	.name      = "msm_camera_ov5647",
+	.dev       = {
+		.platform_data = &msm_camera_sensor_ov5647_data,
+	},
+};
+#endif
+
 #ifdef CONFIG_S5K4E1
 static struct msm_camera_sensor_platform_info s5k4e1_sensor_7627a_info = {
 	.mount_angle = 90
@@ -509,6 +632,7 @@
 	.sensor_name		= "s5k4e1",
 	.sensor_reset_enable	= 1,
 	.sensor_reset		= GPIO_CAM_GP_CAMIF_RESET_N,
+	.pmic_gpio_enable       = 0,
 	.sensor_pwd	     = 85,
 	.vcm_pwd		= GPIO_CAM_GP_CAM_PWDN,
 	.vcm_enable	     = 1,
@@ -540,6 +664,7 @@
 	.sensor_name		= "imx072",
 	.sensor_reset_enable	= 1,
 	.sensor_reset		= GPIO_CAM_GP_CAMIF_RESET_N, /* TODO 106,*/
+	.pmic_gpio_enable       = 0,
 	.sensor_pwd	     = 85,
 	.vcm_pwd		= GPIO_CAM_GP_CAM_PWDN,
 	.vcm_enable	     = 1,
@@ -572,6 +697,7 @@
 	.sensor_name		= "ov9726",
 	.sensor_reset_enable	= 0,
 	.sensor_reset		= GPIO_CAM_GP_CAM1MP_XCLR,
+	.pmic_gpio_enable       = 0,
 	.sensor_pwd	     = 85,
 	.vcm_pwd		= 1,
 	.vcm_enable	     = 0,
@@ -605,6 +731,7 @@
 	.sensor_name		= "mt9e013",
 	.sensor_reset		= 0,
 	.sensor_reset_enable	= 1,
+	.pmic_gpio_enable       = 0,
 	.sensor_pwd		= 85,
 	.vcm_pwd		= 1,
 	.vcm_enable		= 0,
@@ -641,6 +768,7 @@
 static struct msm_camera_sensor_info msm_camera_sensor_ov5640_data = {
 	.sensor_name	    = "ov5640",
 	.sensor_reset_enable    = 1,
+	.pmic_gpio_enable  = 0,
 	.sensor_reset	   = QRD_GPIO_CAM_5MP_RESET,
 	.sensor_pwd	     = QRD_GPIO_CAM_5MP_SHDN_EN,
 	.vcm_pwd		= 0,
@@ -671,8 +799,9 @@
 static struct msm_camera_sensor_info msm_camera_sensor_ov7692_data = {
 	.sensor_name	    = "ov7692",
 	.sensor_reset_enable    = 0,
-	.sensor_reset	   = 0,
-	.sensor_pwd	     = QRD_GPIO_CAM_3MP_PWDN,
+	.pmic_gpio_enable  = 1,
+	.sensor_reset	   = GPIO_SKU1_CAM_VGA_RESET_N,
+	.sensor_pwd	     = GPIO_SKU1_CAM_VGA_SHDN,
 	.vcm_pwd		= 0,
 	.vcm_enable	     = 0,
 	.pdata			= &msm_camera_device_data_front,
@@ -731,6 +860,22 @@
 	#endif
 };
 
+static struct i2c_board_info i2c_camera_devices_evb[] = {
+	#ifdef CONFIG_OV5647
+	{
+		I2C_BOARD_INFO("ov5647", 0x36 << 1),
+	},
+	{
+		I2C_BOARD_INFO("ov5647_af", 0x18 >> 1),
+	},
+	#endif
+	#ifdef CONFIG_WEBCAM_OV7692_QRD
+	{
+		I2C_BOARD_INFO("ov7692", 0x78),
+	},
+	#endif
+};
+
 static struct platform_device *camera_devices_msm[] __initdata = {
 #ifdef CONFIG_S5K4E1
 	&msm_camera_sensor_s5k4e1,
@@ -754,6 +899,15 @@
 	&msm_camera_sensor_ov7692,
 #endif
 };
+
+static struct platform_device *camera_devices_evb[] __initdata = {
+#ifdef CONFIG_OV5647
+	&msm_camera_sensor_ov5647,
+#endif
+#ifdef CONFIG_WEBCAM_OV7692_QRD
+	&msm_camera_sensor_ov7692,
+#endif
+};
 #endif
 
 enum {
@@ -785,24 +939,127 @@
 				ARRAY_SIZE(cam_exp_i2c_info));
 }
 
+#define LCD_CAMERA_LDO_2V8 35 /* SKU1&SKU3 2.8V LDO */
+#define SKU3_LCD_CAMERA_LDO_1V8 40 /* SKU3 1.8V LDO */
+
+static int lcd_camera_ldo_1v8 = SKU3_LCD_CAMERA_LDO_1V8;
+
+static void lcd_camera_power_init(void)
+{
+	int rc = 0;
+
+	pr_debug("lcd_camera_power_init\n");
+
+	lcd_camera_ldo_1v8 = SKU3_LCD_CAMERA_LDO_1V8; /* SKU3 PVT */
+
+	/* LDO_EXT2V8 */
+	if (gpio_request(LCD_CAMERA_LDO_2V8, "lcd_camera_ldo_2v8")) {
+		pr_err("failed to request gpio lcd_camera_ldo_2v8\n");
+		return;
+	}
+
+	rc = gpio_tlmm_config(GPIO_CFG(LCD_CAMERA_LDO_2V8, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s: unable to enable lcd_camera_ldo_2v8!\n", __func__);
+		goto fail_gpio2;
+	}
+
+	/* LDO_EVT1V8 */
+	if (gpio_request(lcd_camera_ldo_1v8, "lcd_camera_ldo_1v8")) {
+		pr_err("failed to request gpio lcd_camera_ldo_1v8\n");
+		goto fail_gpio2;
+	}
+
+	rc = gpio_tlmm_config(GPIO_CFG(lcd_camera_ldo_1v8, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s: unable to enable lcd_camera_ldo_1v8!\n", __func__);
+		goto fail_gpio1;
+	}
+
+	return;
+
+fail_gpio1:
+	gpio_free(lcd_camera_ldo_1v8);
+fail_gpio2:
+	gpio_free(LCD_CAMERA_LDO_2V8);
+
+	return;
+}
+
+static int lcd_camera_power_on_sku3(void)
+{
+	int rc = 0;
+
+	pr_debug("turn on sku3 lcd_camera_ldo_1v8\n");
+	gpio_set_value_cansleep(lcd_camera_ldo_1v8, 1);
+
+	pr_debug("turn on sku3 lcd_camera_ldo\n");
+	gpio_set_value_cansleep(LCD_CAMERA_LDO_2V8, 1);
+
+	return rc;
+}
+
+static int lcd_camera_power_off_sku3(void)
+{
+	int rc = 0;
+
+	pr_debug("turn off sku3 lcd_camera_ldo_1v8\n");
+	gpio_set_value_cansleep(lcd_camera_ldo_1v8, 0);
+
+	pr_debug("turn off sku3 lcd_camera_ldo\n");
+	gpio_set_value_cansleep(LCD_CAMERA_LDO_2V8, 0);
+
+	gpio_free(lcd_camera_ldo_1v8);
+	gpio_free(LCD_CAMERA_LDO_2V8);
+
+	return rc;
+}
+
+int lcd_camera_power_onoff(int on)
+{
+	int rc = 0;
+
+	pr_debug("lcd_camera_power_onoff on = %d,\n", on);
+
+	if (on)
+		rc = lcd_camera_power_on_sku3();
+	else
+		rc = lcd_camera_power_off_sku3();
+
+	return rc;
+}
+EXPORT_SYMBOL(lcd_camera_power_onoff);
+
+
 void __init msm7627a_camera_init(void)
 {
 	int rc;
 
+	pr_debug("msm7627a_camera_init Entered\n");
+	/* LCD and camera power (VREG & LDO) init */
+	if (machine_is_msm7627a_evb())
+		lcd_camera_power_init();
+
 #ifndef CONFIG_MSM_CAMERA_V4L2
 	if (machine_is_msm7627a_qrd1()) {
 		qrd1_camera_gpio_cfg();
 		platform_add_devices(camera_devices_qrd,
 				ARRAY_SIZE(camera_devices_qrd));
-	} else if (machine_is_msm7627a_evb())
-		return;
-	else if (machine_is_msm7627a_qrd3())
+	} else if (machine_is_msm7627a_evb()) {
+		evb_camera_gpio_cfg();
+		platform_add_devices(camera_devices_evb,
+				ARRAY_SIZE(camera_devices_evb));
+	} else if (machine_is_msm7627a_qrd3())
 		return;
 	else
 		platform_add_devices(camera_devices_msm,
 				ARRAY_SIZE(camera_devices_msm));
 #endif
-	if (!machine_is_msm7627a_qrd1())
+	if (!machine_is_msm7627a_qrd1() || !machine_is_msm7627a_evb())
 		register_i2c_devices();
 	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
 
@@ -822,11 +1079,16 @@
 	msm7x27a_init_cam();
 #endif
 #ifndef CONFIG_MSM_CAMERA_V4L2
-	if (machine_is_msm7627a_qrd1())
+	if (machine_is_msm7627a_qrd1()) {
 		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
 				i2c_camera_devices_qrd,
 				ARRAY_SIZE(i2c_camera_devices_qrd));
-	else
+	} else if (machine_is_msm7627a_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,
+				ARRAY_SIZE(i2c_camera_devices_evb));
+	} else
 #endif
 		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
 				i2c_camera_devices,
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 011a4d4..4e856b1 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -28,10 +28,10 @@
 #include "board-msm7627a.h"
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE	     0x260000
+#define MSM_FB_SIZE	     0x261000
 #define MSM7x25A_MSM_FB_SIZE    0xE1000
 #else
-#define MSM_FB_SIZE	     0x195000
+#define MSM_FB_SIZE	     0x196000
 #define MSM7x25A_MSM_FB_SIZE    0x96000
 #endif
 
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 93a6178..88a519d 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -26,6 +26,7 @@
 	|| defined(CONFIG_MMC_MSM_SDC3_SUPPORT)\
 	|| defined(CONFIG_MMC_MSM_SDC4_SUPPORT))
 
+#define MAX_SDCC_CONTROLLER 4
 static unsigned long vreg_sts, gpio_sts;
 
 struct sdcc_gpio {
@@ -72,17 +73,17 @@
 };
 
 static struct msm_gpio sdc2_sleep_cfg_data[] = {
-	{GPIO_CFG(62, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(62, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
 								"sdc2_clk"},
-	{GPIO_CFG(63, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(63, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_cmd"},
-	{GPIO_CFG(64, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(64, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_dat_3"},
-	{GPIO_CFG(65, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(65, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_dat_2"},
-	{GPIO_CFG(66, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(66, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_dat_1"},
-	{GPIO_CFG(67, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(67, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_dat_0"},
 };
 static struct msm_gpio sdc3_cfg_data[] = {
@@ -152,7 +153,7 @@
 		gpio_sdc1_hw_det = 42;
 }
 
-static struct regulator *sdcc_vreg_data[ARRAY_SIZE(sdcc_cfg_data)];
+static struct regulator *sdcc_vreg_data[MAX_SDCC_CONTROLLER];
 static int msm_sdcc_setup_gpio(int dev_id, unsigned int enable)
 {
 	int rc = 0;
@@ -377,14 +378,14 @@
 #endif
 	/* SDIO WLAN slot */
 #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
-	if (mmc_regulator_init(2, "mmc", 2850000))
+	if (mmc_regulator_init(2, "smps3", 1800000))
 		return;
 	msm_add_sdcc(2, &sdc2_plat_data);
 #endif
 	/* Not Used */
 #if (defined(CONFIG_MMC_MSM_SDC4_SUPPORT)\
 		&& !defined(CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT))
-	if (mmc_regulator_init(4, "mmc", 2850000))
+	if (mmc_regulator_init(4, "smps3", 1800000))
 		return;
 	msm_add_sdcc(4, &sdc4_plat_data);
 #endif
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 51da14b..a6b29dc 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -47,6 +47,7 @@
 #include <mach/msm_battery.h>
 #include <linux/smsc911x.h>
 #include <linux/atmel_maxtouch.h>
+#include <linux/fmem.h>
 #include "devices.h"
 #include "timer.h"
 #include "board-msm7x27a-regulator.h"
@@ -370,6 +371,9 @@
 	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
 	.cached = 1,
 	.memory_type = MEMTYPE_EBI1,
+	.request_region = request_fmem_c_region,
+	.release_region = release_fmem_c_region,
+	.reusable = 1,
 };
 
 static struct platform_device android_pmem_adsp_device = {
@@ -672,6 +676,14 @@
 static void msm7x27a_cfg_uart2dm_serial(void) { }
 #endif
 
+struct fmem_platform_data fmem_pdata;
+
+struct platform_device fmem_device = {
+	.name = "fmem",
+	.id = -1,
+	.dev = { .platform_data = &fmem_pdata },
+};
+
 static struct platform_device *rumi_sim_devices[] __initdata = {
 	&msm_device_dmov,
 	&msm_device_smd,
@@ -700,6 +712,7 @@
 	&msm_gsbi1_qup_i2c_device,
 	&msm_device_otg,
 	&msm_device_gadget_peripheral,
+	&fmem_device,
 	&android_usb_device,
 	&android_pmem_device,
 	&android_pmem_adsp_device,
@@ -744,8 +757,19 @@
 	},
 };
 
+#ifdef CONFIG_ANDROID_PMEM
+static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
+		&android_pmem_adsp_pdata,
+		&android_pmem_audio_pdata,
+		&android_pmem_pdata,
+};
+#endif
+
 static void __init size_pmem_devices(void)
 {
+#ifdef CONFIG_ANDROID_PMEM
+	unsigned int i;
+	unsigned int reusable_count = 0;
 
 	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
 		pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
@@ -755,11 +779,30 @@
 		pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
 	}
 
-#ifdef CONFIG_ANDROID_PMEM
 	android_pmem_adsp_pdata.size = pmem_adsp_size;
 	android_pmem_pdata.size = pmem_mdp_size;
 	android_pmem_audio_pdata.size = pmem_audio_size;
+
+	fmem_pdata.size = 0;
+
+	/* Find pmem devices that should use FMEM (reusable) memory.
+	 */
+	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
+
+		if (!reusable_count && pdata->reusable)
+			fmem_pdata.size += pdata->size;
+
+		reusable_count += (pdata->reusable) ? 1 : 0;
+
+		if (pdata->reusable && reusable_count > 1) {
+			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
+				__func__, pdata->name);
+			pdata->reusable = 0;
+		}
+	}
 #endif
+
 }
 
 static void __init reserve_memory_for(struct android_pmem_platform_data *p)
@@ -770,9 +813,12 @@
 static void __init reserve_pmem_memory(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
-	reserve_memory_for(&android_pmem_adsp_pdata);
-	reserve_memory_for(&android_pmem_pdata);
-	reserve_memory_for(&android_pmem_audio_pdata);
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+		if (!pmem_pdata_array[i]->reusable)
+			reserve_memory_for(pmem_pdata_array[i]);
+	}
+
 	msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
 #endif
 }
@@ -798,6 +844,7 @@
 {
 	reserve_info = &msm7x27a_reserve_info;
 	msm_reserve();
+	fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
 }
 
 static void __init msm8625_reserve(void)
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 47a4605..260c880 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -118,6 +118,7 @@
 #define OPTNAV_I2C_SLAVE_ADDR	(0xB0 >> 1)
 #define OPTNAV_IRQ		20
 #define OPTNAV_CHIP_SELECT	19
+#define PMIC_GPIO_SDC4_PWR_EN_N 24  /* PMIC GPIO Number 25 */
 
 /* Macros assume PMIC GPIOs start at 0 */
 #define PM8058_GPIO_PM_TO_SYS(pm_gpio)     (pm_gpio + NR_GPIO_IRQS)
@@ -167,6 +168,19 @@
 		},
 	};
 
+	struct pm8xxx_gpio_init_info sdc4_pwr_en = {
+		PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_PWR_EN_N),
+		{
+			.direction      = PM_GPIO_DIR_OUT,
+			.pull           = PM_GPIO_PULL_NO,
+			.vin_sel        = PM8058_GPIO_VIN_L5,
+			.function       = PM_GPIO_FUNC_NORMAL,
+			.inv_int_pol    = 0,
+			.out_strength   = PM_GPIO_STRENGTH_LOW,
+			.output_value   = 0,
+		},
+	};
+
 	struct pm8xxx_gpio_init_info haptics_enable = {
 		PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE),
 		{
@@ -294,6 +308,23 @@
 		}
 		gpio_set_value_cansleep(sdc4_en.gpio, 0);
 	}
+	/* FFA -> gpio_25 controls vdd of sdcc4 */
+	else {
+		/* SCD4 gpio_25 */
+		rc = pm8xxx_gpio_config(sdc4_pwr_en.gpio, &sdc4_pwr_en.config);
+		if (rc) {
+			pr_err("%s PMIC_GPIO_SDC4_PWR_EN_N config failed: %d\n",
+			       __func__, rc);
+			return rc;
+		}
+
+		rc = gpio_request(sdc4_pwr_en.gpio, "sdc4_pwr_en");
+		if (rc) {
+			pr_err("PMIC_GPIO_SDC4_PWR_EN_N gpio_req failed: %d\n",
+			       rc);
+			return rc;
+		}
+	}
 
 	return 0;
 }
@@ -5478,9 +5509,24 @@
 	if (test_bit(dev_id, &vreg_sts) == enable)
 		return rc;
 
-	if (!enable || enabled_once[dev_id - 1])
-		return 0;
+	if (dev_id == 4) {
+		if (enable) {
+			pr_debug("Enable Vdd dev_%d\n", dev_id);
+			gpio_set_value_cansleep(
+				PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_PWR_EN_N),
+						0);
+			set_bit(dev_id, &vreg_sts);
+		} else {
+			pr_debug("Disable Vdd dev_%d\n", dev_id);
+			gpio_set_value_cansleep(
+				PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_PWR_EN_N),
+				1);
+			clear_bit(dev_id, &vreg_sts);
+		}
+	}
 
+	if (!enable || enabled_once[dev_id - 1])
+			return 0;
 	if (!curr)
 		return -ENODEV;
 
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 74ba1b3..e3fc97f 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2643,15 +2643,19 @@
 #endif /* CONFIG_MSM_DSPS */
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1024 * 600 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1024 * 600 * 4), 4096) * 3) /* 4 bpp x 3 pages */
 #else
-#define MSM_FB_PRIM_BUF_SIZE (1024 * 600 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1024 * 600 * 4), 4096) * 2) /* 4 bpp x 2 pages */
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE  (1920 * 1080 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE  \
+		(roundup((1920 * 1080 * 2), 4096) * 1) /* 2 bpp x 1 page */
 #elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE  (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE  \
+		(roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
 #else
 #define MSM_FB_EXT_BUFT_SIZE	0
 #endif
@@ -2703,10 +2707,11 @@
 #define MSM_ION_MM_SIZE		0x3600000 /* (54MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_WB_SIZE		0x600000 /* 6MB */
+#define MSM_ION_QSECOM_SIZE	0x300000 /* (3MB) */
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_ION_HEAP_NUM	8
+#define MSM_ION_HEAP_NUM	9
 #else
 #define MSM_ION_HEAP_NUM	1
 #endif
@@ -5278,6 +5283,18 @@
 	.align = PAGE_SIZE,
 };
 #endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -5288,14 +5305,6 @@
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *)&co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -5312,14 +5321,6 @@
 			.extra_data = (void *) &fw_co_ion_pdata,
 		},
 		{
-			.id	= ION_CAMERA_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_CAMERA_HEAP_NAME,
-			.size	= MSM_ION_CAMERA_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MFC_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MFC_HEAP_NAME,
@@ -5328,6 +5329,22 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *)&co_ion_pdata,
+		},
+		{
+			.id	= ION_CAMERA_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_CAMERA_HEAP_NAME,
+			.size	= MSM_ION_CAMERA_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = &co_ion_pdata,
+		},
+		{
 			.id	= ION_CP_WB_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_WB_HEAP_NAME,
@@ -5336,6 +5353,14 @@
 			.extra_data = (void *) &cp_wb_ion_pdata,
 		},
 		{
+			.id	= ION_QSECOM_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_QSECOM_HEAP_NAME,
+			.size	= MSM_ION_QSECOM_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_AUDIO_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
 			.name	= ION_AUDIO_HEAP_NAME,
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 8374636..bd7ec87 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -146,7 +146,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = N16(m, n) | SPDIV(SRC_SEL_##s, div), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 
 #define F_MND8(f, nmsb, nlsb, s, div, m, n) \
@@ -155,7 +154,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = N8(nmsb, nlsb, m, n) | SPDIV(SRC_SEL_##s, div), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 
 static struct clk_ops clk_ops_rcg_7x30;
@@ -227,14 +225,13 @@
 static struct clk_ops clk_ops_tcxo = {
 	.enable = tcxo_clk_enable,
 	.disable = tcxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = pcom_is_local,
 };
 
 static struct fixed_clk tcxo_clk = {
-	.rate = 19200000,
 	.c = {
 		.dbg_name = "tcxo_clk",
+		.rate = 19200000,
 		.ops = &clk_ops_tcxo,
 		CLK_INIT(tcxo_clk.c),
 	},
@@ -253,66 +250,65 @@
 static struct clk_ops clk_ops_lpxo = {
 	.enable = lpxo_clk_enable,
 	.disable = lpxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = pcom_is_local,
 };
 
 static struct fixed_clk lpxo_clk = {
-	.rate = 24576000,
 	.c = {
 		.dbg_name = "lpxo_clk",
+		.rate = 24576000,
 		.ops = &clk_ops_lpxo,
 		CLK_INIT(lpxo_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll1_clk = {
-	.rate = 768000000,
 	.en_reg = PLL_ENA_REG,
 	.en_mask = BIT(1),
 	.status_reg = PLL1_STATUS_BASE_REG,
 	.parent = &tcxo_clk.c,
 	.c = {
 		.dbg_name = "pll1_clk",
+		.rate = 768000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll1_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll2_clk = {
-	.rate = 806400000, /* TODO: Support scaling */
 	.en_reg = PLL_ENA_REG,
 	.en_mask = BIT(2),
 	.status_reg = PLL2_STATUS_BASE_REG,
 	.parent = &tcxo_clk.c,
 	.c = {
 		.dbg_name = "pll2_clk",
+		.rate = 806400000, /* TODO: Support scaling */
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll2_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll3_clk = {
-	.rate = 737280000,
 	.en_reg = PLL_ENA_REG,
 	.en_mask = BIT(3),
 	.status_reg = PLL3_STATUS_BASE_REG,
 	.parent = &lpxo_clk.c,
 	.c = {
 		.dbg_name = "pll3_clk",
+		.rate = 737280000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll3_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll4_clk = {
-	.rate = 891000000,
 	.en_reg = PLL_ENA_REG,
 	.en_mask = BIT(4),
 	.status_reg = PLL4_STATUS_BASE_REG,
 	.parent = &lpxo_clk.c,
 	.c = {
 		.dbg_name = "pll4_clk",
+		.rate = 891000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
 	},
@@ -321,7 +317,7 @@
 static struct clk_ops clk_ops_branch;
 
 static struct clk_freq_tbl clk_tbl_axi[] = {
-	F_RAW(1, &lpxo_clk.c, 0, 0, 0, 0, NULL),
+	F_RAW(1, &lpxo_clk.c, 0, 0, 0, NULL),
 	F_END,
 };
 
@@ -998,6 +994,7 @@
 	.ns_reg = CSI_NS_REG,
 	.md_reg = CSI_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(24, 17),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_csi,
 	.current_freq = &rcg_dummy_freq,
@@ -1011,7 +1008,7 @@
 };
 
 static struct clk_freq_tbl clk_tbl_tcxo[] = {
-	F_RAW(19200000, &tcxo_clk.c, 0, 0, 0, 0, NULL),
+	F_RAW(19200000, &tcxo_clk.c, 0, 0, 0, NULL),
 	F_END,
 };
 
@@ -1142,6 +1139,7 @@
 	.ns_reg = UART1DM_NS_REG,
 	.md_reg = UART1DM_NS_REG - 4,
 	.root_en_mask = BIT(11),
+	.mnd_en_mask = BIT(8),
 	.freq_tbl = clk_tbl_uartdm,
 	.ns_mask = F_MASK_MND16,
 	.current_freq = &rcg_dummy_freq,
@@ -1167,6 +1165,7 @@
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_uartdm,
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -1252,7 +1251,7 @@
 	F_BASIC(192000000, pll1,  4),
 	F_BASIC(245760000, pll3,  3),
 	/* Sync to AXI. Hence this "rate" is not fixed. */
-	F_RAW(1, &lpxo_clk.c, 0, BIT(14), 0, 0, NULL),
+	F_RAW(1, &lpxo_clk.c, 0, BIT(14), 0, NULL),
 	F_END,
 };
 
@@ -1354,6 +1353,7 @@
 	.ns_reg = SDCn_NS_REG(1),
 	.md_reg = SDCn_NS_REG(1) - 4,
 	.ns_mask = F_MASK_MND8(19, 12),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_sdc1_3,
 	.current_freq = &rcg_dummy_freq,
@@ -1377,6 +1377,7 @@
 	.ns_reg = SDCn_NS_REG(3),
 	.md_reg = SDCn_NS_REG(3) - 4,
 	.ns_mask = F_MASK_MND8(19, 12),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_sdc1_3,
 	.current_freq = &rcg_dummy_freq,
@@ -1412,6 +1413,7 @@
 	.ns_reg = SDCn_NS_REG(2),
 	.md_reg = SDCn_NS_REG(2) - 4,
 	.ns_mask = F_MASK_MND8(20, 13),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_sdc2_4,
 	.current_freq = &rcg_dummy_freq,
@@ -1435,6 +1437,7 @@
 	.ns_reg = SDCn_NS_REG(4),
 	.md_reg = SDCn_NS_REG(4) - 4,
 	.ns_mask = F_MASK_MND8(20, 13),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_sdc2_4,
 	.current_freq = &rcg_dummy_freq,
@@ -1505,6 +1508,7 @@
 	.md_reg = MDP_LCDC_NS_REG - 4,
 	.root_en_mask = BIT(11),
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_mdp_lcdc,
 	.current_freq = &rcg_dummy_freq,
@@ -1533,8 +1537,8 @@
 };
 
 static struct clk_freq_tbl clk_tbl_mdp_vsync[] = {
-	F_RAW(       0, &gnd_clk.c,  0, (0x3<<2), 0, 0, NULL),
-	F_RAW(24576000, &lpxo_clk.c, 0, (0x1<<2), 0, 0, NULL),
+	F_RAW(       0, &gnd_clk.c,  0, (0x3<<2), 0, NULL),
+	F_RAW(24576000, &lpxo_clk.c, 0, (0x1<<2), 0, NULL),
 	F_END,
 };
 
@@ -1578,6 +1582,7 @@
 	.md_reg = MI2S_RX_NS_REG - 4,
 	.root_en_mask = BIT(11),
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_mi2s_codec,
 	.current_freq = &rcg_dummy_freq,
@@ -1617,6 +1622,7 @@
 	.md_reg = MI2S_TX_NS_REG - 4,
 	.root_en_mask = BIT(11),
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_mi2s_codec,
 	.current_freq = &rcg_dummy_freq,
@@ -1662,6 +1668,7 @@
 	.md_reg = MI2S_NS_REG - 4,
 	.root_en_mask = BIT(11),
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_mi2s,
 	.current_freq = &rcg_dummy_freq,
@@ -1694,7 +1701,6 @@
 		.freq_hz = f, \
 		.md_val = MD16(m, n), \
 		.ns_val = N16(m, n) | SPDIV(SRC_SEL_SDAC_##s, div), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 		.src_clk = &s##_clk.c, \
 	}
 
@@ -1722,6 +1728,7 @@
 	.ns_reg = SDAC_NS_REG,
 	.md_reg = SDAC_NS_REG - 4,
 	.root_en_mask = BIT(11),
+	.mnd_en_mask = BIT(8),
 	.freq_tbl = clk_tbl_sdac,
 	.ns_mask = F_MASK_MND16,
 	.set_rate = set_rate_mnd,
@@ -1765,6 +1772,7 @@
 	},
 	.md_reg = TV_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(23, 16),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_tv,
 	.current_freq = &rcg_dummy_freq,
@@ -1856,6 +1864,7 @@
 	},
 	.md_reg = USBH_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(23, 16),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -1994,6 +2003,7 @@
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_vfe_jpeg,
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -2018,6 +2028,7 @@
 	.root_en_mask = BIT(13),
 	.freq_tbl = clk_tbl_vfe_jpeg,
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -2102,6 +2113,7 @@
 	.root_en_mask = BIT(9),
 	.freq_tbl = clk_tbl_cam,
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -2134,6 +2146,7 @@
 	.ns_reg = VPE_NS_REG,
 	.md_reg = VPE_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(22, 15),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_vpe,
 	.current_freq = &rcg_dummy_freq,
@@ -2170,6 +2183,7 @@
 	.ns_reg = MFC_NS_REG,
 	.md_reg = MFC_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(24, 17),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_mfc,
 	.current_freq = &rcg_dummy_freq,
@@ -2218,6 +2232,7 @@
 	.ns_reg = SPI_NS_REG,
 	.md_reg = SPI_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(19, 12),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_spi,
 	.current_freq = &rcg_dummy_freq,
@@ -2231,10 +2246,10 @@
 };
 
 static struct clk_freq_tbl clk_tbl_lpa_codec[] = {
-	F_RAW(1, NULL, 0, 0, 0, 0, NULL), /* src MI2S_CODEC_RX */
-	F_RAW(2, NULL, 0, 1, 0, 0, NULL), /* src ECODEC_CIF */
-	F_RAW(3, NULL, 0, 2, 0, 0, NULL), /* src MI2S */
-	F_RAW(4, NULL, 0, 3, 0, 0, NULL), /* src SDAC */
+	F_RAW(1, NULL, 0, 0, 0, NULL), /* src MI2S_CODEC_RX */
+	F_RAW(2, NULL, 0, 1, 0, NULL), /* src ECODEC_CIF */
+	F_RAW(3, NULL, 0, 2, 0, NULL), /* src MI2S */
+	F_RAW(4, NULL, 0, 3, 0, NULL), /* src SDAC */
 	F_END,
 };
 
@@ -2260,7 +2275,7 @@
 };
 
 static struct clk_freq_tbl clk_tbl_mdc[] = {
-	F_RAW(1, NULL, 0, 0, 0, 0, NULL),
+	F_RAW(1, NULL, 0, 0, 0, NULL),
 	F_END
 };
 
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 493a210..7c2788de 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -423,7 +423,7 @@
 					RPM_VREG_VOTER3, 1800000, 1800000, 1);
 		} else {
 			rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
-					RPM_VREG_VOTER3, 2200000, 2200000, 1);
+					RPM_VREG_VOTER3, 2100000, 2100000, 1);
 			if (rc)
 				return rc;
 			rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
@@ -470,14 +470,13 @@
 static struct clk_ops clk_ops_pxo = {
 	.enable = pxo_clk_enable,
 	.disable = pxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = local_clk_is_local,
 };
 
 static struct fixed_clk pxo_clk = {
-	.rate = 27000000,
 	.c = {
 		.dbg_name = "pxo_clk",
+		.rate = 27000000,
 		.ops = &clk_ops_pxo,
 		CLK_INIT(pxo_clk.c),
 	},
@@ -496,36 +495,35 @@
 static struct clk_ops clk_ops_cxo = {
 	.enable = cxo_clk_enable,
 	.disable = cxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = local_clk_is_local,
 };
 
 static struct fixed_clk cxo_clk = {
-	.rate = 19200000,
 	.c = {
 		.dbg_name = "cxo_clk",
+		.rate = 19200000,
 		.ops = &clk_ops_cxo,
 		CLK_INIT(cxo_clk.c),
 	},
 };
 
 static struct pll_clk pll2_clk = {
-	.rate = 800000000,
 	.mode_reg = MM_PLL1_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll2_clk",
+		.rate = 800000000,
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll2_clk.c),
 	},
 };
 
 static struct pll_clk pll3_clk = {
-	.rate = 1200000000,
 	.mode_reg = BB_MMCC_PLL2_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll3_clk",
+		.rate = 1200000000,
 		.ops = &clk_ops_pll,
 		.vdd_class = &vdd_sr2_pll,
 		.fmax[VDD_SR2_PLL_ON] = ULONG_MAX,
@@ -534,50 +532,50 @@
 };
 
 static struct pll_vote_clk pll4_clk = {
-	.rate = 393216000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(4),
 	.status_reg = LCC_PLL0_STATUS_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll4_clk",
+		.rate = 393216000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll8_clk = {
-	.rate = 384000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(8),
 	.status_reg = BB_PLL8_STATUS_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll8_clk",
+		.rate = 384000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll8_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll14_clk = {
-	.rate = 480000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(14),
 	.status_reg = BB_PLL14_STATUS_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll14_clk",
+		.rate = 480000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll14_clk.c),
 	},
 };
 
 static struct pll_clk pll15_clk = {
-	.rate = 975000000,
 	.mode_reg = MM_PLL3_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll15_clk",
+		.rate = 975000000,
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll15_clk.c),
 	},
@@ -1246,6 +1244,7 @@
 		.md_reg = GPn_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gp, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1262,7 +1261,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gp[] = {
 	F_GP(        0, gnd,  1, 0, 0),
@@ -1297,6 +1295,7 @@
 		.md_reg = GSBIn_UART_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(31, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_uart, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1313,7 +1312,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
 	F_GSBI_UART(       0, gnd,  1,  0,   0),
@@ -1361,6 +1359,7 @@
 		.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_qup, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1377,7 +1376,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
 	F_GSBI_QUP(       0, gnd,  1, 0,  0),
@@ -1500,6 +1498,7 @@
 		.md_reg = SDCn_APPS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_sdc, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1516,7 +1515,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_sdc[] = {
 	F_SDC(        0, gnd,   1, 0,   0),
@@ -1545,7 +1543,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_tsif_ref[] = {
 	F_TSIF_REF(     0, gnd,  1, 0,   0),
@@ -1564,6 +1561,7 @@
 	.md_reg = TSIF_REF_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_tsif_ref,
 	.current_freq = &rcg_dummy_freq,
@@ -1621,6 +1619,7 @@
 	.md_reg = USB_HS##n##_XCVR_FS_CLK_MD_REG, \
 	.root_en_mask = BIT(11), \
 	.ns_mask = (BM(23, 16) | BM(6, 0)), \
+	.mnd_en_mask = BIT(8), \
 	.set_rate = set_rate_mnd, \
 	.freq_tbl = clk_tbl_usb, \
 	.current_freq = &rcg_dummy_freq, \
@@ -1638,7 +1637,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_usb[] = {
 	F_USB(       0, gnd,  1, 0,  0),
@@ -1667,6 +1665,7 @@
 	.md_reg = USB_HSIC_XCVR_FS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb_hsic,
 	.current_freq = &rcg_dummy_freq,
@@ -1787,6 +1786,7 @@
 		.md_reg = USB_FSn_XCVR_FS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_usb, \
 		.current_freq = &rcg_dummy_freq, \
@@ -2522,6 +2522,7 @@
 		.md_reg = CAMCLK##n##_MD_REG, \
 		.root_en_mask = BIT(2), \
 		.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0), \
+		.mnd_en_mask = BIT(5), \
 		.ctl_mask = BM(7, 6), \
 		.set_rate = set_rate_mnd_8, \
 		.freq_tbl = clk_tbl_cam, \
@@ -2540,7 +2541,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_cam[] = {
 	F_CAM(        0, gnd,  1, 0,  0),
@@ -2569,7 +2569,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_csi[] = {
 	F_CSI(        0, gnd,  1, 0, 0),
@@ -2588,6 +2587,7 @@
 	.md_reg	= CSI0_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_csi,
@@ -2643,6 +2643,7 @@
 	.md_reg	= CSI1_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_csi,
@@ -2698,6 +2699,7 @@
 	.md_reg = CSI2_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_csi,
@@ -3005,7 +3007,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_csi_phytimer[] = {
 	F_CSI_PHYTIMER(        0, gnd,  1, 0, 0),
@@ -3023,6 +3024,7 @@
 	.md_reg = CSIPHYTIMER_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(31, 24) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd_8,
 	.freq_tbl = clk_tbl_csi_phytimer,
@@ -3194,7 +3196,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(20, 16, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gfx2d[] = {
 	F_GFX2D(        0, gnd,  0,  0),
@@ -3308,7 +3309,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 
 static struct clk_freq_tbl clk_tbl_gfx3d_8960[] = {
@@ -3410,7 +3410,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 
 static struct clk_freq_tbl clk_tbl_vcap[] = {
@@ -3487,7 +3486,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 12, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 
 static struct clk_freq_tbl clk_tbl_ijpeg[] = {
@@ -3527,6 +3525,7 @@
 	.md_reg = IJPEG_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(15, 12) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_ijpeg,
@@ -3590,7 +3589,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MND_BANKED8(22, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_mdp[] = {
 	F_MDP(        0, gnd,  0,  0),
@@ -3822,7 +3820,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 #define F_TV(f, s, p_r, d, m, n) \
 	{ \
@@ -3831,7 +3828,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 		.extra_freq_data = (void *)p_r, \
 	}
 /* Switching TV freqs requires PLL reconfiguration. */
@@ -3873,6 +3869,7 @@
 	.md_reg = TV_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_tv,
 	.freq_tbl = clk_tbl_tv,
@@ -3885,6 +3882,21 @@
 	},
 };
 
+static struct cdiv_clk tv_src_div_clk = {
+	.b = {
+		.ctl_reg = TV_NS_REG,
+		.halt_check = NOCHECK,
+	},
+	.ns_reg = TV_NS_REG,
+	.div_offset = 6,
+	.max_div = 2,
+	.c = {
+		.dbg_name = "tv_src_div_clk",
+		.ops = &clk_ops_cdiv,
+		CLK_INIT(tv_src_div_clk.c),
+	},
+};
+
 static struct branch_clk tv_enc_clk = {
 	.b = {
 		.ctl_reg = TV_CC_REG,
@@ -3953,6 +3965,36 @@
 	},
 };
 
+static struct branch_clk rgb_tv_clk = {
+	.b = {
+		.ctl_reg = TV_CC2_REG,
+		.en_mask = BIT(14),
+		.halt_reg = DBG_BUS_VEC_J_REG,
+		.halt_bit = 27,
+	},
+	.parent = &tv_src_clk.c,
+	.c = {
+		.dbg_name = "rgb_tv_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(rgb_tv_clk.c),
+	},
+};
+
+static struct branch_clk npl_tv_clk = {
+	.b = {
+		.ctl_reg = TV_CC2_REG,
+		.en_mask = BIT(16),
+		.halt_reg = DBG_BUS_VEC_J_REG,
+		.halt_bit = 26,
+	},
+	.parent = &tv_src_clk.c,
+	.c = {
+		.dbg_name = "npl_tv_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(npl_tv_clk.c),
+	},
+};
+
 static struct branch_clk hdmi_app_clk = {
 	.b = {
 		.ctl_reg = MISC_CC2_REG,
@@ -3993,7 +4035,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MND_BANKED8(11, 19, n, m, 0, 27, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(6, 11, n), \
-		.mnd_en_mask = (BIT(10) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_vcodec[] = {
 	F_VCODEC(        0, gnd,  0,  0),
@@ -4087,7 +4128,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 11, 10, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 
 static struct clk_freq_tbl clk_tbl_vfe[] = {
@@ -4133,6 +4173,7 @@
 	.md_reg = VFE_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(11, 10) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_vfe,
@@ -4173,7 +4214,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_aif_osr[] = {
 	F_AIF_OSR(       0, gnd,  1, 0,   0),
@@ -4206,6 +4246,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -4231,6 +4272,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -4310,7 +4352,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
 	F_PCM(       0, gnd,  1, 0,   0),
@@ -4342,6 +4383,7 @@
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
@@ -4367,6 +4409,7 @@
 	.md_reg = LCC_SLIMBUS_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 24) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_aif_osr,
 	.current_freq = &rcg_dummy_freq,
@@ -4632,6 +4675,8 @@
 	{ TEST_MM_HS(0x33), &vcap_clk.c },
 	{ TEST_MM_HS(0x34), &vcap_npl_clk.c },
 	{ TEST_MM_HS(0x35), &vcap_axi_clk.c },
+	{ TEST_MM_HS(0x36), &rgb_tv_clk.c },
+	{ TEST_MM_HS(0x37), &npl_tv_clk.c },
 	{ TEST_MM_HS(0x38), &gfx3d_axi_clk.c },
 
 	{ TEST_LPA(0x0F), &mi2s_bit_clk.c },
@@ -4842,6 +4887,7 @@
 	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.1"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.2"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_gss"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("pll2",		pll2_clk.c,	NULL),
 	CLK_LOOKUP("pll8",		pll8_clk.c,	NULL),
 	CLK_LOOKUP("pll4",		pll4_clk.c,	NULL),
@@ -4877,10 +4923,10 @@
 	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c, "msm_serial_hsl.0"),
-	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	"qup_i2c.0"),
 	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	"qup_i2c.3"),
-	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	"qup_i2c.4"),
 	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	"spi_qsd.0"),
 	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	""),
@@ -4911,9 +4957,10 @@
 	CLK_LOOKUP("ce3_core_src_clk",	ce3_src_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("dma_bam_pclk",	dma_bam_p_clk.c,	NULL),
 	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,	"msm_serial_hsl.1"),
+	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,	"qup_i2c.0"),
 	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c,		"qup_i2c.3"),
-	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		"qup_i2c.4"),
 	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		"spi_qsd.0"),
 	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,	"msm_serial_hsl.0"),
@@ -4934,38 +4981,38 @@
 	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
 	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
 	CLK_LOOKUP("core_clk",		amp_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam1_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
-	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		""),
-	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		""),
-	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		""),
-	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		""),
-	CLK_LOOKUP("csi_clk",		csi0_clk.c,		""),
-	CLK_LOOKUP("csi_clk",		csi1_clk.c,		""),
-	CLK_LOOKUP("csi_clk",		csi1_clk.c,		""),
-	CLK_LOOKUP("csi_clk",		csi2_clk.c,		""),
-	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		""),
-	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		""),
-	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		""),
-	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		""),
-	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		""),
-	CLK_LOOKUP("csi_pix_clk",	csi_pix1_clk.c,		""),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		""),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi1_clk.c,		""),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi2_clk.c,		""),
-	CLK_LOOKUP("csiphy_timer_src_clk", csiphy_timer_src_clk.c, ""),
-	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	""),
-	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	""),
-	CLK_LOOKUP("csiphy_timer_clk",	csi2phy_timer_clk.c,	""),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-001a"),
+	CLK_LOOKUP("cam_clk",		cam1_clk.c,	"4-006c"),
+	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		"msm_csid.2"),
+	CLK_LOOKUP("csi_clk",		csi0_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_clk",		csi1_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_clk",		csi2_clk.c,		"msm_csid.2"),
+	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		"msm_csid.2"),
+	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_pix1_clk",	csi_pix1_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi1_clk",	csi_rdi1_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi2_clk",	csi_rdi2_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.0"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.2"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	"msm_csiphy.0"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	"msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi2phy_timer_clk.c,	"msm_csiphy.2"),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi1_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi2_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_esc_clk",	dsi1_esc_clk.c,		NULL),
 	CLK_LOOKUP("dsi_esc_clk",	dsi2_esc_clk.c,		NULL),
-	CLK_DUMMY("rgb_tv_clk",		RGB_TV_CLK,		"", OFF),
-	CLK_DUMMY("npl_tv_clk",		NPL_TV_CLK,		"", OFF),
+	CLK_LOOKUP("rgb_clk",		rgb_tv_clk.c,		""),
+	CLK_LOOKUP("npl_clk",		npl_tv_clk.c,		""),
+
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("bus_clk",		gfx3d_axi_clk.c, "footswitch-8x60.2"),
@@ -4988,18 +5035,20 @@
 	CLK_LOOKUP("lut_clk",		lut_mdp_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("core_clk",		rot_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("core_clk",		rot_clk.c,	"footswitch-8x60.6"),
-	CLK_DUMMY("tv_src_clk",		TV_SRC_CLK,		NULL, OFF),
+	CLK_LOOKUP("tv_src_clk",	tv_src_clk.c,	"footswitch-8x60.4"),
+	CLK_LOOKUP("tv_src_clk",	tv_src_clk.c,		""),
+	CLK_LOOKUP("tv_src_div_clk",	tv_src_div_clk.c,	""),
 	CLK_LOOKUP("core_clk",		vcodec_clk.c,		"msm_vidc.0"),
 	CLK_LOOKUP("core_clk",		vcodec_clk.c,	"footswitch-8x60.7"),
-	CLK_DUMMY("mdp_tv_clk",		MDP_TV_CLK,		NULL, OFF),
-	CLK_DUMMY("tv_clk",		MDP_TV_CLK, "footswitch-8x60.4", OFF),
-	CLK_DUMMY("hdmi_clk",		HDMI_TV_CLK,		"", OFF),
+	CLK_LOOKUP("mdp_tv_clk",	mdp_tv_clk.c,		""),
+	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("core_clk",		vpe_clk.c,	"footswitch-8x60.9"),
-	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		""),
+	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("core_clk",		vfe_clk.c,	"footswitch-8x60.8"),
-	CLK_LOOKUP("csi_vfe_clk",	csi_vfe_clk.c,		""),
+	CLK_LOOKUP("csi_vfe_clk",	csi_vfe_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("bus_clk",		vfe_axi_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("bus_clk",		mdp_axi_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("bus_clk",		rot_axi_clk.c,	"footswitch-8x60.6"),
@@ -5008,7 +5057,9 @@
 	CLK_LOOKUP("bus_b_clk",        vcodec_axi_b_clk.c, "footswitch-8x60.7"),
 	CLK_LOOKUP("bus_clk",		vpe_axi_clk.c,	"footswitch-8x60.9"),
 	CLK_LOOKUP("amp_pclk",		amp_p_clk.c,		NULL),
-	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		""),
+	CLK_LOOKUP("csi_pclk",          csi_p_clk.c,            "msm_csid.0"),
+	CLK_LOOKUP("csi_pclk",          csi_p_clk.c,            "msm_csid.1"),
+	CLK_LOOKUP("csi_pclk",          csi_p_clk.c,            "msm_csid.2"),
 	CLK_LOOKUP("dsi_m_pclk",	dsi1_m_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_s_pclk",	dsi1_s_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_m_pclk",	dsi2_m_p_clk.c,		NULL),
@@ -5028,24 +5079,32 @@
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"footswitch-8x60.6"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,		"msm_vidc.0"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"footswitch-8x60.7"),
-	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		""),
+	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("iface_pclk",	vpe_p_clk.c,	"footswitch-8x60.9"),
+	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
 
-	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		""),
-	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		""),
-	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c, ""),
-	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c, ""),
-	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c, ""),
-	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c, ""),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c, ""),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c, ""),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c, ""),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c, ""),
-	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		""),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		"msm-dai-q6.2"),
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	""),
-	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
 	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	""),
 	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		""),
 	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		""),
@@ -5104,6 +5163,7 @@
 	CLK_LOOKUP("xo",		pxo_clk.c,	"pil_qdsp6v4.0"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.1"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.2"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("pll2",		pll2_clk.c,	NULL),
 	CLK_LOOKUP("pll8",		pll8_clk.c,	NULL),
 	CLK_LOOKUP("pll4",		pll4_clk.c,	NULL),
@@ -5220,10 +5280,13 @@
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0020"),
 	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		"msm_csid.2"),
 	CLK_LOOKUP("csi_clk",		csi0_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_clk",		csi1_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_clk",		csi2_clk.c,		"msm_csid.2"),
 	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		"msm_csid.2"),
 	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		"msm_ispif.0"),
 	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		"msm_ispif.0"),
 	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		NULL),
@@ -5237,8 +5300,11 @@
 			   csiphy_timer_src_clk.c, "msm_csiphy.0"),
 	CLK_LOOKUP("csiphy_timer_src_clk",
 			   csiphy_timer_src_clk.c, "msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.2"),
 	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	"msm_csiphy.0"),
 	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	"msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi2phy_timer_clk.c,	"msm_csiphy.2"),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi1_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi2_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_esc_clk",	dsi1_esc_clk.c,		NULL),
@@ -5287,6 +5353,7 @@
 	CLK_LOOKUP("amp_pclk",		amp_p_clk.c,		NULL),
 	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		"msm_csid.2"),
 	CLK_LOOKUP("dsi_m_pclk",	dsi1_m_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_s_pclk",	dsi1_s_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_m_pclk",	dsi2_m_p_clk.c,		NULL),
@@ -5315,19 +5382,27 @@
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
-	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		NULL),
-	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
-	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		NULL),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		"msm-dai-q6.2"),
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
-	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
 	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	"msm_iommu.0"),
 	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		"msm_iommu.1"),
 	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.2"),
@@ -5599,10 +5674,6 @@
 /* Local clock driver initialization. */
 static void __init msm8960_clock_init(void)
 {
-	/* Copy gfx2d's frequency table because it's modified by both clocks */
-	gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
-			sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
-			GFP_KERNEL);
 
 	if (cpu_is_msm8960()) {
 		rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
@@ -5672,6 +5743,7 @@
 	clk_set_rate(&usb_hsic_xcvr_fs_clk.c, 60000000);
 	clk_set_rate(&usb_hsic_hsic_src_clk.c, 480000000);
 	clk_set_rate(&usb_hsic_hsio_cal_clk.c, 9000000);
+	clk_set_rate(&usb_hsic_system_clk.c, 60000000);
 	/*
 	 * Set the CSI rates to a safe default to avoid warnings when
 	 * switching csi pix and rdi clocks.
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index e53d441..d3f5396 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -318,14 +318,13 @@
 static struct clk_ops clk_ops_pxo = {
 	.enable = pxo_clk_enable,
 	.disable = pxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = xo_clk_is_local,
 };
 
 static struct fixed_clk pxo_clk = {
-	.rate = 27000000,
 	.c = {
 		.dbg_name = "pxo_clk",
+		.rate = 27000000,
 		.ops = &clk_ops_pxo,
 		CLK_INIT(pxo_clk.c),
 	},
@@ -344,49 +343,48 @@
 static struct clk_ops clk_ops_cxo = {
 	.enable = cxo_clk_enable,
 	.disable = cxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = xo_clk_is_local,
 };
 
 static struct fixed_clk cxo_clk = {
-	.rate = 19200000,
 	.c = {
 		.dbg_name = "cxo_clk",
+		.rate = 19200000,
 		.ops = &clk_ops_cxo,
 		CLK_INIT(cxo_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll8_clk = {
-	.rate = 384000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(8),
 	.status_reg = BB_PLL8_STATUS_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll8_clk",
+		.rate = 384000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll8_clk.c),
 	},
 };
 
 static struct pll_clk pll2_clk = {
-	.rate = 800000000,
 	.mode_reg = MM_PLL1_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll2_clk",
+		.rate = 800000000,
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll2_clk.c),
 	},
 };
 
 static struct pll_clk pll3_clk = {
-	.rate = 0, /* TODO: Detect rate dynamically */
 	.mode_reg = MM_PLL2_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll3_clk",
+		.rate = 0, /* TODO: Detect rate dynamically */
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll3_clk.c),
 	},
@@ -417,15 +415,14 @@
 static struct clk_ops clk_ops_pll4 = {
 	.enable = pll4_clk_enable,
 	.disable = pll4_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.get_parent = pll4_clk_get_parent,
 	.is_local = pll4_clk_is_local,
 };
 
 static struct fixed_clk pll4_clk = {
-	.rate = 540672000,
 	.c = {
 		.dbg_name = "pll4_clk",
+		.rate = 540672000,
 		.ops = &clk_ops_pll4,
 		CLK_INIT(pll4_clk.c),
 	},
@@ -1014,6 +1011,7 @@
 		.md_reg = GPn_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gp, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1030,7 +1028,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gp[] = {
 	F_GP(        0, gnd,  1, 0, 0),
@@ -1059,6 +1056,7 @@
 		.md_reg = GSBIn_UART_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(31, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_uart, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1075,7 +1073,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
 	F_GSBI_UART(       0, gnd,  1,  0,   0),
@@ -1123,6 +1120,7 @@
 		.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_qup, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1139,7 +1137,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
 	F_GSBI_QUP(       0, gnd,  1, 0,  0),
@@ -1260,6 +1257,7 @@
 		.md_reg = SDCn_APPS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_sdc, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1276,7 +1274,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_sdc[] = {
 	F_SDC(       0, gnd,   1, 0,   0),
@@ -1302,7 +1299,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_tsif_ref[] = {
 	F_TSIF_REF(     0, gnd,  1, 0,   0),
@@ -1321,6 +1317,7 @@
 	.md_reg = TSIF_REF_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_tsif_ref,
 	.current_freq = &rcg_dummy_freq,
@@ -1369,7 +1366,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_usb[] = {
 	F_USB(       0, gnd,  1, 0,  0),
@@ -1390,6 +1386,7 @@
 	.md_reg = USB_HS1_XCVR_FS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -1423,6 +1420,7 @@
 		.md_reg = USB_FSn_XCVR_FS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_usb, \
 		.current_freq = &rcg_dummy_freq, \
@@ -2033,7 +2031,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_cam[] = {
 	F_CAM(        0, gnd,  1, 0,  0),
@@ -2061,6 +2058,7 @@
 	.md_reg = CAMCLK_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(31, 24) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd_8,
 	.freq_tbl = clk_tbl_cam,
@@ -2199,7 +2197,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(20, 16, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gfx2d[] = {
 	F_GFX2D(        0, gnd,  0,  0),
@@ -2313,7 +2310,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gfx3d[] = {
 	F_GFX3D(        0, gnd,  0,  0),
@@ -2386,7 +2382,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 12, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!n, \
 	}
 static struct clk_freq_tbl clk_tbl_ijpeg[] = {
 	F_IJPEG(        0, gnd,  1, 0,  0),
@@ -2417,6 +2412,7 @@
 	.md_reg = IJPEG_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(15, 12) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_ijpeg,
@@ -2479,7 +2475,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MND_BANKED8(22, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_mdp[] = {
 	F_MDP(        0, gnd,  0,  0),
@@ -2585,7 +2580,6 @@
 		.md_val = MD16(m, n), \
 		.ns_val = NS_MM(31, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_pixel_mdp[] = {
 	F_PIXEL_MDP(        0, gnd,  1,   0,    0),
@@ -2618,6 +2612,7 @@
 	},
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(31, 16) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pixel_mdp,
@@ -2713,7 +2708,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 		.extra_freq_data = p_r, \
 	}
 /* Switching TV freqs requires PLL reconfiguration. */
@@ -2745,6 +2739,7 @@
 	.md_reg = TV_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_tv,
 	.freq_tbl = clk_tbl_tv,
@@ -2846,7 +2841,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(18, 11, n, m, 0, 0, 1, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_vcodec[] = {
 	F_VCODEC(        0, gnd,  0,  0),
@@ -2876,6 +2870,7 @@
 	.md_reg = VCODEC_MD0_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(18, 11) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_vcodec,
@@ -2944,7 +2939,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 11, 10, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_vfe[] = {
 	F_VFE(        0, gnd,   1, 0,  0),
@@ -2982,6 +2976,7 @@
 	.md_reg = VFE_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(11, 10) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_vfe,
@@ -3039,7 +3034,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_aif_osr[] = {
 	F_AIF_OSR(       0, gnd,  1, 0,   0),
@@ -3071,6 +3065,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -3131,7 +3126,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
 	F_PCM(       0, gnd,  1, 0,   0),
@@ -3163,6 +3157,7 @@
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
@@ -3900,11 +3895,6 @@
 	}
 
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	/* Copy gfx2d's frequency table because it's modified by both clocks */
-	gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
-			sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
-			GFP_KERNEL);
-
 	/* Initialize clock registers. */
 	reg_init();
 
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 0bdacec..9e4268f 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -223,14 +223,13 @@
 static struct clk_ops clk_ops_cxo = {
 	.enable = cxo_clk_enable,
 	.disable = cxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = local_clk_is_local,
 };
 
 static struct fixed_clk cxo_clk = {
-	.rate = 19200000,
 	.c = {
 		.dbg_name = "cxo_clk",
+		.rate = 19200000,
 		.ops = &clk_ops_cxo,
 		CLK_INIT(cxo_clk.c),
 	},
@@ -274,7 +273,6 @@
 	.disable = pll_acpu_vote_clk_disable,
 	.auto_off = pll_acpu_vote_clk_disable,
 	.is_enabled = pll_vote_clk_is_enabled,
-	.get_rate = pll_vote_clk_get_rate,
 	.get_parent = pll_vote_clk_get_parent,
 	.is_local = local_clk_is_local,
 };
@@ -285,7 +283,6 @@
 static unsigned int soft_vote_pll0;
 
 static struct pll_vote_clk pll0_clk = {
-	.rate = 276000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(0),
 	.status_reg = BB_PLL0_STATUS_REG,
@@ -294,13 +291,13 @@
 	.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
 	.c = {
 		.dbg_name = "pll0_clk",
+		.rate = 276000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll0_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll0_acpu_clk = {
-	.rate = 276000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(0),
 	.status_reg = BB_PLL0_STATUS_REG,
@@ -308,19 +305,20 @@
 	.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
 	.c = {
 		.dbg_name = "pll0_acpu_clk",
+		.rate = 276000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll0_acpu_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll4_clk = {
-	.rate = 393216000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(4),
 	.status_reg = LCC_PLL0_STATUS_REG,
 	.parent = &cxo_clk.c,
 	.c = {
 		.dbg_name = "pll4_clk",
+		.rate = 393216000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
 	},
@@ -329,7 +327,6 @@
 static unsigned int soft_vote_pll8;
 
 static struct pll_vote_clk pll8_clk = {
-	.rate = 384000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(8),
 	.status_reg = BB_PLL8_STATUS_REG,
@@ -338,13 +335,13 @@
 	.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
 	.c = {
 		.dbg_name = "pll8_clk",
+		.rate = 384000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll8_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll8_acpu_clk = {
-	.rate = 384000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(8),
 	.status_reg = BB_PLL8_STATUS_REG,
@@ -352,29 +349,30 @@
 	.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
 	.c = {
 		.dbg_name = "pll8_acpu_clk",
+		.rate = 384000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll8_acpu_clk.c),
 	},
 };
 
 static struct pll_clk pll9_acpu_clk = {
-	.rate = 440000000,
 	.mode_reg = SC_PLL0_MODE_REG,
 	.c = {
 		.dbg_name = "pll9_acpu_clk",
+		.rate = 440000000,
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll9_acpu_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll14_clk = {
-	.rate = 480000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(11),
 	.status_reg = BB_PLL14_STATUS_REG,
 	.parent = &cxo_clk.c,
 	.c = {
 		.dbg_name = "pll14_clk",
+		.rate = 480000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll14_clk.c),
 	},
@@ -428,6 +426,7 @@
 		.md_reg = GPn_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gp, \
 		.current_freq = &rcg_dummy_freq, \
@@ -444,7 +443,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gp[] = {
 	F_GP(        0, gnd,  1, 0, 0),
@@ -471,6 +469,7 @@
 		.md_reg = GSBIn_UART_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(31, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_uart, \
 		.current_freq = &rcg_dummy_freq, \
@@ -487,7 +486,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
 	F_GSBI_UART(       0, gnd,  1,  0,   0),
@@ -527,6 +525,7 @@
 		.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_qup, \
 		.current_freq = &rcg_dummy_freq, \
@@ -543,7 +542,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
 	F_GSBI_QUP(       0, gnd,  1, 0,  0),
@@ -658,13 +656,14 @@
 		.md_reg = SDCn_APPS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = f_table, \
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #name, \
 			.ops = &clk_ops_rcg_9615, \
-			VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000), \
+			VDD_DIG_FMAX_MAP2(LOW, 26000000, NOMINAL, 52000000), \
 			CLK_INIT(name.c), \
 		}, \
 	}
@@ -674,7 +673,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_sdc1_2[] = {
 	F_SDC(        0, gnd,   1, 0,   0),
@@ -684,7 +682,10 @@
 	F_SDC( 17070000, pll8,  1, 2,  45),
 	F_SDC( 20210000, pll8,  1, 1,  19),
 	F_SDC( 24000000, pll8,  4, 1,   4),
+	F_SDC( 38400000, pll8,  2, 1,   5),
 	F_SDC( 48000000, pll8,  4, 1,   2),
+	F_SDC( 64000000, pll8,  3, 1,   2),
+	F_SDC( 76800000, pll8,  1, 1,   5),
 	F_END
 };
 
@@ -697,7 +698,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_usb[] = {
 	F_USB(       0, gnd,  1, 0,  0),
@@ -724,6 +724,7 @@
 	.md_reg = USB_HS1_XCVR_FS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -748,6 +749,7 @@
 	.md_reg = USB_HS1_SYS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -772,6 +774,7 @@
 	.md_reg = USB_HSIC_XCVR_FS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -796,6 +799,7 @@
 	.md_reg = USB_HSIC_SYSTEM_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb_hsic_sys,
 	.current_freq = &rcg_dummy_freq,
@@ -1129,7 +1133,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_aif_osr[] = {
 	F_AIF_OSR(       0, gnd,  1, 0,   0),
@@ -1162,6 +1165,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1186,6 +1190,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1264,7 +1269,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
 	F_PCM(       0, gnd,  1, 0,   0),
@@ -1296,6 +1300,7 @@
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
@@ -1321,6 +1326,7 @@
 	.md_reg = LCC_SLIMBUS_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 24) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_aif_osr,
 	.current_freq = &rcg_dummy_freq,
@@ -1619,6 +1625,7 @@
 
 static struct clk_lookup msm_clocks_9615[] = {
 	CLK_LOOKUP("xo",	cxo_clk.c,	"msm_otg"),
+	CLK_LOOKUP("xo",	cxo_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("pll0",	pll0_clk.c,	NULL),
 	CLK_LOOKUP("pll8",	pll8_clk.c,	NULL),
 	CLK_LOOKUP("pll14",	pll14_clk.c,	NULL),
@@ -1689,21 +1696,29 @@
 	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	""),
 	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
 	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
-	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		NULL),
-	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
 
-	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("pcm_clk",		pcm_clk.c,			NULL),
+	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("pcm_clk",		pcm_clk.c,	"msm-dai-q6.2"),
 
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
-	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
 	CLK_LOOKUP("core_clk",		dfab_usb_hs_clk.c,	"msm_otg"),
 	CLK_LOOKUP("bus_clk",		dfab_sdc1_clk.c,	"msm_sdcc.1"),
 	CLK_LOOKUP("bus_clk",		dfab_sdc2_clk.c,	"msm_sdcc.2"),
@@ -1821,7 +1836,7 @@
 	pll9_lval = readl_relaxed(SC_PLL0_L_VAL_REG);
 
 	if (pll9_lval == 0x1C)
-		pll9_acpu_clk.rate = 550000000;
+		pll9_acpu_clk.c.rate = 550000000;
 
 	/* Enable PLL4 source on the LPASS Primary PLL Mux */
 	regval = readl_relaxed(LCC_PRI_PLL_CLK_CTL_REG);
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index c02c6f3..4f68fb4 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -192,13 +192,8 @@
 		writel_relaxed(ns_reg_val, clk->ns_reg);
 	}
 
-	/*
-	 * If this freq requires the MN counter to be enabled,
-	 * update the enable mask to match the current bank.
-	 */
-	if (nf->mnd_en_mask)
-		nf->mnd_en_mask = new_bank_masks->mnd_en_mask;
-	/* Update the NS mask to match the current bank. */
+	/* Update the MND_EN and NS masks to match the current bank. */
+	clk->mnd_en_mask = new_bank_masks->mnd_en_mask;
 	clk->ns_mask = new_bank_masks->ns_mask;
 }
 
@@ -343,8 +338,8 @@
 
 	/* Enable MN counter, if applicable. */
 	reg_val = readl_relaxed(reg);
-	if (clk->current_freq->mnd_en_mask) {
-		reg_val |= clk->current_freq->mnd_en_mask;
+	if (clk->current_freq->md_val) {
+		reg_val |= clk->mnd_en_mask;
 		writel_relaxed(reg_val, reg);
 	}
 	/* Enable root. */
@@ -408,8 +403,8 @@
 		writel_relaxed(reg_val, reg);
 	}
 	/* Disable MN counter, if applicable. */
-	if (clk->current_freq->mnd_en_mask) {
-		reg_val &= ~(clk->current_freq->mnd_en_mask);
+	if (clk->current_freq->md_val) {
+		reg_val &= ~(clk->mnd_en_mask);
 		writel_relaxed(reg_val, reg);
 	}
 	/*
@@ -641,7 +636,7 @@
 	ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
 	for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
 		if ((freq->ns_val & ns_mask) == ns_val &&
-		    (!freq->mnd_en_mask || freq->md_val == md_val)) {
+		    (!freq->md_val || freq->md_val == md_val)) {
 			pr_info("%s rate=%d\n", clk->c.dbg_name, freq->freq_hz);
 			break;
 		}
@@ -686,12 +681,6 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-unsigned long pll_vote_clk_get_rate(struct clk *clk)
-{
-	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
-	return pll->rate;
-}
-
 struct clk *pll_vote_clk_get_parent(struct clk *clk)
 {
 	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
@@ -709,7 +698,6 @@
 	.disable = pll_vote_clk_disable,
 	.auto_off = pll_vote_clk_disable,
 	.is_enabled = pll_vote_clk_is_enabled,
-	.get_rate = pll_vote_clk_get_rate,
 	.get_parent = pll_vote_clk_get_parent,
 	.is_local = local_clk_is_local,
 };
@@ -766,12 +754,6 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-static unsigned long pll_clk_get_rate(struct clk *clk)
-{
-	struct pll_clk *pll = to_pll_clk(clk);
-	return pll->rate;
-}
-
 static struct clk *pll_clk_get_parent(struct clk *clk)
 {
 	struct pll_clk *pll = to_pll_clk(clk);
@@ -817,13 +799,11 @@
 	.enable = pll_clk_enable,
 	.disable = pll_clk_disable,
 	.auto_off = pll_clk_disable,
-	.get_rate = pll_clk_get_rate,
 	.get_parent = pll_clk_get_parent,
 	.is_local = local_clk_is_local,
 };
 
 struct clk_ops clk_ops_gnd = {
-	.get_rate = fixed_clk_get_rate,
 	.is_local = local_clk_is_local,
 };
 
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index d312f24..c587b43 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -27,10 +27,12 @@
 
 /* MD Registers */
 #define MD4(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
+		((BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n))) \
+		* !!(n))
 #define MD8(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
-#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
+		((BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n))) \
+		* !!(n))
+#define MD16(m, n) ((BVAL(31, 16, m) | BVAL(15, 0, ~(n))) * !!(n))
 
 /* NS Registers */
 #define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
@@ -101,11 +103,10 @@
  */
 struct clk_freq_tbl {
 	const uint32_t	freq_hz;
-	struct clk	*src_clk;
+	struct clk	*const src_clk;
 	const uint32_t	md_val;
 	const uint32_t	ns_val;
 	const uint32_t	ctl_val;
-	uint32_t	mnd_en_mask;
 	void		*const extra_freq_data;
 };
 
@@ -126,13 +127,12 @@
 	const struct bank_mask_info	bank1_mask;
 };
 
-#define F_RAW(f, sc, m_v, n_v, c_v, m_m, e) { \
+#define F_RAW(f, sc, m_v, n_v, c_v, e) { \
 	.freq_hz = f, \
 	.src_clk = sc, \
 	.md_val = m_v, \
 	.ns_val = n_v, \
 	.ctl_val = c_v, \
-	.mnd_en_mask = m_m, \
 	.extra_freq_data = e, \
 	}
 #define FREQ_END	(UINT_MAX-1)
@@ -185,6 +185,7 @@
 	const uint32_t	root_en_mask;
 	uint32_t	ns_mask;
 	const uint32_t	ctl_mask;
+	uint32_t	mnd_en_mask;
 
 	void		*bank_info;
 	void   (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
@@ -249,29 +250,14 @@
 
 /**
  * struct fixed_clk - fixed rate clock (used for crystal oscillators)
- * @rate: output rate
  * @c: clk
  */
 struct fixed_clk {
-	unsigned long rate;
 	struct clk c;
 };
 
-static inline struct fixed_clk *to_fixed_clk(struct clk *clk)
-{
-	return container_of(clk, struct fixed_clk, c);
-}
-
-static inline unsigned long fixed_clk_get_rate(struct clk *clk)
-{
-	struct fixed_clk *f = to_fixed_clk(clk);
-	return f->rate;
-}
-
-
 /**
  * struct pll_vote_clk - phase locked loop (HW voteable)
- * @rate: output rate
  * @soft_vote: soft voting variable for multiple PLL software instances
  * @soft_vote_mask: soft voting mask for multiple PLL software instances
  * @en_reg: enable register
@@ -281,8 +267,6 @@
  * @c: clk
  */
 struct pll_vote_clk {
-	unsigned long rate;
-
 	u32 *soft_vote;
 	const u32 soft_vote_mask;
 	void __iomem *const en_reg;
@@ -303,14 +287,11 @@
 
 /**
  * struct pll_clk - phase locked loop
- * @rate: output rate
  * @mode_reg: enable register
  * @parent: clock source
  * @c: clk
  */
 struct pll_clk {
-	unsigned long rate;
-
 	void __iomem *const mode_reg;
 
 	struct clk *parent;
@@ -394,7 +375,6 @@
  */
 int pll_vote_clk_enable(struct clk *clk);
 void pll_vote_clk_disable(struct clk *clk);
-unsigned long pll_vote_clk_get_rate(struct clk *clk);
 struct clk *pll_vote_clk_get_parent(struct clk *clk);
 int pll_vote_clk_is_enabled(struct clk *clk);
 
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 4757f7d..ae87bb7 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -23,9 +23,9 @@
 static int rpm_clk_enable(struct clk *clk)
 {
 	unsigned long flags;
-	struct msm_rpm_iv_pair iv;
-	int rc = 0;
 	struct rpm_clk *r = to_rpm_clk(clk);
+	struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
+	int rc = 0;
 	unsigned long this_khz, this_sleep_khz;
 	unsigned long peer_khz = 0, peer_sleep_khz = 0;
 	struct rpm_clk *peer = r->peer;
@@ -39,8 +39,6 @@
 
 	this_sleep_khz = r->last_set_sleep_khz;
 
-	iv.id = r->rpm_clk_id;
-
 	/* Take peer clock's rate into account only if it's enabled. */
 	if (peer->enabled) {
 		peer_khz = peer->last_set_khz;
@@ -48,11 +46,16 @@
 	}
 
 	iv.value = max(this_khz, peer_khz);
+	if (r->branch)
+		iv.value = !!iv.value;
+
 	rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
 	if (rc)
 		goto out;
 
 	iv.value = max(this_sleep_khz, peer_sleep_khz);
+	if (r->branch)
+		iv.value = !!iv.value;
 	rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
 	if (rc) {
 		iv.value = peer_khz;
@@ -76,25 +79,23 @@
 	spin_lock_irqsave(&rpm_clock_lock, flags);
 
 	if (r->last_set_khz) {
-		struct msm_rpm_iv_pair iv;
+		struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
 		struct rpm_clk *peer = r->peer;
 		unsigned long peer_khz = 0, peer_sleep_khz = 0;
 		int rc;
 
-		iv.id = r->rpm_clk_id;
-
 		/* Take peer clock's rate into account only if it's enabled. */
 		if (peer->enabled) {
 			peer_khz = peer->last_set_khz;
 			peer_sleep_khz = peer->last_set_sleep_khz;
 		}
 
-		iv.value = peer_khz;
+		iv.value = r->branch ? !!peer_khz : peer_khz;
 		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
 		if (rc)
 			goto out;
 
-		iv.value = peer_sleep_khz;
+		iv.value = r->branch ? !!peer_sleep_khz : peer_sleep_khz;
 		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
 	}
 	r->enabled = false;
@@ -195,3 +196,9 @@
 	.round_rate = rpm_clk_round_rate,
 	.is_local = rpm_clk_is_local,
 };
+
+struct clk_ops clk_ops_rpm_branch = {
+	.enable = rpm_clk_enable,
+	.disable = rpm_clk_disable,
+	.is_local = rpm_clk_is_local,
+};
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index 24df9b6..2f4a17c 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
 
 struct clk_ops;
 extern struct clk_ops clk_ops_rpm;
+extern struct clk_ops clk_ops_rpm_branch;
 
 struct rpm_clk {
 	const int rpm_clk_id;
@@ -27,6 +28,7 @@
 	/* 0 if active_only. Otherwise, same as last_set_khz. */
 	unsigned last_set_sleep_khz;
 	bool enabled;
+	bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
 
 	struct rpm_clk *peer;
 	struct clk c;
@@ -65,4 +67,37 @@
 		}, \
 	};
 
+#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, rate) \
+	static struct rpm_clk active; \
+	static struct rpm_clk name = { \
+		.rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
+		.rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+		.peer = &active, \
+		.last_set_khz = ((rate) / 1000), \
+		.last_set_sleep_khz = ((rate) / 1000), \
+		.branch = true, \
+		.c = { \
+			.ops = &clk_ops_rpm_branch, \
+			.flags = CLKFLAG_SKIP_AUTO_OFF, \
+			.dbg_name = #name, \
+			.rate = (rate), \
+			CLK_INIT(name.c), \
+		}, \
+	}; \
+	static struct rpm_clk active = { \
+		.rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
+		.rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+		.peer = &name, \
+		.last_set_khz = ((rate) / 1000), \
+		.active_only = true, \
+		.branch = true, \
+		.c = { \
+			.ops = &clk_ops_rpm_branch, \
+			.flags = CLKFLAG_SKIP_AUTO_OFF, \
+			.dbg_name = #active, \
+			.rate = (rate), \
+			CLK_INIT(active.c), \
+		}, \
+	};
+
 #endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 57fd749..5b89fa9 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/clock.c
  *
  * 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
@@ -222,7 +222,7 @@
 unsigned long clk_get_rate(struct clk *clk)
 {
 	if (!clk->ops->get_rate)
-		return 0;
+		return clk->rate;
 
 	return clk->ops->get_rate(clk);
 }
diff --git a/arch/arm/mach-msm/cp14.h b/arch/arm/mach-msm/cp14.h
index 9f7241e..d640412 100644
--- a/arch/arm/mach-msm/cp14.h
+++ b/arch/arm/mach-msm/cp14.h
@@ -325,21 +325,21 @@
 #define RCP14_ETMACTR14()		MRC14(1, c0, c14, 2)
 #define RCP14_ETMACTR15()		MRC14(1, c0, c15, 2)
 #define RCP14_ETMDCVR0()		MRC14(1, c0, c0, 3)
-#define RCP14_ETMDCVR1()		MRC14(1, c0, c1, 3)
 #define RCP14_ETMDCVR2()		MRC14(1, c0, c2, 3)
-#define RCP14_ETMDCVR3()		MRC14(1, c0, c3, 3)
 #define RCP14_ETMDCVR4()		MRC14(1, c0, c4, 3)
-#define RCP14_ETMDCVR5()		MRC14(1, c0, c5, 3)
 #define RCP14_ETMDCVR6()		MRC14(1, c0, c6, 3)
-#define RCP14_ETMDCVR7()		MRC14(1, c0, c7, 3)
+#define RCP14_ETMDCVR8()		MRC14(1, c0, c8, 3)
+#define RCP14_ETMDCVR10()		MRC14(1, c0, c10, 3)
+#define RCP14_ETMDCVR12()		MRC14(1, c0, c12, 3)
+#define RCP14_ETMDCVR14()		MRC14(1, c0, c14, 3)
 #define RCP14_ETMDCMR0()		MRC14(1, c0, c0, 4)
-#define RCP14_ETMDCMR1()		MRC14(1, c0, c1, 4)
 #define RCP14_ETMDCMR2()		MRC14(1, c0, c2, 4)
-#define RCP14_ETMDCMR3()		MRC14(1, c0, c3, 4)
 #define RCP14_ETMDCMR4()		MRC14(1, c0, c4, 4)
-#define RCP14_ETMDCMR5()		MRC14(1, c0, c5, 4)
 #define RCP14_ETMDCMR6()		MRC14(1, c0, c6, 4)
-#define RCP14_ETMDCMR7()		MRC14(1, c0, c7, 4)
+#define RCP14_ETMDCMR8()		MRC14(1, c0, c8, 4)
+#define RCP14_ETMDCMR10()		MRC14(1, c0, c10, 4)
+#define RCP14_ETMDCMR12()		MRC14(1, c0, c12, 4)
+#define RCP14_ETMDCMR14()		MRC14(1, c0, c14, 4)
 #define RCP14_ETMCNTRLDVR0()		MRC14(1, c0, c0, 5)
 #define RCP14_ETMCNTRLDVR1()		MRC14(1, c0, c1, 5)
 #define RCP14_ETMCNTRLDVR2()		MRC14(1, c0, c2, 5)
@@ -389,7 +389,7 @@
 #define RCP14_ETMAUXCR()		MRC14(1, c0, c15, 7)
 #define RCP14_ETMTRACEIDR()		MRC14(1, c1, c0, 0)
 #define RCP14_ETMIDR2()			MRC14(1, c1, c2, 0)
-#define RCP14_ETMVMIDCVR()		MRC14(1, c1, c1, 0)
+#define RCP14_ETMVMIDCVR()		MRC14(1, c1, c0, 1)
 #define RCP14_ETMOSLSR()		MRC14(1, c1, c1, 4)
 /* not available in PFTv1.1 */
 #define RCP14_ETMOSSRR()		MRC14(1, c1, c2, 4)
@@ -462,21 +462,21 @@
 #define WCP14_ETMACTR14(val)		MCR14(val, 1, c0, c14, 2)
 #define WCP14_ETMACTR15(val)		MCR14(val, 1, c0, c15, 2)
 #define WCP14_ETMDCVR0(val)		MCR14(val, 1, c0, c0, 3)
-#define WCP14_ETMDCVR1(val)		MCR14(val, 1, c0, c1, 3)
 #define WCP14_ETMDCVR2(val)		MCR14(val, 1, c0, c2, 3)
-#define WCP14_ETMDCVR3(val)		MCR14(val, 1, c0, c3, 3)
 #define WCP14_ETMDCVR4(val)		MCR14(val, 1, c0, c4, 3)
-#define WCP14_ETMDCVR5(val)		MCR14(val, 1, c0, c5, 3)
 #define WCP14_ETMDCVR6(val)		MCR14(val, 1, c0, c6, 3)
-#define WCP14_ETMDCVR7(val)		MCR14(val, 1, c0, c7, 3)
+#define WCP14_ETMDCVR8(val)		MCR14(val, 1, c0, c8, 3)
+#define WCP14_ETMDCVR10(val)		MCR14(val, 1, c0, c10, 3)
+#define WCP14_ETMDCVR12(val)		MCR14(val, 1, c0, c12, 3)
+#define WCP14_ETMDCVR14(val)		MCR14(val, 1, c0, c14, 3)
 #define WCP14_ETMDCMR0(val)		MCR14(val, 1, c0, c0, 4)
-#define WCP14_ETMDCMR1(val)		MCR14(val, 1, c0, c1, 4)
 #define WCP14_ETMDCMR2(val)		MCR14(val, 1, c0, c2, 4)
-#define WCP14_ETMDCMR3(val)		MCR14(val, 1, c0, c3, 4)
 #define WCP14_ETMDCMR4(val)		MCR14(val, 1, c0, c4, 4)
-#define WCP14_ETMDCMR5(val)		MCR14(val, 1, c0, c5, 4)
 #define WCP14_ETMDCMR6(val)		MCR14(val, 1, c0, c6, 4)
-#define WCP14_ETMDCMR7(val)		MCR14(val, 1, c0, c7, 4)
+#define WCP14_ETMDCMR8(val)		MCR14(val, 1, c0, c8, 4)
+#define WCP14_ETMDCMR10(val)		MCR14(val, 1, c0, c10, 4)
+#define WCP14_ETMDCMR12(val)		MCR14(val, 1, c0, c12, 4)
+#define WCP14_ETMDCMR14(val)		MCR14(val, 1, c0, c14, 4)
 #define WCP14_ETMCNTRLDVR0(val)		MCR14(val, 1, c0, c0, 5)
 #define WCP14_ETMCNTRLDVR1(val)		MCR14(val, 1, c0, c1, 5)
 #define WCP14_ETMCNTRLDVR2(val)		MCR14(val, 1, c0, c2, 5)
@@ -525,7 +525,7 @@
 #define WCP14_ETMAUXCR(val)		MCR14(val, 1, c0, c15, 7)
 #define WCP14_ETMTRACEIDR(val)		MCR14(val, 1, c1, c0, 0)
 #define WCP14_ETMIDR2(val)		MCR14(val, 1, c1, c2, 0)
-#define WCP14_ETMVMIDCVR(val)		MCR14(val, 1, c1, c1, 0)
+#define WCP14_ETMVMIDCVR(val)		MCR14(val, 1, c1, c0, 1)
 #define WCP14_ETMOSLAR(val)		MCR14(val, 1, c1, c0, 4)
 /* not available in PFTv1.1 */
 #define WCP14_ETMOSSRR(val)		MCR14(val, 1, c1, c2, 4)
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 56778e2..107598a 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -50,21 +50,13 @@
 
 static DEFINE_PER_CPU(struct cpufreq_suspend_t, cpufreq_suspend);
 
-static int override_cpu;
-
 static int set_cpu_freq(struct cpufreq_policy *policy, unsigned int new_freq)
 {
 	int ret = 0;
 	struct cpufreq_freqs freqs;
 
 	freqs.old = policy->cur;
-	if (override_cpu) {
-		if (policy->cur == policy->max)
-			return 0;
-		else
-			freqs.new = policy->max;
-	} else
-		freqs.new = new_freq;
+	freqs.new = new_freq;
 	freqs.cpu = policy->cpu;
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	ret = acpuclk_set_rate(policy->cpu, new_freq, SETRATE_CPUFREQ);
@@ -268,25 +260,6 @@
 	}
 }
 
-static ssize_t store_mfreq(struct sysdev_class *class,
-			struct sysdev_class_attribute *attr,
-			const char *buf, size_t count)
-{
-	u64 val;
-
-	if (strict_strtoull(buf, 0, &val) < 0) {
-		pr_err("Invalid parameter to mfreq\n");
-		return 0;
-	}
-	if (val)
-		override_cpu = 1;
-	else
-		override_cpu = 0;
-	return count;
-}
-
-static SYSDEV_CLASS_ATTR(mfreq, 0200, NULL, store_mfreq);
-
 static struct freq_attr *msm_freq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
@@ -310,11 +283,6 @@
 {
 	int cpu;
 
-	int err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
-			&attr_mfreq.attr);
-	if (err)
-		pr_err("Failed to create sysfs mfreq\n");
-
 	for_each_possible_cpu(cpu) {
 		mutex_init(&(per_cpu(cpufreq_suspend, cpu).suspend_mutex));
 		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 9328143..ca85a0a 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -31,6 +31,7 @@
 #include <linux/ion.h>
 #include "clock.h"
 #include "devices.h"
+#include "footswitch.h"
 #include "msm_watchdog.h"
 #include "rpm_stats.h"
 #include "rpm_log.h"
@@ -50,6 +51,7 @@
 #define MSM_UART7DM_PHYS	(MSM_GSBI7_PHYS + 0x40000)
 
 /* GSBI QUP devices */
+#define MSM_GSBI1_QUP_PHYS	(MSM_GSBI1_PHYS + 0x20000)
 #define MSM_GSBI3_QUP_PHYS	(MSM_GSBI3_PHYS + 0x80000)
 #define MSM_GSBI4_QUP_PHYS	(MSM_GSBI4_PHYS + 0x80000)
 #define MSM_GSBI5_QUP_PHYS	(MSM_GSBI5_PHYS + 0x80000)
@@ -66,6 +68,10 @@
 #define MSM_HSUSB1_PHYS		0x12500000
 #define MSM_HSUSB1_SIZE		SZ_4K
 
+/* Address of HS USB3 */
+#define MSM_HSUSB3_PHYS		0x12520000
+#define MSM_HSUSB3_SIZE		SZ_4K
+
 static struct msm_watchdog_pdata msm_watchdog_pdata = {
 	.pet_time = 10000,
 	.bark_time = 11000,
@@ -195,6 +201,46 @@
 	},
 };
 
+static struct resource resources_qup_i2c_gsbi1[] = {
+	{
+		.name	= "gsbi_qup_i2c_addr",
+		.start	= MSM_GSBI1_PHYS,
+		.end	= MSM_GSBI1_PHYS + 4 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_phys_addr",
+		.start	= MSM_GSBI1_QUP_PHYS,
+		.end	= MSM_GSBI1_QUP_PHYS + MSM_QUP_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_err_intr",
+		.start	= APQ8064_GSBI1_QUP_IRQ,
+		.end	= APQ8064_GSBI1_QUP_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "i2c_clk",
+		.start	= 21,
+		.end	= 21,
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.name	= "i2c_sda",
+		.start	= 20,
+		.end	= 20,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+struct platform_device apq8064_device_qup_i2c_gsbi1 = {
+	.name		= "qup_i2c",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(resources_qup_i2c_gsbi1),
+	.resource	= resources_qup_i2c_gsbi1,
+};
+
 struct platform_device apq8064_device_qup_i2c_gsbi3 = {
 	.name		= "qup_i2c",
 	.id		= 3,
@@ -221,6 +267,18 @@
 		.end	= GSBI4_QUP_IRQ,
 		.flags	= IORESOURCE_IRQ,
 	},
+	{
+		.name	= "i2c_clk",
+		.start	= 11,
+		.end	= 11,
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.name	= "i2c_sda",
+		.start	= 10,
+		.end	= 10,
+		.flags	= IORESOURCE_IO,
+	},
 };
 
 struct platform_device apq8064_device_qup_i2c_gsbi4 = {
@@ -306,7 +364,7 @@
 };
 
 struct platform_device apq_cpudai_hdmi_rx = {
-	.name	= "msm-dai-q6",
+	.name	= "msm-dai-q6-hdmi",
 	.id	= 8,
 };
 
@@ -413,6 +471,11 @@
 	.id	= -1,
 };
 
+struct platform_device apq_cpudai_stub = {
+	.name = "msm-dai-stub",
+	.id = -1,
+};
+
 static struct resource resources_ssbi_pmic1[] = {
 	{
 		.start  = MSM_PMIC1_SSBI_CMD_PHYS,
@@ -591,6 +654,30 @@
 	},
 };
 
+static struct resource resources_ehci_host3[] = {
+{
+		.start  = MSM_HSUSB3_PHYS,
+		.end    = MSM_HSUSB3_PHYS + MSM_HSUSB3_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = USB3_HS_IRQ,
+		.end    = USB3_HS_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device apq8064_device_ehci_host3 = {
+	.name           = "msm_ehci_host",
+	.id             = 0,
+	.num_resources  = ARRAY_SIZE(resources_ehci_host3),
+	.resource       = resources_ehci_host3,
+	.dev            = {
+		.dma_mask               = &dma_mask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+};
+
 /* MSM Video core device */
 #ifdef CONFIG_MSM_BUS_SCALING
 static struct msm_bus_vectors vidc_init_vectors[] = {
@@ -1172,6 +1259,17 @@
 	.resource       = msm_gss_resources,
 };
 
+struct platform_device *apq8064_fs_devices[] = {
+	FS_8X60(FS_ROT,    "fs_rot"),
+	FS_8X60(FS_IJPEG,  "fs_ijpeg"),
+	FS_8X60(FS_VFE,    "fs_vfe"),
+	FS_8X60(FS_VPE,    "fs_vpe"),
+	FS_8X60(FS_GFX3D,  "fs_gfx3d"),
+	FS_8X60(FS_VED,    "fs_ved"),
+	FS_8X60(FS_VCAP,   "fs_vcap"),
+};
+unsigned apq8064_num_fs_devices = ARRAY_SIZE(apq8064_fs_devices);
+
 static struct clk_lookup msm_clocks_8064_dummy[] = {
 	CLK_DUMMY("pll2",		PLL2,		NULL, 0),
 	CLK_DUMMY("pll8",		PLL8,		NULL, 0),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 4525bab..19a8db7 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1134,27 +1134,27 @@
 };
 
 #ifdef CONFIG_MSM_CAMERA
-struct resource msm_camera_resources[] = {
+static struct resource msm_cam_gsbi4_i2c_mux_resources[] = {
 	{
-		.name   = "s3d_rw",
+		.name   = "i2c_mux_rw",
 		.start  = 0x008003E0,
-		.end    = 0x008003E0 + SZ_16 - 1,
+		.end    = 0x008003E0 + SZ_8 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 	{
-		.name   = "s3d_ctl",
+		.name   = "i2c_mux_ctl",
 		.start  = 0x008020B8,
-		.end    = 0x008020B8 + SZ_16 - 1,
+		.end    = 0x008020B8 + SZ_4 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 };
 
-int __init msm_get_cam_resources(struct msm_camera_sensor_info *s_info)
-{
-	s_info->resource = msm_camera_resources;
-	s_info->num_resources = ARRAY_SIZE(msm_camera_resources);
-	return 0;
-}
+struct platform_device msm8960_device_i2c_mux_gsbi4 = {
+	.name           = "msm_cam_i2c_mux",
+	.id             = 0,
+	.resource       = msm_cam_gsbi4_i2c_mux_resources,
+	.num_resources  = ARRAY_SIZE(msm_cam_gsbi4_i2c_mux_resources),
+};
 
 static struct resource msm_csiphy0_resources[] = {
 	{
@@ -1186,6 +1186,21 @@
 	},
 };
 
+static struct resource msm_csiphy2_resources[] = {
+	{
+		.name	= "csiphy",
+		.start	= 0x04801400,
+		.end	= 0x04801400 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "csiphy",
+		.start	= MSM8960_CSIPHY_2_2LN_IRQ,
+		.end	= MSM8960_CSIPHY_2_2LN_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 struct platform_device msm8960_device_csiphy0 = {
 	.name           = "msm_csiphy",
 	.id             = 0,
@@ -1200,6 +1215,13 @@
 	.num_resources  = ARRAY_SIZE(msm_csiphy1_resources),
 };
 
+struct platform_device msm8960_device_csiphy2 = {
+	.name           = "msm_csiphy",
+	.id             = 2,
+	.resource       = msm_csiphy2_resources,
+	.num_resources  = ARRAY_SIZE(msm_csiphy2_resources),
+};
+
 static struct resource msm_csid0_resources[] = {
 	{
 		.name	= "csid",
@@ -1230,6 +1252,21 @@
 	},
 };
 
+static struct resource msm_csid2_resources[] = {
+	{
+		.name	= "csid",
+		.start	= 0x04801800,
+		.end	= 0x04801800 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "csid",
+		.start	= CSI_2_IRQ,
+		.end	= CSI_2_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 struct platform_device msm8960_device_csid0 = {
 	.name           = "msm_csid",
 	.id             = 0,
@@ -1244,6 +1281,13 @@
 	.num_resources  = ARRAY_SIZE(msm_csid1_resources),
 };
 
+struct platform_device msm8960_device_csid2 = {
+	.name           = "msm_csid",
+	.id             = 2,
+	.resource       = msm_csid2_resources,
+	.num_resources  = ARRAY_SIZE(msm_csid2_resources),
+};
+
 struct resource msm_ispif_resources[] = {
 	{
 		.name	= "ispif",
@@ -2247,6 +2291,20 @@
 	},
 };
 
+static const char *kgsl_3d0_iommu_ctx_names[] = {
+	"gfx3d_user",
+	/* priv_ctx goes here */
+};
+
+static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = {
+	{
+		.iommu_ctx_names = kgsl_3d0_iommu_ctx_names,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu_ctx_names),
+		.physstart = 0x07C00000,
+		.physend = 0x07C00000 + SZ_1M - 1,
+	},
+};
+
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
 	.pwrlevel = {
 		{
@@ -2283,8 +2341,8 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	.bus_scale_table = &grp3d_bus_scale_pdata,
 #endif
-	.iommu_user_ctx_name = "gfx3d_user",
-	.iommu_priv_ctx_name = NULL,
+	.iommu_data = kgsl_3d0_iommu_data,
+	.iommu_count = ARRAY_SIZE(kgsl_3d0_iommu_data),
 };
 
 struct platform_device msm_kgsl_3d0 = {
@@ -2312,6 +2370,19 @@
 	},
 };
 
+static const char *kgsl_2d0_iommu_ctx_names[] = {
+	"gfx2d0_2d0",
+};
+
+static struct kgsl_device_iommu_data kgsl_2d0_iommu_data[] = {
+	{
+		.iommu_ctx_names = kgsl_2d0_iommu_ctx_names,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_2d0_iommu_ctx_names),
+		.physstart = 0x07D00000,
+		.physend = 0x07D00000 + SZ_1M - 1,
+	},
+};
+
 static struct kgsl_device_platform_data kgsl_2d0_pdata = {
 	.pwrlevel = {
 		{
@@ -2336,8 +2407,8 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	.bus_scale_table = &grp2d0_bus_scale_pdata,
 #endif
-	.iommu_user_ctx_name = "gfx2d0_2d0",
-	.iommu_priv_ctx_name = NULL,
+	.iommu_data = kgsl_2d0_iommu_data,
+	.iommu_count = ARRAY_SIZE(kgsl_2d0_iommu_data),
 };
 
 struct platform_device msm_kgsl_2d0 = {
@@ -2350,6 +2421,19 @@
 	},
 };
 
+static const char *kgsl_2d1_iommu_ctx_names[] = {
+	"gfx2d1_2d1",
+};
+
+static struct kgsl_device_iommu_data kgsl_2d1_iommu_data[] = {
+	{
+		.iommu_ctx_names = kgsl_2d1_iommu_ctx_names,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_2d1_iommu_ctx_names),
+		.physstart = 0x07E00000,
+		.physend = 0x07E00000 + SZ_1M - 1,
+	},
+};
+
 static struct resource kgsl_2d1_resources[] = {
 	{
 		.name = KGSL_2D1_REG_MEMORY,
@@ -2389,8 +2473,8 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	.bus_scale_table = &grp2d1_bus_scale_pdata,
 #endif
-	.iommu_user_ctx_name = "gfx2d1_2d1",
-	.iommu_priv_ctx_name = NULL,
+	.iommu_data = kgsl_2d1_iommu_data,
+	.iommu_count = ARRAY_SIZE(kgsl_2d1_iommu_data),
 };
 
 struct platform_device msm_kgsl_2d1 = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 3944a93..18acb36 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -234,6 +234,30 @@
 	},
 };
 
+static struct resource resources_hsic_host[] = {
+	{
+		.start	= MSM9615_HSIC_PHYS,
+		.end	= MSM9615_HSIC_PHYS + MSM9615_HSIC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= USB_HSIC_IRQ,
+		.end	= USB_HSIC_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_hsic_host = {
+	.name		= "msm_hsic_host",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_hsic_host),
+	.resource	= resources_hsic_host,
+	.dev		= {
+		.dma_mask               = &dma_mask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+};
+
 static struct resource resources_uart_gsbi4[] = {
 	{
 		.start	= GSBI4_UARTDM_IRQ,
@@ -419,7 +443,7 @@
 };
 
 static struct tsens_platform_data msm_tsens_pdata = {
-	.slope			= 910,
+	.slope			= {872, 872, 872, 872, 872},
 	.tsens_factor		= 1000,
 	.hw_type		= MSM_9615,
 	.tsens_num_sensor	= 5,
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 31eee43..c18b6b2 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -178,17 +178,6 @@
 	&msm_device_hsusb_host,
 };
 
-int msm_add_host(unsigned int host, struct msm_usb_host_platform_data *plat)
-{
-	struct platform_device	*pdev;
-
-	pdev = msm_host_devices[host];
-	if (!pdev)
-		return -ENODEV;
-	pdev->dev.platform_data = plat;
-	return platform_device_register(pdev);
-}
-
 static struct resource msm_dmov_resource[] = {
 	{
 		.start = INT_ADM_AARM,
@@ -513,18 +502,6 @@
 	&msm_device_sdc4,
 };
 
-int __init msm_add_sdcc(unsigned int controller, struct mmc_platform_data *plat)
-{
-	struct platform_device	*pdev;
-
-	if (controller < 1 || controller > 4)
-		return -EINVAL;
-
-	pdev = msm_sdcc_devices[controller-1];
-	pdev->dev.platform_data = plat;
-	return platform_device_register(pdev);
-}
-
 #ifdef CONFIG_MSM_CAMERA_V4L2
 static struct resource msm_csic0_resources[] = {
 	{
@@ -715,17 +692,6 @@
 				__func__, ret);
 }
 
-void __init msm_fb_register_device(char *name, void *data)
-{
-	if (!strncmp(name, "mdp", 3))
-		msm_register_device(&msm_mdp_device, data);
-	else if (!strncmp(name, "mipi_dsi", 8))
-		msm_register_device(&msm_mipi_dsi_device, data);
-	else if (!strncmp(name, "lcdc", 4))
-		msm_register_device(&msm_lcdc_device, data);
-	else
-		printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
-}
 
 #define PERPH_WEB_BLOCK_ADDR (0xA9D00040)
 #define PDM0_CTL_OFFSET (0x04)
@@ -815,6 +781,68 @@
 	.resource	= msm8625_resources_uart1,
 };
 
+static struct resource msm8625_uart1_dm_resources[] = {
+	{
+		.start	= MSM_UART1DM_PHYS,
+		.end	= MSM_UART1DM_PHYS + PAGE_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_UART1DM_IRQ,
+		.end	= MSM8625_INT_UART1DM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM8625_INT_UART1DM_RX,
+		.end	= MSM8625_INT_UART1DM_RX,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= DMOV_HSUART1_TX_CHAN,
+		.end	= DMOV_HSUART1_RX_CHAN,
+		.name	= "uartdm_channels",
+		.flags	= IORESOURCE_DMA,
+	},
+	{
+		.start	= DMOV_HSUART1_TX_CRCI,
+		.end	= DMOV_HSUART1_RX_CRCI,
+		.name	= "uartdm_crci",
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device msm8625_device_uart_dm1 = {
+	.name	= "msm_serial_hs",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(msm8625_uart1_dm_resources),
+	.resource	= msm8625_uart1_dm_resources,
+	.dev	= {
+		.dma_mask		= &msm_uart_dm1_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource msm8625_uart2dm_resources[] = {
+	{
+		.start	= MSM_UART2DM_PHYS,
+		.end	= MSM_UART2DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uartdm_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_UART2DM_IRQ,
+		.end	= MSM8625_INT_UART2DM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8625_device_uart_dm2 = {
+	.name	= "msm_serial_hsl",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(msm8625_uart2dm_resources),
+	.resource	= msm8625_uart2dm_resources,
+};
+
 static struct resource msm8625_dmov_resource[] = {
 	{
 		.start	= MSM8625_INT_ADM_AARM,
@@ -866,6 +894,35 @@
 	.resource	= gsbi0_msm8625_qup_resources,
 };
 
+static struct resource gsbi1_msm8625_qup_i2c_resources[] = {
+	{
+		.name	= "qup_phys_addr",
+		.start	= MSM_GSBI1_QUP_PHYS,
+		.end	= MSM_GSBI1_QUP_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "gsbi_qup_i2c_addr",
+		.start	= MSM_GSBI1_PHYS,
+		.end	= MSM_GSBI1_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_err_intr",
+		.start	= MSM8625_INT_ARM11_DMA,
+		.end	= MSM8625_INT_ARM11_DMA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* Use GSBI1 QUP for /dev/i2c-1 */
+struct platform_device msm8625_device_qup_i2c_gsbi1 = {
+	.name		= "qup_i2c",
+	.id		= MSM_GSBI1_QUP_I2C_BUS_ID,
+	.num_resources	= ARRAY_SIZE(gsbi1_qup_i2c_resources),
+	.resource	= gsbi1_msm8625_qup_i2c_resources,
+};
+
 static struct resource msm8625_gpio_resources[] = {
 	{
 		.start	= MSM8625_INT_GPIO_GROUP1,
@@ -884,6 +941,391 @@
 	.num_resources	= ARRAY_SIZE(msm8625_gpio_resources),
 };
 
+static struct resource msm8625_resources_sdc1[] = {
+	{
+		.start	= MSM_SDC1_BASE,
+		.end	= MSM_SDC1_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_SDC1_0,
+		.end	= MSM8625_INT_SDC1_1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "sdcc_dma_chnl",
+		.start	= DMOV_SDC1_CHAN,
+		.end	= DMOV_SDC1_CHAN,
+		.flags	= IORESOURCE_DMA,
+	},
+	{
+		.name	= "sdcc_dma_crci",
+		.start	= DMOV_SDC1_CRCI,
+		.end	= DMOV_SDC1_CRCI,
+		.flags	= IORESOURCE_DMA,
+	}
+};
+
+static struct resource msm8625_resources_sdc2[] = {
+	{
+		.start	= MSM_SDC2_BASE,
+		.end	= MSM_SDC2_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_SDC2_0,
+		.end	= MSM8625_INT_SDC2_1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "sdcc_dma_chnl",
+		.start	= DMOV_SDC2_CHAN,
+		.end	= DMOV_SDC2_CHAN,
+		.flags	= IORESOURCE_DMA,
+	},
+	{
+		.name	= "sdcc_dma_crci",
+		.start	= DMOV_SDC2_CRCI,
+		.end	= DMOV_SDC2_CRCI,
+		.flags	= IORESOURCE_DMA,
+	}
+};
+
+static struct resource msm8625_resources_sdc3[] = {
+	{
+		.start	= MSM_SDC3_BASE,
+		.end	= MSM_SDC3_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_SDC3_0,
+		.end	= MSM8625_INT_SDC3_1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "sdcc_dma_chnl",
+		.start	= DMOV_SDC3_CHAN,
+		.end	= DMOV_SDC3_CHAN,
+		.flags	= IORESOURCE_DMA,
+	},
+	{
+		.name	= "sdcc_dma_crci",
+		.start	= DMOV_SDC3_CRCI,
+		.end	= DMOV_SDC3_CRCI,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource msm8625_resources_sdc4[] = {
+	{
+		.start	= MSM_SDC4_BASE,
+		.end	= MSM_SDC4_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_SDC4_0,
+		.end	= MSM8625_INT_SDC4_1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "sdcc_dma_chnl",
+		.start	= DMOV_SDC4_CHAN,
+		.end	= DMOV_SDC4_CHAN,
+		.flags	= IORESOURCE_DMA,
+	},
+	{
+		.name	= "sdcc_dma_crci",
+		.start	= DMOV_SDC4_CRCI,
+		.end	= DMOV_SDC4_CRCI,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device msm8625_device_sdc1 = {
+	.name		= "msm_sdcc",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(msm8625_resources_sdc1),
+	.resource	= msm8625_resources_sdc1,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm8625_device_sdc2 = {
+	.name		= "msm_sdcc",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(msm8625_resources_sdc2),
+	.resource	= msm8625_resources_sdc2,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm8625_device_sdc3 = {
+	.name		= "msm_sdcc",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(msm8625_resources_sdc3),
+	.resource	= msm8625_resources_sdc3,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm8625_device_sdc4 = {
+	.name		= "msm_sdcc",
+	.id		= 4,
+	.num_resources	= ARRAY_SIZE(msm8625_resources_sdc4),
+	.resource	= msm8625_resources_sdc4,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+static struct platform_device *msm8625_sdcc_devices[] __initdata = {
+	&msm8625_device_sdc1,
+	&msm8625_device_sdc2,
+	&msm8625_device_sdc3,
+	&msm8625_device_sdc4,
+};
+
+int __init msm_add_sdcc(unsigned int controller, struct mmc_platform_data *plat)
+{
+	struct platform_device	*pdev;
+
+	if (controller < 1 || controller > 4)
+		return -EINVAL;
+
+	if (cpu_is_msm8625())
+		pdev = msm8625_sdcc_devices[controller-1];
+	else
+		pdev = msm_sdcc_devices[controller-1];
+
+	pdev->dev.platform_data = plat;
+	return platform_device_register(pdev);
+}
+
+static struct resource msm8625_resources_hsusb_otg[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_USB_HS,
+		.end	= MSM8625_INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8625_device_otg = {
+	.name		= "msm_otg",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(msm8625_resources_hsusb_otg),
+	.resource	= msm8625_resources_hsusb_otg,
+	.dev		= {
+		.dma_mask		= &dma_mask,
+		.coherent_dma_mask	= 0xffffffffULL,
+	},
+};
+
+static struct resource msm8625_resources_gadget_peripheral[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_USB_HS,
+		.end	= MSM8625_INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8625_device_gadget_peripheral = {
+	.name		= "msm_hsusb",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(msm8625_resources_gadget_peripheral),
+	.resource	= msm8625_resources_gadget_peripheral,
+	.dev		= {
+		.dma_mask		= &dma_mask,
+		.coherent_dma_mask	= 0xffffffffULL,
+	},
+};
+
+static struct resource msm8625_resources_hsusb_host[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM8625_INT_USB_HS,
+		.end	= MSM8625_INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8625_device_hsusb_host = {
+	.name		= "msm_hsusb_host",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(msm8625_resources_hsusb_host),
+	.resource	= msm8625_resources_hsusb_host,
+	.dev		= {
+		.dma_mask		= &dma_mask,
+		.coherent_dma_mask	= 0xffffffffULL,
+	},
+};
+
+static struct platform_device *msm8625_host_devices[] = {
+	&msm8625_device_hsusb_host,
+};
+
+int msm_add_host(unsigned int host, struct msm_usb_host_platform_data *plat)
+{
+	struct platform_device	*pdev;
+
+	if (cpu_is_msm8625())
+		pdev = msm8625_host_devices[host];
+	else
+		pdev = msm_host_devices[host];
+	if (!pdev)
+		return -ENODEV;
+	pdev->dev.platform_data = plat;
+	return platform_device_register(pdev);
+}
+
+#ifdef CONFIG_MSM_CAMERA_V4L2
+static struct resource msm8625_csic0_resources[] = {
+	{
+		.name   = "csic",
+		.start  = 0xA0F00000,
+		.end    = 0xA0F00000 + 0x00100000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "csic",
+		.start  = MSM8625_INT_CSI_IRQ_0,
+		.end    = MSM8625_INT_CSI_IRQ_0,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm8625_csic1_resources[] = {
+	{
+		.name   = "csic",
+		.start  = 0xA1000000,
+		.end    = 0xA1000000 + 0x00100000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "csic",
+		.start  = MSM8625_INT_CSI_IRQ_1,
+		.end    = MSM8625_INT_CSI_IRQ_1,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8625_device_csic0 = {
+	.name           = "msm_csic",
+	.id             = 0,
+	.resource       = msm8625_csic0_resources,
+	.num_resources  = ARRAY_SIZE(msm8625_csic0_resources),
+};
+
+struct platform_device msm8625_device_csic1 = {
+	.name           = "msm_csic",
+	.id             = 1,
+	.resource       = msm8625_csic1_resources,
+	.num_resources  = ARRAY_SIZE(msm8625_csic1_resources),
+};
+#endif
+
+static struct resource msm8625_mipi_dsi_resources[] = {
+	{
+		.name   = "mipi_dsi",
+		.start  = MIPI_DSI_HW_BASE,
+		.end    = MIPI_DSI_HW_BASE + 0x000F0000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = MSM8625_INT_DSI_IRQ,
+		.end    = MSM8625_INT_DSI_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msm8625_mipi_dsi_device = {
+	.name   = "mipi_dsi",
+	.id     = 1,
+	.num_resources  = ARRAY_SIZE(msm8625_mipi_dsi_resources),
+	.resource       = msm8625_mipi_dsi_resources,
+};
+
+static struct resource msm8625_mdp_resources[] = {
+	{
+		.name   = "mdp",
+		.start  = MDP_BASE,
+		.end    = MDP_BASE + 0x000F1008 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = MSM8625_INT_MDP,
+		.end    = MSM8625_INT_MDP,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msm8625_mdp_device = {
+	.name   = "mdp",
+	.id     = 0,
+	.num_resources  = ARRAY_SIZE(msm8625_mdp_resources),
+	.resource       = msm8625_mdp_resources,
+};
+
+void __init msm_fb_register_device(char *name, void *data)
+{
+	if (!strncmp(name, "mdp", 3)) {
+		if (cpu_is_msm8625())
+			msm_register_device(&msm8625_mdp_device, data);
+		else
+			msm_register_device(&msm_mdp_device, data);
+	} else if (!strncmp(name, "mipi_dsi", 8)) {
+		if (cpu_is_msm8625())
+			msm_register_device(&msm8625_mipi_dsi_device, data);
+		else
+			msm_register_device(&msm_mipi_dsi_device, data);
+	} else if (!strncmp(name, "lcdc", 4)) {
+			msm_register_device(&msm_lcdc_device, data);
+	} else {
+		printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
+	}
+}
+
+static struct resource msm8625_kgsl_3d0_resources[] = {
+	{
+		.name  = KGSL_3D0_REG_MEMORY,
+		.start = 0xA0000000,
+		.end = 0xA001ffff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = KGSL_3D0_IRQ,
+		.start = MSM8625_INT_GRAPHICS,
+		.end = MSM8625_INT_GRAPHICS,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8625_kgsl_3d0 = {
+	.name = "kgsl-3d0",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(msm8625_kgsl_3d0_resources),
+	.resource = msm8625_kgsl_3d0_resources,
+	.dev = {
+		.platform_data = &kgsl_3d0_pdata,
+	},
+};
+
 static struct clk_lookup msm_clock_8625_dummy[] = {
 	CLK_DUMMY("core_clk",		adm_clk.c,	"msm_dmov", 0),
 	CLK_DUMMY("adsp_clk",		adsp_clk.c,	NULL, 0),
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index be6a645..c2383c6 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -23,6 +23,10 @@
 extern struct platform_device msm7x27a_device_csic0;
 extern struct platform_device msm7x27a_device_csic1;
 extern struct platform_device msm7x27a_device_clkctl;
+
+extern struct platform_device msm8625_device_csic0;
+extern struct platform_device msm8625_device_csic1;
+
 void __init msm8625_init_irq(void);
 void __init msm8625_map_io(void);
 int  ar600x_wlan_power(bool on);
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index fc732da..e9b94f6 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -1181,6 +1181,7 @@
 	.set_grp_async = set_grp3d_async,
 	.idle_timeout = HZ/20,
 	.nap_allowed = true,
+	.idle_needed = true,
 	.clk_map = KGSL_CLK_SRC | KGSL_CLK_CORE |
 		KGSL_CLK_IFACE | KGSL_CLK_MEM,
 };
@@ -1223,6 +1224,7 @@
 	.set_grp_async = NULL,
 	.idle_timeout = HZ/10,
 	.nap_allowed = true,
+	.idle_needed = true,
 	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 };
 
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index c4f57ab..6da7b8f 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -59,10 +59,13 @@
 extern struct platform_device msm8960_device_qup_i2c_gsbi12;
 extern struct platform_device msm8960_device_qup_spi_gsbi1;
 extern struct platform_device msm8960_gemini_device;
+extern struct platform_device msm8960_device_i2c_mux_gsbi4;
 extern struct platform_device msm8960_device_csiphy0;
 extern struct platform_device msm8960_device_csiphy1;
+extern struct platform_device msm8960_device_csiphy2;
 extern struct platform_device msm8960_device_csid0;
 extern struct platform_device msm8960_device_csid1;
+extern struct platform_device msm8960_device_csid2;
 extern struct platform_device msm8960_device_ispif;
 extern struct platform_device msm8960_device_vfe;
 extern struct platform_device msm8960_device_vpe;
@@ -70,6 +73,7 @@
 extern struct platform_device apq8064_device_uart_gsbi1;
 extern struct platform_device apq8064_device_uart_gsbi3;
 extern struct platform_device apq8064_device_uart_gsbi7;
+extern struct platform_device apq8064_device_qup_i2c_gsbi1;
 extern struct platform_device apq8064_device_qup_i2c_gsbi3;
 extern struct platform_device apq8064_device_qup_i2c_gsbi4;
 extern struct platform_device apq8064_device_qup_spi_gsbi5;
@@ -106,6 +110,7 @@
 extern struct platform_device apq8064_device_gadget_peripheral;
 extern struct platform_device apq8064_device_hsusb_host;
 extern struct platform_device apq8064_device_hsic_host;
+extern struct platform_device apq8064_device_ehci_host3;
 
 extern struct platform_device msm_device_i2c;
 
@@ -123,6 +128,17 @@
 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_device_uart_dm1;
+extern struct platform_device msm8625_device_uart_dm2;
+extern struct platform_device msm8625_device_sdc1;
+extern struct platform_device msm8625_device_sdc2;
+extern struct platform_device msm8625_device_sdc3;
+extern struct platform_device msm8625_device_sdc4;
+extern struct platform_device msm8625_device_gadget_peripheral;
+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 msm_slim_ctrl;
 extern struct platform_device msm_device_sps;
@@ -222,9 +238,12 @@
 extern struct platform_device apq_cpudai_afe_02_rx;
 extern struct platform_device apq_cpudai_afe_02_tx;
 extern struct platform_device apq_pcm_afe;
+extern struct platform_device apq_cpudai_stub;
 
 extern struct platform_device *msm_footswitch_devices[];
 extern unsigned msm_num_footswitch_devices;
+extern struct platform_device *apq8064_fs_devices[];
+extern unsigned apq8064_num_fs_devices;
 
 extern struct platform_device fsm_qfp_fuse_device;
 
diff --git a/arch/arm/mach-msm/etm.c b/arch/arm/mach-msm/etm.c
index bee0975..9d04a58 100644
--- a/arch/arm/mach-msm/etm.c
+++ b/arch/arm/mach-msm/etm.c
@@ -377,9 +377,9 @@
 	etm_write(etm_config.etm_addr_access_type[6], ETMACTR6);
 	etm_write(etm_config.etm_addr_access_type[7], ETMACTR7);
 	etm_write(etm_config.etm_data_comp_value[0], ETMDCVR0);
-	etm_write(etm_config.etm_data_comp_value[1], ETMDCVR1);
+	etm_write(etm_config.etm_data_comp_value[1], ETMDCVR2);
 	etm_write(etm_config.etm_data_comp_mask[0], ETMDCMR0);
-	etm_write(etm_config.etm_data_comp_mask[1], ETMDCMR1);
+	etm_write(etm_config.etm_data_comp_mask[1], ETMDCMR2);
 	etm_write(etm_config.etm_counter_reload_value[0], ETMCNTRLDVR0);
 	etm_write(etm_config.etm_counter_reload_value[1], ETMCNTRLDVR1);
 	etm_write(etm_config.etm_counter_enable[0], ETMCNTENR0);
@@ -564,9 +564,9 @@
 	emit_log_word(etm_read(ETMACTR6));
 	emit_log_word(etm_read(ETMACTR7));
 	emit_log_word(etm_read(ETMDCVR0));
-	emit_log_word(etm_read(ETMDCVR1));
+	emit_log_word(etm_read(ETMDCVR2));
 	emit_log_word(etm_read(ETMDCMR0));
-	emit_log_word(etm_read(ETMDCMR1));
+	emit_log_word(etm_read(ETMDCMR2));
 	emit_log_word(etm_read(ETMCNTRLDVR0));
 	emit_log_word(etm_read(ETMCNTRLDVR1));
 	emit_log_word(etm_read(ETMCNTENR0));
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index 5c10463..4609a4b 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -99,8 +99,8 @@
 					clock->reset_rate : DEFAULT_RATE;
 			rc = clk_set_rate(clock->clk, rate);
 			if (rc && rc != -ENOSYS) {
-				pr_err("Failed to set %s rate to %lu Hz.\n",
-					clock->name, clock->rate);
+				pr_err("Failed to set %s %s rate to %lu Hz.\n",
+				       fs->desc.name, clock->name, clock->rate);
 				for (clock--; clock >= fs->clk_data; clock--) {
 					if (clock->enabled)
 						clk_disable_unprepare(
@@ -131,8 +131,8 @@
 		if (clock->enabled)
 			clk_disable_unprepare(clock->clk);
 		if (clock->rate && clk_set_rate(clock->clk, clock->rate))
-			pr_err("Failed to restore %s rate to %lu Hz.\n",
-				clock->name, clock->rate);
+			pr_err("Failed to restore %s %s rate to %lu Hz.\n",
+			       fs->desc.name, clock->name, clock->rate);
 	}
 }
 
@@ -167,14 +167,14 @@
 	if (fs->bus_port0) {
 		rc = msm_bus_axi_portunhalt(fs->bus_port0);
 		if (rc) {
-			pr_err("Port 0 unhalt failed.\n");
+			pr_err("%s port 0 unhalt failed.\n", fs->desc.name);
 			goto err;
 		}
 	}
 	if (fs->bus_port1) {
 		rc = msm_bus_axi_portunhalt(fs->bus_port1);
 		if (rc) {
-			pr_err("Port 1 unhalt failed.\n");
+			pr_err("%s port 1 unhalt failed.\n", fs->desc.name);
 			goto err_port2_halt;
 		}
 	}
@@ -252,14 +252,14 @@
 	if (fs->bus_port0) {
 		rc = msm_bus_axi_porthalt(fs->bus_port0);
 		if (rc) {
-			pr_err("Port 0 halt failed.\n");
+			pr_err("%s port 0 halt failed.\n", fs->desc.name);
 			goto err;
 		}
 	}
 	if (fs->bus_port1) {
 		rc = msm_bus_axi_porthalt(fs->bus_port1);
 		if (rc) {
-			pr_err("Port 1 halt failed.\n");
+			pr_err("%s port 1 halt failed.\n", fs->desc.name);
 			goto err_port2_halt;
 		}
 	}
@@ -329,7 +329,7 @@
 	if (fs->bus_port0) {
 		rc = msm_bus_axi_portunhalt(fs->bus_port0);
 		if (rc) {
-			pr_err("Port 0 unhalt failed.\n");
+			pr_err("%s port 0 unhalt failed.\n", fs->desc.name);
 			goto err;
 		}
 	}
@@ -404,7 +404,7 @@
 	if (fs->bus_port0) {
 		rc = msm_bus_axi_porthalt(fs->bus_port0);
 		if (rc) {
-			pr_err("Port 0 halt failed.\n");
+			pr_err("%s port 0 halt failed.\n", fs->desc.name);
 			goto err;
 		}
 	}
@@ -635,7 +635,8 @@
 		clock->clk = clk_get(&pdev->dev, clock->name);
 		if (IS_ERR(clock->clk)) {
 			rc = PTR_ERR(clock->clk);
-			pr_err("clk_get(%s) failed\n", clock->name);
+			pr_err("%s clk_get(%s) failed\n", fs->desc.name,
+			       clock->name);
 			goto err;
 		}
 		if (!strncmp(clock->name, "core_clk", 8))
diff --git a/arch/arm/mach-msm/footswitch-pcom.c b/arch/arm/mach-msm/footswitch-pcom.c
index 340f19b..f8e84fc 100644
--- a/arch/arm/mach-msm/footswitch-pcom.c
+++ b/arch/arm/mach-msm/footswitch-pcom.c
@@ -205,14 +205,14 @@
 		fs->src_clk = clk_get(dev, "core_clk");
 	}
 	if (IS_ERR(fs->src_clk)) {
-		pr_err("clk_get(src_clk) failed\n");
+		pr_err("%s clk_get(src_clk) failed\n", fs->desc.name);
 		rc = PTR_ERR(fs->src_clk);
 		goto err_src_clk;
 	}
 
 	fs->core_clk = clk_get(dev, "core_clk");
 	if (IS_ERR(fs->core_clk)) {
-		pr_err("clk_get(core_clk) failed\n");
+		pr_err("%s clk_get(core_clk) failed\n", fs->desc.name);
 		rc = PTR_ERR(fs->core_clk);
 		goto err_core_clk;
 	}
@@ -220,7 +220,7 @@
 	if (fs->has_ahb_clk) {
 		fs->ahb_clk = clk_get(dev, "iface_clk");
 		if (IS_ERR(fs->ahb_clk)) {
-			pr_err("clk_get(iface_clk) failed\n");
+			pr_err("%s clk_get(iface_clk) failed\n", fs->desc.name);
 			rc = PTR_ERR(fs->ahb_clk);
 			goto err_ahb_clk;
 		}
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 26adec6..8d40908 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -10,10 +10,13 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/cpu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/vfp.h>
 
+#include <mach/msm_rtb.h>
+
 #include "pm.h"
 #include "qdss.h"
 #include "spm.h"
@@ -49,6 +52,9 @@
 			/*
 			 * OK, proper wakeup, we're done
 			 */
+			pen_release = -1;
+			dmac_flush_range((void *)&pen_release,
+				(void *)(&pen_release + sizeof(pen_release)));
 			break;
 		}
 
@@ -60,6 +66,8 @@
 		 * possible, since we are currently running incoherently, and
 		 * therefore cannot safely call printk() or anything else
 		 */
+		dmac_inv_range((void *)&pen_release,
+			       (void *)(&pen_release + sizeof(pen_release)));
 		pr_debug("CPU%u: spurious wakeup call\n", cpu);
 	}
 }
@@ -109,6 +117,45 @@
 	return cpu == 0 ? -EPERM : 0;
 }
 
+#define CPU_SHIFT	0
+#define CPU_MASK	0xF
+#define CPU_OF(n)	(((n) & CPU_MASK) << CPU_SHIFT)
+#define CPUSET_SHIFT	4
+#define CPUSET_MASK	0xFFFF
+#define CPUSET_OF(n)	(((n) & CPUSET_MASK) << CPUSET_SHIFT)
+
+static int hotplug_rtb_callback(struct notifier_block *nfb,
+				unsigned long action, void *hcpu)
+{
+	/*
+	 * Bits [19:4] of the data are the online mask, lower 4 bits are the
+	 * cpu number that is being changed. Additionally, changes to the
+	 * online_mask that will be done by the current hotplug will be made
+	 * even though they aren't necessarily in the online mask yet.
+	 *
+	 * XXX: This design is limited to supporting at most 16 cpus
+	 */
+	int this_cpumask = CPUSET_OF(1 << (int)hcpu);
+	int cpumask = CPUSET_OF(cpumask_bits(cpu_online_mask)[0]);
+	int cpudata = CPU_OF((int)hcpu) | cpumask;
+
+	switch (action & (~CPU_TASKS_FROZEN)) {
+	case CPU_STARTING:
+		uncached_logk(LOGK_HOTPLUG, (void *)(cpudata | this_cpumask));
+		break;
+	case CPU_DYING:
+		uncached_logk(LOGK_HOTPLUG, (void *)(cpudata & ~this_cpumask));
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+static struct notifier_block hotplug_rtb_notifier = {
+	.notifier_call = hotplug_rtb_callback,
+};
+
 int msm_platform_secondary_init(unsigned int cpu)
 {
 	int ret;
@@ -127,3 +174,9 @@
 
 	return ret;
 }
+
+static int __init init_hotplug_notifier(void)
+{
+	return register_hotcpu_notifier(&hotplug_rtb_notifier);
+}
+early_initcall(init_hotplug_notifier);
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index c274899..32d162d 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -100,12 +100,14 @@
 	cmp	r1, #1
 	bne	skip
 	bl	v7_flush_dcache_all
+	b skip2
 
 skip:	ldr	r0, =saved_state
 	ldr	r1, =saved_state_end
 	sub	r1, r1, r0
 	bl	v7_flush_kern_dcache_area
 
+skip2:
 #ifdef CONFIG_ARCH_MSM_KRAIT
 	ldr	r0, =SCM_SVC_BOOT
 	ldr	r1, =SCM_CMD_TERMINATE_PC
@@ -136,7 +138,9 @@
 #if (NR_CPUS >= 2)
 	mrc	p15, 0, r1, c0, c0, 5	/* MPIDR */
 	ands	r1, r1, #15		/* What CPU am I */
-	addne	r0, r0, #CPU_SAVED_STATE_SIZE
+	mov	r2, #CPU_SAVED_STATE_SIZE
+	mul	r2, r2, r1
+	add	r0, r0, r2
 #endif
 
 	ldmfd   r0, {r4-r14}
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index ba9fc70..96b0083 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -202,6 +202,18 @@
 	uint8_t cam_gpio_set_tbl_size;
 };
 
+enum msm_camera_i2c_mux_mode {
+	MODE_R,
+	MODE_L,
+	MODE_DUAL
+};
+
+struct msm_camera_i2c_conf {
+	uint8_t use_i2c_mux;
+	struct platform_device *mux_dev;
+	enum msm_camera_i2c_mux_mode i2c_mux_mode;
+};
+
 struct msm_camera_sensor_platform_info {
 	int mount_angle;
 	int sensor_reset;
@@ -209,6 +221,7 @@
 	int num_vreg;
 	int32_t (*ext_power_ctrl) (int enable);
 	struct msm_camera_gpio_conf *gpio_conf;
+	struct msm_camera_i2c_conf *i2c_conf;
 };
 
 struct msm_actuator_info {
@@ -238,6 +251,7 @@
 	char *eeprom_data;
 	enum msm_camera_type camera_type;
 	struct msm_actuator_info *actuator_info;
+	int pmic_gpio_enable;
 };
 
 struct msm_camera_board_info {
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 530d2c1..ef7be45 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -52,6 +52,7 @@
 	VFE_MODE_OF_OPERATION_VIDEO,
 	VFE_MODE_OF_OPERATION_RAW_SNAPSHOT,
 	VFE_MODE_OF_OPERATION_ZSL,
+	VFE_MODE_OF_OPERATION_JPEG_SNAPSHOT,
 	VFE_LAST_MODE_OF_OPERATION_ENUM
 };
 
@@ -87,6 +88,7 @@
 	VFE_MSG_V32_START,
 	VFE_MSG_V32_START_RECORDING, /* 20 */
 	VFE_MSG_V32_CAPTURE,
+	VFE_MSG_V32_JPEG_CAPTURE,
 	VFE_MSG_OUTPUT_IRQ,
 	VFE_MSG_V2X_PREVIEW,
 	VFE_MSG_V2X_CAPTURE,
@@ -629,12 +631,6 @@
 	S_EXIT
 };
 
-enum msm_cam_mode {
-	MODE_R,
-	MODE_L,
-	MODE_DUAL
-};
-
 struct msm_cam_clk_info {
 	const char *clk_name;
 	long clk_rate;
@@ -646,7 +642,7 @@
 int msm_camio_vpe_clk_enable(uint32_t);
 int msm_camio_vpe_clk_disable(void);
 
-void msm_camio_mode_config(enum msm_cam_mode mode);
+void msm_camio_mode_config(enum msm_camera_i2c_mux_mode mode);
 int  msm_camio_clk_enable(enum msm_camio_clk_type clk);
 int  msm_camio_clk_disable(enum msm_camio_clk_type clk);
 int  msm_camio_clk_config(uint32_t freq);
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 48eae0c..2d2d2fb 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -20,8 +20,9 @@
 
 enum {
 	VIDEO_FIRMWARE_POOL,
-	LOW_256MB_POOL,
-	HIGH_POOL,
+	VIDEO_MAIN_POOL,
+	VIDEO_MFC_POOL,
+	GEN_POOL,
 };
 
 
diff --git a/arch/arm/mach-msm/include/mach/irqs-8960.h b/arch/arm/mach-msm/include/mach/irqs-8960.h
index dae0f47..012dd74 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8960.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8960.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -268,6 +268,8 @@
 #define PM8921_SEC_IRQ_104			(GIC_SPI_START + 225)
 #define PM8018_SEC_IRQ_107			(GIC_SPI_START + 226)
 #define USB_HSIC_IRQ				(GIC_SPI_START + 229)
+#define MSM8960_CSIPHY_2_2LN_IRQ		(GIC_SPI_START + 228)
+#define CSI_2_IRQ				(GIC_SPI_START + 227)
 
 /* Backwards compatible IRQ macros. */
 #define INT_ADM_AARM				ADM_0_SCSS_0_IRQ
diff --git a/arch/arm/mach-msm/include/mach/msm_adsp.h b/arch/arm/mach-msm/include/mach/msm_adsp.h
index bbae6c1..e40c07d 100644
--- a/arch/arm/mach-msm/include/mach/msm_adsp.h
+++ b/arch/arm/mach-msm/include/mach/msm_adsp.h
@@ -1,7 +1,7 @@
 /* include/asm-arm/arch-msm/msm_adsp.h
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-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
@@ -52,6 +52,14 @@
 		   unsigned queue_id,
 		   void *data, size_t len);
 
+/*Explicitly gererate adsp event */
+int msm_adsp_generate_event(void *data,
+			struct msm_adsp_module *mod,
+			unsigned event_id,
+			unsigned event_length,
+			unsigned event_size,
+			void *msg);
+
 #define ADSP_MESSAGE_ID 0xFFFF
 
 /* Command Queue Indexes */
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8625.h b/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
index 8088a4c..3435c2a 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
@@ -48,11 +48,11 @@
 #define MSM8625_SCU_PHYS		0xC0600000
 #define MSM8625_SCU_SIZE		SZ_256
 
-#define MSM8625_SPM0_PHYS		0xC0200000
-#define MSM8625_SPM0_SIZE		SZ_4K
+#define MSM8625_SAW0_PHYS		0xC0200000
+#define MSM8625_SAW0_SIZE		SZ_4K
 
-#define MSM8625_SPM1_PHYS		0xC0700000
-#define MSM8625_SPM1_SIZE		SZ_4K
+#define MSM8625_SAW1_PHYS		0xC0700000
+#define MSM8625_SAW1_SIZE		SZ_4K
 
 #define MSM8625_CFG_CTL_PHYS		0xA9800000
 #define MSM8625_CFG_CTL_SIZE		SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-copper.h b/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
index a3c9da8..6311dbe 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -23,12 +23,17 @@
  *
  */
 
+#define COPPER_MSM_SHARED_RAM_PHYS	0x18D00000
+
 #define COPPER_QGIC_DIST_PHYS	0xF9000000
 #define COPPER_QGIC_DIST_SIZE	SZ_4K
 
 #define COPPER_QGIC_CPU_PHYS	0xF9002000
 #define COPPER_QGIC_CPU_SIZE	SZ_4K
 
+#define COPPER_APCS_GCC_PHYS	0xF9011000
+#define COPPER_APCS_GCC_SIZE	SZ_4K
+
 #define COPPER_TLMM_PHYS	0xFD400000
 #define COPPER_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index d53910d..27965d3 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,7 +47,9 @@
 
 #if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
 	defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
-	defined(CONFIG_ARCH_MSMCOPPER)
+	defined(CONFIG_ARCH_MSMCOPPER) || defined(CONFIG_ARCH_MSM7X27) || \
+	defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
+	defined(CONFIG_ARCH_MSM8625)
 
 /* Unified iomap */
 
@@ -80,13 +82,28 @@
 #define MSM_APCS_GLB_BASE	IOMEM(0xFA702000)	/*  4K  */
 #define MSM_SAW2_BASE		IOMEM(0xFA703000)	/*  4k  */
 #define MSM_SAW3_BASE		IOMEM(0xFA704000)	/*  4k  */
+#define MSM_VIC_BASE		IOMEM(0xFA100000)	/*  4K */
+#define MSM_CSR_BASE		IOMEM(0xFA101000)	/*  4K */
+#define MSM_GPIO1_BASE		IOMEM(0xFA102000)	/*  4K */
+#define MSM_GPIO2_BASE		IOMEM(0xFA103000)	/*  4K */
+#define MSM_SCU_BASE		IOMEM(0xFA104000)	/*  4K */
+#define MSM_CFG_CTL_BASE	IOMEM(0xFA105000)	/*  4K */
+#define MSM_MDC_BASE		IOMEM(0xFA400000)	/*  1M */
+#define MSM_AD5_BASE		IOMEM(0xFA900000)	/*  13M (D00000)
+							  0xFB600000 */
 
-#if defined(CONFIG_ARCH_MSM9615)
+#define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
+#define MSM8625_SECONDARY_PHYS		0x0FE00000
+
+
+#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 #else
 #define MSM_SHARED_RAM_SIZE	SZ_2M
 #endif
 
+#include "msm_iomap-7xxx.h"
+#include "msm_iomap-8625.h"
 #include "msm_iomap-8960.h"
 #include "msm_iomap-8930.h"
 #include "msm_iomap-8064.h"
@@ -105,29 +122,7 @@
 #elif defined(CONFIG_ARCH_FSM9XXX)
 #include "msm_iomap-fsm9xxx.h"
 #else
-#define MSM_VIC_BASE			IOMEM(0xFA000000)	/* 4K */
-#define MSM_CSR_BASE			IOMEM(0xFA001000)	/* 4K */
-#define MSM_TMR_BASE			MSM_CSR_BASE		/* 4K */
-#define MSM_TMR0_BASE			IOMEM(0xFA002000)	/* 4K */
-#define MSM_GPIO1_BASE			IOMEM(0xFA003000)	/* 4K */
-#define MSM_GPIO2_BASE			IOMEM(0xFA004000)	/* 4K */
-#define MSM_CLK_CTL_BASE		IOMEM(0xFA005000)	/* 4K */
-#define MSM_L2CC_BASE			IOMEM(0xFA006000)	/* 4K */
-#define MSM_QGIC_DIST_BASE		IOMEM(0xFA007000)	/* 4K */
-#define MSM_QGIC_CPU_BASE		IOMEM(0xFA008000)	/* 4K */
-#define MSM_SCU_BASE			IOMEM(0xFA009000)	/* 4K */
-#define MSM_SPM0_BASE			IOMEM(0xFA00A000)	/* 4K */
-#define MSM_SPM1_BASE			IOMEM(0xFA00B000)	/* 4K */
-#define MSM_CFG_CTL_BASE		IOMEM(0xFA00C000)	/* 4K */
-#define MSM_SHARED_RAM_BASE		IOMEM(0xFA100000)	/* 4K */
-#define MSM_MDC_BASE			IOMEM(0xFA200000)	/* 4K */
-#define MSM_AD5_BASE			IOMEM(0xFA300000)	/* 4K */
-#define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
-#define MSM8625_SECONDARY_PHYS		0x0FE00000
-#define MSM_SHARED_RAM_SIZE		SZ_1M
-
-#include "msm_iomap-7xxx.h"
-#include "msm_iomap-8625.h"
+#error "Target compiled without IO map\n"
 #endif
 
 #if defined(CONFIG_DEBUG_MSM_UART1)
diff --git a/arch/arm/mach-msm/include/mach/msm_rtb.h b/arch/arm/mach-msm/include/mach/msm_rtb.h
index ac45cbd..59352d1 100644
--- a/arch/arm/mach-msm/include/mach/msm_rtb.h
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -18,9 +18,15 @@
 	LOGK_READL,
 	LOGK_WRITEL,
 	LOGK_LOGBUF,
+	LOGK_HOTPLUG,
+	LOGK_CTXID,
 	LOGK_OTHER,
 };
 
+struct msm_rtb_platform_data {
+	unsigned int size;
+};
+
 #if defined(CONFIG_MSM_RTB)
 /*
  * returns 1 if data was logged, 0 otherwise
diff --git a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
index d50fe2b..92dfe12 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
@@ -132,6 +132,8 @@
 
 	unsigned int minor_no;
 	struct codec_operations codec_ops;
+	uint32_t buffer_size;
+	uint32_t buffer_count;
 };
 
 #endif /* !CODEC_UTILS_H */
diff --git a/arch/arm/mach-msm/include/mach/qpnp.h b/arch/arm/mach-msm/include/mach/qpnp.h
new file mode 100644
index 0000000..1d2e440
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qpnp.h
@@ -0,0 +1,19 @@
+ /* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/spmi.h>
+
+struct resource *qpnp_get_resource(struct spmi_device *dev,
+				   unsigned int node_idx, unsigned int type,
+				   unsigned int res_num);
+int qpnp_get_irq(struct spmi_device *dev, unsigned int node_idx,
+					  unsigned int res_num);
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index 80ec683..bcb1240 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -117,8 +117,8 @@
 	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_2,
 	MSM_RPM_ID_SYS_FABRIC_CFG_IOCTL,
 	MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
-	MSM_RPM_ID_SYSTEM_FABRIC_ARB_28 =
-		MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 28,
+	MSM_RPM_ID_SYSTEM_FABRIC_ARB_29 =
+		MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 29,
 
 	MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
 	MSM_RPM_ID_MM_FABRIC_HALT_0 =
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index e1d4459..215fdb3 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -103,7 +103,7 @@
 
 static inline int cpu_is_msm7x27(void)
 {
-#ifdef CONFIG_ARCH_MSM7X27
+#if defined(CONFIG_ARCH_MSM7X27) && !defined(CONFIG_ARCH_MSM7X27A)
 	enum msm_cpu cpu = socinfo_get_msm_cpu();
 
 	BUG_ON(cpu == MSM_CPU_UNKNOWN);
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 830db1f..8e74238 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -43,7 +43,7 @@
  */
 unsigned int msm_shared_ram_phys = 0x00100000;
 
-static void msm_map_io(struct map_desc *io_desc, int size)
+static void __init msm_map_io(struct map_desc *io_desc, int size)
 {
 	int i;
 
@@ -292,7 +292,13 @@
 static struct map_desc msm_copper_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, COPPER),
 	MSM_CHIP_DEVICE(QGIC_CPU, COPPER),
+	MSM_CHIP_DEVICE(APCS_GCC, COPPER),
 	MSM_CHIP_DEVICE(TLMM, COPPER),
+	{
+		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
+		.length =   MSM_SHARED_RAM_SIZE,
+		.type =     MT_DEVICE,
+	},
 #ifdef CONFIG_DEBUG_MSMCOPPER_UART
 	MSM_DEVICE(DEBUG_UART),
 #endif
@@ -300,6 +306,7 @@
 
 void __init msm_map_copper_io(void)
 {
+	msm_shared_ram_phys = COPPER_MSM_SHARED_RAM_PHYS;
 	msm_map_io(msm_copper_io_desc, ARRAY_SIZE(msm_copper_io_desc));
 }
 #endif /* CONFIG_ARCH_MSMCOPPER */
@@ -410,8 +417,8 @@
 	MSM_CHIP_DEVICE(SCU, MSM8625),
 	MSM_CHIP_DEVICE(CFG_CTL, MSM8625),
 	MSM_CHIP_DEVICE(CLK_CTL, MSM8625),
-	MSM_CHIP_DEVICE(SPM0, MSM8625),
-	MSM_CHIP_DEVICE(SPM1, MSM8625),
+	MSM_CHIP_DEVICE(SAW0, MSM8625),
+	MSM_CHIP_DEVICE(SAW1, MSM8625),
 #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_domains.c b/arch/arm/mach-msm/iommu_domains.c
index c856455..727b729 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -103,11 +103,11 @@
 	case MSM_SUBSYSTEM_VIDEO_FWARE:
 		return VIDEO_FIRMWARE_POOL;
 	case MSM_SUBSYSTEM_VIDEO:
-		return LOW_256MB_POOL;
+		return VIDEO_MAIN_POOL;
 	case MSM_SUBSYSTEM_CAMERA:
 	case MSM_SUBSYSTEM_DISPLAY:
 	case MSM_SUBSYSTEM_ROTATOR:
-		return HIGH_POOL;
+		return GEN_POOL;
 	default:
 		return 0xFFFFFFFF;
 	}
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index f720fa9..a2ec89b 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.c
@@ -22,8 +22,10 @@
 #include "qdss.h"
 #include "cp14.h"
 
+ /* no of dbg regs + 1 (for storing the reg count) */
 #define MAX_DBG_REGS		(90)
 #define MAX_DBG_STATE_SIZE	(MAX_DBG_REGS * num_possible_cpus())
+ /* no of etm regs + 1 (for storing the reg count) */
 #define MAX_ETM_REGS		(78)
 #define MAX_ETM_STATE_SIZE	(MAX_ETM_REGS * num_possible_cpus())
 
@@ -31,6 +33,9 @@
 #define CPMR_ETMCLKEN		(0x8)
 
 
+uint32_t msm_jtag_save_cntr[NR_CPUS];
+uint32_t msm_jtag_restore_cntr[NR_CPUS];
+
 struct dbg_ctx {
 	uint8_t		arch;
 	bool		arch_supported;
@@ -70,7 +75,7 @@
 		break;
 	case 3:
 		state[i++] = dbg_read(DBGBVR3);
-		state[i++] = dbg_read(DBGBVR3);
+		state[i++] = dbg_read(DBGBCR3);
 		break;
 	case 4:
 		state[i++] = dbg_read(DBGBVR4);
@@ -78,7 +83,7 @@
 		break;
 	case 5:
 		state[i++] = dbg_read(DBGBVR5);
-		state[i++] = dbg_read(DBGBVR5);
+		state[i++] = dbg_read(DBGBCR5);
 		break;
 	case 6:
 		state[i++] = dbg_read(DBGBVR6);
@@ -143,7 +148,7 @@
 		break;
 	case 3:
 		dbg_write(state[i++], DBGBVR3);
-		dbg_write(state[i++], DBGBVR3);
+		dbg_write(state[i++], DBGBCR3);
 		break;
 	case 4:
 		dbg_write(state[i++], DBGBVR4);
@@ -151,7 +156,7 @@
 		break;
 	case 5:
 		dbg_write(state[i++], DBGBVR5);
-		dbg_write(state[i++], DBGBVR5);
+		dbg_write(state[i++], DBGBCR5);
 		break;
 	case 6:
 		dbg_write(state[i++], DBGBVR6);
@@ -937,9 +942,9 @@
 		etm_write(etm.state[i++], ETMSQ12EVR);
 		etm_write(etm.state[i++], ETMSQ21EVR);
 		etm_write(etm.state[i++], ETMSQ23EVR);
+		etm_write(etm.state[i++], ETMSQ31EVR);
 		etm_write(etm.state[i++], ETMSQ32EVR);
 		etm_write(etm.state[i++], ETMSQ13EVR);
-		etm_write(etm.state[i++], ETMSQ31EVR);
 		etm_write(etm.state[i++], ETMSQR);
 		for (j = 0; j < etm.nr_ext_out; j++)
 			i = etm_write_extoutevr(etm.state, i, j);
@@ -1013,6 +1018,10 @@
 
 	cpu = raw_smp_processor_id();
 
+	msm_jtag_save_cntr[cpu]++;
+	/* ensure counter is updated before moving forward */
+	mb();
+
 	if (dbg.arch_supported)
 		dbg_save_state(cpu);
 	if (etm.arch_supported)
@@ -1025,6 +1034,10 @@
 
 	cpu = raw_smp_processor_id();
 
+	msm_jtag_restore_cntr[cpu]++;
+	/* ensure counter is updated before moving forward */
+	mb();
+
 	if (dbg.arch_supported)
 		dbg_restore_state(cpu);
 	if (etm.arch_supported)
@@ -1046,9 +1059,9 @@
 		pr_info("dbg arch %u not supported\n", dbg.arch);
 		goto dbg_out;
 	}
-	dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23);
-	dbg.nr_bp = BMVAL(dbgdidr, 24, 27);
-	dbg.nr_wp = BMVAL(dbgdidr, 28, 31);
+	dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23) + 1;
+	dbg.nr_bp = BMVAL(dbgdidr, 24, 27) + 1;
+	dbg.nr_wp = BMVAL(dbgdidr, 28, 31) + 1;
 
 	/* Allocate dbg state save space */
 	dbg.state = kzalloc(MAX_DBG_STATE_SIZE * sizeof(uint32_t), GFP_KERNEL);
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 5db8b40..7e538b4 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -48,7 +48,7 @@
 
 static int mdm_debug_on;
 static int first_power_on = 1;
-static int hsic_peripheral_status = 1;
+static int hsic_peripheral_status;
 static DEFINE_MUTEX(hsic_status_lock);
 
 static void mdm_peripheral_connect(struct mdm_modem_drv *mdm_drv)
@@ -82,7 +82,7 @@
 	/* Pull RESET gpio low and wait for it to settle. */
 	pr_debug("Pulling RESET gpio low\n");
 	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
-	usleep(1000);
+	usleep_range(5000, 10000);
 
 	/* Deassert RESET first and wait for ir to settle. */
 	pr_debug("%s: Pulling RESET gpio high\n", __func__);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 3b064ff..d26d76b 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/memory.c
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -226,6 +226,25 @@
 	return unstable_limit - mb->start;
 }
 
+/* stable size of all memory banks contiguous to and below this one */
+static unsigned long total_stable_size(unsigned long bank)
+{
+	int i;
+	struct membank *mb = &meminfo.bank[bank];
+	int memtype = reserve_info->paddr_to_memtype(mb->start);
+	unsigned long size;
+
+	size = stable_size(mb, reserve_info->low_unstable_address);
+	for (i = bank - 1, mb = &meminfo.bank[bank - 1]; i >= 0; i--, mb--) {
+		if (mb->start + mb->size != (mb + 1)->start)
+			break;
+		if (reserve_info->paddr_to_memtype(mb->start) != memtype)
+			break;
+		size += stable_size(mb, reserve_info->low_unstable_address);
+	}
+	return size;
+}
+
 static void __init calculate_reserve_limits(void)
 {
 	int i;
@@ -242,7 +261,7 @@
 			continue;
 		}
 		mt = &reserve_info->memtype_reserve_table[memtype];
-		size = stable_size(mb, reserve_info->low_unstable_address);
+		size = total_stable_size(i);
 		mt->limit = max(mt->limit, size);
 	}
 }
@@ -277,10 +296,11 @@
 		if (mt->flags & MEMTYPE_FLAGS_FIXED || !mt->size)
 			continue;
 
-		/* We know we will find a memory bank of the proper size
+		/* We know we will find memory bank(s) of the proper size
 		 * as we have limited the size of the memory pool for
-		 * each memory type to the size of the largest memory
-		 * bank. Choose the memory bank with the highest physical
+		 * each memory type to the largest total size of the memory
+		 * banks which are contiguous and of the correct memory type.
+		 * Choose the memory bank with the highest physical
 		 * address which is large enough, so that we will not
 		 * take memory from the lowest memory bank which the kernel
 		 * is in (and cause boot problems) and so that we might
@@ -293,9 +313,14 @@
 				reserve_info->paddr_to_memtype(mb->start);
 			if (memtype != membank_type)
 				continue;
-			size = stable_size(mb,
-				reserve_info->low_unstable_address);
+			size = total_stable_size(i);
 			if (size >= mt->size) {
+				size = stable_size(mb,
+					reserve_info->low_unstable_address);
+				/* mt->size may be larger than size, all this
+				 * means is that we are carving the memory pool
+				 * out of multiple contiguous memory banks.
+				 */
 				mt->start = mb->start + (size - mt->size);
 				ret = memblock_remove(mt->start, mt->size);
 				BUG_ON(ret);
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index 018e2a6..061998c 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -6,4 +6,5 @@
 obj-$(CONFIG_ARCH_MSM8960) += msm_bus_board_8960.o
 obj-$(CONFIG_ARCH_MSM9615) += msm_bus_board_9615.o
 obj-$(CONFIG_ARCH_APQ8064) += msm_bus_board_8064.o
+obj-$(CONFIG_ARCH_MSM8930) += msm_bus_board_8930.o
 obj-$(CONFIG_DEBUG_FS) += msm_bus_dbg.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
new file mode 100644
index 0000000..36fe156
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
@@ -0,0 +1,878 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/rpm.h>
+#include "msm_bus_core.h"
+
+#define NMASTERS 45
+#define NSLAVES 75
+#define NFAB_8930 5
+
+enum msm_bus_fabric_tiered_slave_type {
+	MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS_0 = 1,
+	MSM_BUS_TIERED_SLAVE_SYSTEM_IMEM,
+
+	MSM_BUS_TIERED_SLAVE_MM_IMEM = 1,
+	MSM_BUS_MMSS_TIERED_SLAVE_FAB_APPS_0,
+
+	MSM_BUS_TIERED_SLAVE_EBI1_CH0 = 1,
+	MSM_BUS_TIERED_SLAVE_KMPSS_L2,
+};
+
+enum msm_bus_8930_master_ports_type {
+	MSM_BUS_SYSTEM_MASTER_PORT_APPSS_FAB = 0,
+	MSM_BUS_MASTER_PORT_SPS,
+	MSM_BUS_MASTER_PORT_ADM_PORT0,
+	MSM_BUS_MASTER_PORT_ADM_PORT1,
+	MSM_BUS_MASTER_PORT_LPASS_PROC,
+	MSM_BUS_MASTER_PORT_MSS,
+	MSM_BUS_MASTER_PORT_RIVA,
+	MSM_BUS_MASTER_PORT_MSS_SW_PROC,
+	MSM_BUS_MASTER_PORT_MSS_FW_PROC,
+	MSM_BUS_MASTER_PORT_LPASS,
+	MSM_BUS_SYSTEM_MASTER_PORT_CPSS_FPB,
+	MSM_BUS_SYSTEM_MASTER_PORT_SYSTEM_FPB,
+	MSM_BUS_SYSTEM_MASTER_PORT_MMSS_FPB,
+	MSM_BUS_SYSTEM_MASTER_PORT_ADM_AHB_CI,
+
+	MSM_BUS_MASTER_PORT_MDP_PORT0 = 0,
+	MSM_BUS_MASTER_PORT_MDP_PORT1,
+	MSM_BUS_MASTER_PORT_GRAPHICS_3D,
+	MSM_BUS_MASTER_PORT_ROTATOR,
+	MSM_BUS_MASTER_PORT_VFE,
+	MSM_BUS_MASTER_PORT_VPE,
+	MSM_BUS_MASTER_PORT_JPEG_ENC,
+	MSM_BUS_MMSS_MASTER_PORT_APPS_FAB,
+	MSM_BUS_MASTER_PORT_HD_CODEC_PORT0,
+	MSM_BUS_MASTER_PORT_HD_CODEC_PORT1,
+
+	MSM_BUS_MASTER_PORT_KMPSS_M0 = 0,
+	MSM_BUS_MASTER_PORT_KMPSS_M1,
+	MSM_BUS_APPSS_MASTER_PORT_FAB_MMSS_0,
+	MSM_BUS_APPSS_MASTER_PORT_FAB_SYSTEM_0,
+};
+
+enum msm_bus_8930_slave_ports_type {
+	MSM_BUS_SLAVE_PORT_MM_IMEM = 0,
+	MSM_BUS_MMSS_SLAVE_PORT_APPS_FAB_0,
+
+	MSM_BUS_SLAVE_PORT_EBI1_CH0 = 0,
+	MSM_BUS_SLAVE_PORT_KMPSS_L2,
+	MSM_BUS_APPSS_SLAVE_PORT_MMSS_FAB,
+	MSM_BUS_SLAVE_PORT_SYSTEM_FAB,
+
+	MSM_BUS_SYSTEM_SLAVE_PORT_APPSS_FAB_0 = 0,
+	MSM_BUS_SLAVE_PORT_SPS,
+	MSM_BUS_SLAVE_PORT_SYSTEM_IMEM,
+	MSM_BUS_SLAVE_PORT_CORESIGHT,
+	MSM_BUS_SLAVE_PORT_KMPSS,
+	MSM_BUS_SLAVE_PORT_MSS,
+	MSM_BUS_SLAVE_PORT_LPASS,
+	MSM_BUS_SYSTEM_SLAVE_PORT_CPSS_FPB,
+	MSM_BUS_SYSTEM_SLAVE_PORT_SYSTEM_FPB,
+	MSM_BUS_SYSTEM_SLAVE_PORT_MMSS_FPB,
+	MSM_BUS_SLAVE_PORT_RIVA,
+};
+
+static int tier2[] = {MSM_BUS_BW_TIER2,};
+static uint32_t master_iids[NMASTERS];
+static uint32_t slave_iids[NSLAVES];
+
+static int mport_kmpss_m0[] = {MSM_BUS_MASTER_PORT_KMPSS_M0,};
+static int mport_kmpss_m1[] = {MSM_BUS_MASTER_PORT_KMPSS_M1,};
+
+static int mmss_mport_apps_fab[] = {MSM_BUS_MMSS_MASTER_PORT_APPS_FAB,};
+static int system_mport_appss_fab[] = {MSM_BUS_SYSTEM_MASTER_PORT_APPSS_FAB,};
+static int sport_ebi1_ch0[] = {
+	MSM_BUS_SLAVE_PORT_EBI1_CH0,
+};
+static int sport_kmpss_l2[] = {MSM_BUS_SLAVE_PORT_KMPSS_L2,};
+static int appss_sport_mmss_fab[] = {MSM_BUS_APPSS_SLAVE_PORT_MMSS_FAB,};
+static int sport_system_fab[] = {MSM_BUS_SLAVE_PORT_SYSTEM_FAB,};
+
+static int tiered_slave_ebi1_ch0[] = {
+	MSM_BUS_TIERED_SLAVE_EBI1_CH0,
+};
+
+static int tiered_slave_kmpss[] = {MSM_BUS_TIERED_SLAVE_KMPSS_L2,};
+
+static struct msm_bus_node_info apps_fabric_info[] = {
+	{
+		.id = MSM_BUS_MASTER_AMPSS_M0,
+		.masterp = mport_kmpss_m0,
+		.num_mports = ARRAY_SIZE(mport_kmpss_m0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_AMPSS_M1,
+		.masterp = mport_kmpss_m1,
+		.num_mports = ARRAY_SIZE(mport_kmpss_m1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI_CH0,
+		.slavep = sport_ebi1_ch0,
+		.num_sports = ARRAY_SIZE(sport_ebi1_ch0),
+		.tier = tiered_slave_ebi1_ch0,
+		.num_tiers = ARRAY_SIZE(tiered_slave_ebi1_ch0),
+		.buswidth = 8,
+		.slaveclk[DUAL_CTX] = "mem_clk",
+		.slaveclk[ACTIVE_CTX] = "mem_a_clk",
+	},
+	{
+		.id = MSM_BUS_SLAVE_AMPSS_L2,
+		.slavep = sport_kmpss_l2,
+		.num_sports = ARRAY_SIZE(sport_kmpss_l2),
+		.tier = tiered_slave_kmpss,
+		.num_tiers = ARRAY_SIZE(tiered_slave_kmpss),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_FAB_MMSS,
+		.gateway = 1,
+		.slavep = appss_sport_mmss_fab,
+		.num_sports = ARRAY_SIZE(appss_sport_mmss_fab),
+		.masterp = mmss_mport_apps_fab,
+		.num_mports = ARRAY_SIZE(mmss_mport_apps_fab),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_FAB_SYSTEM,
+		.gateway = 1,
+		.slavep = sport_system_fab,
+		.num_sports = ARRAY_SIZE(sport_system_fab),
+		.masterp = system_mport_appss_fab,
+		.num_mports = ARRAY_SIZE(system_mport_appss_fab),
+		.buswidth = 8,
+	},
+};
+
+static int mport_sps[] = {MSM_BUS_MASTER_PORT_SPS,};
+static int mport_adm_port0[] = {MSM_BUS_MASTER_PORT_ADM_PORT0,};
+static int mport_adm_port1[] = {MSM_BUS_MASTER_PORT_ADM_PORT1,};
+static int mport_mss[] = {MSM_BUS_MASTER_PORT_MSS,};
+static int mport_lpass_proc[] = {MSM_BUS_MASTER_PORT_LPASS_PROC,};
+static int mport_riva[] = {MSM_BUS_MASTER_PORT_RIVA,};
+static int mport_mss_sw_proc[] = {MSM_BUS_MASTER_PORT_MSS_SW_PROC,};
+static int mport_mss_fw_proc[] = {MSM_BUS_MASTER_PORT_MSS_FW_PROC,};
+static int mport_lpass[] = {MSM_BUS_MASTER_PORT_LPASS,};
+static int system_mport_mmss_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_MMSS_FPB,};
+static int system_mport_adm_ahb_ci[] = {MSM_BUS_SYSTEM_MASTER_PORT_ADM_AHB_CI,};
+static int appss_mport_fab_system[] = {
+	MSM_BUS_APPSS_MASTER_PORT_FAB_SYSTEM_0,
+};
+static int mport_system_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_SYSTEM_FPB,};
+static int system_mport_cpss_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_CPSS_FPB,};
+
+static int system_sport_appss_fab[] = {
+	MSM_BUS_SYSTEM_SLAVE_PORT_APPSS_FAB_0,
+};
+static int system_sport_system_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_SYSTEM_FPB,};
+static int system_sport_cpss_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_CPSS_FPB,};
+static int sport_sps[] = {MSM_BUS_SLAVE_PORT_SPS,};
+static int sport_system_imem[] = {MSM_BUS_SLAVE_PORT_SYSTEM_IMEM,};
+static int sport_coresight[] = {MSM_BUS_SLAVE_PORT_CORESIGHT,};
+static int sport_riva[] = {MSM_BUS_SLAVE_PORT_RIVA,};
+static int sport_kmpss[] = {MSM_BUS_SLAVE_PORT_KMPSS,};
+static int sport_mss[] = {MSM_BUS_SLAVE_PORT_MSS,};
+static int sport_lpass[] = {MSM_BUS_SLAVE_PORT_LPASS,};
+static int sport_mmss_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_MMSS_FPB,};
+
+static int tiered_slave_system_imem[] = {MSM_BUS_TIERED_SLAVE_SYSTEM_IMEM,};
+static int system_tiered_slave_fab_appss[] = {
+	MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS_0,
+};
+
+static struct msm_bus_node_info system_fabric_info[]  = {
+	{
+		.id = MSM_BUS_MASTER_SPS,
+		.masterp = mport_sps,
+		.num_mports = ARRAY_SIZE(mport_sps),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM_PORT0,
+		.masterp = mport_adm_port0,
+		.num_mports = ARRAY_SIZE(mport_adm_port0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM_PORT1,
+		.masterp = mport_adm_port1,
+		.num_mports = ARRAY_SIZE(mport_adm_port1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_LPASS_PROC,
+		.masterp = mport_lpass_proc,
+		.num_mports = ARRAY_SIZE(mport_lpass_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS,
+		.masterp = mport_mss,
+		.num_mports = ARRAY_SIZE(mport_mss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_RIVA,
+		.masterp = mport_riva,
+		.num_mports = ARRAY_SIZE(mport_riva),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS_SW_PROC,
+		.masterp = mport_mss_sw_proc,
+		.num_mports = ARRAY_SIZE(mport_mss_sw_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS_FW_PROC,
+		.masterp = mport_mss_fw_proc,
+		.num_mports = ARRAY_SIZE(mport_mss_fw_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_LPASS,
+		.masterp = mport_lpass,
+		.num_mports = ARRAY_SIZE(mport_lpass),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_SYSTEM_MASTER_MMSS_FPB,
+		.masterp = system_mport_mmss_fpb,
+		.num_mports = ARRAY_SIZE(system_mport_mmss_fpb),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM0_CI,
+		.masterp = system_mport_adm_ahb_ci,
+		.num_mports = ARRAY_SIZE(system_mport_adm_ahb_ci),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_FAB_APPSS,
+		.gateway = 1,
+		.slavep = system_sport_appss_fab,
+		.num_sports = ARRAY_SIZE(system_sport_appss_fab),
+		.masterp = appss_mport_fab_system,
+		.num_mports = ARRAY_SIZE(appss_mport_fab_system),
+		.tier = system_tiered_slave_fab_appss,
+		.num_tiers = ARRAY_SIZE(system_tiered_slave_fab_appss),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_FAB_SYSTEM_FPB,
+		.gateway = 1,
+		.slavep = system_sport_system_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_system_fpb),
+		.masterp = mport_system_fpb,
+		.num_mports = ARRAY_SIZE(mport_system_fpb),
+		.buswidth = 4,
+	},
+	{
+		.id = MSM_BUS_FAB_CPSS_FPB,
+		.gateway = 1,
+		.slavep = system_sport_cpss_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_cpss_fpb),
+		.masterp = system_mport_cpss_fpb,
+		.num_mports = ARRAY_SIZE(system_mport_cpss_fpb),
+		.buswidth = 4,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SPS,
+		.slavep = sport_sps,
+		.num_sports = ARRAY_SIZE(sport_sps),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
+		.slavep = sport_system_imem,
+		.num_sports = ARRAY_SIZE(sport_system_imem),
+		.tier = tiered_slave_system_imem,
+		.num_tiers = ARRAY_SIZE(tiered_slave_system_imem),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_CORESIGHT,
+		.slavep = sport_coresight,
+		.num_sports = ARRAY_SIZE(sport_coresight),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RIVA,
+		.slavep = sport_riva,
+		.num_sports = ARRAY_SIZE(sport_riva),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_AMPSS,
+		.slavep = sport_kmpss,
+		.num_sports = ARRAY_SIZE(sport_kmpss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSS,
+		.slavep = sport_mss,
+		.num_sports = ARRAY_SIZE(sport_mss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_LPASS,
+		.slavep = sport_lpass,
+		.num_sports = ARRAY_SIZE(sport_lpass),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SYSTEM_SLAVE_MMSS_FPB,
+		.slavep = sport_mmss_fpb,
+		.num_sports = ARRAY_SIZE(sport_mmss_fpb),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+};
+
+static int mport_mdp[] = {
+	MSM_BUS_MASTER_PORT_MDP_PORT0,
+	MSM_BUS_MASTER_PORT_MDP_PORT1,
+};
+static int mport_mdp1[] = {MSM_BUS_MASTER_PORT_MDP_PORT1,};
+static int mport_rotator[] = {MSM_BUS_MASTER_PORT_ROTATOR,};
+static int mport_graphics_3d[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D,};
+static int mport_vfe[] = {MSM_BUS_MASTER_PORT_VFE,};
+static int mport_vpe[] = {MSM_BUS_MASTER_PORT_VPE,};
+static int mport_jpeg_enc[] = {MSM_BUS_MASTER_PORT_JPEG_ENC,};
+static int mport_hd_codec_port0[] = {MSM_BUS_MASTER_PORT_HD_CODEC_PORT0,};
+static int mport_hd_codec_port1[] = {MSM_BUS_MASTER_PORT_HD_CODEC_PORT1,};
+static int appss_mport_fab_mmss[] = {
+	MSM_BUS_APPSS_MASTER_PORT_FAB_MMSS_0,
+};
+
+static int mmss_sport_apps_fab[] = {
+	MSM_BUS_MMSS_SLAVE_PORT_APPS_FAB_0,
+};
+static int sport_mm_imem[] = {MSM_BUS_SLAVE_PORT_MM_IMEM,};
+
+static int mmss_tiered_slave_fab_apps[] = {
+	MSM_BUS_MMSS_TIERED_SLAVE_FAB_APPS_0,
+};
+static int tiered_slave_mm_imem[] = {MSM_BUS_TIERED_SLAVE_MM_IMEM,};
+
+
+static struct msm_bus_node_info mmss_fabric_info[]  = {
+	{
+		.id = MSM_BUS_MASTER_MDP_PORT0,
+		.masterp = mport_mdp,
+		.num_mports = ARRAY_SIZE(mport_mdp),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MDP_PORT1,
+		.masterp = mport_mdp1,
+		.num_mports = ARRAY_SIZE(mport_mdp1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ROTATOR,
+		.masterp = mport_rotator,
+		.num_mports = ARRAY_SIZE(mport_rotator),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_GRAPHICS_3D,
+		.masterp = mport_graphics_3d,
+		.num_mports = ARRAY_SIZE(mport_graphics_3d),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_VFE,
+		.masterp = mport_vfe,
+		.num_mports = ARRAY_SIZE(mport_vfe),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_VPE,
+		.masterp = mport_vpe,
+		.num_mports = ARRAY_SIZE(mport_vpe),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_JPEG_ENC,
+		.masterp = mport_jpeg_enc,
+		.num_mports = ARRAY_SIZE(mport_jpeg_enc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_HD_CODEC_PORT0,
+		.masterp = mport_hd_codec_port0,
+		.num_mports = ARRAY_SIZE(mport_hd_codec_port0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_HD_CODEC_PORT1,
+		.masterp = mport_hd_codec_port1,
+		.num_mports = ARRAY_SIZE(mport_hd_codec_port1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_FAB_APPSS,
+		.gateway = 1,
+		.slavep = mmss_sport_apps_fab,
+		.num_sports = ARRAY_SIZE(mmss_sport_apps_fab),
+		.masterp = appss_mport_fab_mmss,
+		.num_mports = ARRAY_SIZE(appss_mport_fab_mmss),
+		.tier = mmss_tiered_slave_fab_apps,
+		.num_tiers = ARRAY_SIZE(mmss_tiered_slave_fab_apps),
+		.buswidth = 16,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MM_IMEM,
+		.slavep = sport_mm_imem,
+		.num_sports = ARRAY_SIZE(sport_mm_imem),
+		.tier = tiered_slave_mm_imem,
+		.num_tiers = ARRAY_SIZE(tiered_slave_mm_imem),
+		.buswidth = 8,
+	},
+};
+
+static struct msm_bus_node_info sys_fpb_fabric_info[]  = {
+	{
+		.id = MSM_BUS_FAB_SYSTEM,
+		.gateway = 1,
+		.slavep = system_sport_system_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_system_fpb),
+		.masterp = mport_system_fpb,
+		.num_mports = ARRAY_SIZE(mport_system_fpb),
+		.buswidth = 4,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_MASTER_SPDM,
+		.ahb = 1,
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_RPM,
+		.ahb = 1,
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_SLAVE_SPDM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RPM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RPM_MSG_RAM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MPM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC1_SSBI1_A,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC1_SSBI1_B,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC1_SSBI1_C,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC2_SSBI2_A,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC2_SSBI2_B,
+		.buswidth = 4,
+		.ahb = 1,
+	},
+};
+
+static struct msm_bus_node_info cpss_fpb_fabric_info[] = {
+	{
+		.id = MSM_BUS_FAB_SYSTEM,
+		.gateway = 1,
+		.slavep = system_sport_cpss_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_cpss_fpb),
+		.masterp = system_mport_cpss_fpb,
+		.num_mports = ARRAY_SIZE(system_mport_cpss_fpb),
+		.buswidth = 4,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI1_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI2_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI3_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI4_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI5_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI6_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI7_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI8_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI9_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI10_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI11_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI12_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI1_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI2_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI3_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI4_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI5_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI6_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI7_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI8_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI9_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI10_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI11_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI12_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_NAND,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS0,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS1,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS2,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS3,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS4,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS5,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_USB_FS1,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_USB_FS2,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_TSIF,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_TSSC,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_PDM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_DIMEM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_TCSR,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_PRNG,
+		.buswidth = 4,
+		.ahb = 1,
+	},
+};
+
+static void msm_bus_board_assign_iids(struct msm_bus_fabric_registration
+	*fabreg, int fabid)
+{
+	int i;
+	for (i = 0; i < fabreg->len; i++) {
+		if (!fabreg->info[i].gateway) {
+			fabreg->info[i].priv_id = fabid + fabreg->info[i].id;
+			if (fabreg->info[i].id < SLAVE_ID_KEY)
+				master_iids[fabreg->info[i].id] =
+					fabreg->info[i].priv_id;
+			else
+				slave_iids[fabreg->info[i].id - (SLAVE_ID_KEY)]
+					= fabreg->info[i].priv_id;
+		} else
+			fabreg->info[i].priv_id = fabreg->info[i].id;
+	}
+}
+
+static int msm_bus_board_8930_get_iid(int id)
+{
+	if ((id < SLAVE_ID_KEY && id >= NMASTERS) ||
+		id >= (SLAVE_ID_KEY + NSLAVES)) {
+		MSM_BUS_ERR("Cannot get iid. Invalid id %d passed\n", id);
+		return -EINVAL;
+	}
+
+	return CHECK_ID(((id < SLAVE_ID_KEY) ? master_iids[id] :
+		slave_iids[id - SLAVE_ID_KEY]), id);
+}
+
+static struct msm_bus_board_algorithm msm_bus_board_algo = {
+	.board_nfab = NFAB_8930,
+	.get_iid = msm_bus_board_8930_get_iid,
+	.assign_iids = msm_bus_board_assign_iids,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_apps_fabric_pdata = {
+	.id = MSM_BUS_FAB_APPSS,
+	.name = "msm_apps_fab",
+	.info = apps_fabric_info,
+	.len = ARRAY_SIZE(apps_fabric_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.haltid = MSM_RPM_ID_APPS_FABRIC_CFG_HALT_0,
+	.offset = MSM_RPM_ID_APPS_FABRIC_ARB_0,
+	.nmasters = 4,
+	.nslaves = 4,
+	.ntieredslaves = 2,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_sys_fabric_pdata = {
+	.id = MSM_BUS_FAB_SYSTEM,
+	.name = "msm_sys_fab",
+	system_fabric_info,
+	ARRAY_SIZE(system_fabric_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.haltid = MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0,
+	.offset = MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
+	.nmasters = 14,
+	.nslaves = 11,
+	.ntieredslaves = 2,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_mm_fabric_pdata = {
+	.id = MSM_BUS_FAB_MMSS,
+	.name = "msm_mm_fab",
+	mmss_fabric_info,
+	ARRAY_SIZE(mmss_fabric_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.haltid = MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
+	.offset = MSM_RPM_ID_MM_FABRIC_ARB_0,
+	.nmasters = 10,
+	.nslaves = 2,
+	.ntieredslaves = 2,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_sys_fpb_pdata = {
+	.id = MSM_BUS_FAB_SYSTEM_FPB,
+	.name = "msm_sys_fpb",
+	sys_fpb_fabric_info,
+	ARRAY_SIZE(sys_fpb_fabric_info),
+	.ahb = 1,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.nmasters = 0,
+	.nslaves = 0,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_cpss_fpb_pdata = {
+	.id = MSM_BUS_FAB_CPSS_FPB,
+	.name = "msm_cpss_fpb",
+	cpss_fpb_fabric_info,
+	ARRAY_SIZE(cpss_fpb_fabric_info),
+	.ahb = 1,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.nmasters = 0,
+	.nslaves = 0,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+};
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index f93a79b..6e79dfe 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/memory_alloc.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -64,7 +65,6 @@
 #endif
 
 struct msm_rtb_state msm_rtb = {
-	.size = SZ_1M,
 	.filter = 1 << LOGK_LOGBUF,
 };
 
@@ -107,16 +107,6 @@
 	start->data = data;
 }
 
-static int __init msm_rtb_set_buffer_size(char *p)
-{
-	int s;
-
-	s = memparse(p, NULL);
-	msm_rtb.size = ALIGN(s, SZ_4K);
-	return 0;
-}
-early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-
 #if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
 static int msm_rtb_get_idx(void)
 {
@@ -178,12 +168,15 @@
 }
 EXPORT_SYMBOL(uncached_logk);
 
-int msm_rtb_init(void)
+int msm_rtb_probe(struct platform_device *pdev)
 {
+	struct msm_rtb_platform_data *d = pdev->dev.platform_data;
 #if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
 	unsigned int cpu;
 #endif
 
+	msm_rtb.size = d->size;
+
 	if (msm_rtb.size <= 0 || msm_rtb.size > SZ_1M)
 		return -EINVAL;
 
@@ -227,4 +220,22 @@
 	msm_rtb.enabled = 1;
 	return 0;
 }
+
+static struct platform_driver msm_rtb_driver = {
+	.driver         = {
+		.name = "msm_rtb",
+		.owner = THIS_MODULE
+	},
+};
+
+static int __init msm_rtb_init(void)
+{
+	return platform_driver_probe(&msm_rtb_driver, msm_rtb_probe);
+}
+
+static void __exit msm_rtb_exit(void)
+{
+	platform_driver_unregister(&msm_rtb_driver);
+}
 module_init(msm_rtb_init)
+module_exit(msm_rtb_exit)
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 6ec9b5d..26b97fa 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -25,6 +25,7 @@
 
 #include <mach/msm_iomap.h>
 #include <mach/msm_xo.h>
+#include <mach/socinfo.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -42,14 +43,8 @@
 #define GSS_CLAMP_ENA		(MSM_CLK_CTL_BASE + 0x2C68)
 #define GSS_CXO_SRC_CTL		(MSM_CLK_CTL_BASE + 0x2C74)
 
-#define PLL5_MODE		(MSM_CLK_CTL_BASE + 0x30E0)
-#define PLL5_L_VAL		(MSM_CLK_CTL_BASE + 0x30E4)
-#define PLL5_M_VAL		(MSM_CLK_CTL_BASE + 0x30E8)
-#define PLL5_N_VAL		(MSM_CLK_CTL_BASE + 0x30EC)
-#define PLL5_CONFIG		(MSM_CLK_CTL_BASE + 0x30F4)
 #define PLL5_STATUS		(MSM_CLK_CTL_BASE + 0x30F8)
 #define PLL_ENA_GSS		(MSM_CLK_CTL_BASE + 0x3480)
-#define PLL_ENA_RPM		(MSM_CLK_CTL_BASE + 0x34A0)
 
 #define PLL5_VOTE		BIT(5)
 #define PLL_STATUS		BIT(16)
@@ -142,13 +137,17 @@
 	writel_relaxed(A5_RESET, base + GSS_CSR_RESET);
 }
 
-static void setup_qgic2_bus_access(void *data)
+static void cfg_qgic2_bus_access(void *data)
 {
 	struct gss_data *drv = data;
-	void __iomem *base = drv->base;
 	int i;
 
-	writel_relaxed(0x2, base + GSS_CSR_CFG_HID);
+	/*
+	 * Apply a 8064 v1.0 workaround to configure QGIC bus access.
+	 * This must be done from Krait 0 to configure the Master ID
+	 * correctly.
+	 */
+	writel_relaxed(0x2, drv->base + GSS_CSR_CFG_HID);
 	for (i = 0; i <= 3; i++)
 		readl_relaxed(drv->qgic2_base);
 }
@@ -233,15 +232,15 @@
 	while (!(readl_relaxed(base + GSS_CSR_POWER_UP_DOWN) & A5_POWER_STATUS))
 		cpu_relax();
 
-	/*
-	 * Apply a 8064 v1.0 workaround to configure QGIC bus access. This must
-	 * be done from Krait 0 to configure the Master ID correctly.
-	 */
-	ret = smp_call_function_single(0, setup_qgic2_bus_access, drv, 1);
-	if (ret) {
-		pr_err("Failed to configure QGIC2 bus access\n");
-		pil_gss_shutdown(pil);
-		return ret;
+	if (cpu_is_apq8064() &&
+	    ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) &&
+	     (SOCINFO_VERSION_MINOR(socinfo_get_version()) == 0))) {
+		ret = smp_call_function_single(0, cfg_qgic2_bus_access, drv, 1);
+		if (ret) {
+			pr_err("Failed to configure QGIC2 bus access\n");
+			pil_gss_shutdown(pil);
+			return ret;
+		}
 	}
 
 	/* Release A5 from reset. */
@@ -263,6 +262,28 @@
 	return pas_init_image(PAS_GSS, metadata, size);
 }
 
+static int pil_gss_shutdown_trusted(struct pil_desc *pil)
+{
+	struct gss_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+
+	/*
+	 * CXO is used in the secure shutdown code to configure the processor
+	 * for low power mode.
+	 */
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable XO\n");
+		return ret;
+	}
+
+	ret = pas_shutdown(PAS_GSS);
+	clk_disable_unprepare(drv->xo);
+	remove_gss_proxy_votes_now(drv);
+
+	return ret;
+}
+
 static int pil_gss_reset_trusted(struct pil_desc *pil)
 {
 	struct gss_data *drv = dev_get_drvdata(pil->dev);
@@ -276,23 +297,26 @@
 	if (err)
 		remove_gss_proxy_votes_now(drv);
 
+	if (cpu_is_apq8064() &&
+	    ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) &&
+	     (SOCINFO_VERSION_MINOR(socinfo_get_version()) == 0))) {
+		err = smp_call_function_single(0, cfg_qgic2_bus_access, drv, 1);
+		if (err) {
+			pr_err("Failed to configure QGIC2 bus access\n");
+			pil_gss_shutdown_trusted(pil);
+			return err;
+		}
+		/*
+		 * On 8064v1.0, pas_auth_and_reset() will not release the A5
+		 * from reset. Linux must do this after cfg_qgic2_bus_access()
+		 * is called on CPU0.
+		 */
+		writel_relaxed(0x0, drv->base + GSS_CSR_RESET);
+	}
+
 	return err;
 }
 
-static int pil_gss_shutdown_trusted(struct pil_desc *pil)
-{
-	struct gss_data *drv = dev_get_drvdata(pil->dev);
-	int ret;
-
-	ret = pas_shutdown(PAS_GSS);
-	if (ret)
-		return ret;
-
-	remove_gss_proxy_votes_now(drv);
-
-	return ret;
-}
-
 static struct pil_reset_ops pil_gss_ops_trusted = {
 	.init_image = pil_gss_init_image_trusted,
 	.verify_blob = nop_verify_blob,
@@ -300,63 +324,6 @@
 	.shutdown = pil_gss_shutdown_trusted,
 };
 
-static void configure_gss_pll(struct gss_data *drv)
-{
-	u32 regval, is_pll_enabled;
-
-	/* Check if PLL5 is enabled by FSM. */
-	is_pll_enabled = readl_relaxed(PLL5_STATUS) & PLL_STATUS;
-	if (!is_pll_enabled) {
-		/* Enable XO reference for PLL5 */
-		clk_prepare_enable(drv->xo);
-
-		/*
-		 * Assert a vote to hold PLL5 on in RPM register until other
-		 * voters are in place.
-		 */
-		regval = readl_relaxed(PLL_ENA_RPM);
-		regval |= PLL5_VOTE;
-		writel_relaxed(regval, PLL_ENA_RPM);
-
-		/* Ref clk = 27MHz and program pll5 to 288MHz */
-		writel_relaxed(0xF, PLL5_L_VAL);
-		writel_relaxed(0x0, PLL5_M_VAL);
-		writel_relaxed(0x1, PLL5_N_VAL);
-
-		regval = readl_relaxed(PLL5_CONFIG);
-		/* Disable the MN accumulator and enable the main output. */
-		regval &= ~BIT(22);
-		regval |= BIT(23);
-
-		/* Set pre-divider and post-divider values to 1 and 1 */
-		regval &= ~BIT(19);
-		regval &= ~(BIT(21)|BIT(20));
-
-		/* Set VCO frequency */
-		regval &= ~(BIT(17)|BIT(16));
-		writel_relaxed(regval, PLL5_CONFIG);
-
-		regval = readl_relaxed(PLL5_MODE);
-		/* De-assert reset to FSM */
-		regval &= ~BIT(21);
-		writel_relaxed(regval, PLL5_MODE);
-
-		/* Program bias count */
-		regval &= ~(0x3F << 14);
-		regval |= (0x1 << 14);
-		writel_relaxed(regval, PLL5_MODE);
-
-		/* Program lock count */
-		regval &= ~(0x3F << 8);
-		regval |= (0x8 << 8);
-		writel_relaxed(regval, PLL5_MODE);
-
-		/* Enable PLL FSM voting */
-		regval |= BIT(20);
-		writel_relaxed(regval, PLL5_MODE);
-	}
-}
-
 static int __devinit pil_gss_probe(struct platform_device *pdev)
 {
 	struct gss_data *drv;
@@ -407,9 +374,6 @@
 
 	INIT_DELAYED_WORK(&drv->work, remove_gss_proxy_votes);
 
-	/* FIXME: Remove when PLL is configured by bootloaders. */
-	configure_gss_pll(drv);
-
 	ret = msm_pil_register(desc);
 	if (ret) {
 		flush_delayed_work_sync(&drv->work);
diff --git a/arch/arm/mach-msm/pil-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
index 511377d..b0bce02 100644
--- a/arch/arm/mach-msm/pil-q6v4.c
+++ b/arch/arm/mach-msm/pil-q6v4.c
@@ -29,11 +29,10 @@
 #include "pil-q6v4.h"
 #include "scm-pas.h"
 
-#define PROXY_VOTE_TIMEOUT	40000
+#define PROXY_VOTE_TIMEOUT	10000
 
 #define QDSP6SS_RST_EVB		0x0
 #define QDSP6SS_RESET		0x04
-#define QDSP6SS_CGC_OVERRIDE	0x18
 #define QDSP6SS_STRAP_TCM	0x1C
 #define QDSP6SS_STRAP_AHB	0x20
 #define QDSP6SS_GFMUX_CTL	0x30
@@ -62,7 +61,6 @@
 
 #define Q6SS_CLK_ENA		BIT(1)
 #define Q6SS_SRC_SWITCH_CLK_OVR	BIT(8)
-#define Q6SS_AXIS_ACLK_EN	BIT(9)
 
 struct q6v4_data {
 	void __iomem *base;
@@ -220,15 +218,6 @@
 	if (err)
 		dev_err(pil->dev, "Failed to unhalt bus port\n");
 
-	/*
-	 * Assert AXIS_ACLK_EN override to allow for correct updating of the
-	 * QDSP6_CORE_STATE status bit. This is mandatory only for the SW Q6
-	 * in 8960v1 and optional elsewhere.
-	 */
-	reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
-	reg |= Q6SS_AXIS_ACLK_EN;
-	writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);
-
 	/* Deassert Q6SS_SS_ARES */
 	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
 	reg &= ~(Q6SS_SS_ARES);
@@ -278,16 +267,6 @@
 	/* Bring Q6 core out of reset and start execution. */
 	writel_relaxed(0x0, drv->base + QDSP6SS_RESET);
 
-	/*
-	 * Re-enable auto-gating of AXIS_ACLK at lease one AXI clock cycle
-	 * after resets are de-asserted.
-	 */
-	mb();
-	usleep_range(1, 10);
-	reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
-	reg &= ~Q6SS_AXIS_ACLK_EN;
-	writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
new file mode 100644
index 0000000..534fc0e
--- /dev/null
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -0,0 +1,202 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/smp_scu.h>
+#include <asm/unified.h>
+#include <mach/msm_iomap.h>
+#include <mach/smp.h>
+#include "pm.h"
+
+#define MSM_CORE1_RESET		0xA8600590
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+int pen_release = -1;
+
+static bool cold_boot_done;
+
+static uint32_t *msm8625_boot_vector;
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void __cpuinit write_pen_release(int val)
+{
+	pen_release = val;
+	smp_wmb();
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static void __iomem *scu_base_addr(void)
+{
+	return MSM_SCU_BASE;
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_secondary_init(0);
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+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)
+			return -ENODEV;
+		/* Reset core 1 out of reset */
+		__raw_writel(0x0, base_ptr);
+		mb();
+		cold_boot_done = true;
+		iounmap(base_ptr);
+	}
+
+	/*
+	 * Set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * This is really belt and braces; we hold unintended secondary
+	 * CPUs in the holding pen until we're ready for them.  However,
+	 * since we haven't sent them a soft interrupt, they shouldn't
+	 * be there.
+	 */
+	write_pen_release(cpu);
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+	gic_raise_softirq(cpumask_of(cpu), 1);
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	void __iomem *scu_base = scu_base_addr();
+
+	unsigned int i, ncores;
+
+	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+static void __init msm8625_boot_vector_init(uint32_t *boot_vector,
+		unsigned long entry)
+{
+	if (!boot_vector)
+		return;
+	msm8625_boot_vector = boot_vector;
+
+	msm8625_boot_vector[0] = 0xE51FF004; /* ldr pc, 4 */
+	msm8625_boot_vector[1] = entry;
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i, value;
+	void __iomem *second_ptr;
+
+	/*
+	 * Initialise the present map, which describes the set of CPUs
+	 * actually populated at the present time.
+	 */
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+
+	scu_enable(scu_base_addr());
+
+	/*
+	 * Write the address of secondary startup into the
+	 * boot remapper register. The secondary CPU branches to this address.
+	 */
+	__raw_writel(MSM8625_SECONDARY_PHYS, (MSM_CFG_CTL_BASE + 0x34));
+	mb();
+
+	second_ptr = ioremap_nocache(MSM8625_SECONDARY_PHYS, SZ_8);
+	if (!second_ptr) {
+		pr_err("failed to ioremap for secondary core\n");
+		return;
+	}
+
+	msm8625_boot_vector_init(second_ptr,
+			virt_to_phys(msm_secondary_startup));
+	iounmap(second_ptr);
+
+	/* Enable boot remapper address: bit 26 for core1 */
+	value = __raw_readl(MSM_CFG_CTL_BASE + 0x30);
+	__raw_writel(value | (0x4 << 24), MSM_CFG_CTL_BASE + 0x30) ;
+	mb();
+}
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index b3c6d1e..ad235de 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -655,6 +655,10 @@
 	void *entry;
 	bool collapsed = 0;
 	int ret;
+	unsigned int saved_gic_cpu_ctrl;
+
+	saved_gic_cpu_ctrl = readl_relaxed(MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+	mb();
 
 	if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: notify_rpm %d\n",
@@ -686,7 +690,9 @@
 #endif
 		cpu_init();
 		writel(0xF0, MSM_QGIC_CPU_BASE + GIC_CPU_PRIMASK);
-		writel(1, MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+		writel_relaxed(saved_gic_cpu_ctrl,
+				MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+		mb();
 		local_fiq_enable();
 	}
 
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index e1934bb..7977d22 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1668,6 +1668,13 @@
 	.valid = suspend_valid_only_mem,
 };
 
+/* Hotplug the "non boot" CPU's and put
+ * the cores into low power mode
+ */
+void msm_pm_cpu_enter_lowpower(unsigned int cpu)
+{
+	return;
+}
 
 /******************************************************************************
  * Restart Definitions
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index 81d4e5b..1f82468 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.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
@@ -14,24 +14,28 @@
 #include <asm/pmu.h>
 #include <mach/irqs.h>
 
-static struct resource cpu_pmu_resource = {
-	.start = INT_ARMQC_PERFMON,
-	.end = INT_ARMQC_PERFMON,
-	.flags	= IORESOURCE_IRQ,
+static struct resource cpu_pmu_resource[] = {
+	{
+		.start = INT_ARMQC_PERFMON,
+		.end = INT_ARMQC_PERFMON,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 #ifdef CONFIG_CPU_HAS_L2_PMU
-static struct resource l2_pmu_resource = {
-	.start = SC_SICL2PERFMONIRPTREQ,
-	.end = SC_SICL2PERFMONIRPTREQ,
-	.flags = IORESOURCE_IRQ,
+static struct resource l2_pmu_resource[] = {
+	{
+		.start = SC_SICL2PERFMONIRPTREQ,
+		.end = SC_SICL2PERFMONIRPTREQ,
+		.flags = IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device l2_pmu_device = {
 	.name		= "l2-arm-pmu",
 	.id		= ARM_PMU_DEVICE_L2,
-	.resource	= &l2_pmu_resource,
-	.num_resources	= 1,
+	.resource	= l2_pmu_resource,
+	.num_resources	= ARRAY_SIZE(l2_pmu_resource),
 };
 
 #endif
@@ -39,8 +43,8 @@
 static struct platform_device cpu_pmu_device = {
 	.name		= "cpu-arm-pmu",
 	.id		= ARM_PMU_DEVICE_CPU,
-	.resource	= &cpu_pmu_resource,
-	.num_resources	= 1,
+	.resource	= cpu_pmu_resource,
+	.num_resources	= ARRAY_SIZE(cpu_pmu_resource),
 };
 
 static struct platform_device *pmu_devices[] = {
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index 33c5a53..1bf2a55 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -3,7 +3,7 @@
  * Register/Interrupt access for userspace aDSP library.
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-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
@@ -280,6 +280,7 @@
 	int rc = 0;
 	static uint32_t init_info_cmd_sent;
 
+	mutex_lock(&adsp_info.lock);
 	if (!init_info_cmd_sent) {
 		init_waitqueue_head(&adsp_info.init_info_wait);
 		msm_get_init_info();
@@ -288,10 +289,13 @@
 			5 * HZ);
 		if (!rc) {
 			MM_ERR("INIT_INFO failed\n");
+			mutex_unlock(&adsp_info.lock);
 			return -ETIMEDOUT;
+
 		}
 		init_info_cmd_sent++;
 	}
+	mutex_unlock(&adsp_info.lock);
 
 	module = find_adsp_module_by_name(&adsp_info, name);
 	if (!module)
@@ -1016,16 +1020,49 @@
 
 int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate)
 {
+	if (!module)
+		return -EINVAL;
+
 	if (module->clk && clk_rate)
 		return clk_set_rate(module->clk, clk_rate);
 
 	return -EINVAL;
 }
 
+int msm_adsp_generate_event(void *data,
+			struct msm_adsp_module *mod,
+			unsigned event_id,
+			unsigned event_length,
+			unsigned event_size,
+			void *msg)
+{
+	unsigned long flags;
+	void (*func)(void *, size_t);
+
+	if (!mod)
+		return -EINVAL;
+
+	if (event_size == sizeof(uint32_t))
+		func = read_event_32;
+	else if (event_size == sizeof(uint16_t))
+		func = read_event_16;
+	else
+		return -EINVAL;
+
+	spin_lock_irqsave(&adsp_cmd_lock, flags);
+	read_event_addr = msg;
+	mod->ops->event(data, event_id, event_length, func);
+	spin_unlock_irqrestore(&adsp_cmd_lock, flags);
+	return 0;
+}
+
 int msm_adsp_enable(struct msm_adsp_module *module)
 {
 	int rc = 0;
 
+	if (!module)
+		return -EINVAL;
+
 	MM_INFO("enable '%s'state[%d] id[%d]\n",
 				module->name, module->state, module->id);
 
@@ -1078,6 +1115,9 @@
 {
 	int rc = 0;
 
+	if (!module)
+		return -EINVAL;
+
 	mutex_lock(&module->lock);
 
 	rc = rpc_adsp_rtos_app_to_modem(RPC_ADSP_RTOS_CMD_DISABLE_EVENT_RSP,
@@ -1092,6 +1132,9 @@
 {
 	int rc = 0;
 
+	if (!module)
+		return -EINVAL;
+
 	switch (module->state) {
 	case ADSP_STATE_DISABLED:
 		MM_DBG("module '%s' already disabled\n", module->name);
@@ -1117,6 +1160,10 @@
 int msm_adsp_disable(struct msm_adsp_module *module)
 {
 	int rc;
+
+	if (!module)
+		return -EINVAL;
+
 	MM_INFO("disable '%s'\n", module->name);
 	mutex_lock(&module->lock);
 	rc = msm_adsp_disable_locked(module);
@@ -1157,6 +1204,7 @@
 
 	spin_lock_init(&adsp_cmd_lock);
 	spin_lock_init(&adsp_write_lock);
+	mutex_init(&adsp_info.lock);
 
 	rc = request_irq(INT_ADSP, adsp_irq_handler, IRQF_TRIGGER_RISING,
 			 "adsp", 0);
diff --git a/arch/arm/mach-msm/qdsp5/adsp.h b/arch/arm/mach-msm/qdsp5/adsp.h
index 0ef27b9..8e5a4f3 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.h
+++ b/arch/arm/mach-msm/qdsp5/adsp.h
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/qdsp5/adsp.h
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2010, 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
@@ -117,6 +117,7 @@
 	struct adsp_rtos_mp_mtoa_init_info_type	*init_info_ptr;
 	wait_queue_head_t	init_info_wait;
 	unsigned 		init_info_state;
+	struct mutex lock;
 };
 
 #define RPC_ADSP_RTOS_ATOM_NULL_PROC 0
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac.c b/arch/arm/mach-msm/qdsp5/audio_aac.c
index 5e1e655..de756eb 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac.c
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -298,6 +298,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		wake_up(&audio->read_wait);
 		msm_adsp_disable(audio->audplay);
@@ -672,24 +673,31 @@
 
 static void audio_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->reserved = 0;
 	audio->out_needed = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	atomic_set(&audio->out_bytes, 0);
 }
 
 static void audio_flush_pcm_buf(struct audio *audio)
 {
 	uint8_t index;
+	unsigned long flags;
 
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 		audio->in[index].used = 0;
 	audio->buf_refresh = 0;
 	audio->read_next = 0;
 	audio->fill_next = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static int audaac_validate_usr_config(struct msm_audio_aac_config *config)
@@ -990,7 +998,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audio_disable(audio);
-		audio->stopped = 1;
 		audio_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac_in.c b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
index c9e60d8..456a8ff 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
@@ -2,7 +2,7 @@
  *
  * aac audio input device
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_aac_in.c,
  * Copyright (C) 2008 Google, Inc.
@@ -320,9 +320,10 @@
 
 		audaac_in_dsp_enable(audio, 0);
 
-		wake_up(&audio->wait);
 		wait_event_interruptible_timeout(audio->wait_enable,
 				audio->running == 0, 1*HZ);
+		audio->stopped = 1;
+		wake_up(&audio->wait);
 		msm_adsp_disable(audio->audrec);
 		if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
 			msm_adsp_disable(audio->audpre);
@@ -697,21 +698,23 @@
 	 * sleep and knowing that system is not able
 	 * to process io request at the moment
 	 */
-	wake_up(&audio->write_wait);
-	mutex_lock(&audio->write_lock);
-	audaac_in_flush(audio);
-	mutex_unlock(&audio->write_lock);
 	wake_up(&audio->wait);
 	mutex_lock(&audio->read_lock);
-	audaac_out_flush(audio);
+	audaac_in_flush(audio);
 	mutex_unlock(&audio->read_lock);
+	wake_up(&audio->write_wait);
+	mutex_lock(&audio->write_lock);
+	audaac_out_flush(audio);
+	mutex_unlock(&audio->write_lock);
 }
 
 static void audaac_in_flush(struct audio_aac_in *audio)
 {
 	int i;
+	unsigned long flags;
 
 	audio->dsp_cnt = 0;
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->in_head = 0;
 	audio->in_tail = 0;
 	audio->in_count = 0;
@@ -720,6 +723,7 @@
 		audio->in[i].size = 0;
 		audio->in[i].read = 0;
 	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
 	MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
 	atomic_set(&audio->in_bytes, 0);
@@ -729,15 +733,18 @@
 static void audaac_out_flush(struct audio_aac_in *audio)
 {
 	int i;
+	unsigned long flags;
 
 	audio->out_head = 0;
-	audio->out_tail = 0;
 	audio->out_count = 0;
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+	audio->out_tail = 0;
 	for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
 		audio->out[i].size = 0;
 		audio->out[i].read = 0;
 		audio->out[i].used = 0;
 	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 /* ------------------- device --------------------- */
@@ -777,7 +784,6 @@
 	}
 	case AUDIO_STOP: {
 		rc = audaac_in_disable(audio);
-		audio->stopped = 1;
 		break;
 	}
 	case AUDIO_FLUSH: {
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 476a63d..d66a270 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -2,7 +2,7 @@
  *
  * amrnb audio decoder device
  *
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
  *
  * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
  *
@@ -302,6 +302,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		wake_up(&audio->read_wait);
 		msm_adsp_disable(audio->audplay);
@@ -628,24 +629,31 @@
 
 static void audamrnb_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->out_needed = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	atomic_set(&audio->out_bytes, 0);
 }
 
 static void audamrnb_flush_pcm_buf(struct audio *audio)
 {
 	uint8_t index;
+	unsigned long flags;
 
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 		audio->in[index].used = 0;
 
 	audio->buf_refresh = 0;
 	audio->read_next = 0;
 	audio->fill_next = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static void audamrnb_ioport_reset(struct audio *audio)
@@ -876,7 +884,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audamrnb_disable(audio);
-		audio->stopped = 1;
 		audamrnb_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrwb.c b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
index e811731..b566c60 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2011-2012 Code Aurora Forum. All rights reserved.
  *
  * All source code in this file is licensed under the following license except
  * where indicated.
@@ -299,6 +299,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		wake_up(&audio->read_wait);
 		msm_adsp_disable(audio->audplay);
@@ -616,25 +617,32 @@
 
 static void audamrwb_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->reserved = 0;
 	audio->out_needed = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	atomic_set(&audio->out_bytes, 0);
 }
 
 static void audamrwb_flush_pcm_buf(struct audio *audio)
 {
 	uint8_t index;
+	unsigned long flags;
 
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 		audio->in[index].used = 0;
 
 	audio->buf_refresh = 0;
 	audio->read_next = 0;
 	audio->fill_next = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static void audamrwb_ioport_reset(struct audio *audio)
@@ -865,7 +873,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audamrwb_disable(audio);
-		audio->stopped = 1;
 		audamrwb_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc.c b/arch/arm/mach-msm/qdsp5/audio_evrc.c
index 3c39b6d..86035db 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc.c
@@ -1,6 +1,6 @@
 /* arch/arm/mach-msm/audio_evrc.c
  *
- * Copyright (c) 2008-2009, 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
  *
  * This code also borrows from audio_aac.c, which is
  * Copyright (C) 2008 Google, Inc.
@@ -291,6 +291,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		wake_up(&audio->read_wait);
 		msm_adsp_disable(audio->audplay);
@@ -615,24 +616,30 @@
 
 static void audevrc_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->out_needed = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	atomic_set(&audio->out_bytes, 0);
 }
 
 static void audevrc_flush_pcm_buf(struct audio *audio)
 {
 	uint8_t index;
+	unsigned long flags;
 
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 		audio->in[index].used = 0;
-
 	audio->buf_refresh = 0;
 	audio->read_next = 0;
 	audio->fill_next = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static void audevrc_ioport_reset(struct audio *audio)
@@ -863,7 +870,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audevrc_disable(audio);
-		audio->stopped = 1;
 		audevrc_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
index 7a5536a..0bdbf5d 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
@@ -2,7 +2,7 @@
  *
  * evrc audio input device
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c,
  * Copyright (C) 2008 Google, Inc.
@@ -281,6 +281,8 @@
 		wake_up(&audio->wait);
 		wait_event_interruptible_timeout(audio->wait_enable,
 				audio->running == 0, 1*HZ);
+		audio->stopped = 1;
+		wake_up(&audio->wait);
 		msm_adsp_disable(audio->audrec);
 		if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
 			msm_adsp_disable(audio->audpre);
@@ -655,21 +657,23 @@
 	 * sleep and knowing that system is not able
 	 * to process io request at the moment
 	 */
-	wake_up(&audio->write_wait);
-	mutex_lock(&audio->write_lock);
-	audevrc_in_flush(audio);
-	mutex_unlock(&audio->write_lock);
 	wake_up(&audio->wait);
 	mutex_lock(&audio->read_lock);
-	audevrc_out_flush(audio);
+	audevrc_in_flush(audio);
 	mutex_unlock(&audio->read_lock);
+	wake_up(&audio->write_wait);
+	mutex_lock(&audio->write_lock);
+	audevrc_out_flush(audio);
+	mutex_unlock(&audio->write_lock);
 }
 
 static void audevrc_in_flush(struct audio_evrc_in *audio)
 {
 	int i;
+	unsigned long flags;
 
 	audio->dsp_cnt = 0;
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->in_head = 0;
 	audio->in_tail = 0;
 	audio->in_count = 0;
@@ -678,6 +682,7 @@
 		audio->in[i].size = 0;
 		audio->in[i].read = 0;
 	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
 	MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
 	atomic_set(&audio->in_bytes, 0);
@@ -687,15 +692,18 @@
 static void audevrc_out_flush(struct audio_evrc_in *audio)
 {
 	int i;
+	unsigned long flags;
 
 	audio->out_head = 0;
-	audio->out_tail = 0;
 	audio->out_count = 0;
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+	audio->out_tail = 0;
 	for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
 		audio->out[i].size = 0;
 		audio->out[i].read = 0;
 		audio->out[i].used = 0;
 	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 /* ------------------- device --------------------- */
@@ -735,7 +743,6 @@
 	}
 	case AUDIO_STOP: {
 		rc = audevrc_in_disable(audio);
-		audio->stopped = 1;
 		break;
 	}
 	case AUDIO_FLUSH: {
diff --git a/arch/arm/mach-msm/qdsp5/audio_mp3.c b/arch/arm/mach-msm/qdsp5/audio_mp3.c
index c4b464a..f6fa62a 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mp3.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 software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -368,6 +368,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		wake_up(&audio->read_wait);
 		msm_adsp_disable(audio->audplay);
@@ -853,12 +854,16 @@
 
 static void audio_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->reserved = 0;
 	audio->out_needed = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	atomic_set(&audio->out_bytes, 0);
 }
 
@@ -885,13 +890,15 @@
 static void audio_flush_pcm_buf(struct audio *audio)
 {
 	uint8_t index;
+	unsigned long flags;
 
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 		audio->in[index].used = 0;
-
 	audio->buf_refresh = 0;
 	audio->read_next = 0;
 	audio->fill_next = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static void audio_ioport_reset(struct audio *audio)
@@ -1366,7 +1373,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audio_disable(audio);
-		audio->stopped = 1;
 		audio_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_mvs.c b/arch/arm/mach-msm/qdsp5/audio_mvs.c
index 9c27485..5ccd18b 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mvs.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mvs.c
@@ -25,7 +25,7 @@
 
 #define MVS_PROG 0x30000014
 #define MVS_VERS 0x00030001
-#define MVS_VERS_COMP_VER2 0x00020001
+#define MVS_VERS_COMP_VER2 0x00060001
 #define MVS_VERS_COMP_VER3 0x00030001
 
 
@@ -67,6 +67,8 @@
 #define MVS_FRAME_MODE_G711_DL 10
 #define MVS_FRAME_MODE_PCM_UL 13
 #define MVS_FRAME_MODE_PCM_DL 14
+#define MVS_FRAME_MODE_PCM_WB_UL 23
+#define MVS_FRAME_MODE_PCM_WB_DL 24
 #define MVS_FRAME_MODE_G729A_UL 17
 #define MVS_FRAME_MODE_G729A_DL 18
 #define MVS_FRAME_MODE_G711A_UL 19
@@ -404,6 +406,11 @@
 		audio->frame_mode = MVS_FRAME_MODE_PCM_DL;
 		break;
 	}
+	case MVS_MODE_PCM_WB: {
+		audio->rate_type = MVS_AMR_MODE_UNDEF;
+		audio->frame_mode = MVS_FRAME_MODE_PCM_WB_DL;
+		break;
+	}
 	case MVS_MODE_IS127:
 	case MVS_MODE_IS733:
 	case MVS_MODE_4GV_NB:
diff --git a/arch/arm/mach-msm/qdsp5/audio_out.c b/arch/arm/mach-msm/qdsp5/audio_out.c
index 7c56037..7d33e05 100644
--- a/arch/arm/mach-msm/qdsp5/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5/audio_out.c
@@ -247,6 +247,7 @@
 
 		audpp_disable(-1, audio);
 
+		audio->stopped = 1;
 		wake_up(&audio->wait);
 		audmgr_disable(&audio->audmgr);
 		audio->out_needed = 0;
@@ -519,7 +520,6 @@
 		break;
 	case AUDIO_STOP:
 		rc = audio_disable(audio);
-		audio->stopped = 1;
 		break;
 	case AUDIO_FLUSH:
 		if (audio->stopped) {
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm.c b/arch/arm/mach-msm/qdsp5/audio_pcm.c
index 02103fc..6468e93 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm.c
@@ -1,7 +1,7 @@
 
 /* audio_pcm.c - pcm audio decoder driver
  *
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * Based on the mp3 decoder driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
  *
@@ -336,6 +336,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		msm_adsp_disable(audio->audplay);
 		audpp_disable(audio->dec_id, audio);
@@ -639,12 +640,16 @@
 
 static void audio_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->reserved = 0;
 	audio->out_needed = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	atomic_set(&audio->out_bytes, 0);
 }
 
@@ -1041,7 +1046,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audio_disable(audio);
-		audio->stopped = 1;
 		audio_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 81813a0..16c70ce 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -218,6 +218,7 @@
 
 		audpcm_in_dsp_enable(audio, 0);
 
+		audio->stopped = 1;
 		wake_up(&audio->wait);
 
 		msm_adsp_disable(audio->audrec);
@@ -613,7 +614,6 @@
 	}
 	case AUDIO_STOP:
 		rc = audpcm_in_disable(audio);
-		audio->stopped = 1;
 		break;
 	case AUDIO_FLUSH:
 		if (audio->stopped) {
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp.c b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
index b12e713..2be5144 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
@@ -2,7 +2,7 @@
  *
  * qcelp 13k audio decoder device
  *
- * Copyright (c) 2008-2009, 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
  *
  * This code is based in part on audio_mp3.c, which is
  * Copyright (C) 2008 Google, Inc.
@@ -288,6 +288,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		wake_up(&audio->read_wait);
 		msm_adsp_disable(audio->audplay);
@@ -612,23 +613,30 @@
 
 static void audqcelp_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->out_needed = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static void audqcelp_flush_pcm_buf(struct audio *audio)
 {
 	uint8_t index;
+	unsigned long flags;
 
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 		audio->in[index].used = 0;
 
 	audio->buf_refresh = 0;
 	audio->read_next = 0;
 	audio->fill_next = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static void audqcelp_ioport_reset(struct audio *audio)
@@ -859,7 +867,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audqcelp_disable(audio);
-		audio->stopped = 1;
 		audqcelp_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
index a339825..a79f721 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
@@ -2,7 +2,7 @@
  *
  * qcelp audio input device
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c,
  * Copyright (C) 2008 Google, Inc.
@@ -279,9 +279,10 @@
 
 		audqcelp_in_dsp_enable(audio, 0);
 
-		wake_up(&audio->wait);
 		wait_event_interruptible_timeout(audio->wait_enable,
 				audio->running == 0, 1*HZ);
+		audio->stopped = 1;
+		wake_up(&audio->wait);
 		msm_adsp_disable(audio->audrec);
 		if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
 			msm_adsp_disable(audio->audpre);
@@ -657,29 +658,32 @@
 	 * sleep and knowing that system is not able
 	 * to process io request at the moment
 	 */
-	wake_up(&audio->write_wait);
-	mutex_lock(&audio->write_lock);
-	audqcelp_in_flush(audio);
-	mutex_unlock(&audio->write_lock);
 	wake_up(&audio->wait);
 	mutex_lock(&audio->read_lock);
-	audqcelp_out_flush(audio);
+	audqcelp_in_flush(audio);
 	mutex_unlock(&audio->read_lock);
+	wake_up(&audio->write_wait);
+	mutex_lock(&audio->write_lock);
+	audqcelp_out_flush(audio);
+	mutex_unlock(&audio->write_lock);
 }
 
 static void audqcelp_in_flush(struct audio_qcelp_in *audio)
 {
 	int i;
+	unsigned long flags;
 
+	audio->eos_ack = 0;
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->dsp_cnt = 0;
 	audio->in_head = 0;
 	audio->in_tail = 0;
 	audio->in_count = 0;
-	audio->eos_ack = 0;
 	for (i = FRAME_NUM-1; i >= 0; i--) {
 		audio->in[i].size = 0;
 		audio->in[i].read = 0;
 	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
 	MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
 	atomic_set(&audio->in_bytes, 0);
@@ -689,15 +693,18 @@
 static void audqcelp_out_flush(struct audio_qcelp_in *audio)
 {
 	int i;
+	unsigned long flags;
 
 	audio->out_head = 0;
-	audio->out_tail = 0;
 	audio->out_count = 0;
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+	audio->out_tail = 0;
 	for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
 		audio->out[i].size = 0;
 		audio->out[i].read = 0;
 		audio->out[i].used = 0;
 	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 /* ------------------- device --------------------- */
@@ -737,7 +744,6 @@
 	}
 	case AUDIO_STOP: {
 		rc = audqcelp_in_disable(audio);
-		audio->stopped = 1;
 		break;
 	}
 	case AUDIO_FLUSH: {
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
index b7e8e1c..7a962b2 100644
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
@@ -266,7 +266,9 @@
 		audio->in[index].used = 0;
 
 	audio->read_next = 0;
+	mutex_lock(&audio->dsp_lock);
 	audio->fill_next = 0;
+	mutex_unlock(&audio->dsp_lock);
 }
 
 static void audvoicememo_ioport_reset(struct audio_voicememo *audio)
@@ -387,6 +389,7 @@
 		rc = msm_rpc_write(audio->sndept, &rhdr, sizeof(rhdr));
 		wait_event_timeout(audio->wait, audio->stopped == 0,
 				1 * HZ);
+		audio->stopped = 1;
 		wake_up(&audio->read_wait);
 		audmgr_disable(&audio->audmgr);
 		audio->enabled = 0;
@@ -536,12 +539,14 @@
 					callback time\n");
 		else if (rec_status == RPC_VOC_REC_STAT_AUTO_STOP) {
 			MM_DBG(" Voice Record AUTO STOP\n");
+			mutex_lock(&audio->lock);
+			audio->stopped = 1;
 			wake_up(&audio->read_wait);
 			audmgr_disable(&audio->audmgr);
-			audio->stopped = 1;
 			audvoicememo_ioport_reset(audio);
 			audio->stopped = 0;
 			audio->enabled = 0;
+			mutex_unlock(&audio->lock);
 		}
 			break;
 		}
@@ -648,7 +653,6 @@
 	case AUDIO_STOP: {
 			MM_DBG("AUDIO_STOP\n");
 			rc = audvoicememo_disable(audio);
-			audio->stopped = 1;
 			audvoicememo_ioport_reset(audio);
 			audio->stopped = 0;
 			MM_DBG("AUDIO_STOP rc %d\n", rc);
diff --git a/arch/arm/mach-msm/qdsp5/audio_wma.c b/arch/arm/mach-msm/qdsp5/audio_wma.c
index cf2ade4..674ee4f 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wma.c
@@ -1,6 +1,6 @@
 /* audio_wma.c - wma audio decoder driver
  *
- * Copyright (c) 2009, 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
  *
@@ -306,6 +306,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		wake_up(&audio->read_wait);
 		msm_adsp_disable(audio->audplay);
@@ -659,11 +660,15 @@
 
 static void audio_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->reserved = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	atomic_set(&audio->out_bytes, 0);
 }
 
@@ -671,11 +676,15 @@
 {
 	uint8_t index;
 
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 		audio->in[index].used = 0;
 	audio->buf_refresh = 0;
 	audio->read_next = 0;
 	audio->fill_next = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static void audio_ioport_reset(struct audio *audio)
@@ -905,7 +914,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audio_disable(audio);
-		audio->stopped = 1;
 		audio_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_wmapro.c b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
index d9b384a..c2a0b93 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wmapro.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.
  *
  * All source code in this file is licensed under the following license except
  * where indicated.
@@ -301,6 +301,7 @@
 			rc = -EFAULT;
 		else
 			rc = 0;
+		audio->stopped = 1;
 		wake_up(&audio->write_wait);
 		wake_up(&audio->read_wait);
 		msm_adsp_disable(audio->audplay);
@@ -648,23 +649,30 @@
 
 static void audio_flush(struct audio *audio)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	audio->out[0].used = 0;
 	audio->out[1].used = 0;
 	audio->out_head = 0;
 	audio->out_tail = 0;
 	audio->reserved = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 	atomic_set(&audio->out_bytes, 0);
 }
 
 static void audio_flush_pcm_buf(struct audio *audio)
 {
 	uint8_t index;
+	unsigned long flags;
 
+	spin_lock_irqsave(&audio->dsp_lock, flags);
 	for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 		audio->in[index].used = 0;
 	audio->buf_refresh = 0;
 	audio->read_next = 0;
 	audio->fill_next = 0;
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
 }
 
 static void audio_ioport_reset(struct audio *audio)
@@ -894,7 +902,6 @@
 	case AUDIO_STOP:
 		MM_DBG("AUDIO_STOP\n");
 		rc = audio_disable(audio);
-		audio->stopped = 1;
 		audio_ioport_reset(audio);
 		audio->stopped = 0;
 		break;
diff --git a/arch/arm/mach-msm/qdsp5/audpp.c b/arch/arm/mach-msm/qdsp5/audpp.c
index 3e834d8..2dbb5dc0 100644
--- a/arch/arm/mach-msm/qdsp5/audpp.c
+++ b/arch/arm/mach-msm/qdsp5/audpp.c
@@ -4,7 +4,7 @@
  * common code to deal with the AUDPP dsp task (audio postproc)
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-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
@@ -124,6 +124,8 @@
 	uint16_t avsync[CH_COUNT * AUDPP_CLNT_MAX_COUNT + 1];
 	struct audpp_event_callback *cb_tbl[MAX_EVENT_CALLBACK_CLIENTS];
 
+	spinlock_t avsync_lock;
+
 	wait_queue_head_t event_wait;
 };
 
@@ -237,13 +239,24 @@
 	}
 }
 
+static void audpp_fake_event(struct audpp_state *audpp, int id,
+			     unsigned event, unsigned arg)
+{
+	uint16_t msg[1];
+	msg[0] = arg;
+	audpp->func[id] (audpp->private[id], event, msg);
+}
+
 static void audpp_dsp_event(void *data, unsigned id, size_t len,
 			    void (*getevent) (void *ptr, size_t len))
 {
 	struct audpp_state *audpp = data;
+	unsigned long flags;
 	uint16_t msg[8];
+	int cid = 0;
 
 	if (id == AUDPP_MSG_AVSYNC_MSG) {
+		spin_lock_irqsave(&audpp->avsync_lock, flags);
 		getevent(audpp->avsync, sizeof(audpp->avsync));
 
 		/* mask off any channels we're not watching to avoid
@@ -252,6 +265,7 @@
 		 * we next read...
 		 */
 		audpp->avsync[0] &= audpp->avsync_mask;
+		spin_unlock_irqrestore(&audpp->avsync_lock, flags);
 		return;
 	}
 
@@ -278,13 +292,28 @@
 	case AUDPP_MSG_CFG_MSG:
 		if (msg[0] == AUDPP_MSG_ENA_ENA) {
 			MM_INFO("ENABLE\n");
-			audpp->enabled = 1;
-			audpp_broadcast(audpp, id, msg);
+			if (!audpp->enabled) {
+				audpp->enabled = 1;
+				audpp_broadcast(audpp, id, msg);
+			} else {
+				cid = msg[1];
+				audpp_fake_event(audpp, cid,
+					id, AUDPP_MSG_ENA_ENA);
+			}
+
 		} else if (msg[0] == AUDPP_MSG_ENA_DIS) {
-			MM_INFO("DISABLE\n");
-			audpp->enabled = 0;
-			wake_up(&audpp->event_wait);
-			audpp_broadcast(audpp, id, msg);
+			if (audpp->open_count == 0) {
+				MM_INFO("DISABLE\n");
+				audpp->enabled = 0;
+				wake_up(&audpp->event_wait);
+				audpp_broadcast(audpp, id, msg);
+			} else {
+				cid = msg[1];
+				audpp_fake_event(audpp, cid,
+					id, AUDPP_MSG_ENA_DIS);
+				audpp->func[cid] = NULL;
+				audpp->private[cid] = NULL;
+			}
 		} else {
 			MM_ERR("invalid config msg %d\n", msg[0]);
 		}
@@ -307,17 +336,10 @@
 	.event = audpp_dsp_event,
 };
 
-static void audpp_fake_event(struct audpp_state *audpp, int id,
-			     unsigned event, unsigned arg)
-{
-	uint16_t msg[1];
-	msg[0] = arg;
-	audpp->func[id] (audpp->private[id], event, msg);
-}
-
 int audpp_enable(int id, audpp_event_func func, void *private)
 {
 	struct audpp_state *audpp = &the_audpp_state;
+	uint16_t msg[8];
 	int res = 0;
 
 	if (id < -1 || id > 4)
@@ -350,12 +372,15 @@
 		msm_adsp_enable(audpp->mod);
 		audpp_dsp_config(1);
 	} else {
-		unsigned long flags;
-		local_irq_save(flags);
-		if (audpp->enabled)
-			audpp_fake_event(audpp, id,
-					 AUDPP_MSG_CFG_MSG, AUDPP_MSG_ENA_ENA);
-		local_irq_restore(flags);
+		if (audpp->enabled) {
+			msg[0] = AUDPP_MSG_ENA_ENA;
+			msg[1] = id;
+			res = msm_adsp_generate_event(audpp, audpp->mod,
+					 AUDPP_MSG_CFG_MSG, sizeof(msg),
+					 sizeof(uint16_t), (void *)msg);
+			if (res < 0)
+				goto out;
+		}
 	}
 
 	res = 0;
@@ -368,7 +393,7 @@
 void audpp_disable(int id, void *private)
 {
 	struct audpp_state *audpp = &the_audpp_state;
-	unsigned long flags;
+	uint16_t msg[8];
 	int rc;
 
 	if (id < -1 || id > 4)
@@ -384,11 +409,13 @@
 	if (audpp->private[id] != private)
 		goto out;
 
-	local_irq_save(flags);
-	audpp_fake_event(audpp, id, AUDPP_MSG_CFG_MSG, AUDPP_MSG_ENA_DIS);
-	audpp->func[id] = NULL;
-	audpp->private[id] = NULL;
-	local_irq_restore(flags);
+	msg[0] = AUDPP_MSG_ENA_DIS;
+	msg[1] = id;
+	rc = msm_adsp_generate_event(audpp, audpp->mod,
+				 AUDPP_MSG_CFG_MSG, sizeof(msg),
+				 sizeof(uint16_t), (void *)msg);
+	if (rc < 0)
+		goto out;
 
 	if (--audpp->open_count == 0) {
 		MM_DBG("disable\n");
@@ -420,13 +447,13 @@
 	if (BAD_ID(id))
 		return;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&the_audpp_state.avsync_lock, flags);
 	if (rate)
 		the_audpp_state.avsync_mask |= (1 << id);
 	else
 		the_audpp_state.avsync_mask &= (~(1 << id));
 	the_audpp_state.avsync[0] &= the_audpp_state.avsync_mask;
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&the_audpp_state.avsync_lock, flags);
 
 	cmd.cmd_id = AUDPP_CMD_AVSYNC;
 	cmd.object_number = id;
@@ -438,7 +465,8 @@
 
 unsigned audpp_avsync_sample_count(int id)
 {
-	uint16_t *avsync = the_audpp_state.avsync;
+	struct audpp_state *audpp = &the_audpp_state;
+	uint16_t *avsync = audpp->avsync;
 	unsigned val;
 	unsigned long flags;
 	unsigned mask;
@@ -448,12 +476,12 @@
 
 	mask = 1 << id;
 	id = id * AUDPP_AVSYNC_INFO_SIZE + 2;
-	local_irq_save(flags);
+	spin_lock_irqsave(&audpp->avsync_lock, flags);
 	if (avsync[0] & mask)
 		val = (avsync[id] << 16) | avsync[id + 1];
 	else
 		val = 0;
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&audpp->avsync_lock, flags);
 
 	return val;
 }
@@ -461,7 +489,8 @@
 
 unsigned audpp_avsync_byte_count(int id)
 {
-	uint16_t *avsync = the_audpp_state.avsync;
+	struct audpp_state *audpp = &the_audpp_state;
+	uint16_t *avsync = audpp->avsync;
 	unsigned val;
 	unsigned long flags;
 	unsigned mask;
@@ -471,12 +500,12 @@
 
 	mask = 1 << id;
 	id = id * AUDPP_AVSYNC_INFO_SIZE + 5;
-	local_irq_save(flags);
+	spin_lock_irqsave(&audpp->avsync_lock, flags);
 	if (avsync[0] & mask)
 		val = (avsync[id] << 16) | avsync[id + 1];
 	else
 		val = 0;
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&audpp->avsync_lock, flags);
 
 	return val;
 }
@@ -826,6 +855,8 @@
 
 	init_waitqueue_head(&audpp->event_wait);
 
+	spin_lock_init(&audpp->avsync_lock);
+
 	for (idx = 0; idx < audpp->dec_database->num_dec; idx++) {
 		audpp->dec_info_table[idx].codec = -1;
 		audpp->dec_info_table[idx].pid = 0;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c b/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
index c38fefc..d43c961 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5v2/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) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -76,6 +76,9 @@
 
 #define MASK_32BITS     0xFFFFFFFF
 
+#define MAX_BUF 4
+#define BUFSZ (524288)
+
 #define __CONTAINS(r, v, l) ({					\
 	typeof(r) __r = r;					\
 	typeof(v) __v = v;					\
@@ -1192,6 +1195,8 @@
 		audio->out_sample_rate = config.sample_rate;
 		audio->out_channel_mode = config.channel_count;
 		audio->out_bits = config.bits;
+		audio->buffer_count = config.buffer_count;
+		audio->buffer_size = config.buffer_size;
 		MM_DBG("AUDIO_SET_CONFIG: config.bits = %d\n", config.bits);
 		rc = 0;
 		break;
@@ -1199,7 +1204,8 @@
 
 	case AUDIO_GET_CONFIG:{
 		struct msm_audio_config config;
-		config.buffer_count = 2;
+		config.buffer_count = audio->buffer_count;
+		config.buffer_size = audio->buffer_size;
 		config.sample_rate = audio->out_sample_rate;
 		if (audio->out_channel_mode == AUDPP_CMD_PCM_INTF_MONO_V)
 			config.channel_count = 1;
@@ -1518,6 +1524,8 @@
 	dec_attrb |= audlpa_decs[audio->minor_no].dec_attrb;
 	audio->codec_ops.ioctl = audlpa_decs[audio->minor_no].ioctl;
 	audio->codec_ops.adec_params = audlpa_decs[audio->minor_no].adec_params;
+	audio->buffer_size = BUFSZ;
+	audio->buffer_count = MAX_BUF;
 
 	dec_attrb |= MSM_AUD_MODE_LP;
 
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 37428da..541f62f 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -505,12 +505,19 @@
 		return;
 	pr_debug("%s: handle[%p]\n", __func__, handle);
 
+	if (apr_reset_workqueue == NULL) {
+		pr_err("%s: apr_reset_workqueue is NULL\n", __func__);
+		return;
+	}
+
 	apr_reset_worker = kzalloc(sizeof(struct apr_reset_work),
-					GFP_ATOMIC);
-	if (apr_reset_worker == NULL || apr_reset_workqueue == NULL) {
+							GFP_ATOMIC);
+
+	if (apr_reset_worker == NULL) {
 		pr_err("%s: mem failure\n", __func__);
 		return;
 	}
+
 	apr_reset_worker->handle = handle;
 	INIT_WORK(&apr_reset_worker->work, apr_reset_deregister);
 	queue_work(apr_reset_workqueue, &apr_reset_worker->work);
diff --git a/arch/arm/mach-msm/qdss-ptm.c b/arch/arm/mach-msm/qdss-ptm.c
index 96a727a..c0dc58e 100644
--- a/arch/arm/mach-msm/qdss-ptm.c
+++ b/arch/arm/mach-msm/qdss-ptm.c
@@ -67,9 +67,9 @@
 #define ETMSQ12EVR		(0x180)
 #define ETMSQ21EVR		(0x184)
 #define ETMSQ23EVR		(0x188)
-#define ETMSQ32EVR		(0x18C)
-#define ETMSQ13EVR		(0x190)
-#define ETMSQ31EVR		(0x194)
+#define ETMSQ31EVR		(0x18C)
+#define ETMSQ32EVR		(0x190)
+#define ETMSQ13EVR		(0x194)
 #define ETMSQR			(0x19C)
 #define ETMEXTOUTEVRn(n)	(0x1A0 + (n * 4))
 #define ETMCIDCVRn(n)		(0x1B0 + (n * 4))
@@ -91,7 +91,7 @@
 #define ETMTSEVR		(0x1F8)
 #define ETMAUXCR		(0x1FC)
 #define ETMTRACEIDR		(0x200)
-#define ETMVMIDCVR		(0x204)
+#define ETMVMIDCVR		(0x240)
 /* Management registers (0x300-0x314) */
 #define ETMOSLAR		(0x300)
 #define ETMOSLSR		(0x304)
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 747b585..e0d0dd8 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -190,10 +190,7 @@
 
 static int __init scm_pas_init(void)
 {
-	/* TODO: Remove once bus scaling driver is in place */
-	if (!cpu_is_apq8064())
-		scm_perf_client = msm_bus_scale_register_client(
-				&scm_pas_bus_pdata);
+	scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
 	if (!scm_perf_client)
 		pr_warn("unable to register bus client\n");
 	scm_bus_clk = clk_get_sys("scm", "bus_clk");
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index b95c3aa..bca1e0c 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -273,6 +273,38 @@
 #define MSM_TRIG_A2WCNSS_SMSM_INT
 #endif
 
+/*
+ * stub out legacy macros if they are not being used so that the legacy
+ * code compiles even though it is not used
+ *
+ * these definitions should not be used in active code and will cause
+ * an early failure
+ */
+#ifndef INT_A9_M2A_0
+#define INT_A9_M2A_0 -1
+#endif
+#ifndef INT_A9_M2A_5
+#define INT_A9_M2A_5 -1
+#endif
+#ifndef INT_ADSP_A11
+#define INT_ADSP_A11 -1
+#endif
+#ifndef INT_ADSP_A11_SMSM
+#define INT_ADSP_A11_SMSM -1
+#endif
+#ifndef INT_DSPS_A11
+#define INT_DSPS_A11 -1
+#endif
+#ifndef INT_DSPS_A11_SMSM
+#define INT_DSPS_A11_SMSM -1
+#endif
+#ifndef INT_WCNSS_A11
+#define INT_WCNSS_A11 -1
+#endif
+#ifndef INT_WCNSS_A11_SMSM
+#define INT_WCNSS_A11_SMSM -1
+#endif
+
 #define SMD_LOOPBACK_CID 100
 
 #define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 0ec88d5..9b10ffd 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -218,6 +218,7 @@
 
 	/* 8064 IDs */
 	[109] = MSM_CPU_8064,
+	[130] = MSM_CPU_8064,
 
 	/* 8930 IDs */
 	[116] = MSM_CPU_8930,
@@ -603,7 +604,7 @@
 
 arch_initcall(socinfo_init_sysdev);
 
-void *setup_dummy_socinfo(void)
+static void * __init setup_dummy_socinfo(void)
 {
 	if (machine_is_msm8960_rumi3() || machine_is_msm8960_sim() ||
 	    machine_is_msm8960_cdp())
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index 78fd922..b155781 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -65,12 +65,7 @@
 #elif defined(CONFIG_MSM_SPM_V2)
 
 enum {
-	MSM_SPM_REG_SAW2_SECURE,
-	MSM_SPM_REG_SAW2_ID,
 	MSM_SPM_REG_SAW2_CFG,
-	MSM_SPM_REG_SAW2_STS0,
-	MSM_SPM_REG_SAW2_STS1,
-	MSM_SPM_REG_SAW2_VCTL,
 	MSM_SPM_REG_SAW2_AVS_CTL,
 	MSM_SPM_REG_SAW2_AVS_HYSTERESIS,
 	MSM_SPM_REG_SAW2_SPM_CTL,
@@ -79,8 +74,13 @@
 	MSM_SPM_REG_SAW2_PMIC_DATA_1,
 	MSM_SPM_REG_SAW2_RST,
 
-	MSM_SPM_REG_NR_INITIALIZE,
-	MSM_SPM_REG_SAW2_SEQ_ENTRY = MSM_SPM_REG_NR_INITIALIZE,
+	MSM_SPM_REG_NR_INITIALIZE = MSM_SPM_REG_SAW2_RST,
+	MSM_SPM_REG_SAW2_ID,
+	MSM_SPM_REG_SAW2_SECURE,
+	MSM_SPM_REG_SAW2_STS0,
+	MSM_SPM_REG_SAW2_STS1,
+	MSM_SPM_REG_SAW2_VCTL,
+	MSM_SPM_REG_SAW2_SEQ_ENTRY ,
 
 	MSM_SPM_REG_NR
 };
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 07a9241..9970c90 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -122,9 +122,13 @@
 	if (pdev && pwlanconfig)
 		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
 					WCNSS_WLAN_SWITCH_ON);
-	if (!ret)
+	/* delay PIL operation, this SSR may be happening soon after kernel
+	 * resumes because of a SMSM RESET by Riva when APPS was suspended.
+	 * PIL fails to locate the images without this delay */
+	if (!ret) {
+		msleep(1000);
 		pil_force_boot("wcnss");
-
+	}
 	ss_restart_inprogress = false;
 	enable_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
 
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 14536f6..946899d 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -17,6 +17,8 @@
 #include <asm/thread_notify.h>
 #include <asm/tlbflush.h>
 
+#include <mach/msm_rtb.h>
+
 static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 unsigned int cpu_last_asid = ASID_FIRST_VERSION;
 #ifdef CONFIG_SMP
@@ -25,6 +27,7 @@
 
 static void write_contextidr(u32 contextidr)
 {
+	uncached_logk(LOGK_CTXID, (void *)contextidr);
 	asm("mcr	p15, 0, %0, c13, c0, 1" : : "r" (contextidr));
 	isb();
 }
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
old mode 100644
new mode 100755
index 7d2e44f..8dcce03
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1136,4 +1136,6 @@
 apq8064_cdp		MACH_APQ8064_CDP	APQ8064_CDP		3948
 apq8064_mtp		MACH_APQ8064_MTP	APQ8064_MTP		3949
 apq8064_liquid		MACH_APQ8064_LIQUID	APQ8064_LIQUID		3951
+mpq8064_hrd		MACH_MPQ8064_HRD	MPQ8064_HRD		3994
+mpq8064_dtv		MACH_MPQ8064_DTV	MPQ8064_DTV		3995
 msm7627a_qrd3		MACH_MSM7627A_QRD3	MSM7627A_QRD3		4005
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 851189d..58bf45d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@
 
 source "drivers/spi/Kconfig"
 
+source "drivers/spmi/Kconfig"
+
 source "drivers/slimbus/Kconfig"
 
 source "drivers/pps/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index e18822cd..82008ed 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -51,6 +51,7 @@
 obj-$(CONFIG_TARGET_CORE)	+= target/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
+obj-$(CONFIG_SPMI)		+= spmi/
 obj-$(CONFIG_SLIMBUS)		+= slimbus/
 obj-y				+= net/
 obj-$(CONFIG_ATM)		+= atm/
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index a9faff0..371d319 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -52,8 +52,8 @@
 #define MAX_EQUIP_ID 12
 
 /* Maximum number of pkt reg supported at initialization*/
-extern unsigned int diag_max_registration;
-extern unsigned int diag_threshold_registration;
+extern unsigned int diag_max_reg;
+extern unsigned int diag_threshold_reg;
 
 #define APPEND_DEBUG(ch) \
 do {							\
@@ -128,6 +128,7 @@
 	struct diag_client_map *client_map;
 	int *data_ready;
 	int num_clients;
+	int polling_reg_flag;
 	struct diag_write_device *buf_tbl;
 
 	/* Memory pool parameters */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index a703148..efba92b 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -60,8 +60,8 @@
 static unsigned int max_clients = 15;
 static unsigned int threshold_client_limit = 30;
 /* This is the maximum number of pkt registrations supported at initialization*/
-unsigned int diag_max_registration = 500;
-unsigned int diag_threshold_registration = 650;
+unsigned int diag_max_reg = 600;
+unsigned int diag_threshold_reg = 750;
 
 /* Timer variables */
 static struct timer_list drain_timer;
@@ -230,7 +230,7 @@
 	}
 #endif /* DIAG over USB */
 	/* Delete the pkt response table entry for the exiting process */
-	for (i = 0; i < diag_max_registration; i++)
+	for (i = 0; i < diag_max_reg; i++)
 			if (driver->table[i].process_id == current->tgid)
 					driver->table[i].process_id = 0;
 
@@ -256,15 +256,49 @@
 	return -ENOMEM;
 }
 
+int diag_find_polling_reg(int i)
+{
+	uint16_t subsys_id, cmd_code_lo, cmd_code_hi;
+
+	subsys_id = driver->table[i].subsys_id;
+	cmd_code_lo = driver->table[i].cmd_code_lo;
+	cmd_code_hi = driver->table[i].cmd_code_hi;
+	if (driver->table[i].cmd_code == 0x0C)
+		return 1;
+	else if (driver->table[i].cmd_code == 0xFF) {
+		if (subsys_id == 0x04 && cmd_code_hi == 0x0E &&
+			 cmd_code_lo == 0x0E)
+			return 1;
+		else if (subsys_id == 0x08 && cmd_code_hi == 0x02 &&
+			 cmd_code_lo == 0x02)
+			return 1;
+		else if (subsys_id == 0x32 && cmd_code_hi == 0x03  &&
+			 cmd_code_lo == 0x03)
+			return 1;
+	}
+	return 0;
+}
+
 void diag_clear_reg(int proc_num)
 {
 	int i;
 
-	for (i = 0; i < diag_max_registration; i++) {
+	mutex_lock(&driver->diagchar_mutex);
+	/* reset polling flag */
+	driver->polling_reg_flag = 0;
+	for (i = 0; i < diag_max_reg; i++) {
 		if (driver->table[i].client_id == proc_num) {
 			driver->table[i].process_id = 0;
 		}
 	}
+	/* re-scan the registration table */
+	for (i = 0; i < diag_max_reg; i++) {
+		if (diag_find_polling_reg(i) == 1) {
+			driver->polling_reg_flag = 1;
+			break;
+		}
+	}
+	mutex_unlock(&driver->diagchar_mutex);
 }
 
 void diag_add_reg(int j, struct bindpkt_params *params,
@@ -275,6 +309,11 @@
 	driver->table[j].subsys_id = params->subsys_id;
 	driver->table[j].cmd_code_lo = params->cmd_code_lo;
 	driver->table[j].cmd_code_hi = params->cmd_code_hi;
+
+	/* check if incoming reg is polling & polling is yet not registered */
+	if (driver->polling_reg_flag == 0)
+		if (diag_find_polling_reg(j) == 1)
+			driver->polling_reg_flag = 1;
 	if (params->proc_id == APPS_PROC) {
 		driver->table[j].process_id = current->tgid;
 		driver->table[j].client_id = APPS_PROC;
@@ -296,7 +335,7 @@
 		struct bindpkt_params_per_process *pkt_params =
 			 (struct bindpkt_params_per_process *) ioarg;
 		mutex_lock(&driver->diagchar_mutex);
-		for (i = 0; i < diag_max_registration; i++) {
+		for (i = 0; i < diag_max_reg; i++) {
 			if (driver->table[i].process_id == 0) {
 				diag_add_reg(i, pkt_params->params,
 						&success, &count_entries);
@@ -308,19 +347,20 @@
 				}
 			}
 		}
-		if (i < diag_threshold_registration) {
+		if (i < diag_threshold_reg) {
 			/* Increase table size by amount required */
-			diag_max_registration += pkt_params->count -
+			diag_max_reg += pkt_params->count -
 							 count_entries;
 			/* Make sure size doesnt go beyond threshold */
-			if (diag_max_registration > diag_threshold_registration)
-				diag_max_registration =
-						 diag_threshold_registration;
+			if (diag_max_reg > diag_threshold_reg) {
+				diag_max_reg = diag_threshold_reg;
+				pr_info("diag: best case memory allocation\n");
+			}
 			temp_buf = krealloc(driver->table,
-					 diag_max_registration*sizeof(struct
+					 diag_max_reg*sizeof(struct
 					 diag_master_table), GFP_KERNEL);
 			if (!temp_buf) {
-				diag_max_registration -= pkt_params->count -
+				diag_max_reg -= pkt_params->count -
 							 count_entries;
 				pr_alert("diag: Insufficient memory for reg.");
 				mutex_unlock(&driver->diagchar_mutex);
@@ -328,7 +368,7 @@
 			} else {
 				driver->table = temp_buf;
 			}
-			for (j = i; j < diag_max_registration; j++) {
+			for (j = i; j < diag_max_reg; j++) {
 				diag_add_reg(j, pkt_params->params,
 						&success, &count_entries);
 				if (pkt_params->count > count_entries) {
@@ -338,6 +378,7 @@
 					return success;
 				}
 			}
+			mutex_unlock(&driver->diagchar_mutex);
 		} else {
 			mutex_unlock(&driver->diagchar_mutex);
 			pr_err("Max size reached, Pkt Registration failed for"
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 07322cd..7f26856 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -598,7 +598,7 @@
 	}
 
 	pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
-	for (i = 0; i < diag_max_registration; i++) {
+	for (i = 0; i < diag_max_reg; i++) {
 		entry = driver->table[i];
 		if (entry.process_id != NO_PROCESS) {
 			if (entry.cmd_code == cmd_code && entry.subsys_id ==
@@ -891,8 +891,8 @@
 	/* Check for polling for Apps only DIAG */
 	else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
 		(*(buf+2) == 0x03)) {
-		/* If there is NO MODEM present */
-		if (!(driver->ch)) {
+		/* If no one has registered for polling */
+		if (!(driver->polling_reg_flag)) {
 			/* Respond to polling for Apps only DIAG */
 			for (i = 0; i < 3; i++)
 				driver->apps_rsp_buf[i] = *(buf+i);
@@ -901,13 +901,10 @@
 
 			ENCODE_RSP_AND_SEND(15);
 			return 0;
-		} else {
-			/* Since Modem is present, send error response */
-			return 1;
 		}
 	}
 	 /* Check for ID for NO MODEM present */
-	else if (!(driver->ch)) {
+	else if (!(driver->polling_reg_flag)) {
 		/* respond to 0x0 command */
 		if (*buf == 0x00) {
 			for (i = 0; i < 55; i++)
@@ -1041,9 +1038,9 @@
 	queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
 	queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
 	/* Poll SMD CNTL channels to check for data */
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_cntl_work));
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_cntl_work));
+	diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
+	diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
+	diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
 	/* Poll USB channel to check for data*/
 	queue_work(driver->diag_wq, &(driver->diag_read_work));
 #ifdef CONFIG_DIAG_SDIO_PIPE
@@ -1377,7 +1374,7 @@
 							, GFP_KERNEL)) == NULL)
 		goto err;
 	if (driver->table == NULL &&
-	     (driver->table = kzalloc(diag_max_registration*
+	     (driver->table = kzalloc(diag_max_reg*
 		      sizeof(struct diag_master_table),
 		       GFP_KERNEL)) == NULL)
 		goto err;
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index df2cd65..2c3dc54 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -19,6 +19,66 @@
 
 #define HDR_SIZ 8
 
+void diag_smd_cntl_notify(void *ctxt, unsigned event)
+{
+	int r1, r2;
+
+	if (!(driver->ch_cntl))
+		return;
+
+	switch (event) {
+	case SMD_EVENT_DATA:
+		r1 = smd_read_avail(driver->ch_cntl);
+		r2 = smd_cur_packet_size(driver->ch_cntl);
+		if (r1 > 0 && r1 == r2)
+			queue_work(driver->diag_wq,
+				 &(driver->diag_read_smd_cntl_work));
+		else
+			pr_debug("diag: incomplete pkt on Modem CNTL ch\n");
+		break;
+	}
+}
+
+void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event)
+{
+	int r1, r2;
+
+	if (!(driver->chqdsp_cntl))
+		return;
+
+	switch (event) {
+	case SMD_EVENT_DATA:
+		r1 = smd_read_avail(driver->chqdsp_cntl);
+		r2 = smd_cur_packet_size(driver->chqdsp_cntl);
+		if (r1 > 0 && r1 == r2)
+			queue_work(driver->diag_wq,
+				 &(driver->diag_read_smd_qdsp_cntl_work));
+		else
+			pr_debug("diag: incomplete pkt on LPASS CNTL ch\n");
+		break;
+	}
+}
+
+void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event)
+{
+	int r1, r2;
+
+	if (!(driver->ch_wcnss_cntl))
+		return;
+
+	switch (event) {
+	case SMD_EVENT_DATA:
+		r1 = smd_read_avail(driver->ch_wcnss_cntl);
+		r2 = smd_cur_packet_size(driver->ch_wcnss_cntl);
+		if (r1 > 0 && r1 == r2)
+			queue_work(driver->diag_wq,
+				 &(driver->diag_read_smd_wcnss_cntl_work));
+		else
+			pr_debug("diag: incomplete pkt on WCNSS CNTL ch\n");
+		break;
+	}
+}
+
 static void diag_smd_cntl_send_req(int proc_num)
 {
 	int data_len = 0, type = -1, count_bytes = 0, j, r, flag = 0;
@@ -30,6 +90,11 @@
 	void *buf = NULL;
 	smd_channel_t *smd_ch = NULL;
 
+	if (pkt_params == NULL) {
+		pr_alert("diag: Memory allocation failure\n");
+		return;
+	}
+
 	if (proc_num == MODEM_PROC) {
 		buf = driver->buf_in_cntl;
 		smd_ch = driver->ch_cntl;
@@ -62,6 +127,17 @@
 		while (count_bytes + HDR_SIZ <= r) {
 			type = *(uint32_t *)(buf);
 			data_len = *(uint32_t *)(buf + 4);
+			if (type < DIAG_CTRL_MSG_REG ||
+					 type > DIAG_CTRL_MSG_F3_MASK_V2) {
+				pr_alert("diag: Invalid Msg type %d proc %d",
+					 type, proc_num);
+				break;
+			}
+			if (data_len < 0 || data_len > r) {
+				pr_alert("diag: Invalid data len %d proc %d",
+					 data_len, proc_num);
+				break;
+			}
 			count_bytes = count_bytes+HDR_SIZ+data_len;
 			if (type == DIAG_CTRL_MSG_REG && r >= count_bytes) {
 				msg = buf+HDR_SIZ;
@@ -70,6 +146,10 @@
 				pkt_params->count = msg->count_entries;
 				temp = kzalloc(pkt_params->count * sizeof(struct
 						 bindpkt_params), GFP_KERNEL);
+				if (temp == NULL) {
+					pr_alert("diag: Memory alloc fail\n");
+					return;
+				}
 				for (j = 0; j < pkt_params->count; j++) {
 					temp->cmd_code = msg->cmd_code;
 					temp->subsys_id = msg->subsysid;
@@ -93,11 +173,12 @@
 	kfree(pkt_params);
 	if (flag) {
 		/* Poll SMD CNTL channels to check for data */
-		queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
-		queue_work(driver->diag_wq,
-			 &(driver->diag_read_smd_qdsp_cntl_work));
-		queue_work(driver->diag_wq,
-			 &(driver->diag_read_smd_wcnss_cntl_work));
+		if (proc_num == MODEM_PROC)
+			diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
+		else if (proc_num == QDSP_PROC)
+			diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
+		else if (proc_num == WCNSS_PROC)
+			diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
 	}
 }
 
@@ -116,21 +197,6 @@
 	diag_smd_cntl_send_req(WCNSS_PROC);
 }
 
-static void diag_smd_cntl_notify(void *ctxt, unsigned event)
-{
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
-}
-
-static void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event)
-{
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_cntl_work));
-}
-
-static void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event)
-{
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_cntl_work));
-}
-
 static int diag_smd_cntl_probe(struct platform_device *pdev)
 {
 	int r = 0;
@@ -192,6 +258,7 @@
 
 void diagfwd_cntl_init(void)
 {
+	driver->polling_reg_flag = 0;
 	if (driver->buf_in_cntl == NULL) {
 		driver->buf_in_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_cntl == NULL)
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 542138d..a76d36d 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,26 @@
 #ifndef DIAGFWD_CNTL_H
 #define DIAGFWD_CNTL_H
 
-#define DIAG_CTRL_MSG_REG 1	/* Message registration commands */
+/* Message registration commands */
+#define DIAG_CTRL_MSG_REG		1
+/* Message passing for DTR events */
+#define DIAG_CTRL_MSG_DTR		2
+/* Control Diag sleep vote, buffering etc */
+#define DIAG_CTRL_MSG_DIAGMODE		3
+/* Diag data based on "light" diag mask */
+#define DIAG_CTRL_MSG_DIAGDATA		4
+/* Deprecated */
+#define DIAG_CTRL_MSG_LOG_MASK		5
+#define DIAG_CTRL_MSG_EVENT_MASK	6
+#define DIAG_CTRL_MSG_F3_MASK		7
+/* Send diag internal feature mask 'diag_int_feature_mask' */
+#define DIAG_CTRL_MSG_FEATURE		8
+/* Send Diag log mask for a particular equip id */
+#define DIAG_CTRL_MSG_EQUIP_LOG_MASK	9
+/* Send Diag event mask */
+#define DIAG_CTRL_MSG_EVENT_MASK_V2	10
+/* Send Diag F3 mask */
+#define DIAG_CTRL_MSG_F3_MASK_V2	11
 
 struct cmd_code_range {
 	uint16_t cmd_code_lo;
@@ -34,5 +53,8 @@
 void diag_read_smd_cntl_work_fn(struct work_struct *);
 void diag_read_smd_qdsp_cntl_work_fn(struct work_struct *);
 void diag_read_smd_wcnss_cntl_work_fn(struct work_struct *);
+void diag_smd_cntl_notify(void *ctxt, unsigned event);
+void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event);
+void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event);
 
 #endif
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index f5367ef..d1a9fe6 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -122,19 +122,19 @@
 				"failed to enable clock in probe\n");
 		return -EPERM;
 	}
-	val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET) &
-					PRNG_LFSR_CFG_MASK;
-	val |= PRNG_LFSR_CFG_MASK;
-	writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
-
-	/* The PRNG CONFIG register should be first written before reading */
-	mb();
-
 	/* Enable PRNG h/w only if it is NOT ON */
 	val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET) &
 					PRNG_HW_ENABLE;
 	/* PRNG H/W is not ON */
 	if (val != PRNG_HW_ENABLE) {
+		val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET) &
+					PRNG_LFSR_CFG_MASK;
+		val |= PRNG_LFSR_CFG_MASK;
+		writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
+
+		/* The PRNG CONFIG register should be first written */
+		mb();
+
 		reg_val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET)
 						& PRNG_CONFIG_MASK;
 		reg_val |= PRNG_HW_ENABLE;
@@ -242,9 +242,6 @@
 
 static int __init msm_rng_init(void)
 {
-	if (cpu_is_apq8064())
-		return -ENODEV;
-
 	return platform_driver_register(&rng_driver);
 }
 
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index d725851..5276bcc 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto Engine driver.
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011 - 2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@
 #define DST_INDEX_SG_CMD(index) (index & 0x3fff)
 #define ADM_DESC_LAST  (1 << 31)
 #define QCE_FIFO_SIZE  0x8000
+
 /*
  * CE HW device structure.
  * Each engine has an instance of the structure.
@@ -128,6 +129,7 @@
 {
 	unsigned int val;
 	unsigned int rev;
+	unsigned int ret;
 
 	val = (uint32_t)(*((uint32_t *)pce_dev->ce_dm.buffer.version));
 	if (((val & 0xfffffff) != 0x0000043) &&
@@ -144,6 +146,23 @@
 				"Qualcomm Crypto 4.2 device found at 0x%x\n",
 				pce_dev->phy_iobase);
 		pce_dev->ce_dm.ce_block_size = 64;
+
+		/* Configure the crypto register to support 64byte CRCI if it
+		 * is not XPU protected and the HW version of device is greater
+		 * than 0x42.
+		 * Crypto config register returns a 0 when it is XPU protected.
+		 */
+
+		ret = readl_relaxed(pce_dev->iobase + CRYPTO_CONFIG_REG);
+		if (ret) {
+			val = (CRYPTO_REQ_SIZE_ENUM_64_BYTES <<
+					CRYPTO_REQ_SIZE) |
+				(CRYPTO_FIFO_ENUM_64_BYTES <<
+					CRYPTO_FIFO_THRESHOLD);
+
+			writel_relaxed(val, pce_dev->iobase +
+					CRYPTO_CONFIG_REG);
+		} /* end of if (ret) */
 	} else {
 		if (rev == 0x40) {
 			dev_info(pce_dev->pdev,
@@ -152,12 +171,6 @@
 			pce_dev->ce_dm.ce_block_size = 16;
 		}
 	}
-	/*
-	* This is a temporary change - until Data Mover changes its
-	* configuration from 16 byte crci to 64 byte crci.
-	*/
-	if (cpu_is_msm9615())
-		pce_dev->ce_dm.ce_block_size = 16;
 
 	dev_info(pce_dev->pdev,
 			"IO base 0x%x\n, ce_in channel %d     , "
@@ -2609,4 +2622,4 @@
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Mona Hossain <mhossain@codeaurora.org>");
 MODULE_DESCRIPTION("Crypto Engine driver");
-MODULE_VERSION("2.14");
+MODULE_VERSION("2.15");
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index ad0c7b1..347ab88 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -206,16 +206,13 @@
 	if (ion_carveout_request_region(carveout_heap))
 		return -EINVAL;
 
-	if (ION_IS_CACHED(flags))
-		ret_value = remap_pfn_range(vma, vma->vm_start,
-			       __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
-			       vma->vm_end - vma->vm_start,
-			       vma->vm_page_prot);
-	else
-		ret_value = remap_pfn_range(vma, vma->vm_start,
-			       __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
-					vma->vm_end - vma->vm_start,
-					pgprot_noncached(vma->vm_page_prot));
+	if (!ION_IS_CACHED(flags))
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	ret_value =  remap_pfn_range(vma, vma->vm_start,
+			__phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
+			vma->vm_end - vma->vm_start,
+			vma->vm_page_prot);
 
 	if (ret_value)
 		ion_carveout_release_region(carveout_heap);
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index a6b0cf6..ff561dc 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -450,18 +450,14 @@
 			return -EINVAL;
 		}
 
-		 if (ION_IS_CACHED(flags))
-			ret_value =  remap_pfn_range(vma, vma->vm_start,
-				__phys_to_pfn(buffer->priv_phys) +
-				vma->vm_pgoff,
-				vma->vm_end - vma->vm_start,
-				vma->vm_page_prot);
-		else
-			ret_value = remap_pfn_range(vma, vma->vm_start,
-				__phys_to_pfn(buffer->priv_phys) +
-				vma->vm_pgoff,
-				vma->vm_end - vma->vm_start,
-				pgprot_noncached(vma->vm_page_prot));
+		if (!ION_IS_CACHED(flags))
+			vma->vm_page_prot = pgprot_writecombine(
+							vma->vm_page_prot);
+
+		ret_value =  remap_pfn_range(vma, vma->vm_start,
+			__phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
+			vma->vm_end - vma->vm_start,
+			vma->vm_page_prot);
 
 		if (ret_value)
 			ion_cp_release_region(cp_heap);
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index d37a811..2f9e80c 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -136,7 +136,7 @@
 		return -EINVAL;
 
 	if (!ION_IS_CACHED(flags))
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 
 	for (i = 0; i < data->nrpages; i++)
 		if (vm_insert_page(vma, vma->vm_start + i * PAGE_SIZE,
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 2a2892e..a81dbd3 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -91,7 +91,7 @@
 				const struct fmem_data *fmem_info =
 					fmem_get_info();
 				heap->base = fmem_info->phys -
-					     fmem_info->reserved_size;
+					     fmem_info->reserved_size_low;
 				cp_data->virt_addr = fmem_info->virt;
 				pr_info("ION heap %s using FMEM\n",
 							shared_heap->name);
@@ -159,6 +159,10 @@
 				heap->base = fmem_info->phys;
 				data->virt_addr = fmem_info->virt;
 				pr_info("ION heap %s using FMEM\n", heap->name);
+			} else if (data->mem_is_fmem) {
+				const struct fmem_data *fmem_info =
+					fmem_get_info();
+				heap->base = fmem_info->phys + fmem_info->size;
 			}
 			align = data->align;
 			break;
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 1806886..7e684c0 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -229,6 +229,19 @@
 #define A3XX_VBIF_FIXED_SORT_EN 0x300C
 #define A3XX_VBIF_FIXED_SORT_SEL0 0x300D
 #define A3XX_VBIF_FIXED_SORT_SEL1 0x300E
+#define A3XX_VBIF_ABIT_SORT 0x301C
+#define A3XX_VBIF_ABIT_SORT_CONF 0x301D
+#define A3XX_VBIF_GATE_OFF_WRREQ_EN 0x302A
+#define A3XX_VBIF_IN_RD_LIM_CONF0 0x302C
+#define A3XX_VBIF_IN_RD_LIM_CONF1 0x302D
+#define A3XX_VBIF_IN_WR_LIM_CONF0 0x3030
+#define A3XX_VBIF_IN_WR_LIM_CONF1 0x3031
+#define A3XX_VBIF_OUT_RD_LIM_CONF0 0x3034
+#define A3XX_VBIF_OUT_WR_LIM_CONF0 0x3035
+#define A3XX_VBIF_DDR_OUT_MAX_BURST 0x3036
+#define A3XX_VBIF_ARB_CTL 0x303C
+#define A3XX_VBIF_OUT_AXI_AOOO_EN 0x305E
+#define A3XX_VBIF_OUT_AXI_AOOO 0x305F
 
 /* Bit flags for RBBM_CTL */
 #define RBBM_RBBM_CTL_RESET_PWR_CTR1  (1 << 1)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 06f4a14..73d00b3 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -581,6 +581,7 @@
 
 	device->ftbl->irqctrl(device, 0);
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
+	del_timer_sync(&device->idle_timer);
 
 	/* Power down the device */
 	kgsl_pwrctrl_disable(device);
@@ -978,15 +979,6 @@
 	}
 	mutex_unlock(&kgsl_driver.process_mutex);
 
-	BUG_ON(!mutex_is_locked(&device->mutex));
-	list_for_each_entry(entry, &device->memqueue, list) {
-		if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, size)) {
-			result = &entry->memdesc;
-			return result;
-		}
-
-	}
-
 	while (1) {
 		struct adreno_context *adreno_context = NULL;
 		context = idr_get_next(&device->context_idr, &next);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index f68bc41..6525d9b 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -130,7 +130,7 @@
 /* Use shadow RAM */
 #define HLSQ_SHADOW_BASE		(0x10000+SSIZE*2)
 
-#define REG_TO_MEM_LOOP_COUNT_SHIFT	15
+#define REG_TO_MEM_LOOP_COUNT_SHIFT	18
 
 #define BUILD_PC_DRAW_INITIATOR(prim_type, source_select, index_size, \
 	vis_cull_mode) \
@@ -1109,11 +1109,13 @@
 
 	/* Constant save */
 	cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG1, 0x000003ff,
-			   17, (HLSQ_SHADOW_BASE + 0x2000) / 4,
+			   2 + REG_TO_MEM_LOOP_COUNT_SHIFT,
+			   (HLSQ_SHADOW_BASE + 0x2000) / 4,
 			   drawctxt->constant_save_commands[1].gpuaddr);
 
 	cmd = rmw_regtomem(cmd, A3XX_SP_FS_CTRL_REG1, 0x000003ff,
-			   17, (HLSQ_SHADOW_BASE + 0x2000 + SSIZE) / 4,
+			   2 + REG_TO_MEM_LOOP_COUNT_SHIFT,
+			   (HLSQ_SHADOW_BASE + 0x2000 + SSIZE) / 4,
 			   drawctxt->constant_save_commands[2].gpuaddr);
 
 	cmd = rmw_regtomem(cmd, A3XX_SP_FS_OBJ_OFFSET_REG, 0x00ff0000,
@@ -2546,14 +2548,29 @@
 		0x00000001);
 	msleep(20);
 
-	/*
-	 * enable fixed master AXI port of 0x0 for all clients to keep
-	 * traffic from going to random places
-	 */
+	/* Set up 16 deep read/write request queues */
 
-	adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_EN, 0x0001003F);
-	adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_SEL0, 0x00000000);
-	adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_SEL1, 0x00000000);
+	adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
+	adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
+	adreno_regwrite(device, A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
+	adreno_regwrite(device, A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
+	adreno_regwrite(device, A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000303);
+	adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
+	adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
+
+	/* Enable WR-REQ */
+	adreno_regwrite(device, A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x000000FF);
+
+	/* Set up round robin arbitration between both AXI ports */
+	adreno_regwrite(device, A3XX_VBIF_ARB_CTL, 0x00000030);
+
+	/* Set up AOOO */
+	adreno_regwrite(device, A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003C);
+	adreno_regwrite(device, A3XX_VBIF_OUT_AXI_AOOO, 0x003C003C);
+
+	/* Enable 1K sort */
+	adreno_regwrite(device, A3XX_VBIF_ABIT_SORT, 0x000000FF);
+	adreno_regwrite(device, A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
 
 	/* Make all blocks contribute to the GPU BUSY perf counter */
 	adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 98e3810..7902f30 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -876,6 +876,7 @@
 
 int adreno_postmortem_dump(struct kgsl_device *device, int manual)
 {
+	bool saved_nap;
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 
 	BUG_ON(device == NULL);
@@ -907,17 +908,28 @@
 	KGSL_LOG_DUMP(device, "BUS CLK = %lu ",
 		kgsl_get_clkrate(pwr->ebi1_clk));
 
-	/*
-	 * Disable the irq, idle timer, and workqueue so we don't
-	 * get interrupted
-	 */
-	kgsl_pwrctrl_stop_work(device);
+	/* Disable the idle timer so we don't get interrupted */
+	del_timer_sync(&device->idle_timer);
+	mutex_unlock(&device->mutex);
+	flush_workqueue(device->work_queue);
+	mutex_lock(&device->mutex);
+
+	/* Turn off napping to make sure we have the clocks full
+	   attention through the following process */
+	saved_nap = device->pwrctrl.nap_allowed;
+	device->pwrctrl.nap_allowed = false;
 
 	/* Force on the clocks */
-	kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON);
+	kgsl_pwrctrl_wake(device);
+
+	/* Disable the irq */
+	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
 
 	adreno_dump(device);
 
+	/* Restore nap mode */
+	device->pwrctrl.nap_allowed = saved_nap;
+
 	/* On a manual trigger, turn on the interrupts and put
 	   the clocks to sleep.  They will recover themselves
 	   on the next event.  For a hang, leave things as they
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index caedf26..0361387 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -64,7 +64,7 @@
 
 #define GSL_RB_WRITE(ring, gpuaddr, data) \
 	do { \
-		writel_relaxed(data, ring); \
+		*ring = data; \
 		wmb(); \
 		kgsl_cffdump_setmem(gpuaddr, data, 4); \
 		ring++; \
@@ -93,7 +93,7 @@
 #define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */
 #define GSL_RB_GET_READPTR(rb, data) \
 	do { \
-		*(data) = readl_relaxed(&(rb)->memptrs->rptr); \
+		*(data) = rb->memptrs->rptr; \
 	} while (0)
 #else
 #define GSL_RB_CNTL_NO_UPDATE 0x1 /* disable */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1a0a17d..9333dca 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -49,20 +49,20 @@
 
 static struct ion_client *kgsl_ion_client;
 
-#ifdef CONFIG_GENLOCK
-
 /**
  * kgsl_add_event - Add a new timstamp event for the KGSL device
  * @device - KGSL device for the new event
  * @ts - the timestamp to trigger the event on
  * @cb - callback function to call when the timestamp expires
  * @priv - private data for the specific event type
+ * @owner - driver instance that owns this event
  *
  * @returns - 0 on success or error code on failure
  */
 
 static int kgsl_add_event(struct kgsl_device *device, u32 ts,
-	void (*cb)(struct kgsl_device *, void *, u32), void *priv)
+	void (*cb)(struct kgsl_device *, void *, u32), void *priv,
+	struct kgsl_device_private *owner)
 {
 	struct kgsl_event *event;
 	struct list_head *n;
@@ -86,6 +86,7 @@
 	event->timestamp = ts;
 	event->priv = priv;
 	event->func = cb;
+	event->owner = owner;
 
 	/* Add the event in order to the list */
 
@@ -105,7 +106,36 @@
 	queue_work(device->work_queue, &device->ts_expired_ws);
 	return 0;
 }
-#endif
+
+/**
+ * kgsl_cancel_events - Cancel all events for a process
+ * @device - KGSL device for the events to cancel
+ * @owner - driver instance that owns the events to cancel
+ *
+ */
+static void kgsl_cancel_events(struct kgsl_device *device,
+	struct kgsl_device_private *owner)
+{
+	struct kgsl_event *event, *event_tmp;
+	unsigned int cur = device->ftbl->readtimestamp(device,
+		KGSL_TIMESTAMP_RETIRED);
+
+	list_for_each_entry_safe(event, event_tmp, &device->events, list) {
+		if (event->owner != owner)
+			continue;
+		/*
+		 * "cancel" the events by calling their callback.
+		 * Currently, events are used for lock and memory
+		 * management, so if the process is dying the right
+		 * thing to do is release or free.
+		 */
+		if (event->func)
+			event->func(device, event->priv, cur);
+
+		list_del(&event->list);
+		kfree(event);
+	}
+}
 
 static inline struct kgsl_mem_entry *
 kgsl_mem_entry_create(void)
@@ -227,44 +257,10 @@
 	idr_remove(&dev_priv->device->context_idr, id);
 }
 
-/* to be called when a process is destroyed, this walks the memqueue and
- * frees any entryies that belong to the dying process
- */
-static void kgsl_memqueue_cleanup(struct kgsl_device *device,
-				     struct kgsl_process_private *private)
-{
-	struct kgsl_mem_entry *entry, *entry_tmp;
-
-	if (!private)
-		return;
-
-	BUG_ON(!mutex_is_locked(&device->mutex));
-
-	list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) {
-		if (entry->priv == private) {
-			list_del(&entry->list);
-			kgsl_mem_entry_put(entry);
-		}
-	}
-}
-
-static void kgsl_memqueue_freememontimestamp(struct kgsl_device *device,
-				  struct kgsl_mem_entry *entry,
-				  uint32_t timestamp,
-				  enum kgsl_timestamp_type type)
-{
-	BUG_ON(!mutex_is_locked(&device->mutex));
-
-	entry->free_timestamp = timestamp;
-
-	list_add_tail(&entry->list, &device->memqueue);
-}
-
 static void kgsl_timestamp_expired(struct work_struct *work)
 {
 	struct kgsl_device *device = container_of(work, struct kgsl_device,
 		ts_expired_ws);
-	struct kgsl_mem_entry *entry, *entry_tmp;
 	struct kgsl_event *event, *event_tmp;
 	uint32_t ts_processed;
 
@@ -274,15 +270,6 @@
 	ts_processed = device->ftbl->readtimestamp(device,
 		KGSL_TIMESTAMP_RETIRED);
 
-	/* Flush the freememontimestamp queue */
-	list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) {
-		if (timestamp_cmp(ts_processed, entry->free_timestamp) < 0)
-			break;
-
-		list_del(&entry->list);
-		kgsl_mem_entry_put(entry);
-	}
-
 	/* Process expired events */
 	list_for_each_entry_safe(event, event_tmp, &device->events, list) {
 		if (timestamp_cmp(ts_processed, event->timestamp) < 0)
@@ -404,6 +391,8 @@
 		wait_for_completion(&device->suspend_gate);
 		mutex_lock(&device->mutex);
 	}
+	/* Don't let the timer wake us during suspended sleep. */
+	del_timer_sync(&device->idle_timer);
 	switch (device->state) {
 		case KGSL_STATE_INIT:
 			break;
@@ -415,7 +404,6 @@
 			/* Get the completion ready to be waited upon. */
 			INIT_COMPLETION(device->hwaccess_gate);
 			device->ftbl->suspend_context(device);
-			kgsl_pwrctrl_stop_work(device);
 			device->ftbl->stop(device);
 			kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND);
 			break;
@@ -498,7 +486,6 @@
 					struct kgsl_device, display_off);
 	KGSL_PWR_WARN(device, "early suspend start\n");
 	mutex_lock(&device->mutex);
-	kgsl_pwrctrl_stop_work(device);
 	kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
 	kgsl_pwrctrl_sleep(device);
 	mutex_unlock(&device->mutex);
@@ -645,14 +632,13 @@
 
 	device->open_count--;
 	if (device->open_count == 0) {
-		kgsl_pwrctrl_stop_work(device);
 		result = device->ftbl->stop(device);
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
 	}
 	/* clean up any to-be-freed entries that belong to this
 	 * process and this device
 	 */
-	kgsl_memqueue_cleanup(device, private);
+	kgsl_cancel_events(device, dev_priv);
 
 	mutex_unlock(&device->mutex);
 	kfree(dev_priv);
@@ -997,6 +983,16 @@
 	return 0;
 }
 
+static void kgsl_freemem_event_cb(struct kgsl_device *device,
+	void *priv, u32 timestamp)
+{
+	struct kgsl_mem_entry *entry = priv;
+	spin_lock(&entry->priv->mem_lock);
+	list_del(&entry->list);
+	spin_unlock(&entry->priv->mem_lock);
+	kgsl_mem_entry_put(entry);
+}
+
 static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private
 						    *dev_priv, unsigned int cmd,
 						    void *data)
@@ -1007,13 +1003,11 @@
 
 	spin_lock(&dev_priv->process_priv->mem_lock);
 	entry = kgsl_sharedmem_find(dev_priv->process_priv, param->gpuaddr);
-	if (entry)
-		list_del(&entry->list);
 	spin_unlock(&dev_priv->process_priv->mem_lock);
 
 	if (entry) {
-		kgsl_memqueue_freememontimestamp(dev_priv->device, entry,
-					param->timestamp, param->type);
+		result = kgsl_add_event(dev_priv->device, param->timestamp,
+					kgsl_freemem_event_cb, entry, dev_priv);
 	} else {
 		KGSL_DRV_ERR(dev_priv->device,
 			"invalid gpuaddr %08x\n", param->gpuaddr);
@@ -1763,6 +1757,7 @@
  * @timestamp - Timestamp to trigger the event
  * @data - User space buffer containing struct kgsl_genlock_event_priv
  * @len - length of the userspace buffer
+ * @owner - driver instance that owns this event
  * @returns 0 on success or error code on error
  *
  * Attack to a genlock handle and register an event to release the
@@ -1770,7 +1765,8 @@
  */
 
 static int kgsl_add_genlock_event(struct kgsl_device *device,
-	u32 timestamp, void __user *data, int len)
+	u32 timestamp, void __user *data, int len,
+	struct kgsl_device_private *owner)
 {
 	struct kgsl_genlock_event_priv *event;
 	struct kgsl_timestamp_event_genlock priv;
@@ -1795,7 +1791,8 @@
 		return ret;
 	}
 
-	ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event);
+	ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event,
+			     owner);
 	if (ret)
 		kfree(event);
 
@@ -1803,7 +1800,8 @@
 }
 #else
 static long kgsl_add_genlock_event(struct kgsl_device *device,
-	u32 timestamp, void __user *data, int len)
+	u32 timestamp, void __user *data, int len,
+	struct kgsl_device_private *owner)
 {
 	return -EINVAL;
 }
@@ -1826,7 +1824,8 @@
 	switch (param->type) {
 	case KGSL_TIMESTAMP_EVENT_GENLOCK:
 		ret = kgsl_add_genlock_event(dev_priv->device,
-			param->timestamp, param->priv, param->len);
+			param->timestamp, param->priv, param->len,
+			dev_priv);
 		break;
 	default:
 		ret = -EINVAL;
@@ -2183,7 +2182,6 @@
 	INIT_WORK(&device->idle_check_ws, kgsl_idle_check);
 	INIT_WORK(&device->ts_expired_ws, kgsl_timestamp_expired);
 
-	INIT_LIST_HEAD(&device->memqueue);
 	INIT_LIST_HEAD(&device->events);
 
 	ret = kgsl_mmu_init(device);
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 1135adb..3e8aac3 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -199,7 +199,7 @@
 	if (ts_diff == 0)
 		return 0;
 
-	return ((ts_diff > 0) || (ts_diff < -20000)) ? 1 : -1;
+	return ((ts_diff > 0) || (ts_diff < -25000)) ? 1 : -1;
 }
 
 static inline void
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 8ea5279..2fb1e43 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -126,6 +126,7 @@
 	void (*func)(struct kgsl_device *, void *, u32);
 	void *priv;
 	struct list_head list;
+	struct kgsl_device_private *owner;
 };
 
 
@@ -154,7 +155,6 @@
 	uint32_t state;
 	uint32_t requested_state;
 
-	struct list_head memqueue;
 	unsigned int active_cnt;
 	struct completion suspend_gate;
 
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index fe5677e..97b5ef1 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.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
@@ -382,26 +382,27 @@
 kgsl_pt_map_set(struct kgsl_gpummu_pt *pt, uint32_t pte, uint32_t val)
 {
 	uint32_t *baseptr = (uint32_t *)pt->base.hostptr;
-
-	writel_relaxed(val, &baseptr[pte]);
+	BUG_ON(pte*sizeof(uint32_t) >= pt->base.size);
+	baseptr[pte] = val;
 }
 
 static inline uint32_t
 kgsl_pt_map_get(struct kgsl_gpummu_pt *pt, uint32_t pte)
 {
 	uint32_t *baseptr = (uint32_t *)pt->base.hostptr;
-	return readl_relaxed(&baseptr[pte]) & GSL_PT_PAGE_ADDR_MASK;
+	BUG_ON(pte*sizeof(uint32_t) >= pt->base.size);
+	return baseptr[pte] & GSL_PT_PAGE_ADDR_MASK;
 }
 
 static unsigned int kgsl_gpummu_pt_get_flags(struct kgsl_pagetable *pt,
 				enum kgsl_deviceid id)
 {
 	unsigned int result = 0;
-	struct kgsl_gpummu_pt *gpummu_pt = (struct kgsl_gpummu_pt *)
-						pt->priv;
+	struct kgsl_gpummu_pt *gpummu_pt;
 
 	if (pt == NULL)
 		return 0;
+	gpummu_pt = pt->priv;
 
 	spin_lock(&pt->lock);
 	if (gpummu_pt->tlb_flags && (1<<id)) {
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index e4e561c..194067b 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -24,11 +24,23 @@
 #include "kgsl_mmu.h"
 #include "kgsl_sharedmem.h"
 
+/*
+ * On APQ8064, KGSL can control a maximum of 4 IOMMU devices: 2 user and 2
+ * priv domains, 1 each for each of the AXI ports attached to the GPU.  8660
+ * and 8960 have only one AXI port, so maximum allowable IOMMU devices for those
+ * chips is 2.
+ */
+
+#define KGSL_IOMMU_MAX_DEV 4
+
+struct kgsl_iommu_device {
+	struct device *dev;
+	int attached;
+};
+
 struct kgsl_iommu {
-	struct device *iommu_user_dev;
-	int iommu_user_dev_attached;
-	struct device *iommu_priv_dev;
-	int iommu_priv_dev_attached;
+	struct kgsl_iommu_device dev[KGSL_IOMMU_MAX_DEV];
+	int dev_count;
 };
 
 static int kgsl_iommu_pt_equal(struct kgsl_pagetable *pt,
@@ -58,89 +70,101 @@
 {
 	struct iommu_domain *domain;
 	struct kgsl_iommu *iommu = mmu->priv;
+	int i;
 
 	BUG_ON(mmu->hwpagetable == NULL);
 	BUG_ON(mmu->hwpagetable->priv == NULL);
 
 	domain = mmu->hwpagetable->priv;
 
-	if (iommu->iommu_user_dev_attached) {
-		iommu_detach_device(domain, iommu->iommu_user_dev);
-		iommu->iommu_user_dev_attached = 0;
+	for (i = 0; i < iommu->dev_count; i++) {
+		iommu_detach_device(domain, iommu->dev[i].dev);
+		iommu->dev[i].attached = 0;
 		KGSL_MEM_INFO(mmu->device,
-				"iommu %p detached from user dev of MMU: %p\n",
-				domain, mmu);
-	}
-	if (iommu->iommu_priv_dev_attached) {
-		iommu_detach_device(domain, iommu->iommu_priv_dev);
-		iommu->iommu_priv_dev_attached = 0;
-		KGSL_MEM_INFO(mmu->device,
-				"iommu %p detached from priv dev of MMU: %p\n",
-				domain, mmu);
+			"iommu %p detached from user dev of MMU: %p\n",
+			domain, mmu);
 	}
 }
 
 static int kgsl_attach_pagetable_iommu_domain(struct kgsl_mmu *mmu)
 {
 	struct iommu_domain *domain;
-	int ret = 0;
 	struct kgsl_iommu *iommu = mmu->priv;
+	int i, ret = 0;
 
 	BUG_ON(mmu->hwpagetable == NULL);
 	BUG_ON(mmu->hwpagetable->priv == NULL);
 
 	domain = mmu->hwpagetable->priv;
 
-	if (iommu->iommu_user_dev && !iommu->iommu_user_dev_attached) {
-		ret = iommu_attach_device(domain, iommu->iommu_user_dev);
-		if (ret) {
-			KGSL_MEM_ERR(mmu->device,
-			"Failed to attach device, err %d\n", ret);
-			goto done;
-		}
-		iommu->iommu_user_dev_attached = 1;
-		KGSL_MEM_INFO(mmu->device,
-				"iommu %p attached to user dev of MMU: %p\n",
+	for (i = 0; i < iommu->dev_count; i++) {
+		if (iommu->dev[i].attached == 0) {
+			ret = iommu_attach_device(domain, iommu->dev[i].dev);
+			if (ret) {
+				KGSL_MEM_ERR(mmu->device,
+					"Failed to attach device, err %d\n",
+						ret);
+				goto done;
+			}
+
+			iommu->dev[i].attached = 1;
+			KGSL_MEM_INFO(mmu->device,
+				"iommu %p detached from user dev of MMU: %p\n",
 				domain, mmu);
-	}
-	if (iommu->iommu_priv_dev && !iommu->iommu_priv_dev_attached) {
-		ret = iommu_attach_device(domain, iommu->iommu_priv_dev);
-		if (ret) {
-			KGSL_MEM_ERR(mmu->device,
-				"Failed to attach device, err %d\n", ret);
-			iommu_detach_device(domain, iommu->iommu_user_dev);
-			iommu->iommu_user_dev_attached = 0;
-			goto done;
 		}
-		iommu->iommu_priv_dev_attached = 1;
-		KGSL_MEM_INFO(mmu->device,
-				"iommu %p attached to priv dev of MMU: %p\n",
-				domain, mmu);
 	}
+
 done:
 	return ret;
 }
 
+static int _get_iommu_ctxs(struct kgsl_iommu *iommu, struct kgsl_device *device,
+	struct kgsl_device_iommu_data *data)
+{
+	int i;
+
+	for (i = 0; i < data->iommu_ctx_count; i++) {
+		if (iommu->dev_count >= KGSL_IOMMU_MAX_DEV) {
+			KGSL_CORE_ERR("Tried to attach too many IOMMU "
+				"devices\n");
+			return -ENOMEM;
+		}
+
+		if (!data->iommu_ctx_names[i])
+			continue;
+
+		iommu->dev[iommu->dev_count].dev =
+			msm_iommu_get_ctx(data->iommu_ctx_names[i]);
+		if (iommu->dev[iommu->dev_count].dev == NULL) {
+			KGSL_CORE_ERR("Failed to iommu dev handle for "
+				"device %s\n", data->iommu_ctx_names[i]);
+			return -EINVAL;
+		}
+
+		iommu->dev_count++;
+	}
+
+	return 0;
+}
+
 static int kgsl_get_iommu_ctxt(struct kgsl_iommu *iommu,
 				struct kgsl_device *device)
 {
-	int status = 0;
 	struct platform_device *pdev =
 		container_of(device->parentdev, struct platform_device, dev);
 	struct kgsl_device_platform_data *pdata_dev = pdev->dev.platform_data;
-	if (pdata_dev->iommu_user_ctx_name)
-		iommu->iommu_user_dev = msm_iommu_get_ctx(
-					pdata_dev->iommu_user_ctx_name);
-	if (pdata_dev->iommu_priv_ctx_name)
-		iommu->iommu_priv_dev = msm_iommu_get_ctx(
-					pdata_dev->iommu_priv_ctx_name);
-	if (!iommu->iommu_user_dev) {
-		KGSL_CORE_ERR("Failed to get user iommu dev handle for "
-				"device %s\n",
-				pdata_dev->iommu_user_ctx_name);
-		status = -EINVAL;
+	int i, ret = 0;
+
+	/* Go through the IOMMU data and attach all the domains */
+
+	for (i = 0; i < pdata_dev->iommu_count; i++) {
+		ret = _get_iommu_ctxs(iommu, device,
+			&pdata_dev->iommu_data[i]);
+		if (ret)
+			break;
 	}
-	return status;
+
+	return ret;
 }
 
 static void kgsl_iommu_setstate(struct kgsl_device *device,
@@ -182,8 +206,6 @@
 		return -ENOMEM;
 	}
 
-	iommu->iommu_priv_dev_attached = 0;
-	iommu->iommu_user_dev_attached = 0;
 	status = kgsl_get_iommu_ctxt(iommu, device);
 	if (status) {
 		kfree(iommu);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 1ef71a4..b671f86 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -66,8 +66,17 @@
 		struct kgsl_pwrlevel *pwrlevel = &pwr->pwrlevels[new_level];
 		pwr->active_pwrlevel = new_level;
 		if ((test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags)) ||
-			(device->state == KGSL_STATE_NAP))
+			(device->state == KGSL_STATE_NAP)) {
+			/*
+			 * On some platforms, instability is caused on
+			 * changing clock freq when the core is busy.
+			 * Idle the gpu core before changing the clock freq.
+			 */
+			if (pwr->idle_needed == true)
+				device->ftbl->idle(device,
+						KGSL_TIMEOUT_DEFAULT);
 			clk_set_rate(pwr->grp_clks[0], pwrlevel->gpu_freq);
+		}
 		if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) {
 			if (pwr->pcl)
 				msm_bus_scale_client_update_request(pwr->pcl,
@@ -362,7 +371,6 @@
 		}
 	}
 }
-EXPORT_SYMBOL(kgsl_pwrctrl_clk);
 
 void kgsl_pwrctrl_axi(struct kgsl_device *device, int state)
 {
@@ -499,6 +507,7 @@
 	pwr->power_flags = 0;
 
 	pwr->nap_allowed = pdata->nap_allowed;
+	pwr->idle_needed = pdata->idle_needed;
 	pwr->interval_timeout = pdata->idle_timeout;
 	pwr->ebi1_clk = clk_get(&pdev->dev, "bus_clk");
 	if (IS_ERR(pwr->ebi1_clk))
@@ -870,16 +879,6 @@
 }
 EXPORT_SYMBOL(kgsl_pwrctrl_disable);
 
-void kgsl_pwrctrl_stop_work(struct kgsl_device *device)
-{
-	del_timer_sync(&device->idle_timer);
-	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
-	mutex_unlock(&device->mutex);
-	flush_workqueue(device->work_queue);
-	mutex_lock(&device->mutex);
-}
-EXPORT_SYMBOL(kgsl_pwrctrl_stop_work);
-
 void kgsl_pwrctrl_set_state(struct kgsl_device *device, unsigned int state)
 {
 	trace_kgsl_pwr_set_state(device, state);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 23e2bd1..f474c21 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -50,6 +50,7 @@
 	struct regulator *gpu_reg;
 	uint32_t pcl;
 	unsigned int nap_allowed;
+	unsigned int idle_needed;
 	const char *regulator_name;
 	const char *irq_name;
 	s64 time;
@@ -58,7 +59,6 @@
 };
 
 void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
-void kgsl_pwrctrl_clk(struct kgsl_device *device, int state);
 int kgsl_pwrctrl_init(struct kgsl_device *device);
 void kgsl_pwrctrl_close(struct kgsl_device *device);
 void kgsl_timer(unsigned long data);
@@ -73,7 +73,6 @@
 void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device);
 void kgsl_pwrctrl_enable(struct kgsl_device *device);
 void kgsl_pwrctrl_disable(struct kgsl_device *device);
-void kgsl_pwrctrl_stop_work(struct kgsl_device *device);
 static inline unsigned long kgsl_get_clkrate(struct clk *clk)
 {
 	return (clk != NULL) ? clk_get_rate(clk) : 0;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 7211879..389ed6d 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -636,13 +636,17 @@
 			uint32_t *dst,
 			unsigned int offsetbytes)
 {
+	uint32_t *src;
 	BUG_ON(memdesc == NULL || memdesc->hostptr == NULL || dst == NULL);
-	WARN_ON(offsetbytes + sizeof(unsigned int) > memdesc->size);
+	WARN_ON(offsetbytes % sizeof(uint32_t) != 0);
+	if (offsetbytes % sizeof(uint32_t) != 0)
+		return -EINVAL;
 
-	if (offsetbytes + sizeof(unsigned int) > memdesc->size)
+	WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
+	if (offsetbytes + sizeof(uint32_t) > memdesc->size)
 		return -ERANGE;
-
-	*dst = readl_relaxed(memdesc->hostptr + offsetbytes);
+	src = (uint32_t *)(memdesc->hostptr + offsetbytes);
+	*dst = *src;
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_sharedmem_readl);
@@ -652,12 +656,19 @@
 			unsigned int offsetbytes,
 			uint32_t src)
 {
+	uint32_t *dst;
 	BUG_ON(memdesc == NULL || memdesc->hostptr == NULL);
-	BUG_ON(offsetbytes + sizeof(unsigned int) > memdesc->size);
+	WARN_ON(offsetbytes % sizeof(uint32_t) != 0);
+	if (offsetbytes % sizeof(uint32_t) != 0)
+		return -EINVAL;
 
+	WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
+	if (offsetbytes + sizeof(uint32_t) > memdesc->size)
+		return -ERANGE;
 	kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes,
-		src, sizeof(uint));
-	writel_relaxed(src, memdesc->hostptr + offsetbytes);
+		src, sizeof(uint32_t));
+	dst = (uint32_t *)(memdesc->hostptr + offsetbytes);
+	*dst = src;
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_sharedmem_writel);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 718fac9..cb3da90 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -584,6 +584,8 @@
 	device->ftbl->irqctrl(device, 0);
 	z180_idle(device, KGSL_TIMEOUT_DEFAULT);
 
+	del_timer_sync(&device->idle_timer);
+
 	kgsl_mmu_stop(device);
 
 	/* Disable the clocks before the power rail. */
diff --git a/drivers/hwmon/msm_adc.c b/drivers/hwmon/msm_adc.c
index b8d581e..39bfc3a 100644
--- a/drivers/hwmon/msm_adc.c
+++ b/drivers/hwmon/msm_adc.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
@@ -1380,7 +1380,7 @@
 	},
 };
 
-static int msm_adc_probe(struct platform_device *pdev)
+static int __devinit msm_adc_probe(struct platform_device *pdev)
 {
 	struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
 	struct msm_adc_drv *msm_adc;
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 5f8faee..0902c61 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -165,6 +165,7 @@
 };
 
 static struct pm8xxx_adc *pmic_adc;
+static struct regulator *pa_therm;
 
 static struct pm8xxx_adc_scale_fn adc_scale_fn[] = {
 	[ADC_SCALE_DEFAULT] = {pm8xxx_adc_scale_default},
@@ -238,26 +239,21 @@
 
 static int32_t pm8xxx_adc_patherm_power(bool on)
 {
-	static struct regulator *pa_therm;
-	struct pm8xxx_adc *adc_pmic = pmic_adc;
 	int rc = 0;
-	if (on) {
-		pa_therm = regulator_get(adc_pmic->dev,
-						"pa_therm");
-		if (IS_ERR(pa_therm)) {
-			rc = PTR_ERR(pa_therm);
-			pr_err("failed to request pa_therm vreg "
-					"with error %d\n", rc);
-			return rc;
-		}
 
+	if (!pa_therm) {
+		pr_err("pm8xxx adc pa_therm not valid\n");
+		return -EINVAL;
+	}
+
+	if (on) {
 		rc = regulator_set_voltage(pa_therm,
 				PM8XXX_ADC_PA_THERM_VREG_UV_MIN,
 				PM8XXX_ADC_PA_THERM_VREG_UV_MAX);
 		if (rc < 0) {
 			pr_err("failed to set the voltage for "
 					"pa_therm with error %d\n", rc);
-			goto fail;
+			return rc;
 		}
 
 		rc = regulator_set_optimum_mode(pa_therm,
@@ -265,25 +261,25 @@
 		if (rc < 0) {
 			pr_err("failed to set optimum mode for "
 					"pa_therm with error %d\n", rc);
-			goto fail;
+			return rc;
 		}
 
-		if (regulator_enable(pa_therm)) {
-			pr_err("failed to enable pa_therm vreg with "
-						"error %d\n", rc);
-			goto fail;
+		rc = regulator_enable(pa_therm);
+		if (rc < 0) {
+			pr_err("failed to enable pa_therm vreg "
+					"with error %d\n", rc);
+			return rc;
 		}
 	} else {
-		if (pa_therm != NULL) {
-			regulator_disable(pa_therm);
-			regulator_put(pa_therm);
+		rc = regulator_disable(pa_therm);
+		if (rc < 0) {
+			pr_err("failed to disable pa_therm vreg "
+					"with error %d\n", rc);
+			return rc;
 		}
 	}
 
 	return rc;
-fail:
-	regulator_put(pa_therm);
-	return rc;
 }
 
 static int32_t pm8xxx_adc_channel_power_enable(uint32_t channel,
@@ -293,7 +289,7 @@
 
 	switch (channel)
 	case ADC_MPP_1_AMUX8:
-		pm8xxx_adc_patherm_power(power_cntrl);
+		rc = pm8xxx_adc_patherm_power(power_cntrl);
 
 	return rc;
 }
@@ -769,6 +765,9 @@
 	struct pm8xxx_adc *adc_pmic = pmic_adc;
 	int rc = 0;
 
+	if (!pm8xxx_adc_initialized)
+		return -ENODEV;
+
 	if (!adc_pmic->mpp_base) {
 		rc = -EINVAL;
 		pr_info("PM8xxx MPP base invalid with error %d\n", rc);
@@ -1138,6 +1137,10 @@
 	wake_lock_destroy(&adc_pmic->adc_wakelock);
 	platform_set_drvdata(pdev, NULL);
 	pmic_adc = NULL;
+	if (!pa_therm) {
+		regulator_put(pa_therm);
+		pa_therm = NULL;
+	}
 	for (i = 0; i < adc_pmic->adc_num_board_channel; i++)
 		device_remove_file(adc_pmic->dev,
 				&adc_pmic->sens_attr[i].dev_attr);
@@ -1252,6 +1255,13 @@
 		dev_err(&pdev->dev, "failed to initialize pm8xxx hwmon adc\n");
 	}
 	adc_pmic->hwmon = hwmon_device_register(adc_pmic->dev);
+
+	pa_therm = regulator_get(adc_pmic->dev, "pa_therm");
+	if (IS_ERR(pa_therm)) {
+		rc = PTR_ERR(pa_therm);
+		pr_err("failed to request pa_therm vreg with error %d\n", rc);
+		pa_therm = NULL;
+	}
 	return 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index c8b4707..4988313 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -324,13 +324,13 @@
 {
 	dev->clk_state = state;
 	if (state != 0) {
-		clk_prepare_enable(dev->clk);
-		clk_prepare_enable(dev->pclk);
+		clk_enable(dev->clk);
+		clk_enable(dev->pclk);
 	} else {
 		qup_update_state(dev, QUP_RESET_STATE);
-		clk_disable_unprepare(dev->clk);
+		clk_disable(dev->clk);
 		qup_config_core_on_en(dev);
-		clk_disable_unprepare(dev->pclk);
+		clk_disable(dev->pclk);
 	}
 }
 
@@ -1285,6 +1285,8 @@
 	dev->suspended = 0;
 	mutex_init(&dev->mlock);
 	dev->clk_state = 0;
+	clk_prepare(dev->clk);
+	clk_prepare(dev->pclk);
 	setup_timer(&dev->pwr_timer, qup_i2c_pwr_timer, (unsigned long) dev);
 
 	pm_runtime_set_active(&pdev->dev);
@@ -1344,6 +1346,8 @@
 	}
 	free_irq(dev->err_irq, dev);
 	i2c_del_adapter(&dev->adapter);
+	clk_unprepare(dev->clk);
+	clk_unprepare(dev->pclk);
 	clk_put(dev->clk);
 	clk_put(dev->pclk);
 	qup_i2c_free_gpios(dev);
@@ -1378,6 +1382,8 @@
 	del_timer_sync(&dev->pwr_timer);
 	if (dev->clk_state != 0)
 		qup_i2c_pwr_mgmt(dev, 0);
+	clk_unprepare(dev->clk);
+	clk_unprepare(dev->pclk);
 	qup_i2c_free_gpios(dev);
 	return 0;
 }
@@ -1387,6 +1393,8 @@
 	struct platform_device *pdev = to_platform_device(device);
 	struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
 	BUG_ON(qup_i2c_request_gpios(dev) != 0);
+	clk_prepare(dev->clk);
+	clk_prepare(dev->pclk);
 	dev->suspended = 0;
 	return 0;
 }
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index d2a8879..40aae69 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -18,7 +18,7 @@
 #include <linux/firmware.h>
 #include <linux/i2c.h>
 #include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
@@ -611,22 +611,23 @@
 		if (!finger[id].status)
 			continue;
 
-		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
-				finger[id].status != MXT_RELEASE ?
-				finger[id].area : 0);
-		input_report_abs(input_dev, ABS_MT_POSITION_X,
-				finger[id].x);
-		input_report_abs(input_dev, ABS_MT_POSITION_Y,
-				finger[id].y);
-		input_report_abs(input_dev, ABS_MT_PRESSURE,
-				finger[id].status != MXT_RELEASE ?
-				finger[id].pressure : 0);
-		input_mt_sync(input_dev);
+		input_mt_slot(input_dev, id);
+		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+				finger[id].status != MXT_RELEASE);
 
-		if (finger[id].status == MXT_RELEASE)
-			finger[id].status = 0;
-		else
+		if (finger[id].status != MXT_RELEASE) {
 			finger_num++;
+			input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+					finger[id].area);
+			input_report_abs(input_dev, ABS_MT_POSITION_X,
+					finger[id].x);
+			input_report_abs(input_dev, ABS_MT_POSITION_Y,
+					finger[id].y);
+			input_report_abs(input_dev, ABS_MT_PRESSURE,
+					finger[id].area);
+		} else {
+			finger[id].status = 0;
+		}
 	}
 
 	input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
@@ -1841,6 +1842,7 @@
 			     0, 255, 0, 0);
 
 	/* For multi touch */
+	input_mt_init_slots(input_dev, MXT_MAX_FINGER);
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			     0, MXT_MAX_AREA, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
diff --git a/drivers/input/touchscreen/cyttsp-i2c.c b/drivers/input/touchscreen/cyttsp-i2c.c
index a60dbf5..267e481 100644
--- a/drivers/input/touchscreen/cyttsp-i2c.c
+++ b/drivers/input/touchscreen/cyttsp-i2c.c
@@ -710,25 +710,26 @@
 	else if (!(g_bl_data.bl_status & BL_CHECKSUM_MASK) &&
 			(appid_lo == ts->platform_data->correct_fw_ver))
 		fw_upgrade = 1;
-	else
-		if ((appid_hi == g_bl_data.appid_hi) &&
-			(appid_lo == g_bl_data.appid_lo)) {
-			if (appver_hi > g_bl_data.appver_hi) {
+	else if ((appid_hi == g_bl_data.appid_hi) &&
+			(appid_lo == g_bl_data.appid_lo))
+			if (appver_hi > g_bl_data.appver_hi)
 				fw_upgrade = 1;
-			} else if ((appver_hi == g_bl_data.appver_hi) &&
-					 (appver_lo > g_bl_data.appver_lo)) {
-					fw_upgrade = 1;
-				} else {
-					fw_upgrade = 0;
-					pr_info("%s: Firmware version "
-					"lesser/equal to existing firmware, "
-					"upgrade not needed\n", __func__);
-				}
-		} else {
-			fw_upgrade = 0;
-			pr_info("%s: Firware versions do not match, "
-						"cannot upgrade\n", __func__);
-		}
+			else if ((appver_hi == g_bl_data.appver_hi) &&
+					 (appver_lo > g_bl_data.appver_lo))
+				fw_upgrade = 1;
+			else {
+				fw_upgrade = 0;
+				pr_info("%s: Firmware version "
+				"lesser/equal to existing firmware, "
+				"upgrade not needed\n", __func__);
+			}
+	else if (appid_lo == ts->platform_data->correct_fw_ver)
+		fw_upgrade = 1;
+	else {
+		fw_upgrade = 0;
+		pr_info("%s: Firmware versions do not match, "
+					"cannot upgrade\n", __func__);
+	}
 
 	if (fw_upgrade) {
 		pr_info("%s: Starting firmware upgrade\n", __func__);
diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c
index 57b11c9..ed6ab4d 100644
--- a/drivers/media/radio/radio-iris-transport.c
+++ b/drivers/media/radio/radio-iris-transport.c
@@ -4,7 +4,7 @@
  *  FM HCI_SMD ( FM HCI Shared Memory Driver) is Qualcomm's Shared memory driver
  *  for the HCI protocol. This file is based on drivers/bluetooth/hci_vhci.c
  *
- *  Copyright (c) 2000-2001, 2011 Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2000-2001, 2011-2012 Code Aurora Forum. All rights reserved.
  *
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
  *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
@@ -25,6 +25,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
+#include <linux/workqueue.h>
 #include <mach/msm_smd.h>
 #include <media/radio-iris.h>
 
@@ -35,6 +36,8 @@
 };
 struct radio_data hs;
 
+static struct work_struct *reset_worker;
+
 static void radio_hci_smd_destruct(struct radio_hci_dev *hdev)
 {
 	radio_hci_unregister_dev(hs.hdev);
@@ -92,6 +95,30 @@
 	return 0;
 }
 
+
+static void send_disable_event(struct work_struct *worker)
+{
+	struct sk_buff *skb;
+	unsigned char buf[6] = { 0x0f, 0x04, 0x01, 0x02, 0x4c, 0x00 };
+	int len = sizeof(buf);
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (!skb) {
+		FMDERR("Memory not allocated for the socket");
+		return;
+	}
+
+	FMDERR("FM INSERT DISABLE Rx Event");
+
+	memcpy(skb_put(skb, len), buf, len);
+
+	skb_orphan(skb);
+	skb->dev = (struct net_device   *)hs.hdev;
+
+	radio_hci_recv_frame(skb);
+	kfree(worker);
+}
+
 static void radio_hci_smd_notify_cmd(void *data, unsigned int event)
 {
 	struct radio_hci_dev *hdev = hs.hdev;
@@ -106,7 +133,15 @@
 		tasklet_schedule(&hs.rx_task);
 		break;
 	case SMD_EVENT_OPEN:
+		break;
 	case SMD_EVENT_CLOSE:
+		reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC);
+		if (!reset_worker) {
+			FMDERR("Out of memory");
+			break;
+		}
+		INIT_WORK(reset_worker, send_disable_event);
+		schedule_work(reset_worker);
 		break;
 	default:
 		break;
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 545c61c..793f063 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -1589,7 +1589,7 @@
 	if (status)
 		return;
 
-	iris_q_event(radio, IRIS_EVT_RADIO_READY);
+	iris_q_event(radio, IRIS_EVT_RADIO_DISABLED);
 
 	radio_hci_req_complete(hdev, status);
 }
@@ -2609,7 +2609,7 @@
 
 		} else
 			retval = -EINVAL;
-
+		break;
 	case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
 		if (retval < 0) {
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index ca44c34..e70a0a5 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -33,8 +33,7 @@
 	  MICRON 2M YUV Sensor
 config IMX074
 	bool "Sensor IMX074 (BAYER 13.5M)"
-	depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM8960)
-	default y
+	depends on MSM_CAMERA
 	---help---
 	SONY 13.5 MP Bayer Sensor
 config OV5640
@@ -43,6 +42,12 @@
 	default n
 	---help---
 	Omni 5M YUV Sensor
+
+config OV5647
+	bool "Sensor ov5647 (BAYER 5M)"
+	depends on MSM_CAMERA
+	---help---
+	  OV 5M Bayer Sensor with AutoFocus
 config WEBCAM_OV7692_QRD
 	bool "Sensor OV7692 QRD(VGA YUV)"
 	depends on MSM_CAMERA && ARCH_MSM7X27A && !MSM_CAMERA_V4L2
@@ -51,7 +56,7 @@
 	  Omni Vision VGA YUV Sensor for QRD Devices
 config MT9M114
         bool "Sensor MT9M114 (YUV 1.26M)"
-        depends on MSM_CAMERA && ARCH_MSM8960
+        depends on MSM_CAMERA
         ---help---
         APTINA 1.26 MP yuv Sensor
 config WEBCAM_OV7692
@@ -120,8 +125,7 @@
 
 config IMX074_ACT
 	bool "Actuator IMX074 (BAYER 13.5M)"
-	depends on MSM_CAMERA && ARCH_MSM8960
-	default y
+	depends on MSM_CAMERA
 	---help---
 	Actuator for SONY 13.5 MP Bayer Sensor
 
@@ -177,8 +181,7 @@
 
 config OV2720
 	bool "Sensor ov2720 (Omnivision 2MP)"
-	depends on MSM_CAMERA && ARCH_MSM8960
-	default y
+	depends on MSM_CAMERA
 
 config VB6801
 	bool "Sensor vb6801"
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index b91449a..8703669 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -44,6 +44,8 @@
 obj-$(CONFIG_QS_S5K4E1) += qs_s5k4e1.o qs_s5k4e1_reg.o
 obj-$(CONFIG_VB6801) += vb6801.o
 obj-$(CONFIG_IMX072) += imx072.o imx072_reg.o
+obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
+obj-$(CONFIG_OV5647) += ov5647.o ov5647_reg.o
 obj-$(CONFIG_WEBCAM_OV7692) += ov7692.o
 obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd.o
 obj-$(CONFIG_OV5640) += ov5640.o
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
index e4d340d4..78eef72 100644
--- a/drivers/media/video/msm/actuators/imx074_act.c
+++ b/drivers/media/video/msm/actuators/imx074_act.c
@@ -197,6 +197,11 @@
 		(struct v4l2_subdev *)sdev);
 }
 
+static int imx074_act_power_down(void *act_info)
+{
+	return (int) msm_actuator_af_power_down(&imx074_act_t);
+}
+
 static struct msm_actuator_ctrl_t imx074_act_t = {
 	.i2c_driver = &imx074_act_i2c_driver,
 	.i2c_addr = 0xE4,
@@ -205,6 +210,7 @@
 		.a_init_table = imx074_i2c_add_driver_table,
 		.a_create_subdevice = imx074_act_create_subdevice,
 		.a_config = imx074_act_config,
+		.a_power_down = imx074_act_power_down,
 	},
 
 	.i2c_client = {
@@ -238,6 +244,10 @@
 		.f_pix_den = 10,
 		.total_f_dist_num = 197681,
 		.total_f_dist_den = 1000,
+		.hor_view_angle_num = 548,
+		.hor_view_angle_den = 10,
+		.ver_view_angle_num = 425,
+		.ver_view_angle_den = 10,
 	},
 
 	/* Initialize scenario */
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 7a0ee4d..d247467 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -138,6 +138,10 @@
 	{"csi_pclk", -1},
 };
 
+static struct camera_vreg_t csid_vreg_info[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+};
+
 static int msm_csid_init(struct v4l2_subdev *sd, uint32_t *csid_version)
 {
 	int rc = 0;
@@ -155,11 +159,25 @@
 		return rc;
 	}
 
+	rc = msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 1);
+	if (rc < 0) {
+		pr_err("%s: regulator on failed\n", __func__);
+		goto vreg_config_failed;
+	}
+
+	rc = msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 1);
+	if (rc < 0) {
+		pr_err("%s: regulator enable failed\n", __func__);
+		goto vreg_enable_failed;
+	}
+
 	rc = msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
 		csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 1);
 	if (rc < 0) {
-		iounmap(csid_dev->base);
-		return rc;
+		pr_err("%s: regulator enable failed\n", __func__);
+		goto clk_enable_failed;
 	}
 
 #if DBG_CSID
@@ -167,8 +185,17 @@
 #endif
 
 	*csid_version = csid_dev->hw_version;
-
 	return 0;
+
+clk_enable_failed:
+	msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+vreg_enable_failed:
+	msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+vreg_config_failed:
+	iounmap(csid_dev->base);
+	return rc;
 }
 
 static int msm_csid_release(struct v4l2_subdev *sd)
@@ -183,6 +210,12 @@
 	msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
 		csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
 
+	msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+
+	msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+
 	iounmap(csid_dev->base);
 	return 0;
 }
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/video/msm/csi/msm_csid.h
index f90abf2..105cd49 100644
--- a/drivers/media/video/msm/csi/msm_csid.h
+++ b/drivers/media/video/msm/csi/msm_csid.h
@@ -23,6 +23,7 @@
 	struct resource *mem;
 	struct resource *irq;
 	struct resource *io;
+	struct regulator *csi_vdd;
 	void __iomem *base;
 	struct mutex mutex;
 	uint32_t hw_version;
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index 109b3dd..315cca7 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.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
@@ -79,21 +79,14 @@
 	msm_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
 
 	for (i = 0; i < csiphy_params->lane_cnt; i++) {
-		msm_io_w(0x00, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
-		msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+		msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
 		msm_io_w(csiphy_params->settle_cnt,
 			csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*i);
-		msm_io_w(0x00000052,
-			csiphybase + MIPI_CSIPHY_LNn_CFG5_ADDR + 0x40*i);
 	}
 
-	msm_io_w(0x00000000, csiphybase + MIPI_CSIPHY_LNCK_CFG1_ADDR);
-	msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+	msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
 	msm_io_w(csiphy_params->settle_cnt,
 			 csiphybase + MIPI_CSIPHY_LNCK_CFG3_ADDR);
-	msm_io_w(0x5, csiphybase + MIPI_CSIPHY_LNCK_CFG4_ADDR);
-	msm_io_w(0x2, csiphybase + MIPI_CSIPHY_LNCK_CFG5_ADDR);
-	msm_io_w(0x0, csiphybase + 0x128);
 
 	msm_io_w(0x24,
 		csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR);
diff --git a/drivers/media/video/msm/io/Makefile b/drivers/media/video/msm/io/Makefile
index 584738d..c567be2 100644
--- a/drivers/media/video/msm/io/Makefile
+++ b/drivers/media/video/msm/io/Makefile
@@ -1,3 +1,4 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_eeprom.o
+EXTRA_CFLAGS += -Idrivers/media/video/msm
+obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_eeprom.o msm_camera_i2c_mux.o
 obj-$(CONFIG_MSM_CAMERA) += msm_io_util.o
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.c b/drivers/media/video/msm/io/msm_camera_i2c_mux.c
new file mode 100644
index 0000000..ad3128b
--- /dev/null
+++ b/drivers/media/video/msm/io/msm_camera_i2c_mux.c
@@ -0,0 +1,186 @@
+/* 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/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include "msm.h"
+#include "msm_camera_i2c_mux.h"
+
+static int msm_i2c_mux_config(struct i2c_mux_device *mux_device, uint8_t *mode)
+{
+	uint32_t val;
+	val = msm_io_r(mux_device->ctl_base);
+	if (*mode == MODE_DUAL) {
+		msm_io_w(val | 0x3, mux_device->ctl_base);
+	} else if (*mode == MODE_L) {
+		msm_io_w(((val | 0x2) & ~(0x1)), mux_device->ctl_base);
+		val = msm_io_r(mux_device->ctl_base);
+		CDBG("the camio mode config left value is %d\n", val);
+	} else {
+		msm_io_w(((val | 0x1) & ~(0x2)), mux_device->ctl_base);
+		val = msm_io_r(mux_device->ctl_base);
+		CDBG("the camio mode config right value is %d\n", val);
+	}
+	return 0;
+}
+
+static int msm_i2c_mux_init(struct i2c_mux_device *mux_device)
+{
+	int rc = 0, val = 0;
+	if (mux_device->use_count == 0) {
+		mux_device->ctl_base = ioremap(mux_device->ctl_mem->start,
+			resource_size(mux_device->ctl_mem));
+		if (!mux_device->ctl_base) {
+			rc = -ENOMEM;
+			return rc;
+		}
+		mux_device->rw_base = ioremap(mux_device->rw_mem->start,
+			resource_size(mux_device->rw_mem));
+		if (!mux_device->rw_base) {
+			rc = -ENOMEM;
+			iounmap(mux_device->ctl_base);
+			return rc;
+		}
+		val = msm_io_r(mux_device->rw_base);
+		msm_io_w((val | 0x200), mux_device->rw_base);
+	}
+	mux_device->use_count++;
+	return 0;
+};
+
+static int msm_i2c_mux_release(struct i2c_mux_device *mux_device)
+{
+	int val = 0;
+	mux_device->use_count--;
+	if (mux_device->use_count == 0) {
+		val = msm_io_r(mux_device->rw_base);
+		msm_io_w((val & ~0x200), mux_device->rw_base);
+		iounmap(mux_device->rw_base);
+		iounmap(mux_device->ctl_base);
+	}
+	return 0;
+}
+
+static long msm_i2c_mux_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct i2c_mux_device *mux_device;
+	int rc = 0;
+	mux_device = v4l2_get_subdevdata(sd);
+	if (mux_device == NULL) {
+		rc = -ENOMEM;
+		return rc;
+	}
+	mutex_lock(&mux_device->mutex);
+	switch (cmd) {
+	case VIDIOC_MSM_I2C_MUX_CFG:
+		rc = msm_i2c_mux_config(mux_device, (uint8_t *) arg);
+		break;
+	case VIDIOC_MSM_I2C_MUX_INIT:
+		rc = msm_i2c_mux_init(mux_device);
+		break;
+	case VIDIOC_MSM_I2C_MUX_RELEASE:
+		rc = msm_i2c_mux_release(mux_device);
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+	}
+	mutex_unlock(&mux_device->mutex);
+	return rc;
+}
+
+static struct v4l2_subdev_core_ops msm_i2c_mux_subdev_core_ops = {
+	.ioctl = &msm_i2c_mux_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_i2c_mux_subdev_ops = {
+	.core = &msm_i2c_mux_subdev_core_ops,
+};
+
+static int __devinit i2c_mux_probe(struct platform_device *pdev)
+{
+	struct i2c_mux_device *mux_device;
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	mux_device = kzalloc(sizeof(struct i2c_mux_device), GFP_KERNEL);
+	if (!mux_device) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&mux_device->subdev, &msm_i2c_mux_subdev_ops);
+	v4l2_set_subdevdata(&mux_device->subdev, mux_device);
+	platform_set_drvdata(pdev, &mux_device->subdev);
+	mutex_init(&mux_device->mutex);
+
+	mux_device->ctl_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "i2c_mux_ctl");
+	if (!mux_device->ctl_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->ctl_io = request_mem_region(mux_device->ctl_mem->start,
+		resource_size(mux_device->ctl_mem), pdev->name);
+	if (!mux_device->ctl_io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->rw_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "i2c_mux_rw");
+	if (!mux_device->rw_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->rw_io = request_mem_region(mux_device->rw_mem->start,
+		resource_size(mux_device->rw_mem), pdev->name);
+	if (!mux_device->rw_io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->pdev = pdev;
+	return 0;
+
+i2c_mux_no_resource:
+	mutex_destroy(&mux_device->mutex);
+	kfree(mux_device);
+	return 0;
+}
+
+static struct platform_driver i2c_mux_driver = {
+	.probe = i2c_mux_probe,
+	.driver = {
+		.name = MSM_I2C_MUX_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_camera_i2c_mux_init_module(void)
+{
+	return platform_driver_register(&i2c_mux_driver);
+}
+
+static void __exit msm_camera_i2c_mux_exit_module(void)
+{
+	platform_driver_unregister(&i2c_mux_driver);
+}
+
+module_init(msm_camera_i2c_mux_init_module);
+module_exit(msm_camera_i2c_mux_exit_module);
+MODULE_DESCRIPTION("MSM Camera I2C mux driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.h b/drivers/media/video/msm/io/msm_camera_i2c_mux.h
new file mode 100644
index 0000000..94394fc
--- /dev/null
+++ b/drivers/media/video/msm/io/msm_camera_i2c_mux.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_I2C_MUX_H
+#define MSM_I2C_MUX_H
+
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct i2c_mux_device {
+	struct platform_device *pdev;
+	struct v4l2_subdev subdev;
+	struct resource *ctl_mem;
+	struct resource *ctl_io;
+	void __iomem *ctl_base;
+	struct resource *rw_mem;
+	struct resource *rw_io;
+	void __iomem *rw_base;
+	struct mutex mutex;
+	unsigned use_count;
+};
+
+struct i2c_mux_cfg_params {
+	struct v4l2_subdev *subdev;
+	void *parms;
+};
+
+#define VIDIOC_MSM_I2C_MUX_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct i2c_mux_cfg_params)
+
+#define VIDIOC_MSM_I2C_MUX_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 14, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_I2C_MUX_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct v4l2_subdev*)
+
+#endif
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index ed77185..84d441d 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -157,7 +157,7 @@
 	D("Waiting for config status\n");
 	rc = wait_event_interruptible_timeout(queue->wait,
 		!list_empty_careful(&queue->list),
-		out->timeout_ms);
+		msecs_to_jiffies(out->timeout_ms));
 	D("Waiting is over for config status\n");
 	if (list_empty_careful(&queue->list)) {
 		if (!rc)
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 40bc160..55c0da1 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -48,6 +48,7 @@
 #define MSM_VFE_DRV_NAME "msm_vfe"
 #define MSM_VPE_DRV_NAME "msm_vpe"
 #define MSM_GEMINI_DRV_NAME "msm_gemini"
+#define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
 
 /* msm queue management APIs*/
 
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index d111452..ea969cf 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -32,11 +32,6 @@
 static struct clk *camio_imem_clk;
 static struct regulator *fs_ijpeg;
 
-static struct platform_device *camio_dev;
-static struct resource *s3drw_io, *s3dctl_io;
-static struct resource *s3drw_mem, *s3dctl_mem;
-void __iomem *s3d_rw, *s3d_ctl;
-
 void msm_io_w(u32 data, void __iomem *addr)
 {
 	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
@@ -234,89 +229,6 @@
 	return rc;
 }
 
-int32_t msm_camio_3d_enable(const struct msm_camera_sensor_info *s_info)
-{
-	int32_t val = 0, rc = 0;
-	char s3drw[] = "s3d_rw";
-	char s3dctl[] = "s3d_ctl";
-	struct platform_device *pdev = camio_dev;
-	pdev->resource = s_info->resource;
-	pdev->num_resources = s_info->num_resources;
-
-	s3drw_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, s3drw);
-	if (!s3drw_mem) {
-		pr_err("%s: no mem resource?\n", __func__);
-		return -ENODEV;
-	}
-	s3dctl_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, s3dctl);
-	if (!s3dctl_mem) {
-		pr_err("%s: no mem resource?\n", __func__);
-		return -ENODEV;
-	}
-	s3drw_io = request_mem_region(s3drw_mem->start,
-		resource_size(s3drw_mem), pdev->name);
-	if (!s3drw_io)
-		return -EBUSY;
-
-	s3d_rw = ioremap(s3drw_mem->start,
-		resource_size(s3drw_mem));
-	if (!s3d_rw) {
-		rc = -ENOMEM;
-		goto s3drw_nomem;
-	}
-	s3dctl_io = request_mem_region(s3dctl_mem->start,
-		resource_size(s3dctl_mem), pdev->name);
-	if (!s3dctl_io) {
-		rc = -EBUSY;
-		goto s3dctl_busy;
-	}
-	s3d_ctl = ioremap(s3dctl_mem->start,
-		resource_size(s3dctl_mem));
-	if (!s3d_ctl) {
-		rc = -ENOMEM;
-		goto s3dctl_nomem;
-	}
-
-	val = msm_io_r(s3d_rw);
-	msm_io_w((val | 0x200), s3d_rw);
-	return rc;
-
-s3dctl_nomem:
-	release_mem_region(s3dctl_mem->start, resource_size(s3dctl_mem));
-s3dctl_busy:
-	iounmap(s3d_rw);
-s3drw_nomem:
-	release_mem_region(s3drw_mem->start, resource_size(s3drw_mem));
-return rc;
-}
-
-void msm_camio_3d_disable(void)
-{
-	int32_t val = 0;
-	msm_io_w((val & ~0x200), s3d_rw);
-	iounmap(s3d_ctl);
-	release_mem_region(s3dctl_mem->start, resource_size(s3dctl_mem));
-	iounmap(s3d_rw);
-	release_mem_region(s3drw_mem->start, resource_size(s3drw_mem));
-}
-
-void msm_camio_mode_config(enum msm_cam_mode mode)
-{
-	uint32_t val;
-	val = msm_io_r(s3d_ctl);
-	if (mode == MODE_DUAL) {
-		msm_io_w(val | 0x3, s3d_ctl);
-	} else if (mode == MODE_L) {
-		msm_io_w(((val | 0x2) & ~(0x1)), s3d_ctl);
-		val = msm_io_r(s3d_ctl);
-		CDBG("the camio mode config left value is %d\n", val);
-	} else {
-		msm_io_w(((val | 0x1) & ~(0x2)), s3d_ctl);
-		val = msm_io_r(s3d_ctl);
-		CDBG("the camio mode config right value is %d\n", val);
-	}
-}
-
 void msm_camio_bus_scale_cfg(struct msm_bus_scale_pdata *cam_bus_scale_table,
 		enum msm_bus_perf_setting perf_setting)
 {
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index c9a9f1b..fdd1f0e 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -199,6 +199,19 @@
 		vfe_params.data = (void *)&free_buf;
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		break;
+	case VFE_MSG_V32_JPEG_CAPTURE:
+		free_buf.num_planes = 1;
+		free_buf.ch_paddr[0] = IMEM_Y_OFFSET;
+		free_buf.ch_paddr[1] = IMEM_CBCR_OFFSET;
+		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
+		cfgcmd.value = &vfe_id;
+		vfe_params.vfe_cfg = &cfgcmd;
+		vfe_params.data = (void *)&free_buf;
+		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+		/* Write the same buffer into PONG */
+		cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
+		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+		break;
 	case VFE_MSG_OUTPUT_IRQ:
 		D("%s Got OUTPUT_IRQ: Getting free buf id = %d",
 						__func__, vfe_id);
@@ -349,6 +362,35 @@
 		stats.buffer = msm_pmem_stats_ptov_lookup(&pmctl->sync,
 						isp_stats->buffer,
 						&(stats.fd));
+		switch (isp_stats->id) {
+		case MSG_ID_STATS_AEC:
+			stats.aec.buff = stats.buffer;
+			stats.aec.fd = stats.fd;
+			break;
+		case MSG_ID_STATS_AF:
+			stats.af.buff = stats.buffer;
+			stats.af.fd = stats.fd;
+			break;
+		case MSG_ID_STATS_AWB:
+			stats.awb.buff = stats.buffer;
+			stats.awb.fd = stats.fd;
+			break;
+		case MSG_ID_STATS_IHIST:
+			stats.ihist.buff = stats.buffer;
+			stats.ihist.fd = stats.fd;
+			break;
+		case MSG_ID_STATS_RS:
+			stats.rs.buff = stats.buffer;
+			stats.rs.fd = stats.fd;
+			break;
+		case MSG_ID_STATS_CS:
+			stats.cs.buff = stats.buffer;
+			stats.cs.fd = stats.fd;
+			break;
+		default:
+			pr_err("%s: Invalid msg type", __func__);
+			break;
+		}
 		if (!stats.buffer) {
 			pr_err("%s: msm_pmem_stats_ptov_lookup error\n",
 							__func__);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 99d9911..b539d19 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -598,6 +598,14 @@
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CFG);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_MODULE_CFG);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_PIXEL_IF_CFG);
+	if (msm_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
+		VFE33_HW_NUMBER) {
+		msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI0_CFG);
+		msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI1_CFG);
+	}  else {
+		++p;
+		++p;
+	}
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_REALIGN_BUF);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CHROMA_UP);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_STATS_CFG);
@@ -702,8 +710,6 @@
 	msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
 		vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
 
-	msm_io_dump(vfe32_ctrl->vfebase, vfe32_ctrl->register_total * 4);
-
 	/* Ensure the write order while writing
 	to the command register using the barrier */
 	msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
@@ -851,7 +857,9 @@
 	/* capture command is valid for both idle and active state. */
 	vfe32_ctrl->outpath.out1.capture_cnt = num_frames_capture;
 	if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
-		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
 		vfe32_ctrl->outpath.out0.capture_cnt =
 			num_frames_capture;
 	}
@@ -887,6 +895,9 @@
 				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
 		}
 	}
+
+	vfe32_ctrl->vfe_capture_count = num_frames_capture;
+
 	msm_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camio_bus_scale_cfg(
@@ -1286,16 +1297,31 @@
 		rc = vfe32_capture_raw(snapshot_cnt);
 		break;
 	case VFE_CMD_CAPTURE:
-		pr_info("vfe32_proc_general: cmdID = %s\n",
-			vfe32_general_cmd[cmd->id]);
+		CDBG("vfe32_proc_general: cmdID = %s op mode = %d\n",
+			vfe32_general_cmd[cmd->id], vfe32_ctrl->operation_mode);
 		if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
 				sizeof(uint32_t))) {
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
-		/* Configure primary channel */
-		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
-						  VFE_MSG_OUTPUT_PRIMARY);
+
+		if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
+			if (snapshot_cnt != 1) {
+				pr_err("only support 1 inline snapshot\n");
+				rc = -EINVAL;
+				goto proc_general_done;
+			}
+			/* Configure primary channel for JPEG */
+			rc = vfe32_configure_pingpong_buffers(
+				VFE_MSG_V32_JPEG_CAPTURE,
+				VFE_MSG_OUTPUT_PRIMARY);
+		} else {
+			/* Configure primary channel */
+			rc = vfe32_configure_pingpong_buffers(
+				VFE_MSG_V32_CAPTURE,
+				VFE_MSG_OUTPUT_PRIMARY);
+		}
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				   " for primary output", __func__);
@@ -2610,7 +2636,9 @@
 	}
 
 	if ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
-		(vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB)) {
+		(vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) ||
+		(vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) ||
+		(vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) {
 		/* in snapshot mode */
 		/* later we need to add check for live snapshot mode. */
 		if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
@@ -2858,6 +2886,8 @@
 	*/
 	out_bool = ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
 		vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
 		vfe32_ctrl->operation_mode == VFE_OUTPUTS_RAW ||
 		vfe32_ctrl->liveshot_state == VFE_STATE_STARTED ||
 		vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED ||
@@ -2899,6 +2929,10 @@
 			vfe32_ctrl->operation_mode ==
 				VFE_OUTPUTS_MAIN_AND_THUMB ||
 			vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_THUMB_AND_JPEG ||
+			vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_JPEG_AND_THUMB ||
+			vfe32_ctrl->operation_mode ==
 				VFE_OUTPUTS_RAW ||
 			vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED)
 			vfe32_ctrl->outpath.out0.capture_cnt--;
@@ -3392,6 +3426,10 @@
 				vfe32_ctrl->operation_mode ==
 					VFE_OUTPUTS_MAIN_AND_THUMB ||
 				vfe32_ctrl->operation_mode ==
+					VFE_OUTPUTS_THUMB_AND_JPEG ||
+				vfe32_ctrl->operation_mode ==
+					VFE_OUTPUTS_JPEG_AND_THUMB ||
+				vfe32_ctrl->operation_mode ==
 					VFE_OUTPUTS_RAW) {
 				if ((vfe32_ctrl->outpath.out0.capture_cnt == 0)
 						&& (vfe32_ctrl->outpath.out1.
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 62c3639..0d8be58 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -223,7 +223,7 @@
 #define V32_OUT_CLAMP_OFF         0x00000524
 #define V32_OUT_CLAMP_LEN         8
 
-#define V32_OPERATION_CFG_LEN     36
+#define V32_OPERATION_CFG_LEN     44
 
 #define V32_AXI_OUT_OFF           0x00000038
 #define V32_AXI_OUT_LEN           216
@@ -875,6 +875,9 @@
 #define VFE_DMI_DATA_LO                 0x000005A4
 #define VFE_BUS_IO_FORMAT_CFG           0x000006F8
 #define VFE_PIXEL_IF_CFG                0x000006FC
+#define VFE_RDI0_CFG                    0x00000734
+#define VFE_RDI1_CFG                    0x000007A4
+
 #define VFE_VIOLATION_STATUS            0x000007B4
 
 #define VFE33_DMI_DATA_HI               0x000005A0
diff --git a/drivers/media/video/msm/ov5647.c b/drivers/media/video/msm/ov5647.c
new file mode 100644
index 0000000..2a6e7be
--- /dev/null
+++ b/drivers/media/video/msm/ov5647.c
@@ -0,0 +1,1201 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/bitops.h>
+#include <linux/leds.h>
+#include <mach/camera.h>
+#include <media/msm_camera.h>
+#include "ov5647.h"
+
+/* 16bit address - 8 bit context register structure */
+#define Q8	0x00000100
+#define Q10	0x00000400
+
+#define REG_OV5647_GAIN_MSB           0x350A
+#define REG_OV5647_GAIN_LSB           0x350B
+#define REG_OV5647_LINE_HSB           0x3500
+#define REG_OV5647_LINE_MSB           0x3501
+#define REG_OV5647_LINE_LSB           0x3502
+
+/* MCLK */
+#define OV5647_MASTER_CLK_RATE 24000000
+
+/* AF Total steps parameters */
+#define OV5647_TOTAL_STEPS_NEAR_TO_FAR	32
+
+#define OV5647_REG_PREV_FRAME_LEN_1	31
+#define OV5647_REG_PREV_FRAME_LEN_2	32
+#define OV5647_REG_PREV_LINE_LEN_1	33
+#define OV5647_REG_PREV_LINE_LEN_2	34
+
+#define OV5647_REG_SNAP_FRAME_LEN_1	15
+#define OV5647_REG_SNAP_FRAME_LEN_2	16
+#define OV5647_REG_SNAP_LINE_LEN_1	17
+#define OV5647_REG_SNAP_LINE_LEN_2	18
+#define MSB                             1
+#define LSB                             0
+
+/* Debug switch */
+#ifdef CDBG
+#undef CDBG
+#endif
+#ifdef CDBG_HIGH
+#undef CDBG_HIGH
+#endif
+
+/*#define OV5647_VERBOSE_DGB*/
+
+#ifdef OV5647_VERBOSE_DGB
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#define CDBG_HIGH(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#define CDBG_HIGH(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+/*for debug*/
+#ifdef CDBG
+#undef CDBG
+#endif
+#define CDBG(fmt, args...) printk(fmt, ##args)
+
+static uint8_t  mode_mask = 0x09;
+struct ov5647_work_t {
+	struct work_struct work;
+};
+
+static struct ov5647_work_t *ov5647_sensorw;
+static struct ov5647_work_t *ov5647_af_sensorw;
+static struct i2c_client *ov5647_af_client;
+static struct i2c_client *ov5647_client;
+
+struct ov5647_ctrl_t {
+	const struct  msm_camera_sensor_info *sensordata;
+
+	uint32_t sensormode;
+	uint32_t fps_divider;/* init to 1 * 0x00000400 */
+	uint32_t pict_fps_divider;/* init to 1 * 0x00000400 */
+	uint16_t fps;
+
+	uint16_t curr_lens_pos;
+	uint16_t curr_step_pos;
+	uint16_t my_reg_gain;
+	uint32_t my_reg_line_count;
+	uint16_t total_lines_per_frame;
+
+	enum ov5647_resolution_t prev_res;
+	enum ov5647_resolution_t pict_res;
+	enum ov5647_resolution_t curr_res;
+	enum ov5647_test_mode_t  set_test;
+};
+
+static bool CSI_CONFIG;
+static struct ov5647_ctrl_t *ov5647_ctrl;
+
+static DECLARE_WAIT_QUEUE_HEAD(ov5647_wait_queue);
+static DECLARE_WAIT_QUEUE_HEAD(ov5647_af_wait_queue);
+DEFINE_MUTEX(ov5647_mut);
+
+static uint16_t prev_line_length_pck;
+static uint16_t prev_frame_length_lines;
+static uint16_t snap_line_length_pck;
+static uint16_t snap_frame_length_lines;
+
+static int ov5647_i2c_rxdata(unsigned short saddr,
+		unsigned char *rxdata, int length)
+{
+	struct i2c_msg msgs[] = {
+		{
+			.addr  = saddr,
+			.flags = 0,
+			.len   = 2,
+			.buf   = rxdata,
+		},
+		{
+			.addr  = saddr,
+			.flags = I2C_M_RD,
+			.len   = 1,
+			.buf   = rxdata,
+		},
+	};
+	if (i2c_transfer(ov5647_client->adapter, msgs, 2) < 0) {
+		CDBG("ov5647_i2c_rxdata faild 0x%x\n", saddr);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int32_t ov5647_i2c_txdata(unsigned short saddr,
+		unsigned char *txdata, int length)
+{
+	struct i2c_msg msg[] = {
+		{
+			.addr = saddr,
+			.flags = 0,
+			.len = length,
+			.buf = txdata,
+		},
+	};
+	if (i2c_transfer(ov5647_client->adapter, msg, 1) < 0) {
+		CDBG("ov5647_i2c_txdata faild 0x%x\n", saddr);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int32_t ov5647_i2c_read(unsigned short raddr,
+		unsigned short *rdata)
+{
+	int32_t rc = 0;
+	unsigned char buf[2];
+
+	if (!rdata)
+		return -EIO;
+	CDBG("%s:saddr:0x%x raddr:0x%x data:0x%x",
+		__func__, ov5647_client->addr, raddr, *rdata);
+	memset(buf, 0, sizeof(buf));
+	buf[0] = (raddr & 0xFF00) >> 8;
+	buf[1] = (raddr & 0x00FF);
+	rc = ov5647_i2c_rxdata(ov5647_client->addr >> 1, buf, 1);
+	if (rc < 0) {
+		CDBG("ov5647_i2c_read 0x%x failed!\n", raddr);
+		return rc;
+	}
+	*rdata = buf[0];
+	CDBG("ov5647_i2c_read 0x%x val = 0x%x!\n", raddr, *rdata);
+
+	return rc;
+}
+
+static int32_t ov5647_i2c_write_b_sensor(unsigned short waddr, uint8_t bdata)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[3];
+
+	memset(buf, 0, sizeof(buf));
+	buf[0] = (waddr & 0xFF00) >> 8;
+	buf[1] = (waddr & 0x00FF);
+	buf[2] = bdata;
+	CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
+	rc = ov5647_i2c_txdata(ov5647_client->addr >> 1, buf, 3);
+	if (rc < 0) {
+		pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+				waddr, bdata);
+	}
+	return rc;
+}
+
+static int32_t ov5647_i2c_write_b_table(struct ov5647_i2c_reg_conf const
+		*reg_conf_tbl, int num)
+{
+	int i;
+	int32_t rc = -EIO;
+
+	for (i = 0; i < num; i++) {
+		rc = ov5647_i2c_write_b_sensor(reg_conf_tbl->waddr,
+				reg_conf_tbl->wdata);
+		if (rc < 0)
+			break;
+		reg_conf_tbl++;
+	}
+	return rc;
+}
+
+static int32_t ov5647_af_i2c_txdata(unsigned short saddr,
+		unsigned char *txdata, int length)
+{
+	struct i2c_msg msg[] = {
+		{
+			.addr = saddr,
+			.flags = 0,
+			.len = length,
+			.buf = txdata,
+		},
+	};
+	if (i2c_transfer(ov5647_af_client->adapter, msg, 1) < 0) {
+		pr_err("ov5647_af_i2c_txdata faild 0x%x\n", saddr);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int32_t ov5647_af_i2c_write_b_sensor(uint8_t waddr, uint8_t bdata)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[2];
+
+	memset(buf, 0, sizeof(buf));
+	buf[0] = waddr;
+	buf[1] = bdata;
+	CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
+	rc = ov5647_af_i2c_txdata(ov5647_af_client->addr, buf, 2);
+	if (rc < 0) {
+		pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+				waddr, bdata);
+	}
+	return rc;
+}
+
+static void ov5647_start_stream(void)
+{
+	CDBG("CAMERA_DBG: 0x4202 0x0, stream on...\r\n");
+	ov5647_i2c_write_b_sensor(0x4202, 0x00);/* streaming on */
+}
+
+static void ov5647_stop_stream(void)
+{
+	CDBG("CAMERA_DBG: 0x4202 0xf, stream off...\r\n");
+	ov5647_i2c_write_b_sensor(0x4202, 0x0f);/* streaming off */
+}
+
+static void ov5647_group_hold_on(void)
+{
+	ov5647_i2c_write_b_sensor(0x0104, 0x01);
+}
+
+static void ov5647_group_hold_off(void)
+{
+	ov5647_i2c_write_b_sensor(0x0104, 0x0);
+}
+
+static void ov5647_get_pict_fps(uint16_t fps, uint16_t *pfps)
+{
+	/* input fps is preview fps in Q8 format */
+	uint32_t divider, d1, d2;
+	uint32_t preview_pclk = 0x37, snapshot_pclk = 0x4f;
+
+	d1 = (prev_frame_length_lines * 0x00000400) / snap_frame_length_lines;
+	d2 = (prev_line_length_pck * 0x00000400) / snap_line_length_pck;
+	divider = (d1 * d2*preview_pclk/snapshot_pclk) / 0x400;
+	CDBG(KERN_ERR "ov5647_get_pict_fps divider = %d", divider);
+	/*Verify PCLK settings and frame sizes.*/
+	*pfps = (uint16_t) (fps * divider / 0x400);
+}
+
+static uint16_t ov5647_get_prev_lines_pf(void)
+{
+	if (ov5647_ctrl->prev_res == QTR_SIZE)
+		return prev_frame_length_lines;
+	else
+		return snap_frame_length_lines;
+}
+
+static uint16_t ov5647_get_prev_pixels_pl(void)
+{
+	if (ov5647_ctrl->prev_res == QTR_SIZE)
+		return prev_line_length_pck;
+	else
+		return snap_line_length_pck;
+}
+
+static uint16_t ov5647_get_pict_lines_pf(void)
+{
+	if (ov5647_ctrl->pict_res == QTR_SIZE)
+		return prev_frame_length_lines;
+	else
+		return snap_frame_length_lines;
+}
+
+static uint16_t ov5647_get_pict_pixels_pl(void)
+{
+	if (ov5647_ctrl->pict_res == QTR_SIZE)
+		return prev_line_length_pck;
+	else
+		return snap_line_length_pck;
+}
+
+static uint32_t ov5647_get_pict_max_exp_lc(void)
+{
+	return snap_frame_length_lines * 24;
+}
+
+static int32_t ov5647_set_fps(struct fps_cfg   *fps)
+{
+	uint16_t total_lines_per_frame;
+	int32_t rc = 0;
+
+	ov5647_ctrl->fps_divider = fps->fps_div;
+	ov5647_ctrl->pict_fps_divider = fps->pict_fps_div;
+
+	if (ov5647_ctrl->sensormode == SENSOR_PREVIEW_MODE) {
+		total_lines_per_frame = (uint16_t)
+		((prev_frame_length_lines * ov5647_ctrl->fps_divider) / 0x400);
+	} else {
+		total_lines_per_frame = (uint16_t)
+		((snap_frame_length_lines * ov5647_ctrl->fps_divider) / 0x400);
+	}
+
+	ov5647_group_hold_on();
+	rc = ov5647_i2c_write_b_sensor(0x0340,
+			((total_lines_per_frame & 0xFF00) >> 8));
+	rc = ov5647_i2c_write_b_sensor(0x0341,
+			(total_lines_per_frame & 0x00FF));
+	ov5647_group_hold_off();
+
+	return rc;
+}
+
+static inline uint8_t ov5647_byte(uint16_t word, uint8_t offset)
+{
+	return word >> (offset * BITS_PER_BYTE);
+}
+
+static int32_t ov5647_write_exp_gain(uint16_t gain, uint32_t line)
+{
+	int rc = 0;
+	uint16_t max_line;
+	u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
+	uint8_t gain_lsb, gain_hsb;
+	ov5647_ctrl->my_reg_gain = gain;
+	ov5647_ctrl->my_reg_line_count = (uint16_t)line;
+
+	CDBG(KERN_ERR "preview exposure setting 0x%x, 0x%x, %d",
+		 gain, line, line);
+
+	gain_lsb = (uint8_t) (ov5647_ctrl->my_reg_gain);
+	gain_hsb = (uint8_t)((ov5647_ctrl->my_reg_gain & 0x300)>>8);
+	/* adjust frame rate */
+	if (line > 980) {
+		rc = ov5647_i2c_write_b_sensor(0x380E,
+			 (uint8_t)((line+4) >> 8)) ;
+		rc = ov5647_i2c_write_b_sensor(0x380F,
+			 (uint8_t)((line+4) & 0x00FF)) ;
+		max_line = line + 4;
+	} else if (max_line > 984) {
+		rc = ov5647_i2c_write_b_sensor(0x380E,
+			 (uint8_t)(984 >> 8)) ;
+		rc = ov5647_i2c_write_b_sensor(0x380F,
+			 (uint8_t)(984 & 0x00FF)) ;
+		max_line = 984;
+	}
+
+	line = line<<4;
+	/* ov5647 need this operation */
+	intg_time_hsb = (u8)(line>>16);
+	intg_time_msb = (u8) ((line & 0xFF00) >> 8);
+	intg_time_lsb = (u8) (line & 0x00FF);
+
+	ov5647_group_hold_on();
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb) ;
+	ov5647_group_hold_off();
+
+	return rc;
+}
+
+
+static int32_t ov5647_set_pict_exp_gain(uint16_t gain, uint32_t line)
+{
+	uint16_t max_line;
+	int rc = 0;
+	uint8_t gain_lsb, gain_hsb;
+	u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
+
+	ov5647_ctrl->my_reg_gain = gain;
+	ov5647_ctrl->my_reg_line_count = (uint16_t)line;
+
+	gain_lsb = (uint8_t) (ov5647_ctrl->my_reg_gain);
+	gain_hsb = (uint8_t)((ov5647_ctrl->my_reg_gain & 0x300)>>8);
+
+	CDBG(KERN_ERR "snapshot exposure seting 0x%x, 0x%x, %d"
+		, gain, line, line);
+
+	if (line > 1964) {
+		rc = ov5647_i2c_write_b_sensor(0x380E,
+			 (uint8_t)((line+4) >> 8)) ;
+		rc = ov5647_i2c_write_b_sensor(0x380F,
+			 (uint8_t)((line+4) & 0x00FF)) ;
+		max_line = line + 4;
+	} else if (max_line > 1968) {
+		rc = ov5647_i2c_write_b_sensor(0x380E,
+			 (uint8_t)(1968 >> 8)) ;
+		rc = ov5647_i2c_write_b_sensor(0x380F,
+			 (uint8_t)(1968 & 0x00FF)) ;
+		max_line = 1968;
+	}
+	line = line<<4;
+	/* ov5647 need this operation */
+	intg_time_hsb = (u8)(line>>16);
+	intg_time_msb = (u8) ((line & 0xFF00) >> 8);
+	intg_time_lsb = (u8) (line & 0x00FF);
+
+	/* FIXME for BLC trigger */
+	ov5647_group_hold_on();
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb - 1) ;
+
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb) ;
+	ov5647_group_hold_off();
+
+	msleep(500);
+	return rc;
+
+}
+
+static int32_t ov5647_move_focus(int direction, int32_t num_steps)
+{
+	uint8_t   code_val_msb = 0;
+	uint8_t   code_val_lsb = 0;
+	int16_t   step_direction, actual_step, next_position;
+	int rc;
+
+	if (num_steps == 0)
+		return 0;
+
+	if (direction == MOVE_NEAR)
+		step_direction = 20;
+	else if (direction == MOVE_FAR)
+		step_direction = -20;
+	else
+		return -EINVAL;
+
+	actual_step = (int16_t)(step_direction * num_steps);
+	next_position = (int16_t)ov5647_ctrl->curr_lens_pos + actual_step;
+	if (next_position < 0) {
+		CDBG(KERN_ERR "%s: OV5647 position(=%d) out of range",
+			__func__, next_position);
+		next_position = 0;
+	}
+	if (next_position > 0x3FF) {
+		CDBG(KERN_ERR "%s: OV5647 position(=%d) out of range",
+			__func__, next_position);
+		next_position = 0x3FF;
+	}
+	ov5647_ctrl->curr_lens_pos = next_position;
+
+	code_val_msb = (uint8_t)((ov5647_ctrl->curr_lens_pos & 0x03FF) >> 4);
+	code_val_lsb = (uint8_t)((ov5647_ctrl->curr_lens_pos & 0x000F) << 4);
+	code_val_lsb |= mode_mask;
+
+	rc = ov5647_af_i2c_write_b_sensor(code_val_msb, code_val_lsb);
+	/* DAC Setting */
+	if (rc != 0) {
+		CDBG(KERN_ERR "%s: WRITE ERROR lsb = 0x%x, msb = 0x%x",
+			__func__, code_val_lsb, code_val_msb);
+	} else {
+		CDBG(KERN_ERR "%s: Successful lsb = 0x%x, msb = 0x%x",
+			__func__, code_val_lsb, code_val_msb);
+		/* delay may set based on the steps moved
+		when I2C write successful */
+		msleep(100);
+	}
+	return 0;
+}
+
+static int32_t ov5647_set_default_focus(uint8_t af_step)
+{
+	uint8_t  code_val_msb = 0;
+	uint8_t  code_val_lsb = 0;
+	int rc = 0;
+
+	ov5647_ctrl->curr_lens_pos = 200;
+
+
+	code_val_msb = (ov5647_ctrl->curr_lens_pos & 0x03FF) >> 4;
+	code_val_lsb = (ov5647_ctrl->curr_lens_pos & 0x000F) << 4;
+	code_val_lsb |= mode_mask;
+
+	CDBG(KERN_ERR "ov5647_set_default_focus:lens pos = %d",
+		 ov5647_ctrl->curr_lens_pos);
+	rc = ov5647_af_i2c_write_b_sensor(code_val_msb, code_val_lsb);
+	/* DAC Setting */
+	if (rc != 0)
+		CDBG(KERN_ERR "%s: WRITE ERROR lsb = 0x%x, msb = 0x%x",
+			__func__, code_val_lsb, code_val_msb);
+	else
+		CDBG(KERN_ERR "%s: WRITE successful lsb = 0x%x, msb = 0x%x",
+			__func__, code_val_lsb, code_val_msb);
+
+	usleep_range(10000, 11000);
+	return 0;
+}
+
+static int32_t ov5647_test(enum ov5647_test_mode_t mo)
+{
+	int32_t rc = 0;
+
+	if (mo != TEST_OFF)
+		rc = ov5647_i2c_write_b_sensor(0x0601, (uint8_t) mo);
+
+	return rc;
+}
+
+static void ov5647_reset_sensor(void)
+{
+	ov5647_i2c_write_b_sensor(0x103, 0x1);
+}
+
+
+static int32_t ov5647_sensor_setting(int update_type, int rt)
+{
+
+	int32_t rc = 0;
+	struct msm_camera_csi_params ov5647_csi_params;
+
+	ov5647_stop_stream();
+
+	/* wait for clk/data really stop */
+	if ((rt == RES_CAPTURE) || (CSI_CONFIG == 0))
+		msleep(66);
+	else
+		msleep(266);
+
+	CDBG("CAMERA_DBG1: 0x4800 regVal:0x25\r\n");
+	ov5647_i2c_write_b_sensor(0x4800, 0x25);/* streaming off */
+
+	usleep_range(10000, 11000);
+
+	if (update_type == REG_INIT) {
+		ov5647_reset_sensor();
+		ov5647_i2c_write_b_table(ov5647_regs.rec_settings,
+			ov5647_regs.rec_size);
+		CSI_CONFIG = 0;
+	} else if (update_type == UPDATE_PERIODIC) {
+			/* turn off flash when preview */
+
+			if (rt == RES_PREVIEW) {
+				ov5647_i2c_write_b_table(ov5647_regs.reg_prev,
+					 ov5647_regs.reg_prev_size);
+				CDBG("CAMERA_DBG:preview settings...\r\n");
+			} else {
+				ov5647_i2c_write_b_table(ov5647_regs.reg_snap,
+					 ov5647_regs.reg_snap_size);
+				CDBG("CAMERA_DBG:snapshot settings...\r\n");
+			}
+
+			msleep(20);
+			if (!CSI_CONFIG) {
+				msm_camio_vfe_clk_rate_set(192000000);
+				ov5647_csi_params.data_format = CSI_8BIT;
+				ov5647_csi_params.lane_cnt = 2;
+				ov5647_csi_params.lane_assign = 0xe4;
+				ov5647_csi_params.dpcm_scheme = 0;
+				ov5647_csi_params.settle_cnt = 10;
+				rc = msm_camio_csi_config(&ov5647_csi_params);
+				msleep(20);
+				CSI_CONFIG = 1;
+			/* exit powerdown state */
+				ov5647_i2c_write_b_sensor(0x0100, 0x01);
+			}
+			CDBG("CAMERA_DBG: 0x4800 regVal:0x04\r\n");
+			/* streaming on */
+			ov5647_i2c_write_b_sensor(0x4800, 0x04);
+			msleep(266);
+			ov5647_start_stream();
+			msleep(30);
+	}
+	return rc;
+}
+
+static int32_t ov5647_video_config(int mode)
+{
+	int32_t rc = 0;
+	int rt;
+	CDBG("video config\n");
+	/* change sensor resolution if needed */
+	if (ov5647_ctrl->prev_res == QTR_SIZE)
+		rt = RES_PREVIEW;
+	else
+		rt = RES_CAPTURE;
+	if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+		return rc;
+	if (ov5647_ctrl->set_test) {
+		if (ov5647_test(ov5647_ctrl->set_test) < 0)
+			return  rc;
+	}
+
+	ov5647_ctrl->curr_res = ov5647_ctrl->prev_res;
+	ov5647_ctrl->sensormode = mode;
+	return rc;
+}
+
+static int32_t ov5647_snapshot_config(int mode)
+{
+	int32_t rc = 0;
+	int rt;
+
+	/*change sensor resolution if needed */
+	if (ov5647_ctrl->curr_res != ov5647_ctrl->pict_res) {
+		if (ov5647_ctrl->pict_res == QTR_SIZE)
+			rt = RES_PREVIEW;
+		else
+			rt = RES_CAPTURE;
+		if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+			return rc;
+	}
+
+	ov5647_ctrl->curr_res = ov5647_ctrl->pict_res;
+	ov5647_ctrl->sensormode = mode;
+	return rc;
+}
+
+static int32_t ov5647_raw_snapshot_config(int mode)
+{
+	int32_t rc = 0;
+	int rt;
+
+	/* change sensor resolution if needed */
+	if (ov5647_ctrl->curr_res != ov5647_ctrl->pict_res) {
+		if (ov5647_ctrl->pict_res == QTR_SIZE)
+			rt = RES_PREVIEW;
+		else
+			rt = RES_CAPTURE;
+		if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+			return rc;
+	}
+
+	ov5647_ctrl->curr_res = ov5647_ctrl->pict_res;
+	ov5647_ctrl->sensormode = mode;
+	return rc;
+}
+
+static int32_t ov5647_set_sensor_mode(int mode,
+		int res)
+{
+	int32_t rc = 0;
+
+	switch (mode) {
+	case SENSOR_PREVIEW_MODE:
+		rc = ov5647_video_config(mode);
+		break;
+	case SENSOR_SNAPSHOT_MODE:
+		rc = ov5647_snapshot_config(mode);
+		break;
+	case SENSOR_RAW_SNAPSHOT_MODE:
+		rc = ov5647_raw_snapshot_config(mode);
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+static int32_t ov5647_power_down(void)
+{
+	ov5647_stop_stream();
+	return 0;
+}
+
+static int ov5647_probe_init_done(const struct msm_camera_sensor_info *data)
+{
+	CDBG("probe done\n");
+	gpio_direction_output(data->sensor_pwd, 1);
+	return 0;
+}
+
+static int ov5647_probe_init_sensor(const struct msm_camera_sensor_info *data)
+{
+	int32_t rc = 0;
+	uint16_t regaddress1 = 0x300a;
+	uint16_t regaddress2 = 0x300b;
+	uint16_t chipid1 = 0;
+	uint16_t chipid2 = 0;
+
+	CDBG("%s: %d\n", __func__, __LINE__);
+
+	gpio_direction_output(data->sensor_pwd, 0);
+	usleep_range(4000, 4100);
+	gpio_direction_output(data->sensor_reset, 1);
+	usleep_range(2000, 2100);
+
+	ov5647_i2c_read(regaddress1, &chipid1);
+	if (chipid1 != 0x56) {
+		rc = -ENODEV;
+		pr_err("ov5647_probe_init_sensor fail chip id doesnot match\n");
+		goto init_probe_fail;
+	}
+
+	ov5647_i2c_read(regaddress2, &chipid2);
+	if (chipid2 != 0x47) {
+		rc = -ENODEV;
+		pr_err("ov5647_probe_init_sensor fail chip id doesnot match\n");
+		goto init_probe_fail;
+	}
+
+	pr_err("ID1: 0x%x\n", chipid1);
+	pr_err("ID2: 0x%x\n", chipid2);
+	goto init_probe_done;
+
+init_probe_fail:
+	pr_err(" ov5647_probe_init_sensor fails\n");
+	ov5647_probe_init_done(data);
+	return rc;
+init_probe_done:
+	pr_debug(" ov5647_probe_init_sensor finishes\n");
+	gpio_direction_output(data->sensor_pwd, 1);
+	return rc;
+}
+
+
+static int ov5647_sensor_open_init(const struct msm_camera_sensor_info *data)
+{
+	int32_t rc = 0;
+
+	CDBG("%s: %d\n", __func__, __LINE__);
+	CDBG("Calling ov5647_sensor_open_init\n");
+
+	ov5647_ctrl = kzalloc(sizeof(struct ov5647_ctrl_t), GFP_KERNEL);
+	if (!ov5647_ctrl) {
+		CDBG("ov5647_init failed!\n");
+		rc = -ENOMEM;
+		goto init_done;
+	}
+	ov5647_ctrl->fps_divider = 1 * 0x00000400;
+	ov5647_ctrl->pict_fps_divider = 1 * 0x00000400;
+	ov5647_ctrl->set_test = TEST_OFF;
+	ov5647_ctrl->prev_res = QTR_SIZE;
+	ov5647_ctrl->pict_res = FULL_SIZE;
+
+	if (data)
+		ov5647_ctrl->sensordata = data;
+
+	prev_frame_length_lines = 0x3d8;
+
+	prev_line_length_pck = 0x768*2;
+
+	snap_frame_length_lines = 0x7b0;
+
+	snap_line_length_pck = 0xa8c;
+
+	/* enable mclk first */
+	msm_camio_clk_rate_set(OV5647_MASTER_CLK_RATE);
+
+	gpio_direction_output(data->sensor_pwd, 1);
+	gpio_direction_output(data->sensor_reset, 0);
+	usleep_range(10000, 11000);
+	/* power on camera ldo and vreg */
+	if (ov5647_ctrl->sensordata->pmic_gpio_enable)
+		lcd_camera_power_onoff(1);
+	usleep_range(10000, 11000); /*waiting for ldo stable*/
+	gpio_direction_output(data->sensor_pwd, 0);
+	msleep(20);
+	gpio_direction_output(data->sensor_reset, 1);
+	msleep(25);
+
+	CDBG("init settings\n");
+	if (ov5647_ctrl->prev_res == QTR_SIZE)
+		rc = ov5647_sensor_setting(REG_INIT, RES_PREVIEW);
+	else
+		rc = ov5647_sensor_setting(REG_INIT, RES_CAPTURE);
+	ov5647_ctrl->fps = 30 * Q8;
+
+	/* enable AF actuator */
+	if (ov5647_ctrl->sensordata->vcm_enable) {
+		CDBG("enable AF actuator, gpio = %d\n",
+			 ov5647_ctrl->sensordata->vcm_pwd);
+		rc = gpio_request(ov5647_ctrl->sensordata->vcm_pwd,
+						"ov5647_af");
+		if (!rc)
+			gpio_direction_output(
+				ov5647_ctrl->sensordata->vcm_pwd,
+				 1);
+		else {
+			pr_err("ov5647_ctrl gpio request failed!\n");
+			goto init_fail;
+		}
+		msleep(20);
+		rc = ov5647_set_default_focus(0);
+		if (rc < 0) {
+			gpio_direction_output(ov5647_ctrl->sensordata->vcm_pwd,
+								0);
+			gpio_free(ov5647_ctrl->sensordata->vcm_pwd);
+		}
+	}
+	if (rc < 0)
+		goto init_fail;
+	else
+		goto init_done;
+init_fail:
+	CDBG("init_fail\n");
+	ov5647_probe_init_done(data);
+	/* No need to power OFF camera ldo and vreg
+	affects Display while resume */
+init_done:
+	CDBG("init_done\n");
+	return rc;
+}
+
+static int ov5647_i2c_remove(struct i2c_client *client)
+{
+	return 0;
+}
+
+static int ov5647_init_client(struct i2c_client *client)
+{
+	/* Initialize the MSM_CAMI2C Chip */
+	init_waitqueue_head(&ov5647_wait_queue);
+	return 0;
+}
+
+static int ov5647_af_init_client(struct i2c_client *client)
+{
+	/* Initialize the MSM_CAMI2C Chip */
+	init_waitqueue_head(&ov5647_af_wait_queue);
+	return 0;
+}
+
+static const struct i2c_device_id ov5647_af_i2c_id[] = {
+	{"ov5647_af", 0},
+	{ }
+};
+
+static int ov5647_af_i2c_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	int rc = 0;
+	CDBG("ov5647_af_probe called!\n");
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		CDBG("i2c_check_functionality failed\n");
+		goto probe_failure;
+	}
+
+	ov5647_af_sensorw = kzalloc(sizeof(struct ov5647_work_t), GFP_KERNEL);
+	if (!ov5647_af_sensorw) {
+		CDBG("kzalloc failed.\n");
+		rc = -ENOMEM;
+		goto probe_failure;
+	}
+
+	i2c_set_clientdata(client, ov5647_af_sensorw);
+	ov5647_af_init_client(client);
+	ov5647_af_client = client;
+
+	msleep(50);
+
+	CDBG("ov5647_af_probe successed! rc = %d\n", rc);
+	return 0;
+
+probe_failure:
+	CDBG("ov5647_af_probe failed! rc = %d\n", rc);
+	return rc;
+}
+
+static const struct i2c_device_id ov5647_i2c_id[] = {
+	{"ov5647", 0}, {}
+};
+
+static int ov5647_i2c_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	int rc = 0;
+	CDBG("ov5647_probe called!\n");
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		CDBG("i2c_check_functionality failed\n");
+		goto probe_failure;
+	}
+
+	ov5647_sensorw = kzalloc(sizeof(struct ov5647_work_t), GFP_KERNEL);
+	if (!ov5647_sensorw) {
+		CDBG("kzalloc failed.\n");
+		rc = -ENOMEM;
+		goto probe_failure;
+	}
+
+	i2c_set_clientdata(client, ov5647_sensorw);
+	ov5647_init_client(client);
+	ov5647_client = client;
+
+	msleep(50);
+
+	CDBG("ov5647_probe successed! rc = %d\n", rc);
+	return 0;
+
+probe_failure:
+	CDBG("ov5647_probe failed! rc = %d\n", rc);
+	return rc;
+}
+
+static int __devexit ov5647_remove(struct i2c_client *client)
+{
+	struct ov5647_work_t *sensorw = i2c_get_clientdata(client);
+	free_irq(client->irq, sensorw);
+	ov5647_client = NULL;
+	kfree(sensorw);
+	return 0;
+}
+
+static int __devexit ov5647_af_remove(struct i2c_client *client)
+{
+	struct ov5647_work_t *ov5647_af = i2c_get_clientdata(client);
+	free_irq(client->irq, ov5647_af);
+	ov5647_af_client = NULL;
+	kfree(ov5647_af);
+	return 0;
+}
+
+static struct i2c_driver ov5647_i2c_driver = {
+	.id_table = ov5647_i2c_id,
+	.probe  = ov5647_i2c_probe,
+	.remove = ov5647_i2c_remove,
+	.driver = {
+		.name = "ov5647",
+	},
+};
+
+static struct i2c_driver ov5647_af_i2c_driver = {
+	.id_table = ov5647_af_i2c_id,
+	.probe  = ov5647_af_i2c_probe,
+	.remove = __exit_p(ov5647_af_i2c_remove),
+	.driver = {
+		.name = "ov5647_af",
+	},
+};
+
+int ov5647_sensor_config(void __user *argp)
+{
+	struct sensor_cfg_data cdata;
+	long   rc = 0;
+	if (copy_from_user(&cdata,
+				(void *)argp,
+				sizeof(struct sensor_cfg_data)))
+		return -EFAULT;
+	mutex_lock(&ov5647_mut);
+	CDBG("ov5647_sensor_config: cfgtype = %d\n",
+			cdata.cfgtype);
+	switch (cdata.cfgtype) {
+	case CFG_GET_PICT_FPS:
+		ov5647_get_pict_fps(
+			cdata.cfg.gfps.prevfps,
+			&(cdata.cfg.gfps.pictfps));
+
+		if (copy_to_user((void *)argp,
+			&cdata,
+			sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PREV_L_PF:
+		cdata.cfg.prevl_pf =
+			ov5647_get_prev_lines_pf();
+
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PREV_P_PL:
+		cdata.cfg.prevp_pl =
+			ov5647_get_prev_pixels_pl();
+
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PICT_L_PF:
+		cdata.cfg.pictl_pf =
+			ov5647_get_pict_lines_pf();
+
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PICT_P_PL:
+		cdata.cfg.pictp_pl =
+			ov5647_get_pict_pixels_pl();
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PICT_MAX_EXP_LC:
+		cdata.cfg.pict_max_exp_lc =
+			ov5647_get_pict_max_exp_lc();
+
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_SET_FPS:
+	case CFG_SET_PICT_FPS:
+		rc = ov5647_set_fps(&(cdata.cfg.fps));
+		break;
+	case CFG_SET_EXP_GAIN:
+		rc = ov5647_write_exp_gain(cdata.cfg.exp_gain.gain,
+				cdata.cfg.exp_gain.line);
+		break;
+	case CFG_SET_PICT_EXP_GAIN:
+		rc = ov5647_set_pict_exp_gain(cdata.cfg.exp_gain.gain,
+				cdata.cfg.exp_gain.line);
+		break;
+	case CFG_SET_MODE:
+		rc = ov5647_set_sensor_mode(cdata.mode, cdata.rs);
+		break;
+	case CFG_PWR_DOWN:
+		rc = ov5647_power_down();
+		break;
+	case CFG_MOVE_FOCUS:
+		rc = ov5647_move_focus(cdata.cfg.focus.dir,
+				cdata.cfg.focus.steps);
+		break;
+	case CFG_SET_DEFAULT_FOCUS:
+		rc = ov5647_set_default_focus(cdata.cfg.focus.steps);
+		break;
+
+	case CFG_GET_AF_MAX_STEPS:
+		cdata.max_steps = OV5647_TOTAL_STEPS_NEAR_TO_FAR;
+		if (copy_to_user((void *)argp,
+					&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_SET_EFFECT:
+		rc = ov5647_set_default_focus(cdata.cfg.effect);
+		break;
+	default:
+		rc = -EFAULT;
+		break;
+	}
+	mutex_unlock(&ov5647_mut);
+
+	return rc;
+}
+
+static int ov5647_sensor_release(void)
+{
+	int rc = -EBADF;
+	unsigned short rdata;
+
+	mutex_lock(&ov5647_mut);
+	ov5647_power_down();
+	msleep(20);
+	ov5647_i2c_read(0x3018, &rdata);
+	rdata |= 0x18; /*set bit 3 bit 4 to 1*/
+	ov5647_i2c_write_b_sensor(0x3018, rdata);/*write back*/
+	msleep(20);
+
+	gpio_set_value(ov5647_ctrl->sensordata->sensor_pwd, 1);
+	usleep_range(5000, 5100);
+	if (ov5647_ctrl->sensordata->vcm_enable) {
+		gpio_direction_output(ov5647_ctrl->sensordata->vcm_pwd, 0);
+		gpio_free(ov5647_ctrl->sensordata->vcm_pwd);
+	}
+
+	/* No need to power OFF camera ldo and vreg
+	affects Display while resume */
+
+	kfree(ov5647_ctrl);
+	ov5647_ctrl = NULL;
+	CDBG("ov5647_release completed\n");
+	mutex_unlock(&ov5647_mut);
+
+	return rc;
+}
+
+static int ov5647_sensor_probe(const struct msm_camera_sensor_info *info,
+		struct msm_sensor_ctrl *s)
+{
+	int rc = 0;
+
+	CDBG("%s E\n", __func__);
+
+	gpio_direction_output(info->sensor_pwd, 1);
+	gpio_direction_output(info->sensor_reset, 0);
+	usleep_range(1000, 1100);
+	/* turn on ldo and vreg */
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(1);
+
+	rc = i2c_add_driver(&ov5647_i2c_driver);
+	if (rc < 0 || ov5647_client == NULL) {
+		rc = -ENOTSUPP;
+		CDBG("I2C add driver ov5647 failed");
+		goto probe_fail_2;
+	}
+	if (info->vcm_enable) {
+		rc = i2c_add_driver(&ov5647_af_i2c_driver);
+		if (rc < 0 || ov5647_af_client == NULL) {
+			rc = -ENOTSUPP;
+			CDBG("I2C add driver ov5647 af failed");
+			goto probe_fail_3;
+		}
+	}
+	msm_camio_clk_rate_set(OV5647_MASTER_CLK_RATE);
+
+	rc = ov5647_probe_init_sensor(info);
+	if (rc < 0)
+		goto probe_fail_1;
+
+	s->s_init = ov5647_sensor_open_init;
+	s->s_release = ov5647_sensor_release;
+	s->s_config  = ov5647_sensor_config;
+	s->s_mount_angle = info->sensor_platform_info->mount_angle;
+	gpio_set_value(info->sensor_pwd, 1);
+	ov5647_probe_init_done(info);
+	/* turn off ldo and vreg */
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
+
+	CDBG("%s X", __func__);
+	return rc;
+
+probe_fail_3:
+	i2c_del_driver(&ov5647_af_i2c_driver);
+probe_fail_2:
+	i2c_del_driver(&ov5647_i2c_driver);
+probe_fail_1:
+	/* turn off ldo and vreg */
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
+	CDBG("ov5647_sensor_probe: SENSOR PROBE FAILS!\n");
+	CDBG("%s X", __func__);
+	return rc;
+}
+
+static int __devinit ov5647_probe(struct platform_device *pdev)
+{
+	return msm_camera_drv_start(pdev, ov5647_sensor_probe);
+}
+
+static struct platform_driver msm_camera_driver = {
+	.probe = ov5647_probe,
+	.driver = {
+		.name = "msm_camera_ov5647",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init ov5647_init(void)
+{
+	return platform_driver_register(&msm_camera_driver);
+}
+
+module_init(ov5647_init);
+MODULE_DESCRIPTION("Omnivision 5 MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/ov5647.h b/drivers/media/video/msm/ov5647.h
new file mode 100644
index 0000000..b43f15c
--- /dev/null
+++ b/drivers/media/video/msm/ov5647.h
@@ -0,0 +1,92 @@
+/* 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 OV5647_H
+#define OV5647_H
+#include <linux/types.h>
+#include <mach/board.h>
+
+extern struct ov5647_reg ov5647_regs;
+extern int lcd_camera_power_onoff(int on);
+extern struct rw_semaphore leds_list_lock;
+extern struct list_head leds_list;
+
+struct ov5647_i2c_reg_conf {
+	unsigned short waddr;
+	unsigned short wdata;
+};
+
+enum ov5647_test_mode_t {
+	TEST_OFF,
+	TEST_1,
+	TEST_2,
+	TEST_3
+};
+
+enum ov5647_resolution_t {
+	QTR_SIZE,
+	FULL_SIZE,
+	INVALID_SIZE
+};
+enum ov5647_setting {
+	RES_PREVIEW,
+	RES_CAPTURE
+};
+enum ov5647_reg_update {
+	/* Sensor egisters that need to be updated during initialization */
+	REG_INIT,
+	/* Sensor egisters that needs periodic I2C writes */
+	UPDATE_PERIODIC,
+	/* All the sensor Registers will be updated */
+	UPDATE_ALL,
+	/* Not valid update */
+	UPDATE_INVALID
+};
+
+enum ov5647_reg_pll {
+	E013_VT_PIX_CLK_DIV,
+	E013_VT_SYS_CLK_DIV,
+	E013_PRE_PLL_CLK_DIV,
+	E013_PLL_MULTIPLIER,
+	E013_OP_PIX_CLK_DIV,
+	E013_OP_SYS_CLK_DIV
+};
+
+enum ov5647_reg_mode {
+	E013_X_ADDR_START,
+	E013_X_ADDR_END,
+	E013_Y_ADDR_START,
+	E013_Y_ADDR_END,
+	E013_X_OUTPUT_SIZE,
+	E013_Y_OUTPUT_SIZE,
+	E013_DATAPATH_SELECT,
+	E013_READ_MODE,
+	E013_ANALOG_CONTROL5,
+	E013_DAC_LD_4_5,
+	E013_SCALING_MODE,
+	E013_SCALE_M,
+	E013_LINE_LENGTH_PCK,
+	E013_FRAME_LENGTH_LINES,
+	E013_COARSE_INTEGRATION_TIME,
+	E013_FINE_INTEGRATION_TIME,
+	E013_FINE_CORRECTION
+};
+
+struct ov5647_reg {
+	const struct ov5647_i2c_reg_conf *rec_settings;
+	const unsigned short rec_size;
+	const struct ov5647_i2c_reg_conf *reg_prev;
+	const unsigned short reg_prev_size;
+	const struct ov5647_i2c_reg_conf *reg_snap;
+	const unsigned short reg_snap_size;
+};
+#endif /* OV5647_H */
diff --git a/drivers/media/video/msm/ov5647_reg.c b/drivers/media/video/msm/ov5647_reg.c
new file mode 100644
index 0000000..4a0fed4
--- /dev/null
+++ b/drivers/media/video/msm/ov5647_reg.c
@@ -0,0 +1,219 @@
+/* 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 "ov5647.h"
+struct ov5647_i2c_reg_conf ov5647_prev_settings[] = {
+	/*1280*960 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps
+	for back to preview*/
+	{0x3035, 0x21},
+	{0x3036, 0x37},
+	{0x3821, 0x07},
+	{0x3820, 0x41},
+	{0x3612, 0x09},
+	{0x3618, 0x00},
+	{0x380c, 0x07},
+	{0x380d, 0x68},
+	{0x380e, 0x03},
+	{0x380f, 0xd8},
+	{0x3814, 0x31},
+	{0x3815, 0x31},
+	{0x3709, 0x52},
+	{0x3808, 0x05},
+	{0x3809, 0x00},
+	{0x380a, 0x03},
+	{0x380b, 0xc0},
+	{0x3800, 0x00},
+	{0x3801, 0x18},
+	{0x3802, 0x00},
+	{0x3803, 0x0e},
+	{0x3804, 0x0a},
+	{0x3805, 0x27},
+	{0x3806, 0x07},
+	{0x3807, 0x95},
+	{0x4004, 0x02},
+};
+
+struct ov5647_i2c_reg_conf ov5647_snap_settings[] = {
+	/*2608*1952 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps*/
+	{0x3035, 0x21},
+	{0x3036, 0x4f},
+	{0x3821, 0x06},
+	{0x3820, 0x00},
+	{0x3612, 0x0b},
+	{0x3618, 0x04},
+	{0x380c, 0x0a},
+	{0x380d, 0x8c},
+	{0x380e, 0x07},
+	{0x380f, 0xb0},
+	{0x3814, 0x11},
+	{0x3815, 0x11},
+	{0x3709, 0x12},
+	{0x3808, 0x0a},
+	{0x3809, 0x30},
+	{0x380a, 0x07},
+	{0x380b, 0xa0},
+	{0x3800, 0x00},
+	{0x3801, 0x04},
+	{0x3802, 0x00},
+	{0x3803, 0x00},
+	{0x3804, 0x0a},
+	{0x3805, 0x3b},
+	{0x3806, 0x07},
+	{0x3807, 0xa3},
+	{0x4004, 0x04},
+};
+
+struct ov5647_i2c_reg_conf ov5647_recommend_settings[] = {
+	{0x3035, 0x11},
+	{0x303c, 0x11},
+	{0x370c, 0x03},
+	{0x5000, 0x06},
+	{0x5003, 0x08},
+	{0x5a00, 0x08},
+	{0x3000, 0xff},
+	{0x3001, 0xff},
+	{0x3002, 0xff},
+	{0x301d, 0xf0},
+	{0x3a18, 0x00},
+	{0x3a19, 0xf8},
+	{0x3c01, 0x80},
+	{0x3b07, 0x0c},
+	{0x3708, 0x64},
+	{0x3630, 0x2e},
+	{0x3632, 0xe2},
+	{0x3633, 0x23},
+	{0x3634, 0x44},
+	{0x3620, 0x64},
+	{0x3621, 0xe0},
+	{0x3600, 0x37},
+	{0x3704, 0xa0},
+	{0x3703, 0x5a},
+	{0x3715, 0x78},
+	{0x3717, 0x01},
+	{0x3731, 0x02},
+	{0x370b, 0x60},
+	{0x3705, 0x1a},
+	{0x3f05, 0x02},
+	{0x3f06, 0x10},
+	{0x3f01, 0x0a},
+	{0x3a08, 0x01},
+	{0x3a0f, 0x58},
+	{0x3a10, 0x50},
+	{0x3a1b, 0x58},
+	{0x3a1e, 0x50},
+	{0x3a11, 0x60},
+	{0x3a1f, 0x28},
+	{0x4001, 0x02},
+	{0x4000, 0x09},
+	{0x3000, 0x00},
+	{0x3001, 0x00},
+	{0x3002, 0x00},
+	{0x3017, 0xe0},
+	{0x301c, 0xfc},
+	{0x3636, 0x06},
+	{0x3016, 0x08},
+	{0x3827, 0xec},
+	{0x3018, 0x44},
+	{0x3035, 0x21},
+	{0x3106, 0xf5},
+	{0x3034, 0x18},
+	{0x301c, 0xf8},
+	/*lens setting*/
+	{0x5000, 0x86},
+	{0x5800, 0x11},
+	{0x5801, 0x0c},
+	{0x5802, 0x0a},
+	{0x5803, 0x0b},
+	{0x5804, 0x0d},
+	{0x5805, 0x13},
+	{0x5806, 0x09},
+	{0x5807, 0x05},
+	{0x5808, 0x03},
+	{0x5809, 0x03},
+	{0x580a, 0x06},
+	{0x580b, 0x08},
+	{0x580c, 0x05},
+	{0x580d, 0x01},
+	{0x580e, 0x00},
+	{0x580f, 0x00},
+	{0x5810, 0x02},
+	{0x5811, 0x06},
+	{0x5812, 0x05},
+	{0x5813, 0x01},
+	{0x5814, 0x00},
+	{0x5815, 0x00},
+	{0x5816, 0x02},
+	{0x5817, 0x06},
+	{0x5818, 0x09},
+	{0x5819, 0x05},
+	{0x581a, 0x04},
+	{0x581b, 0x04},
+	{0x581c, 0x06},
+	{0x581d, 0x09},
+	{0x581e, 0x11},
+	{0x581f, 0x0c},
+	{0x5820, 0x0b},
+	{0x5821, 0x0b},
+	{0x5822, 0x0d},
+	{0x5823, 0x13},
+	{0x5824, 0x22},
+	{0x5825, 0x26},
+	{0x5826, 0x26},
+	{0x5827, 0x24},
+	{0x5828, 0x24},
+	{0x5829, 0x24},
+	{0x582a, 0x22},
+	{0x582b, 0x20},
+	{0x582c, 0x22},
+	{0x582d, 0x26},
+	{0x582e, 0x22},
+	{0x582f, 0x22},
+	{0x5830, 0x42},
+	{0x5831, 0x22},
+	{0x5832, 0x02},
+	{0x5833, 0x24},
+	{0x5834, 0x22},
+	{0x5835, 0x22},
+	{0x5836, 0x22},
+	{0x5837, 0x26},
+	{0x5838, 0x42},
+	{0x5839, 0x26},
+	{0x583a, 0x06},
+	{0x583b, 0x26},
+	{0x583c, 0x24},
+	{0x583d, 0xce},
+	/* manual AWB,manual AE,close Lenc,open WBC*/
+	{0x3503, 0x03}, /*manual AE*/
+	{0x3501, 0x10},
+	{0x3502, 0x80},
+	{0x350a, 0x00},
+	{0x350b, 0x7f},
+	{0x5001, 0x01}, /*manual AWB*/
+	{0x5180, 0x08},
+	{0x5186, 0x04},
+	{0x5187, 0x00},
+	{0x5188, 0x04},
+	{0x5189, 0x00},
+	{0x518a, 0x04},
+	{0x518b, 0x00},
+	{0x5000, 0x06}, /*No lenc,WBC on*/
+};
+
+struct ov5647_reg ov5647_regs = {
+	.rec_settings = &ov5647_recommend_settings[0],
+	.rec_size = ARRAY_SIZE(ov5647_recommend_settings),
+	.reg_prev = &ov5647_prev_settings[0],
+	.reg_prev_size = ARRAY_SIZE(ov5647_prev_settings),
+	.reg_snap = &ov5647_snap_settings[0],
+	.reg_snap_size = ARRAY_SIZE(ov5647_snap_settings),
+};
diff --git a/drivers/media/video/msm/ov7692.h b/drivers/media/video/msm/ov7692.h
index e43a17d..fc9cf1c 100644
--- a/drivers/media/video/msm/ov7692.h
+++ b/drivers/media/video/msm/ov7692.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,11 @@
 #include <linux/types.h>
 #include <mach/board.h>
 
+#define INVMASK(v)  (0xff-v)
+#define OV7692Core_WritePREG(pTbl)  OV7692_WritePRegs \
+			(pTbl, sizeof(pTbl)/sizeof(pTbl[0]))
+
+extern int lcd_camera_power_onoff(int on);
 struct reg_addr_val_pair_struct {
 	uint8_t	reg_addr;
 	uint8_t	reg_val;
@@ -46,5 +51,616 @@
 	/* Not valid update */
 	UPDATE_INVALID
 };
+
+/*OV SENSOR SCCB*/
+struct OV7692_WREG {
+	uint8_t addr;
+	uint8_t data;
+	uint8_t mask;
+} OV7692_WREG;
+
+#ifdef CONFIG_WEBCAM_OV7692_QRD
+/*  96MHz PCLK @ 24MHz MCLK */
+struct reg_addr_val_pair_struct ov7692_init_settings_array[] = {
+	{0x12, 0x80},
+	{0x0e, 0x08},
+	{0x69, 0x52},
+	{0x1e, 0xb3},
+	{0x48, 0x42},
+	{0xff, 0x01},
+	{0xae, 0xa0},
+	{0xa8, 0x26},
+	{0xb4, 0xc0},
+	{0xb5, 0x40},
+	{0xff, 0x00},
+	{0x0c, 0x00},
+	{0x62, 0x10},
+	{0x12, 0x00},
+	{0x17, 0x65},
+	{0x18, 0xa4},
+	{0x19, 0x0a},
+	{0x1a, 0xf6},
+	{0x3e, 0x30},
+	{0x64, 0x0a},
+	{0xff, 0x01},
+	{0xb4, 0xc0},
+	{0xff, 0x00},
+	{0x67, 0x20},
+	{0x81, 0x3f},
+	{0xcc, 0x02},
+	{0xcd, 0x80},
+	{0xce, 0x01},
+	{0xcf, 0xe0},
+	{0xc8, 0x02},
+	{0xc9, 0x80},
+	{0xca, 0x01},
+	{0xcb, 0xe0},
+	{0xd0, 0x48},
+	{0x82, 0x03},
+	/*{0x0e, 0x00},*/
+	{0x70, 0x00},
+	{0x71, 0x34},
+	{0x74, 0x28},
+	{0x75, 0x98},
+	{0x76, 0x00},
+	{0x77, 0x64},
+	{0x78, 0x01},
+	{0x79, 0xc2},
+	{0x7a, 0x4e},
+	{0x7b, 0x1f},
+	{0x7c, 0x00},
+	{0x11, 0x00},
+	{0x20, 0x00},
+	{0x21, 0x23},
+	{0x50, 0x9a},
+	{0x51, 0x80},
+	{0x4c, 0x7d},
+	/*{0x0e, 0x00},*/
+	{0x85, 0x10},
+	{0x86, 0x00},
+	{0x87, 0x00},
+	{0x88, 0x00},
+	{0x89, 0x2a},
+	{0x8a, 0x26},
+	{0x8b, 0x22},
+	{0xbb, 0x7a},
+	{0xbc, 0x69},
+	{0xbd, 0x11},
+	{0xbe, 0x13},
+	{0xbf, 0x81},
+	{0xc0, 0x96},
+	{0xc1, 0x1e},
+	{0xb7, 0x05},
+	{0xb8, 0x09},
+	{0xb9, 0x00},
+	{0xba, 0x18},
+	{0x5a, 0x1f},
+	{0x5b, 0x9f},
+	{0x5c, 0x6a},
+	{0x5d, 0x42},
+	{0x24, 0x78},
+	{0x25, 0x68},
+	{0x26, 0xb3},
+	{0xa3, 0x0b},
+	{0xa4, 0x15},
+	{0xa5, 0x2a},
+	{0xa6, 0x51},
+	{0xa7, 0x63},
+	{0xa8, 0x74},
+	{0xa9, 0x83},
+	{0xaa, 0x91},
+	{0xab, 0x9e},
+	{0xac, 0xaa},
+	{0xad, 0xbe},
+	{0xae, 0xce},
+	{0xaf, 0xe5},
+	{0xb0, 0xf3},
+	{0xb1, 0xfb},
+	{0xb2, 0x06},
+	{0x8c, 0x5c},
+	{0x8d, 0x11},
+	{0x8e, 0x12},
+	{0x8f, 0x19},
+	{0x90, 0x50},
+	{0x91, 0x20},
+	{0x92, 0x96},
+	{0x93, 0x80},
+	{0x94, 0x13},
+	{0x95, 0x1b},
+	{0x96, 0xff},
+	{0x97, 0x00},
+	{0x98, 0x3d},
+	{0x99, 0x36},
+	{0x9a, 0x51},
+	{0x9b, 0x43},
+	{0x9c, 0xf0},
+	{0x9d, 0xf0},
+	{0x9e, 0xf0},
+	{0x9f, 0xff},
+	{0xa0, 0x68},
+	{0xa1, 0x62},
+	{0xa2, 0x0e},
+};
+#endif
+/* Exposure Compensation */
+struct OV7692_WREG ov7692_exposure_compensation_lv0_tbl[] = {
+	/*@@ +1.7EV*/
+	{0x24, 0xc0},
+	{0x25, 0xb8},
+	{0x26, 0xe6},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv1_tbl[] = {
+	/*@@ +1.0EV*/
+	{0x24, 0xa8},
+	{0x25, 0xa0},
+	{0x26, 0xc4},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv2_default_tbl[] = {
+	/*@@ default*/
+	{0x24, 0x86},
+	{0x25, 0x76},
+	{0x26, 0xb3},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv3_tbl[] = {
+	/*@@ -1.0EV*/
+	{0x24, 0x70},
+	{0x25, 0x60},
+	{0x26, 0xa2},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv4_tbl[] = {
+	/*@@ -1.7EV*/
+	{0x24, 0x50},
+	{0x25, 0x40},
+	{0x26, 0xa2},
+};
+
+struct OV7692_WREG ov7692_antibanding_off_tbl[] = {
+	{0x13, 0xE5, INVMASK(0x20)},
+};
+
+struct OV7692_WREG ov7692_antibanding_auto_tbl[] = {
+	{0x13, 0x20, INVMASK(0x20)},
+	{0x14, 0x14, INVMASK(0x17)},
+};
+
+struct OV7692_WREG ov7692_antibanding_50z_tbl[] = {
+	/*Band 50Hz*/
+	{0x13, 0x20, INVMASK(0x20)},
+	{0x14, 0x17, INVMASK(0x17)},
+};
+
+struct OV7692_WREG ov7692_antibanding_60z_tbl[] = {
+	/*Band 60Hz*/
+	{0x13, 0x20, INVMASK(0x20)},
+	{0x14, 0x16, INVMASK(0x17)},
+};
+
+/*Saturation*/
+struct OV7692_WREG ov7692_saturation_lv0_tbl[] = {
+	/*Saturation level 0*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x00, INVMASK(0xff)},
+	{0xd9, 0x00, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv1_tbl[] = {
+	/*Saturation level 1*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x10, INVMASK(0xff)},
+	{0xd9, 0x10, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv2_tbl[] = {
+	/*Saturation level 2*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x20, INVMASK(0xff)},
+	{0xd9, 0x20, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+
+};
+
+struct OV7692_WREG ov7692_saturation_lv3_tbl[] = {
+	/*Saturation level 3*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x30, INVMASK(0xff)},
+	{0xd9, 0x30, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+
+};
+
+struct OV7692_WREG ov7692_saturation_default_lv4_tbl[] = {
+	/*Saturation level 4 (default)*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x40, INVMASK(0xff)},
+	{0xd9, 0x40, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv5_tbl[] = {
+	/*Saturation level 5*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x50, INVMASK(0xff)},
+	{0xd9, 0x50, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv6_tbl[] = {
+	/*Saturation level 6*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x60, INVMASK(0xff)},
+	{0xd9, 0x60, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv7_tbl[] = {
+	/*Saturation level 7*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x70, INVMASK(0xff)},
+	{0xd9, 0x70, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv8_tbl[] = {
+	/*Saturation level 8*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x80, INVMASK(0xff)},
+	{0xd9, 0x80, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+/*EFFECT*/
+struct OV7692_WREG ov7692_effect_normal_tbl[] = {
+	{0x81, 0x00, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x00, },
+	{0xda, 0x80, },
+	{0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_mono_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x80, },
+	{0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_bw_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x80, },
+	{0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_sepia_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x40, },
+	{0xdb, 0xa0, },
+};
+
+struct OV7692_WREG ov7692_effect_bluish_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0xc0, },
+	{0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_reddish_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x80, },
+	{0xdb, 0xc0, },
+};
+
+struct OV7692_WREG ov7692_effect_greenish_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x60, },
+	{0xdb, 0x60, },
+};
+
+struct OV7692_WREG ov7692_effect_negative_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x80, },
+	{0xd2, 0x40, },
+	{0xda, 0x80, },
+	{0xdb, 0x80, },
+};
+
+/*Contrast*/
+struct OV7692_WREG ov7692_contrast_lv0_tbl[] = {
+	/*Contrast -4*/
+	{0xb2, 0x29},
+	{0xa3, 0x55},
+	{0xa4, 0x5b},
+	{0xa5, 0x67},
+	{0xa6, 0x7e},
+	{0xa7, 0x89},
+	{0xa8, 0x93},
+	{0xa9, 0x9c},
+	{0xaa, 0xa4},
+	{0xab, 0xac},
+	{0xac, 0xb3},
+	{0xad, 0xbe},
+	{0xae, 0xc7},
+	{0xaf, 0xd5},
+	{0xb0, 0xdd},
+	{0xb1, 0xe1},
+};
+
+struct OV7692_WREG ov7692_contrast_lv1_tbl[] = {
+	/*Contrast -3*/
+	{0xb2, 0x20},
+	{0xa3, 0x43},
+	{0xa4, 0x4a},
+	{0xa5, 0x58},
+	{0xa6, 0x73},
+	{0xa7, 0x80},
+	{0xa8, 0x8b},
+	{0xa9, 0x96},
+	{0xaa, 0x9f},
+	{0xab, 0xa8},
+	{0xac, 0xb1},
+	{0xad, 0xbe},
+	{0xae, 0xc9},
+	{0xaf, 0xd8},
+	{0xb0, 0xe2},
+	{0xb1, 0xe8},
+};
+
+struct OV7692_WREG ov7692_contrast_lv2_tbl[] = {
+	/*Contrast -2*/
+	{0xb2, 0x18},
+	{0xa3, 0x31},
+	{0xa4, 0x39},
+	{0xa5, 0x4a},
+	{0xa6, 0x68},
+	{0xa7, 0x77},
+	{0xa8, 0x84},
+	{0xa9, 0x90},
+	{0xaa, 0x9b},
+	{0xab, 0xa5},
+	{0xac, 0xaf},
+	{0xad, 0xbe},
+	{0xae, 0xca},
+	{0xaf, 0xdc},
+	{0xb0, 0xe7},
+	{0xb1, 0xee},
+};
+
+struct OV7692_WREG ov7692_contrast_lv3_tbl[] = {
+	/*Contrast -1*/
+	{0xb2, 0x10},
+	{0xa3, 0x1f},
+	{0xa4, 0x28},
+	{0xa5, 0x3b},
+	{0xa6, 0x5d},
+	{0xa7, 0x6e},
+	{0xa8, 0x7d},
+	{0xa9, 0x8a},
+	{0xaa, 0x96},
+	{0xab, 0xa2},
+	{0xac, 0xad},
+	{0xad, 0xbe},
+	{0xae, 0xcc},
+	{0xaf, 0xe0},
+	{0xb0, 0xed},
+	{0xb1, 0xf4},
+};
+
+struct OV7692_WREG ov7692_contrast_default_lv4_tbl[] = {
+	/*Contrast 0*/
+	{0xb2, 0x6},
+	{0xa3, 0xb},
+	{0xa4, 0x15},
+	{0xa5, 0x2a},
+	{0xa6, 0x51},
+	{0xa7, 0x63},
+	{0xa8, 0x74},
+	{0xa9, 0x83},
+	{0xaa, 0x91},
+	{0xab, 0x9e},
+	{0xac, 0xaa},
+	{0xad, 0xbe},
+	{0xae, 0xce},
+	{0xaf, 0xe5},
+	{0xb0, 0xf3},
+	{0xb1, 0xfb},
+};
+
+struct OV7692_WREG ov7692_contrast_lv5_tbl[] = {
+	/*Contrast 1*/
+	{0xb2, 0xc},
+	{0xa3, 0x4},
+	{0xa4, 0xc},
+	{0xa5, 0x1f},
+	{0xa6, 0x45},
+	{0xa7, 0x58},
+	{0xa8, 0x6b},
+	{0xa9, 0x7c},
+	{0xaa, 0x8d},
+	{0xab, 0x9d},
+	{0xac, 0xac},
+	{0xad, 0xc3},
+	{0xae, 0xd2},
+	{0xaf, 0xe8},
+	{0xb0, 0xf2},
+	{0xb1, 0xf7},
+};
+
+struct OV7692_WREG ov7692_contrast_lv6_tbl[] = {
+	/*Contrast 2*/
+	{0xb2, 0x1},
+	{0xa3, 0x2},
+	{0xa4, 0x9},
+	{0xa5, 0x1a},
+	{0xa6, 0x3e},
+	{0xa7, 0x4a},
+	{0xa8, 0x59},
+	{0xa9, 0x6a},
+	{0xaa, 0x79},
+	{0xab, 0x8e},
+	{0xac, 0xa4},
+	{0xad, 0xc1},
+	{0xae, 0xdb},
+	{0xaf, 0xf4},
+	{0xb0, 0xff},
+	{0xb1, 0xff},
+};
+
+struct OV7692_WREG ov7692_contrast_lv7_tbl[] = {
+	/*Contrast 3*/
+	{0xb2, 0xc},
+	{0xa3, 0x4},
+	{0xa4, 0x8},
+	{0xa5, 0x17},
+	{0xa6, 0x27},
+	{0xa7, 0x3d},
+	{0xa8, 0x54},
+	{0xa9, 0x60},
+	{0xaa, 0x77},
+	{0xab, 0x85},
+	{0xac, 0xa4},
+	{0xad, 0xc6},
+	{0xae, 0xd2},
+	{0xaf, 0xe9},
+	{0xb0, 0xf0},
+	{0xb1, 0xf7},
+};
+
+struct OV7692_WREG ov7692_contrast_lv8_tbl[] = {
+	/*Contrast 4*/
+	{0xb2, 0x1},
+	{0xa3, 0x4},
+	{0xa4, 0x4},
+	{0xa5, 0x7},
+	{0xa6, 0xb},
+	{0xa7, 0x17},
+	{0xa8, 0x2a},
+	{0xa9, 0x41},
+	{0xaa, 0x59},
+	{0xab, 0x6b},
+	{0xac, 0x8b},
+	{0xad, 0xb1},
+	{0xae, 0xd2},
+	{0xaf, 0xea},
+	{0xb0, 0xf4},
+	{0xb1, 0xff},
+};
+
+	/*Sharpness*/
+struct OV7692_WREG ov7692_sharpness_lv0_tbl[] = {
+	/*Sharpness 0*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0x00, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv1_tbl[] = {
+	/*Sharpness 1*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0x01, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_default_lv2_tbl[] = {
+	/*Sharpness Auto (Default)*/
+	{0xb4, 0x00, INVMASK(0x20)},
+	{0xb6, 0x00, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv3_tbl[] = {
+	/*Sharpness 3*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0x66, INVMASK(0x04)},
+};
+struct OV7692_WREG ov7692_sharpness_lv4_tbl[] = {
+	/*Sharpness 4*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0x99, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv5_tbl[] = {
+	/*Sharpness 5*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0xcc, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv6_tbl[] = {
+	/*Sharpness 6*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0xff, INVMASK(0x1f)},
+};
+
+	/* ISO TYPE*/
+struct OV7692_WREG ov7692_iso_type_auto[] = {
+	/*@@ISO Auto*/
+	{0x14, 0x20, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_100[] = {
+	/*@@ISO 100*/
+	{0x14, 0x00, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_200[] = {
+	/*@@ISO 200*/
+	{0x14, 0x10, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_400[] = {
+	/*@@ISO 400*/
+	{0x14, 0x20, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_800[] = {
+	/*@@ISO 800*/
+	{0x14, 0x30, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_1600[] = {
+	/*@@ISO 1600*/
+	{0x14, 0x40, INVMASK(0x70)},
+};
+
+	/*Light Mode*/
+struct OV7692_WREG ov7692_wb_def[] = {
+	{0x13, 0xf7},
+	{0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_custom[] = {
+	{0x13, 0xf5},
+	{0x01, 0x56},
+	{0x02, 0x50},
+	{0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_inc[] = {
+	{0x13, 0xf5},
+	{0x01, 0x66},
+	{0x02, 0x40},
+	{0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_daylight[] = {
+	{0x13, 0xf5},
+	{0x01, 0x43},
+	{0x02, 0x5d},
+	{0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_cloudy[] = {
+	{0x13, 0xf5},
+	{0x01, 0x48},
+	{0x02, 0x63},
+	{0x15, 0x00},
+};
+
 #endif
 
diff --git a/drivers/media/video/msm/ov7692_qrd.c b/drivers/media/video/msm/ov7692_qrd.c
index e558e57..d83f28e 100644
--- a/drivers/media/video/msm/ov7692_qrd.c
+++ b/drivers/media/video/msm/ov7692_qrd.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
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/* #define DEBUG */
-
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/i2c.h>
@@ -52,129 +50,9 @@
 
 
 /*============================================================================
-  DATA DECLARATIONS
-  ============================================================================*/
-/*  96MHz PCLK @ 24MHz MCLK */
-struct reg_addr_val_pair_struct ov7692_init_settings_array[] = {
-	{0x12, 0x80},
-	{0x0e, 0x08},
-	{0x69, 0x52},
-	{0x1e, 0xb3},
-	{0x48, 0x42},
-	{0xff, 0x01},
-	{0xae, 0xa0},
-	{0xa8, 0x26},
-	{0xb4, 0xc0},
-	{0xb5, 0x40},
-	{0xff, 0x00},
-	{0x0c, 0x00},
-	{0x62, 0x10},
-	{0x12, 0x00},
-	{0x17, 0x65},
-	{0x18, 0xa4},
-	{0x19, 0x0a},
-	{0x1a, 0xf6},
-	{0x3e, 0x30},
-	{0x64, 0x0a},
-	{0xff, 0x01},
-	{0xb4, 0xc0},
-	{0xff, 0x00},
-	{0x67, 0x20},
-	{0x81, 0x3f},
-	{0xcc, 0x02},
-	{0xcd, 0x80},
-	{0xce, 0x01},
-	{0xcf, 0xe0},
-	{0xc8, 0x02},
-	{0xc9, 0x80},
-	{0xca, 0x01},
-	{0xcb, 0xe0},
-	{0xd0, 0x48},
-	{0x82, 0x03},
-	{0x0e, 0x00},
-	{0x70, 0x00},
-	{0x71, 0x34},
-	{0x74, 0x28},
-	{0x75, 0x98},
-	{0x76, 0x00},
-	{0x77, 0x64},
-	{0x78, 0x01},
-	{0x79, 0xc2},
-	{0x7a, 0x4e},
-	{0x7b, 0x1f},
-	{0x7c, 0x00},
-	{0x11, 0x00},
-	{0x20, 0x00},
-	{0x21, 0x23},
-	{0x50, 0x9a},
-	{0x51, 0x80},
-	{0x4c, 0x7d},
-	{0x0e, 0x00},
-	{0x85, 0x10},
-	{0x86, 0x00},
-	{0x87, 0x00},
-	{0x88, 0x00},
-	{0x89, 0x2a},
-	{0x8a, 0x26},
-	{0x8b, 0x22},
-	{0xbb, 0x7a},
-	{0xbc, 0x69},
-	{0xbd, 0x11},
-	{0xbe, 0x13},
-	{0xbf, 0x81},
-	{0xc0, 0x96},
-	{0xc1, 0x1e},
-	{0xb7, 0x05},
-	{0xb8, 0x09},
-	{0xb9, 0x00},
-	{0xba, 0x18},
-	{0x5a, 0x1f},
-	{0x5b, 0x9f},
-	{0x5c, 0x6a},
-	{0x5d, 0x42},
-	{0x24, 0x78},
-	{0x25, 0x68},
-	{0x26, 0xb3},
-	{0xa3, 0x0b},
-	{0xa4, 0x15},
-	{0xa5, 0x2a},
-	{0xa6, 0x51},
-	{0xa7, 0x63},
-	{0xa8, 0x74},
-	{0xa9, 0x83},
-	{0xaa, 0x91},
-	{0xab, 0x9e},
-	{0xac, 0xaa},
-	{0xad, 0xbe},
-	{0xae, 0xce},
-	{0xaf, 0xe5},
-	{0xb0, 0xf3},
-	{0xb1, 0xfb},
-	{0xb2, 0x06},
-	{0x8c, 0x5c},
-	{0x8d, 0x11},
-	{0x8e, 0x12},
-	{0x8f, 0x19},
-	{0x90, 0x50},
-	{0x91, 0x20},
-	{0x92, 0x96},
-	{0x93, 0x80},
-	{0x94, 0x13},
-	{0x95, 0x1b},
-	{0x96, 0xff},
-	{0x97, 0x00},
-	{0x98, 0x3d},
-	{0x99, 0x36},
-	{0x9a, 0x51},
-	{0x9b, 0x43},
-	{0x9c, 0xf0},
-	{0x9d, 0xf0},
-	{0x9e, 0xf0},
-	{0x9f, 0xff},
-	{0xa0, 0x68},
-	{0xa1, 0x62},
-	{0xa2, 0x0e},
-};
+			DATA DECLARATIONS
+============================================================================*/
+
 
 static bool OV7692_CSI_CONFIG;
 /* 816x612, 24MHz MCLK 96MHz PCLK */
@@ -214,6 +92,10 @@
 static struct ov7692_ctrl_t *ov7692_ctrl;
 static DECLARE_WAIT_QUEUE_HEAD(ov7692_wait_queue);
 DEFINE_MUTEX(ov7692_mut);
+static int effect_value;
+static int16_t ov7692_effect = CAMERA_EFFECT_OFF;
+static unsigned int SAT_U = 0x80;
+static unsigned int SAT_V = 0x80;
 
 /*=============================================================*/
 
@@ -284,14 +166,33 @@
 	memset(buf, 0, sizeof(buf));
 	buf[0] = waddr;
 	buf[1] = bdata;
-
+	CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
 	rc = ov7692_i2c_txdata(ov7692_client->addr >> 1, buf, 2);
 	if (rc < 0)
 		CDBG("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
-				waddr, bdata);
+		waddr, bdata);
+
 	return rc;
 }
 
+static int32_t OV7692_WritePRegs(struct OV7692_WREG *pTb, int32_t len)
+{
+	int32_t i, ret = 0;
+	uint8_t regv;
+
+	for (i = 0; i < len; i++) {
+		if (pTb[i].mask == 0) {
+			ov7692_i2c_write_b_sensor(pTb[i].addr, pTb[i].data);
+		} else {
+			ov7692_i2c_read(pTb[i].addr, &regv, 1);
+			regv &= pTb[i].mask;
+			regv |= (pTb[i].data & (~pTb[i].mask));
+			ov7692_i2c_write_b_sensor(pTb[i].addr, regv);
+		}
+	}
+	return ret;
+}
+
 static int32_t ov7692_sensor_setting(int update_type, int rt)
 {
 	int32_t i, array_length;
@@ -314,8 +215,6 @@
 			ov7692_csi_params.dpcm_scheme = 0;
 			ov7692_csi_params.settle_cnt = 0x14;
 
-			rc = msm_camio_csi_config(&ov7692_csi_params);
-			msleep(20);
 			array_length = sizeof(ov7692_init_settings_array) /
 				sizeof(ov7692_init_settings_array[0]);
 			for (i = 0; i < array_length; i++) {
@@ -325,6 +224,10 @@
 				if (rc < 0)
 					return rc;
 			}
+			usleep_range(10000, 11000);
+			rc = msm_camio_csi_config(&ov7692_csi_params);
+			usleep_range(10000, 11000);
+			ov7692_i2c_write_b_sensor(0x0e, 0x00);
 			OV7692_CSI_CONFIG = 1;
 			msleep(20);
 			return rc;
@@ -371,6 +274,442 @@
 	return rc;
 }
 
+static int ov7692_set_exposure_compensation(int compensation)
+{
+	long rc = 0;
+
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...exposure_compensation = %d\n",
+		 __func__ , compensation);
+	switch (compensation) {
+	case CAMERA_EXPOSURE_COMPENSATION_LV0:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV0\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv0_tbl);
+		break;
+	case CAMERA_EXPOSURE_COMPENSATION_LV1:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV1\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv1_tbl);
+		break;
+	case CAMERA_EXPOSURE_COMPENSATION_LV2:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV2\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv2_default_tbl);
+		break;
+	case CAMERA_EXPOSURE_COMPENSATION_LV3:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV3\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv3_tbl);
+		break;
+	case CAMERA_EXPOSURE_COMPENSATION_LV4:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV3\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv4_tbl);
+		break;
+	default:
+		CDBG("--CAMERA--ERROR CAMERA_EXPOSURE_COMPENSATION\n");
+		break;
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static long ov7692_set_antibanding(int antibanding)
+{
+	long rc = 0;
+
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...antibanding = %d\n", __func__, antibanding);
+	switch (antibanding) {
+	case CAMERA_ANTIBANDING_OFF:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_OFF\n");
+		break;
+	case CAMERA_ANTIBANDING_60HZ:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_60HZ\n");
+		rc = OV7692Core_WritePREG(ov7692_antibanding_60z_tbl);
+		break;
+	case CAMERA_ANTIBANDING_50HZ:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_50HZ\n");
+		rc = OV7692Core_WritePREG(ov7692_antibanding_50z_tbl);
+		break;
+	case CAMERA_ANTIBANDING_AUTO:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_AUTO\n");
+		rc = OV7692Core_WritePREG(ov7692_antibanding_auto_tbl);
+		break;
+	default:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_ERROR COMMAND\n");
+		break;
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_saturation(int saturation)
+{
+	long rc = 0;
+
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...saturation = %d\n", __func__ , saturation);
+
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		switch (saturation) {
+		case CAMERA_SATURATION_LV0:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV0\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv0_tbl);
+			break;
+		case CAMERA_SATURATION_LV1:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV1\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv1_tbl);
+			break;
+		case CAMERA_SATURATION_LV2:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV2\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv2_tbl);
+			break;
+		case CAMERA_SATURATION_LV3:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV3\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv3_tbl);
+			break;
+		case CAMERA_SATURATION_LV4:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV4\n");
+			rc = OV7692Core_WritePREG(
+				ov7692_saturation_default_lv4_tbl);
+			break;
+		case CAMERA_SATURATION_LV5:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV5\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv5_tbl);
+			break;
+		case CAMERA_SATURATION_LV6:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV6\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv6_tbl);
+			break;
+		case CAMERA_SATURATION_LV7:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV7\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv7_tbl);
+			break;
+		case CAMERA_SATURATION_LV8:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV8\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv8_tbl);
+			break;
+		default:
+			CDBG("--CAMERA--CAMERA_SATURATION_ERROR COMMAND\n");
+			break;
+		}
+	}
+
+	/*for recover saturation level when change special effect*/
+	switch (saturation) {
+	case CAMERA_SATURATION_LV0:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV0\n");
+		SAT_U = 0x00;
+		SAT_V = 0x00;
+		break;
+	case CAMERA_SATURATION_LV1:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV1\n");
+		SAT_U = 0x10;
+		SAT_V = 0x10;
+		break;
+	case CAMERA_SATURATION_LV2:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV2\n");
+		SAT_U = 0x20;
+		SAT_V = 0x20;
+		break;
+	case CAMERA_SATURATION_LV3:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV3\n");
+		SAT_U = 0x30;
+		SAT_V = 0x30;
+		break;
+	case CAMERA_SATURATION_LV4:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV4\n");
+		SAT_U = 0x40;
+		SAT_V = 0x40;
+		break;
+	case CAMERA_SATURATION_LV5:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV5\n");
+		SAT_U = 0x50;
+		SAT_V = 0x50;
+		break;
+	case CAMERA_SATURATION_LV6:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV6\n");
+		SAT_U = 0x60;
+		SAT_V = 0x60;
+		break;
+	case CAMERA_SATURATION_LV7:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV7\n");
+		SAT_U = 0x70;
+		SAT_V = 0x70;
+		break;
+	case CAMERA_SATURATION_LV8:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV8\n");
+		SAT_U = 0x80;
+		SAT_V = 0x80;
+		break;
+	default:
+		CDBG("--CAMERA--CAMERA_SATURATION_ERROR COMMAND\n");
+		break;
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static long ov7692_set_effect(int mode, int effect)
+{
+	int rc = 0;
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+
+	switch (mode) {
+	case SENSOR_PREVIEW_MODE:
+		break;
+	case SENSOR_HFR_60FPS_MODE:
+		break;
+	case SENSOR_HFR_90FPS_MODE:
+		/* Context A Special Effects */
+		CDBG("-CAMERA- %s ...SENSOR_PREVIEW_MODE\n", __func__);
+		break;
+	case SENSOR_SNAPSHOT_MODE:
+		/* Context B Special Effects */
+		CDBG("-CAMERA- %s ...SENSOR_SNAPSHOT_MODE\n", __func__);
+		break;
+	default:
+		break;
+	}
+	effect_value = effect;
+	switch (effect) {
+	case CAMERA_EFFECT_OFF: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_OFF\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_normal_tbl);
+		/* for recover saturation level
+		 when change special effect*/
+		ov7692_i2c_write_b_sensor(0xda, SAT_U);
+		/* for recover saturation level
+		when change special effect*/
+		ov7692_i2c_write_b_sensor(0xdb, SAT_V);
+		break;
+	}
+	case CAMERA_EFFECT_MONO: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_MONO\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_mono_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_BW: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_BW\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_bw_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_BLUISH: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_BLUISH\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_bluish_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_SOLARIZE: {
+		CDBG("%s ...CAMERA_EFFECT_NEGATIVE(No Support)!\n", __func__);
+		break;
+	}
+	case CAMERA_EFFECT_SEPIA: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_SEPIA\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_sepia_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_REDDISH: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_REDDISH\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_reddish_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_GREENISH: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_GREENISH\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_greenish_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_NEGATIVE: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_NEGATIVE\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_negative_tbl);
+		break;
+	}
+	default: {
+		CDBG("--CAMERA-- %s ...Default(Not Support)\n", __func__);
+	}
+	}
+	ov7692_effect = effect;
+	/*Refresh Sequencer */
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_contrast(int contrast)
+{
+	int rc = 0;
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...contrast = %d\n", __func__ , contrast);
+
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		switch (contrast) {
+		case CAMERA_CONTRAST_LV0:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV0\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv0_tbl);
+			break;
+		case CAMERA_CONTRAST_LV1:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV1\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv1_tbl);
+			break;
+		case CAMERA_CONTRAST_LV2:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV2\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv2_tbl);
+			break;
+		case CAMERA_CONTRAST_LV3:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV3\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv3_tbl);
+			break;
+		case CAMERA_CONTRAST_LV4:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV4\n");
+			rc = OV7692Core_WritePREG(
+				ov7692_contrast_default_lv4_tbl);
+			break;
+		case CAMERA_CONTRAST_LV5:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV5\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv5_tbl);
+			break;
+		case CAMERA_CONTRAST_LV6:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV6\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv6_tbl);
+			break;
+		case CAMERA_CONTRAST_LV7:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV7\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv7_tbl);
+			break;
+		case CAMERA_CONTRAST_LV8:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV8\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv8_tbl);
+			break;
+		default:
+			CDBG("--CAMERA--CAMERA_CONTRAST_ERROR COMMAND\n");
+			break;
+		}
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_sharpness(int sharpness)
+{
+	int rc = 0;
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...sharpness = %d\n", __func__ , sharpness);
+
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		switch (sharpness) {
+		case CAMERA_SHARPNESS_LV0:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV0\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv0_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV1:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV1\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv1_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV2:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV2\n");
+			rc = OV7692Core_WritePREG(
+				ov7692_sharpness_default_lv2_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV3:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV3\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv3_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV4:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV4\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv4_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV5:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV5\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv5_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV6:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV6\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv6_tbl);
+			break;
+		default:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_ERROR COMMAND\n");
+			break;
+		}
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_iso(int8_t iso_type)
+{
+	long rc = 0;
+
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...iso_type = %d\n", __func__ , iso_type);
+	switch (iso_type) {
+	case CAMERA_ISO_TYPE_AUTO:
+		CDBG("--CAMERA--CAMERA_ISO_TYPE_AUTO\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_auto);
+		break;
+	case CAMEAR_ISO_TYPE_HJR:
+		CDBG("--CAMERA--CAMEAR_ISO_TYPE_HJR\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_auto);
+		break;
+	case CAMEAR_ISO_TYPE_100:
+		CDBG("--CAMERA--CAMEAR_ISO_TYPE_100\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_100);
+		break;
+	case CAMERA_ISO_TYPE_200:
+		CDBG("--CAMERA--CAMERA_ISO_TYPE_200\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_200);
+		break;
+	case CAMERA_ISO_TYPE_400:
+		CDBG("--CAMERA--CAMERA_ISO_TYPE_400\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_400);
+		break;
+	case CAMEAR_ISO_TYPE_800:
+		CDBG("--CAMERA--CAMEAR_ISO_TYPE_800\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_800);
+		break;
+	case CAMERA_ISO_TYPE_1600:
+		CDBG("--CAMERA--CAMERA_ISO_TYPE_1600\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_1600);
+		break;
+	default:
+		CDBG("--CAMERA--ERROR ISO TYPE\n");
+		break;
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_wb_oem(uint8_t param)
+{
+	int rc = 0;
+	CDBG("--CAMERA--%s runs\r\n", __func__);
+
+	switch (param) {
+	case CAMERA_WB_AUTO:
+		CDBG("--CAMERA--CAMERA_WB_AUTO\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_def);
+		break;
+	case CAMERA_WB_CUSTOM:
+		CDBG("--CAMERA--CAMERA_WB_CUSTOM\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_custom);
+		break;
+	case CAMERA_WB_INCANDESCENT:
+		CDBG("--CAMERA--CAMERA_WB_INCANDESCENT\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_inc);
+		break;
+	case CAMERA_WB_DAYLIGHT:
+		CDBG("--CAMERA--CAMERA_WB_DAYLIGHT\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_daylight);
+		break;
+	case CAMERA_WB_CLOUDY_DAYLIGHT:
+		CDBG("--CAMERA--CAMERA_WB_CLOUDY_DAYLIGHT\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_cloudy);
+		break;
+	default:
+		break;
+	}
+	return rc;
+}
+
 static void ov7692_power_on(void)
 {
 	CDBG("%s\n", __func__);
@@ -392,13 +731,12 @@
 static void ov7692_hw_reset(void)
 {
 	CDBG("--CAMERA-- %s ... (Start...)\n", __func__);
-	gpio_set_value(ov7692_reset_gpio, 1);   /* reset camera reset pin */
-	msleep(20);
+	gpio_set_value(ov7692_reset_gpio, 1);   /*reset camera reset pin*/
+	usleep_range(5000, 5100);
 	gpio_set_value(ov7692_reset_gpio, 0);
-	msleep(20);
+	usleep_range(5000, 5100);
 	gpio_set_value(ov7692_reset_gpio, 1);
-	msleep(20);
-
+	usleep_range(1000, 1100);
 	CDBG("--CAMERA-- %s ... (End...)\n", __func__);
 }
 
@@ -458,6 +796,9 @@
 
 	if (data)
 		ov7692_ctrl->sensordata = data;
+	/* turn on LDO for PVT */
+	if (data->pmic_gpio_enable)
+		lcd_camera_power_onoff(1);
 
 	/* enable mclk first */
 
@@ -465,7 +806,7 @@
 	msleep(20);
 
 	ov7692_power_on();
-	msleep(20);
+	usleep_range(5000, 5100);
 
 	rc = ov7692_probe_init_sensor(data);
 	if (rc < 0) {
@@ -481,6 +822,8 @@
 
 init_fail:
 	CDBG(" ov7692_sensor_open_init fail\n");
+	if (data->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
 	kfree(ov7692_ctrl);
 init_done:
 	CDBG("ov7692_sensor_open_init done\n");
@@ -559,14 +902,160 @@
 	CDBG("ov7692_sensor_config: cfgtype = %d\n", cdata.cfgtype);
 	switch (cdata.cfgtype) {
 	case CFG_SET_MODE:
-		rc = ov7692_set_sensor_mode(cdata.mode,
-				cdata.rs);
+		rc = ov7692_set_sensor_mode(cdata.mode, cdata.rs);
+		break;
+	case CFG_SET_EFFECT:
+		CDBG("--CAMERA-- CFG_SET_EFFECT mode=%d, effect = %d !!\n",
+			 cdata.mode, cdata.cfg.effect);
+		rc = ov7692_set_effect(cdata.mode, cdata.cfg.effect);
+		break;
+	case CFG_START:
+		CDBG("--CAMERA-- CFG_START (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_PWR_UP:
+		CDBG("--CAMERA-- CFG_PWR_UP (Not Support) !!\n");
+		/* Not Support */
 		break;
 	case CFG_PWR_DOWN:
+		CDBG("--CAMERA-- CFG_PWR_DOWN !!\n");
 		ov7692_power_down();
 		break;
+	case CFG_WRITE_EXPOSURE_GAIN:
+		CDBG("--CAMERA-- CFG_WRITE_EXPOSURE_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_DEFAULT_FOCUS:
+		CDBG("--CAMERA-- CFG_SET_DEFAULT_FOCUS (Not Implement) !!\n");
+		break;
+	case CFG_MOVE_FOCUS:
+		CDBG("--CAMERA-- CFG_MOVE_FOCUS (Not Implement) !!\n");
+		break;
+	case CFG_REGISTER_TO_REAL_GAIN:
+		CDBG("--CAMERA-- CFG_REGISTER_TO_REAL_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_REAL_TO_REGISTER_GAIN:
+		CDBG("--CAMERA-- CFG_REAL_TO_REGISTER_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_FPS:
+		CDBG("--CAMERA-- CFG_SET_FPS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_PICT_FPS:
+		CDBG("--CAMERA-- CFG_SET_PICT_FPS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_BRIGHTNESS:
+		CDBG("--CAMERA-- CFG_SET_BRIGHTNESS  !!\n");
+		/* rc = ov7692_set_brightness(cdata.cfg.brightness); */
+		break;
+	case CFG_SET_CONTRAST:
+		CDBG("--CAMERA-- CFG_SET_CONTRAST  !!\n");
+		rc = ov7692_set_contrast(cdata.cfg.contrast);
+		break;
+	case CFG_SET_ZOOM:
+		CDBG("--CAMERA-- CFG_SET_ZOOM (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_EXPOSURE_MODE:
+		CDBG("--CAMERA-- CFG_SET_EXPOSURE_MODE !!\n");
+		/* rc = ov7692_set_exposure_mode(cdata.cfg.ae_mode); */
+		break;
+	case CFG_SET_WB:
+		CDBG("--CAMERA-- CFG_SET_WB!!\n");
+		ov7692_set_wb_oem(cdata.cfg.wb_val);
+		rc = 0 ;
+		break;
+	case CFG_SET_ANTIBANDING:
+		CDBG("--CAMERA-- CFG_SET_ANTIBANDING antibanding = %d !!\n",
+			 cdata.cfg.antibanding);
+		rc = ov7692_set_antibanding(cdata.cfg.antibanding);
+		break;
+	case CFG_SET_EXP_GAIN:
+		CDBG("--CAMERA-- CFG_SET_EXP_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_PICT_EXP_GAIN:
+		CDBG("--CAMERA-- CFG_SET_PICT_EXP_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_LENS_SHADING:
+		CDBG("--CAMERA-- CFG_SET_LENS_SHADING !!\n");
+		/* rc = ov7692_lens_shading_enable(cdata.cfg.lens_shading); */
+		break;
+	case CFG_GET_PICT_FPS:
+		CDBG("--CAMERA-- CFG_GET_PICT_FPS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PREV_L_PF:
+		CDBG("--CAMERA-- CFG_GET_PREV_L_PF (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PREV_P_PL:
+		CDBG("--CAMERA-- CFG_GET_PREV_P_PL (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PICT_L_PF:
+		CDBG("--CAMERA-- CFG_GET_PICT_L_PF (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PICT_P_PL:
+		CDBG("--CAMERA-- CFG_GET_PICT_P_PL (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_AF_MAX_STEPS:
+		CDBG("--CAMERA-- CFG_GET_AF_MAX_STEPS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PICT_MAX_EXP_LC:
+		CDBG("--CAMERA-- CFG_GET_PICT_MAX_EXP_LC (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SEND_WB_INFO:
+		CDBG("--CAMERA-- CFG_SEND_WB_INFO (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SENSOR_INIT:
+		CDBG("--CAMERA-- CFG_SENSOR_INIT (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_SATURATION:
+		CDBG("--CAMERA-- CFG_SET_SATURATION !!\n");
+		rc = ov7692_set_saturation(cdata.cfg.saturation);
+		break;
+	case CFG_SET_SHARPNESS:
+		CDBG("--CAMERA-- CFG_SET_SHARPNESS !!\n");
+		rc = ov7692_set_sharpness(cdata.cfg.sharpness);
+		break;
+	case CFG_SET_TOUCHAEC:
+		CDBG("--CAMERA-- CFG_SET_TOUCHAEC!!\n");
+		/* ov7692_set_touchaec(cdata.cfg.aec_cord.x,
+			 cdata.cfg.aec_cord.y); */
+		rc = 0 ;
+		break;
+	case CFG_SET_AUTO_FOCUS:
+		CDBG("--CAMERA-- CFG_SET_AUTO_FOCUS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_AUTOFLASH:
+		CDBG("--CAMERA-- CFG_SET_AUTOFLASH (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_EXPOSURE_COMPENSATION:
+		CDBG("--CAMERA-- CFG_SET_EXPOSURE_COMPENSATION !\n");
+		rc = ov7692_set_exposure_compensation(
+			cdata.cfg.exp_compensation);
+		break;
+	case CFG_SET_ISO:
+		CDBG("--CAMERA-- CFG_SET_ISO !\n");
+		rc = ov7692_set_iso(cdata.cfg.iso_type);
+		break;
 	default:
-		rc = -EFAULT;
+		CDBG("--CAMERA-- %s: Command=%d (Not Implement) !!\n",
+			 __func__, cdata.cfgtype);
+		rc = -EINVAL;
 		break;
 	}
 
@@ -577,6 +1066,7 @@
 static int ov7692_sensor_release(void)
 {
 	int rc = -EBADF;
+
 	mutex_lock(&ov7692_mut);
 	ov7692_sw_reset();
 	ov7692_power_down();
@@ -614,20 +1104,23 @@
 		rc = -ENOTSUPP;
 		goto probe_fail;
 	}
-
+	pr_debug("%s: %d Entered\n", __func__, __LINE__);
 	rc = ov7692_probe_init_gpio(info);
 	if (rc < 0) {
 		CDBG("%s: gpio init failed\n", __func__);
 		goto probe_fail;
 	}
+	/* turn on LDO for PVT */
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(1);
 
 	ov7692_power_down();
 
 	msm_camio_clk_rate_set(24000000);
-	msleep(20);
+	usleep_range(5000, 5100);
 
 	ov7692_power_on();
-	msleep(20);
+	usleep_range(5000, 5100);
 
 	if (info->sensor_reset_enable)
 		ov7692_hw_reset();
@@ -645,12 +1138,18 @@
 	s->s_camera_type = FRONT_CAMERA_2D;
 	s->s_mount_angle = info->sensor_platform_info->mount_angle;
 
+	/* ov7692_sw_reset(); */
 	ov7692_power_down();
 
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
+
 	return rc;
 
 probe_fail:
 	CDBG("ov7692_sensor_probe: SENSOR PROBE FAILS!\n");
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
 	i2c_del_driver(&ov7692_i2c_driver);
 	return rc;
 }
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index f31aece..92700f6 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -38,7 +38,7 @@
 static struct msm_camera_i2c_reg_conf imx074_prev_settings[] = {
 	{0x0307, 0x2D}, /*pll_multiplier*/
 	{0x0340, 0x06}, /*frame_length_lines_hi*/
-	{0x0341, 0x2D}, /*frame_length_lines_lo*/
+	{0x0341, 0x34}, /*frame_length_lines_lo*/
 	{0x0342, 0x11}, /*line_length_pclk_hi*/
 	{0x0343, 0x78}, /*line_length_pclk_lo*/
 	{0x0347, 0x00}, /*y_addr_start*/
@@ -161,9 +161,9 @@
 		.x_output = 0x838,
 		.y_output = 0x618,
 		.line_length_pclk = 0x1178,
-		.frame_length_lines = 0x62D,
+		.frame_length_lines = 0x634,
 		.vt_pixel_clk = 216000000,
-		.op_pixel_clk = 216000000,
+		.op_pixel_clk = 108000000,
 		.binning_factor = 2,
 	},
 };
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d0b4f1f..cade3d6 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -13,6 +13,7 @@
 #include "msm_sensor.h"
 #include "msm.h"
 #include "msm_ispif.h"
+#include "msm_camera_i2c_mux.h"
 
 /*=============================================================*/
 
@@ -449,6 +450,26 @@
 	{"cam_clk", MSM_SENSOR_MCLK_24HZ},
 };
 
+int32_t msm_sensor_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_INIT, NULL);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_CFG, (void *)&i2c_conf->i2c_mux_mode);
+	return 0;
+}
+
+int32_t msm_sensor_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+				VIDIOC_MSM_I2C_MUX_RELEASE, NULL);
+	return 0;
+}
+
 int32_t msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
 {
 	int32_t rc = 0;
@@ -506,6 +527,10 @@
 	if (data->sensor_platform_info->ext_power_ctrl != NULL)
 		data->sensor_platform_info->ext_power_ctrl(1);
 
+	if (data->sensor_platform_info->i2c_conf &&
+		data->sensor_platform_info->i2c_conf->use_i2c_mux)
+		msm_sensor_enable_i2c_mux(data->sensor_platform_info->i2c_conf);
+
 	return rc;
 enable_clk_failed:
 		msm_camera_config_gpio_table(data, 0);
@@ -531,6 +556,11 @@
 {
 	struct msm_camera_sensor_info *data = s_ctrl->sensordata;
 	CDBG("%s\n", __func__);
+	if (data->sensor_platform_info->i2c_conf &&
+		data->sensor_platform_info->i2c_conf->use_i2c_mux)
+		msm_sensor_disable_i2c_mux(
+			data->sensor_platform_info->i2c_conf);
+
 	if (data->sensor_platform_info->ext_power_ctrl != NULL)
 		data->sensor_platform_info->ext_power_ctrl(0);
 	msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index 2177991..954dd2f 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -114,8 +114,8 @@
 	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
 	{0x0306, 0x00}, /* pll_multiplier */
 	{0x0307, 0xA5}, /* pll_multiplier */
-	{0x0202, 0x02}, /* coarse_integration_time */
-	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0202, 0x03}, /* coarse_integration_time */
+	{0x0203, 0xD8}, /* coarse_integration_time */
 	{0x0340, 0x03}, /* frame_length_lines */
 	{0x0341, 0xE0}, /* frame_length_lines */
 	{0x0342, 0x14}, /* line_length_pck */
@@ -152,7 +152,7 @@
 	{0x0306, 0x00}, /* pll_multiplier */
 	{0x0307, 0xA5}, /* pll_multiplier */
 	{0x0202, 0x02}, /* coarse_integration_time */
-	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0203, 0x90}, /* coarse_integration_time */
 	{0x0340, 0x02}, /* frame_length_lines */
 	{0x0341, 0x98}, /* frame_length_lines */
 	{0x0342, 0x14}, /* line_length_pck */
@@ -188,10 +188,10 @@
 	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
 	{0x0306, 0x00}, /* pll_multiplier */
 	{0x0307, 0xA5}, /* pll_multiplier */
-	{0x0202, 0x02}, /* coarse_integration_time */
-	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0202, 0x01}, /* coarse_integration_time */
+	{0x0203, 0xFA}, /* coarse_integration_time */
 	{0x0340, 0x02}, /* frame_length_lines */
-	{0x0341, 0x0D}, /* frame_length_lines */
+	{0x0341, 0x02}, /* frame_length_lines */
 	{0x0342, 0x14}, /* line_length_pck */
 	{0x0343, 0xD8}, /* line_length_pck */
 	{0x0344, 0x01}, /* x_addr_start */
@@ -519,7 +519,7 @@
 		.x_output = 864,
 		.y_output = 480,
 		.line_length_pclk = 5336,
-		.frame_length_lines = 525,
+		.frame_length_lines = 514,
 		.vt_pixel_clk = 330000000,
 		.op_pixel_clk = 320000000,
 		.binning_factor = 1,
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 315705c..ce81746 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -35,6 +35,7 @@
 #include "vsg-subdev.h"
 
 #define WFD_VERSION KERNEL_VERSION(0, 0, 1)
+#define WFD_DEVICE_NUMBER 38
 #define DEFAULT_WFD_WIDTH 640
 #define DEFAULT_WFD_HEIGHT 480
 #define VSG_SCRATCH_BUFFERS 1
@@ -1155,7 +1156,8 @@
 	wfd_dev->pvdev->fops = &g_wfd_fops;
 	wfd_dev->pvdev->ioctl_ops = &g_wfd_ioctl_ops;
 
-	rc = video_register_device(wfd_dev->pvdev, VFL_TYPE_GRABBER, -1);
+	rc = video_register_device(wfd_dev->pvdev, VFL_TYPE_GRABBER,
+			WFD_DEVICE_NUMBER);
 	if (rc) {
 		WFD_MSG_ERR("Failed to register the device\n");
 		goto err_video_register_device;
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index e4d8bd5..8049975 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -42,7 +42,7 @@
 #define PM8921_VERSION_MASK	0xFFF0
 #define PM8921_VERSION_VALUE	0x06F0
 #define PM8922_VERSION_VALUE	0x0AF0
-#define PM8917_VERSION_VALUE	0x12F0
+#define PM8917_VERSION_VALUE	0x0CF0
 #define PM8921_REVISION_MASK	0x000F
 
 #define REG_PM8921_PON_CNTRL_3	0x01D
@@ -427,9 +427,26 @@
 	NCP("8921_ncp", 0x090),
 };
 
+/*
+ * PM8917 adds 6 LDOs and a boost regulator beyond those available on PM8921.
+ * It also replaces SMPS 3 with FTSMPS 3.  PM8917 does not have an NCP.
+ */
+static struct pm8xxx_vreg pm8917_regulator_data[] = {
+	/*   name	     pc_name	    ctrl   test   hpm_min */
+	PLDO("8917_l30",     "8917_l30_pc", 0x0A3, 0x0A4, LDO_150),
+	PLDO("8917_l31",     "8917_l31_pc", 0x0A5, 0x0A6, LDO_150),
+	PLDO("8917_l32",     "8917_l32_pc", 0x0A7, 0x0A8, LDO_150),
+	PLDO("8917_l33",     "8917_l33_pc", 0x0C6, 0x0C7, LDO_150),
+	PLDO("8917_l34",     "8917_l34_pc", 0x0D2, 0x0D3, LDO_150),
+	PLDO("8917_l35",     "8917_l35_pc", 0x0D4, 0x0D5, LDO_300),
+
+	/*    name          ctrl */
+	BOOST("8917_boost", 0x04B),
+};
+
 #define MAX_NAME_COMPARISON_LEN 32
 
-static int __devinit match_regulator(
+static int __devinit match_regulator(enum pm8xxx_version version,
 	struct pm8xxx_regulator_core_platform_data *core_data, char *name)
 {
 	int found = 0;
@@ -452,6 +469,25 @@
 			break;
 		}
 	}
+	if (version == PM8XXX_VERSION_8917) {
+		for (i = 0; i < ARRAY_SIZE(pm8917_regulator_data); i++) {
+			if (pm8917_regulator_data[i].rdesc.name
+			    && strncmp(pm8917_regulator_data[i].rdesc.name,
+					name, MAX_NAME_COMPARISON_LEN) == 0) {
+				core_data->is_pin_controlled = false;
+				core_data->vreg = &pm8917_regulator_data[i];
+				found = 1;
+				break;
+			} else if (pm8917_regulator_data[i].rdesc_pc.name
+			      && strncmp(pm8917_regulator_data[i].rdesc_pc.name,
+					name, MAX_NAME_COMPARISON_LEN) == 0) {
+				core_data->is_pin_controlled = true;
+				core_data->vreg = &pm8917_regulator_data[i];
+				found = 1;
+				break;
+			}
+		}
+	}
 
 	if (!found)
 		pr_err("could not find a match for regulator: %s\n", name);
@@ -466,8 +502,11 @@
 	int ret = 0;
 	struct mfd_cell *mfd_regulators;
 	struct pm8xxx_regulator_core_platform_data *cdata;
+	enum pm8xxx_version version;
 	int i;
 
+	version = pm8xxx_get_version(pmic->dev);
+
 	/* Add one device for each regulator used by the board. */
 	mfd_regulators = kzalloc(sizeof(struct mfd_cell)
 				 * (pdata->num_regulators), GFP_KERNEL);
@@ -488,6 +527,8 @@
 	}
 	for (i = 0; i < ARRAY_SIZE(regulator_data); i++)
 		mutex_init(&regulator_data[i].pc_lock);
+	for (i = 0; i < ARRAY_SIZE(pm8917_regulator_data); i++)
+		mutex_init(&pm8917_regulator_data[i].pc_lock);
 
 	for (i = 0; i < pdata->num_regulators; i++) {
 		if (!pdata->regulator_pdatas[i].init_data.constraints.name) {
@@ -495,7 +536,7 @@
 			ret = -EINVAL;
 			goto bail;
 		}
-		if (!match_regulator(&cdata[i],
+		if (!match_regulator(version, &cdata[i],
 		      pdata->regulator_pdatas[i].init_data.constraints.name)) {
 			ret = -ENODEV;
 			goto bail;
@@ -519,6 +560,8 @@
 bail:
 	for (i = 0; i < ARRAY_SIZE(regulator_data); i++)
 		mutex_destroy(&regulator_data[i].pc_lock);
+	for (i = 0; i < ARRAY_SIZE(pm8917_regulator_data); i++)
+		mutex_destroy(&pm8917_regulator_data[i].pc_lock);
 	kfree(mfd_regulators);
 	kfree(cdata);
 	return ret;
@@ -908,6 +951,9 @@
 		if (pmic->mfd_regulators) {
 			for (i = 0; i < ARRAY_SIZE(regulator_data); i++)
 				mutex_destroy(&regulator_data[i].pc_lock);
+			for (i = 0; i < ARRAY_SIZE(pm8917_regulator_data); i++)
+				mutex_destroy(
+					&pm8917_regulator_data[i].pc_lock);
 		}
 		kfree(pmic->mfd_regulators);
 		kfree(pmic->regulator_cdata);
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
index 14c9ec4..17b518e 100644
--- a/drivers/mfd/pm8xxx-irq.c
+++ b/drivers/mfd/pm8xxx-irq.c
@@ -102,6 +102,7 @@
 		goto bail;
 	}
 
+	cp &= ~PM_IRQF_WRITE;
 	rc = pm8xxx_writeb(chip->dev,
 			SSBI_REG_ADDR_IRQ_CONFIG(chip->base_addr), cp);
 	if (rc)
@@ -127,7 +128,10 @@
 		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
 		goto bail;
 	}
-
+	/*
+	 * Set the write bit here as this could be a unrequested irq
+	 * whose PM_IRQF_WRITE bit is not set
+	 */
 	cp |= PM_IRQF_WRITE;
 	rc = pm8xxx_writeb(chip->dev,
 			SSBI_REG_ADDR_IRQ_CONFIG(chip->base_addr), cp);
@@ -222,7 +226,7 @@
 	irq_bit = pmirq % 8;
 
 	if (chip->config[pmirq] == 0) {
-		pr_warn("masking rouge irq=%d pmirq=%d\n", d->irq, pmirq);
+		pr_warn("masking rogue irq=%d pmirq=%d\n", d->irq, pmirq);
 		chip->config[pmirq] = irq_bit << PM_IRQF_BITS_SHIFT;
 	}
 
@@ -242,7 +246,7 @@
 	irq_bit = pmirq % 8;
 
 	if (chip->config[pmirq] == 0) {
-		pr_warn("mask acking rouge irq=%d pmirq=%d\n", d->irq, pmirq);
+		pr_warn("mask acking rogue irq=%d pmirq=%d\n", d->irq, pmirq);
 		chip->config[pmirq] = irq_bit << PM_IRQF_BITS_SHIFT;
 	}
 
@@ -295,6 +299,12 @@
 			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
 	}
 
+	/*
+	 * The PM_IRQF_WRITE flag serves as an indication that this interrupt
+	 * been requested
+	 */
+	chip->config[pmirq] |= PM_IRQF_WRITE;
+
 	config = chip->config[pmirq] | PM_IRQF_CLR;
 	return pm8xxx_write_config_irq(chip, block, config);
 }
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index eb0048a..b655848 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -139,6 +139,12 @@
 #define PM8901_DELAY_AFTER_REG_DISABLE_MS	4
 #define PM8901_DELAY_BEFORE_SHUTDOWN_MS		8
 
+#define REG_PM8XXX_XO_CNTRL_2	0x114
+#define MP3_1_MASK	0xE0
+#define MP3_2_MASK	0x1C
+#define MP3_1_SHIFT	5
+#define MP3_2_SHIFT	2
+
 struct pm8xxx_misc_chip {
 	struct list_head			link;
 	struct pm8xxx_misc_platform_data	pdata;
@@ -540,7 +546,7 @@
 		case PM8XXX_VERSION_8018:
 			rc = pm8xxx_misc_masked_write(chip,
 				REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
-				(enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+				(enable ? SLEEP_CTRL_SMPL_EN_RESET
 					   : SLEEP_CTRL_SMPL_EN_PWR_OFF));
 			break;
 		case PM8XXX_VERSION_8058:
@@ -552,7 +558,7 @@
 		case PM8XXX_VERSION_8921:
 			rc = pm8xxx_misc_masked_write(chip,
 				REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
-				(enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+				(enable ? SLEEP_CTRL_SMPL_EN_RESET
 					   : SLEEP_CTRL_SMPL_EN_PWR_OFF));
 			break;
 		default:
@@ -1046,6 +1052,48 @@
 }
 EXPORT_SYMBOL_GPL(pm8xxx_preload_dVdd);
 
+int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+				enum pm8xxx_aux_clk_div divider, bool enable)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	u8 clk_mask = 0, value = 0;
+
+	if (clk_id == CLK_MP3_1) {
+		clk_mask = MP3_1_MASK;
+		value = divider << MP3_1_SHIFT;
+	} else if (clk_id == CLK_MP3_2) {
+		clk_mask = MP3_2_MASK;
+		value = divider << MP3_2_SHIFT;
+	} else {
+		pr_err("Invalid clock id of %d\n", clk_id);
+		return -EINVAL;
+	}
+	if (!enable)
+		value = 0;
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8038:
+		case PM8XXX_VERSION_8921:
+			pm8xxx_misc_masked_write(chip,
+					REG_PM8XXX_XO_CNTRL_2, clk_mask, value);
+			break;
+		default:
+			/* Functionality not supported */
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_aux_clk_control);
+
 static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
 {
 	const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index 87abcda..d1d9132 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.c
@@ -241,6 +241,12 @@
 	},
 };
 
+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);
@@ -261,15 +267,6 @@
 static int tabla_reset(struct tabla *tabla)
 {
 	int ret;
-	struct pm_gpio param = {
-		.direction      = PM_GPIO_DIR_OUT,
-		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
-		.output_value   = 1,
-		.pull	   = PM_GPIO_PULL_NO,
-		.vin_sel	= PM_GPIO_VIN_S4,
-		.out_strength   = PM_GPIO_STRENGTH_MED,
-		.function       = PM_GPIO_FUNC_NORMAL,
-	};
 
 	if (tabla->reset_gpio) {
 		ret = gpio_request(tabla->reset_gpio, "CDC_RESET");
@@ -280,10 +277,6 @@
 			return ret;
 		}
 
-		ret = pm8xxx_gpio_config(tabla->reset_gpio, &param);
-		if (ret)
-			pr_err("%s: Failed to configure gpio\n", __func__);
-
 		gpio_direction_output(tabla->reset_gpio, 1);
 		msleep(20);
 		gpio_direction_output(tabla->reset_gpio, 0);
@@ -367,6 +360,8 @@
 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);
@@ -386,9 +381,19 @@
 		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_devs, ARRAY_SIZE(tabla_devs),
+			      tabla_dev, tabla_dev_size,
 			      NULL, 0);
 	if (ret != 0) {
 		dev_err(tabla->dev, "Failed to add children: %d\n", ret);
@@ -647,7 +652,7 @@
 	struct tabla_i2c *tabla;
 
 	tabla = get_i2c_tabla_device_info(reg);
-	if (tabla->client == NULL) {
+	if (tabla == NULL || tabla->client == NULL) {
 		pr_err("failed to get device info\n");
 		return -ENODEV;
 	}
@@ -684,7 +689,7 @@
 	u8 i = 0;
 
 	tabla = get_i2c_tabla_device_info(reg);
-	if (tabla->client == NULL) {
+	if (tabla == NULL || tabla->client == NULL) {
 		pr_err("failed to get device info\n");
 		return -ENODEV;
 	}
@@ -753,12 +758,12 @@
 	if (!pdata) {
 		dev_dbg(&client->dev, "no platform data?\n");
 		ret = -EINVAL;
-		goto fail;
+		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 fail;
+		goto err_tabla;
 	}
 	tabla->dev = &client->dev;
 	tabla->reset_gpio = pdata->reset_gpio;
@@ -964,11 +969,9 @@
 
 	tabla = slim_get_devicedata(pdev);
 	tabla_deinit_slimslave(tabla);
-	tabla_device_exit(tabla);
 	tabla_disable_supplies(tabla);
 	slim_remove_device(tabla->slim_slave);
-	kfree(tabla);
-
+	tabla_device_exit(tabla);
 	return 0;
 }
 
diff --git a/drivers/mfd/wcd9310-slimslave.c b/drivers/mfd/wcd9310-slimslave.c
index dd586fa..12ac27f 100644
--- a/drivers/mfd/wcd9310-slimslave.c
+++ b/drivers/mfd/wcd9310-slimslave.c
@@ -236,7 +236,7 @@
 		 */
 		if ((slave_port_id >
 				SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) &&
-			(slave_port_id <
+			(slave_port_id <=
 			 SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID)) {
 				payload_rx = payload_rx  |
 				(1 <<
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 43eb169..0066cd8 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -627,6 +627,13 @@
 	  TrustZone Operating Environment (TZBSP) using Secure Channel
 	  Manager (SCM) interface.
 
+config QSEECOM
+	tristate "Qualcomm Secure Execution Communicator driver"
+	help
+	  Provides a communication interface between userspace and
+	  Qualcomm Secure Execution Environment (QSEE) using Secure Channel
+	  Manager (SCM) interface.
+
 config QFP_FUSE
 	tristate "QFPROM Fuse Read/Write support"
 	help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 6b5fdcc..fb78f4e 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -64,4 +64,5 @@
 	+= msm_migrate_pages.o
 obj-$(CONFIG_PMIC8058_XOADC) += pmic8058-xoadc.o
 obj-$(CONFIG_TZCOM) += tzcom.o
+obj-$(CONFIG_QSEECOM) += qseecom.o
 obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
diff --git a/drivers/misc/pmem.c b/drivers/misc/pmem.c
index f0d523e..2f48d71 100644
--- a/drivers/misc/pmem.c
+++ b/drivers/misc/pmem.c
@@ -2785,7 +2785,8 @@
 	pmem[id].dev.name = pdata->name;
 	pmem[id].dev.minor = id;
 	pmem[id].dev.fops = &pmem_fops;
-	pr_info("pmem: Initializing %s (user-space) as %s\n",
+	pmem[id].reusable = pdata->reusable;
+	pr_info("pmem: Initializing %s as %s\n",
 		pdata->name, pdata->cached ? "cached" : "non-cached");
 
 	if (misc_register(&pmem[id].dev)) {
@@ -2793,24 +2794,23 @@
 		goto err_cant_register_device;
 	}
 
-	pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
-		pmem[id].memory_type, PAGE_SIZE);
-	if (!pmem[id].base) {
-		pr_err("pmem: Cannot allocate from reserved memory for %s\n",
-		 pdata->name);
-		goto err_misc_deregister;
+	if (!pmem[id].reusable) {
+		pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
+			pmem[id].memory_type, PAGE_SIZE);
+		if (!pmem[id].base) {
+			pr_err("pmem: Cannot allocate from reserved memory for %s\n",
+				pdata->name);
+			goto err_misc_deregister;
+		}
 	}
 
-	pr_info("allocating %lu bytes at %p (%lx physical) for %s\n",
-		pmem[id].size, pmem[id].vbase, pmem[id].base, pmem[id].name);
-
-	pmem[id].reusable = pdata->reusable;
 	/* reusable pmem requires map on demand */
 	pmem[id].map_on_demand = pdata->map_on_demand || pdata->reusable;
 	if (pmem[id].map_on_demand) {
 		if (pmem[id].reusable) {
 			const struct fmem_data *fmem_info = fmem_get_info();
 			pmem[id].area = fmem_info->area;
+			pmem[id].base = fmem_info->phys;
 		} else {
 			pmem_vma = get_vm_area(pmem[id].size, VM_IOREMAP);
 			if (!pmem_vma) {
@@ -2844,12 +2844,17 @@
 	if (pdata->release_region)
 		pmem[id].mem_release = pdata->release_region;
 
+	pr_info("allocating %lu bytes at %lx physical for %s\n",
+		pmem[id].size, pmem[id].base, pmem[id].name);
+
 	return 0;
 
 cleanup_vm:
-	remove_vm_area(pmem_vma);
+	if (!pmem[id].reusable)
+		remove_vm_area(pmem_vma);
 err_free:
-	free_contiguous_memory_by_paddr(pmem[id].base);
+	if (!pmem[id].reusable)
+		free_contiguous_memory_by_paddr(pmem[id].base);
 err_misc_deregister:
 	misc_deregister(&pmem[id].dev);
 err_cant_register_device:
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
new file mode 100644
index 0000000..e4c3152
--- /dev/null
+++ b/drivers/misc/qseecom.c
@@ -0,0 +1,1490 @@
+/* Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
+ *
+ * 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) "QSEECOM: %s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/ion.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/qseecom.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/scm.h>
+#include <mach/peripheral-loader.h>
+#include "qseecom_legacy.h"
+
+#define QSEECOM_DEV			"qseecom"
+#define QSEOS_VERSION_13		0x13
+#define QSEOS_VERSION_14		0x14
+#define QSEOS_CHECK_VERSION_CMD		0x00001803;
+
+enum qseecom_command_scm_resp_type {
+	QSEOS_APP_ID = 0xEE01,
+	QSEOS_LISTENER_ID
+};
+
+enum qseecom_qceos_cmd_id {
+	QSEOS_APP_START_COMMAND      = 0x01,
+	QSEOS_APP_SHUTDOWN_COMMAND,
+	QSEOS_APP_LOOKUP_COMMAND,
+	QSEOS_REGISTER_LISTENER,
+	QSEOS_DEREGISTER_LISTENER,
+	QSEOS_CLIENT_SEND_DATA_COMMAND,
+	QSEOS_LISTENER_DATA_RSP_COMMAND,
+	QSEOS_CMD_MAX     = 0xEFFFFFFF
+};
+
+enum qseecom_qceos_cmd_status {
+	QSEOS_RESULT_SUCCESS = 0,
+	QSEOS_RESULT_INCOMPLETE,
+	QSEOS_RESULT_FAILURE  = 0xFFFFFFFF
+};
+
+__packed struct qseecom_check_app_ireq {
+	uint32_t qsee_cmd_id;
+	char     app_name[MAX_APP_NAME_SIZE];
+};
+
+__packed struct qseecom_load_app_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t mdt_len;		/* Length of the mdt file */
+	uint32_t img_len;		/* Length of .bxx and .mdt files */
+	uint32_t phy_addr;		/* phy addr of the start of image */
+	char     app_name[MAX_APP_NAME_SIZE];	/* application name*/
+};
+
+__packed struct qseecom_unload_app_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t  app_id;
+};
+
+__packed struct qseecom_register_listener_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t listener_id;
+	void *sb_ptr;
+	uint32_t sb_len;
+};
+
+__packed struct qseecom_unregister_listener_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t  listener_id;
+};
+
+__packed struct qseecom_client_send_data_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t app_id;
+	void *req_ptr;
+	uint32_t req_len;
+	void *rsp_ptr;   /* First 4 bytes should always be the return status */
+	uint32_t rsp_len;
+};
+
+/* send_data resp */
+__packed struct qseecom_client_listener_data_irsp {
+	uint32_t qsee_cmd_id;
+	uint32_t listener_id;
+};
+
+/*
+ * struct qseecom_command_scm_resp - qseecom response buffer
+ * @cmd_status: value from enum tz_sched_cmd_status
+ * @sb_in_rsp_addr: points to physical location of response
+ *                buffer
+ * @sb_in_rsp_len: length of command response
+ */
+__packed struct qseecom_command_scm_resp {
+	uint32_t result;
+	enum qseecom_command_scm_resp_type resp_type;
+	unsigned int data;
+};
+
+static struct class *driver_class;
+static dev_t qseecom_device_no;
+static struct cdev qseecom_cdev;
+
+/* Data structures used in legacy support */
+static void *pil;
+static uint32_t pil_ref_cnt;
+static DEFINE_MUTEX(pil_access_lock);
+
+static DEFINE_MUTEX(send_msg_lock);
+static DEFINE_MUTEX(qsee_bw_mutex);
+static DEFINE_MUTEX(app_access_lock);
+
+static int qsee_bw_count;
+static struct clk *qseecom_bus_clk;
+static uint32_t qsee_perf_client;
+
+struct qseecom_registered_listener_list {
+	struct list_head                 list;
+	struct qseecom_register_listener_req svc;
+	u8  *sb_reg_req;
+	u8 *sb_virt;
+	s32 sb_phys;
+	size_t sb_length;
+	struct ion_handle *ihandle; /* Retrieve phy addr */
+
+	wait_queue_head_t          rcv_req_wq;
+	int                        rcv_req_flag;
+};
+
+struct qseecom_registered_app_list {
+	struct list_head                 list;
+	u32  app_id;
+	u32  ref_cnt;
+};
+
+struct qseecom_control {
+	struct ion_client *ion_clnt;		/* Ion client */
+	struct list_head  registered_listener_list_head;
+	spinlock_t        registered_listener_list_lock;
+
+	struct list_head  registered_app_list_head;
+	spinlock_t        registered_app_list_lock;
+
+	wait_queue_head_t send_resp_wq;
+	int               send_resp_flag;
+
+	uint32_t          qseos_version;
+};
+
+struct qseecom_client_handle {
+	u32  app_id;
+	u8 *sb_virt;
+	s32 sb_phys;
+	uint32_t user_virt_sb_base;
+	size_t sb_length;
+	struct ion_handle *ihandle;		/* Retrieve phy addr */
+};
+
+struct qseecom_listener_handle {
+	u32               id;
+};
+
+static struct qseecom_control qseecom;
+
+struct qseecom_dev_handle {
+	bool               service;
+	union {
+		struct qseecom_client_handle client;
+		struct qseecom_listener_handle listener;
+	};
+	bool released;
+	int               abort;
+	wait_queue_head_t abort_wq;
+	atomic_t          ioctl_count;
+};
+
+static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
+		struct qseecom_register_listener_req svc)
+{
+	struct qseecom_registered_listener_list *ptr;
+	int unique = 1;
+	unsigned long flags;
+
+	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) {
+			pr_err("Service id: %u is already registered\n",
+					ptr->svc.listener_id);
+			unique = 0;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+	return unique;
+}
+
+static struct qseecom_registered_listener_list *__qseecom_find_svc(
+						int32_t listener_id)
+{
+	struct qseecom_registered_listener_list *entry = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+	list_for_each_entry(entry, &qseecom.registered_listener_list_head, list)
+	{
+		if (entry->svc.listener_id == listener_id)
+			break;
+	}
+	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+	return entry;
+}
+
+static int __qseecom_set_sb_memory(struct qseecom_registered_listener_list *svc,
+				struct qseecom_dev_handle *handle,
+				struct qseecom_register_listener_req *listener)
+{
+	int ret = 0;
+	unsigned int flags = 0;
+	struct qseecom_register_listener_ireq req;
+	struct qseecom_command_scm_resp resp;
+	ion_phys_addr_t pa;
+
+	/* Get the handle of the shared fd */
+	svc->ihandle = ion_import_fd(qseecom.ion_clnt, listener->ifd_data_fd);
+	if (svc->ihandle == NULL) {
+		pr_err("Ion client could not retrieve the handle\n");
+		return -ENOMEM;
+	}
+
+	/* Get the physical address of the ION BUF */
+	ret = ion_phys(qseecom.ion_clnt, svc->ihandle, &pa, &svc->sb_length);
+
+	/* Populate the structure for sending scm call to load image */
+	svc->sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt,
+							svc->ihandle, flags);
+	svc->sb_phys = pa;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_14) {
+		req.qsee_cmd_id = QSEOS_REGISTER_LISTENER;
+		req.listener_id = svc->svc.listener_id;
+		req.sb_len = svc->sb_length;
+		req.sb_ptr = (void *)svc->sb_phys;
+
+		resp.result = QSEOS_RESULT_INCOMPLETE;
+
+		ret = scm_call(SCM_SVC_TZSCHEDULER, 1,  &req,
+					sizeof(req), &resp, sizeof(resp));
+		if (ret) {
+			pr_err("qseecom_scm_call failed with err: %d\n", ret);
+			return -EINVAL;
+		}
+
+		if (resp.result != QSEOS_RESULT_SUCCESS) {
+			pr_err("Error SB registration req: resp.result = %d\n",
+					resp.result);
+			return -EPERM;
+		}
+	} else {
+		struct qseecom_command cmd;
+		struct qseecom_response resp;
+		struct qse_pr_init_sb_req_s sb_init_req;
+		struct qse_pr_init_sb_rsp_s sb_init_rsp;
+
+		svc->sb_reg_req = kzalloc((sizeof(sb_init_req) +
+					sizeof(sb_init_rsp)), GFP_KERNEL);
+
+		sb_init_req.pr_cmd = TZ_SCHED_CMD_ID_REGISTER_LISTENER;
+		sb_init_req.listener_id = svc->svc.listener_id;
+		sb_init_req.sb_len = svc->sb_length;
+		sb_init_req.sb_ptr = svc->sb_phys;
+
+		memcpy(svc->sb_reg_req, &sb_init_req, sizeof(sb_init_req));
+
+		/* It will always be a new cmd from this method */
+		cmd.cmd_type = TZ_SCHED_CMD_NEW;
+		cmd.sb_in_cmd_addr = (u8 *)(virt_to_phys(svc->sb_reg_req));
+		cmd.sb_in_cmd_len = sizeof(sb_init_req);
+
+		resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
+
+		ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &cmd, sizeof(cmd)
+				, &resp, sizeof(resp));
+
+		if (ret) {
+			pr_err("qseecom_scm_call failed with err: %d\n", ret);
+			return -EINVAL;
+		}
+
+		if (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
+			pr_err("SB registration fail resp.cmd_status %d\n",
+							resp.cmd_status);
+			return -EINVAL;
+		}
+		memset(svc->sb_virt, 0, svc->sb_length);
+	}
+	return 0;
+}
+
+static int qseecom_register_listener(struct qseecom_dev_handle *data,
+					void __user *argp)
+{
+	int ret = 0;
+	unsigned long flags;
+	struct qseecom_register_listener_req rcvd_lstnr;
+	struct qseecom_registered_listener_list *new_entry;
+
+	ret = copy_from_user(&rcvd_lstnr, argp, sizeof(rcvd_lstnr));
+	if (ret) {
+		pr_err("copy_from_user failed\n");
+		return ret;
+	}
+
+	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;
+	}
+
+	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
+	if (!new_entry) {
+		pr_err("kmalloc failed\n");
+		return -ENOMEM;
+	}
+	memcpy(&new_entry->svc, &rcvd_lstnr, sizeof(rcvd_lstnr));
+	new_entry->rcv_req_flag = 0;
+
+	new_entry->svc.listener_id = rcvd_lstnr.listener_id;
+	new_entry->sb_length = rcvd_lstnr.sb_size;
+	if (__qseecom_set_sb_memory(new_entry, data, &rcvd_lstnr)) {
+		pr_err("qseecom_set_sb_memoryfailed\n");
+		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;
+}
+
+static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
+{
+	int ret = 0;
+	unsigned long flags;
+	uint32_t unmap_mem = 0;
+	struct qseecom_register_listener_ireq req;
+	struct qseecom_registered_listener_list *ptr_svc = NULL;
+	struct qseecom_command_scm_resp resp;
+	struct ion_handle *ihandle = NULL;		/* Retrieve phy addr */
+
+	if (qseecom.qseos_version == QSEOS_VERSION_14) {
+		req.qsee_cmd_id = QSEOS_DEREGISTER_LISTENER;
+		req.listener_id = data->listener.id;
+		resp.result = QSEOS_RESULT_INCOMPLETE;
+
+		ret = scm_call(SCM_SVC_TZSCHEDULER, 1,  &req,
+					sizeof(req), &resp, sizeof(resp));
+		if (ret) {
+			pr_err("qseecom_scm_call failed with err: %d\n", ret);
+			return ret;
+		}
+
+		if (resp.result != QSEOS_RESULT_SUCCESS) {
+			pr_err("SB deregistartion: result=%d\n", resp.result);
+			return -EPERM;
+		}
+	} else {
+		struct qse_pr_init_sb_req_s sb_init_req;
+		struct qseecom_command cmd;
+		struct qseecom_response resp;
+		struct qseecom_registered_listener_list *svc;
+
+		svc = __qseecom_find_svc(data->listener.id);
+		sb_init_req.pr_cmd = TZ_SCHED_CMD_ID_REGISTER_LISTENER;
+		sb_init_req.listener_id = data->listener.id;
+		sb_init_req.sb_len = 0;
+		sb_init_req.sb_ptr = 0;
+
+		memcpy(svc->sb_reg_req, &sb_init_req, sizeof(sb_init_req));
+
+		/* It will always be a new cmd from this method */
+		cmd.cmd_type = TZ_SCHED_CMD_NEW;
+		cmd.sb_in_cmd_addr = (u8 *)(virt_to_phys(svc->sb_reg_req));
+		cmd.sb_in_cmd_len = sizeof(sb_init_req);
+		resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
+
+		ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &cmd, sizeof(cmd),
+					&resp, sizeof(resp));
+		if (ret) {
+			pr_err("qseecom_scm_call failed with err: %d\n", ret);
+			return ret;
+		}
+		kzfree(svc->sb_reg_req);
+		if (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
+			pr_err("Error with SB initialization\n");
+			return -EPERM;
+		}
+	}
+	data->abort = 1;
+	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+	list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head,
+			list) {
+		if (ptr_svc->svc.listener_id == data->listener.id) {
+			wake_up_all(&ptr_svc->rcv_req_wq);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+
+	while (atomic_read(&data->ioctl_count) > 1) {
+		if (wait_event_interruptible(data->abort_wq,
+				atomic_read(&data->ioctl_count) <= 1)) {
+			pr_err("Interrupted from abort\n");
+			ret = -ERESTARTSYS;
+			break;
+		}
+	}
+
+	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+	list_for_each_entry(ptr_svc,
+			&qseecom.registered_listener_list_head,
+			list)
+	{
+		if (ptr_svc->svc.listener_id == data->listener.id) {
+			if (ptr_svc->sb_virt) {
+				unmap_mem = 1;
+				ihandle = ptr_svc->ihandle;
+				}
+			list_del(&ptr_svc->list);
+			kzfree(ptr_svc);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+
+	/* Unmap the memory */
+	if (unmap_mem) {
+		if (!IS_ERR_OR_NULL(ihandle)) {
+			ion_unmap_kernel(qseecom.ion_clnt, ihandle);
+			ion_free(qseecom.ion_clnt, ihandle);
+			}
+	}
+	data->released = true;
+	return ret;
+}
+
+static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data,
+						void __user *argp)
+{
+	ion_phys_addr_t pa;
+	int32_t ret;
+	unsigned int flags = 0;
+	struct qseecom_set_sb_mem_param_req req;
+	uint32_t len;
+
+	/* Copy the relevant information needed for loading the image */
+	if (__copy_from_user(&req, (void __user *)argp, sizeof(req)))
+		return -EFAULT;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_13) {
+		long pil_error;
+		mutex_lock(&pil_access_lock);
+		if (pil_ref_cnt == 0) {
+			pil = pil_get("tzapps");
+			if (IS_ERR(pil)) {
+				pr_err("Playready PIL image load failed\n");
+				pil_error = PTR_ERR(pil);
+				pil = NULL;
+				pr_debug("tzapps image load FAILED\n");
+				mutex_unlock(&pil_access_lock);
+				return pil_error;
+			}
+		}
+		pil_ref_cnt++;
+		mutex_unlock(&pil_access_lock);
+	}
+	/* Get the handle of the shared fd */
+	data->client.ihandle = ion_import_fd(qseecom.ion_clnt, req.ifd_data_fd);
+	if (IS_ERR_OR_NULL(data->client.ihandle)) {
+		pr_err("Ion client could not retrieve the handle\n");
+		return -ENOMEM;
+	}
+	/* Get the physical address of the ION BUF */
+	ret = ion_phys(qseecom.ion_clnt, data->client.ihandle, &pa, &len);
+	/* Populate the structure for sending scm call to load image */
+	data->client.sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt,
+							data->client.ihandle,
+							flags);
+	data->client.sb_phys = pa;
+	data->client.sb_length = req.sb_len;
+	data->client.user_virt_sb_base = req.virt_sb_base;
+	return 0;
+}
+
+
+static int __qseecom_listener_has_sent_rsp(struct qseecom_dev_handle *data)
+{
+	int ret;
+	ret = (qseecom.send_resp_flag != 0);
+	return ret || data->abort;
+}
+
+static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
+					struct qseecom_command_scm_resp *resp)
+{
+	int ret = 0;
+	uint32_t lstnr;
+	unsigned long flags;
+	struct qseecom_client_listener_data_irsp send_data_rsp;
+	struct qseecom_registered_listener_list *ptr_svc = NULL;
+
+
+	while (resp->result == QSEOS_RESULT_INCOMPLETE) {
+		lstnr = resp->data;
+		/*
+		 * Wake up blocking lsitener service with the lstnr id
+		 */
+		spin_lock_irqsave(&qseecom.registered_listener_list_lock,
+					flags);
+		list_for_each_entry(ptr_svc,
+				&qseecom.registered_listener_list_head, list) {
+			if (ptr_svc->svc.listener_id == lstnr) {
+				ptr_svc->rcv_req_flag = 1;
+				wake_up_interruptible(&ptr_svc->rcv_req_wq);
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
+				flags);
+		if (ptr_svc->svc.listener_id != lstnr) {
+			pr_warning("Service requested for does on exist\n");
+			return -ERESTARTSYS;
+		}
+		pr_debug("waking up rcv_req_wq and "
+				"waiting for send_resp_wq\n");
+		if (wait_event_interruptible(qseecom.send_resp_wq,
+				__qseecom_listener_has_sent_rsp(data))) {
+			pr_warning("Interrupted: exiting send_cmd loop\n");
+			return -ERESTARTSYS;
+		}
+
+		if (data->abort) {
+			pr_err("Aborting driver\n");
+			return -ENODEV;
+		}
+		qseecom.send_resp_flag = 0;
+		send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
+		send_data_rsp.listener_id  = lstnr ;
+
+		ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
+					(const void *)&send_data_rsp,
+					sizeof(send_data_rsp), resp,
+					sizeof(*resp));
+		if (ret) {
+			pr_err("qseecom_scm_call failed with err: %d\n", ret);
+			return ret;
+		}
+	}
+	return ret;
+}
+
+static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
+{
+	struct qseecom_registered_app_list *entry = NULL;
+	unsigned long flags = 0;
+	u32 app_id = 0;
+	struct ion_handle *ihandle;	/* Ion handle */
+	struct qseecom_load_img_req load_img_req;
+	int32_t ret;
+	ion_phys_addr_t pa = 0;
+	uint32_t len;
+	struct qseecom_command_scm_resp resp;
+	struct qseecom_check_app_ireq req;
+	/* Copy the relevant information needed for loading the image */
+	if (__copy_from_user(&load_img_req,
+				(void __user *)argp,
+				sizeof(struct qseecom_load_img_req))) {
+		pr_err("copy_from_user failed\n");
+		return -EFAULT;
+	}
+
+	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+	memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
+
+	/*  SCM_CALL  to check if app_id for the mentioned app exists */
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,  &req,
+				sizeof(struct qseecom_check_app_ireq),
+				&resp, sizeof(resp));
+
+	if (resp.result == QSEOS_RESULT_FAILURE)
+		app_id = 0;
+	else
+		app_id = resp.data;
+
+	if (app_id) {
+		pr_warn("App id already exists\n");
+		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+		list_for_each_entry(entry,
+				&qseecom.registered_app_list_head, list){
+			if (entry->app_id == app_id) {
+				entry->ref_cnt++;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(
+				&qseecom.registered_app_list_lock, flags);
+	} else {
+		struct qseecom_load_app_ireq load_req;
+
+		pr_warn("App id does not exist\n");
+		/* Get the handle of the shared fd */
+		ihandle = ion_import_fd(qseecom.ion_clnt,
+					load_img_req.ifd_data_fd);
+		if (IS_ERR_OR_NULL(ihandle)) {
+			pr_err("Ion client could not retrieve the handle\n");
+			return -ENOMEM;
+		}
+
+		/* Get the physical address of the ION BUF */
+		ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &len);
+
+		/* Populate the structure for sending scm call to load image */
+		load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
+		load_req.mdt_len = load_img_req.mdt_len;
+		load_req.img_len = load_img_req.img_len;
+		load_req.phy_addr = pa;
+
+		/*  SCM_CALL  to load the app and get the app_id back */
+		ret = scm_call(SCM_SVC_TZSCHEDULER, 1,  &load_req,
+				sizeof(struct qseecom_load_app_ireq),
+				&resp, sizeof(resp));
+
+		if (resp.result == QSEOS_RESULT_INCOMPLETE) {
+			ret = __qseecom_process_incomplete_cmd(data, &resp);
+			if (ret) {
+				pr_err("process_incomplete_cmd failed err: %d\n",
+						ret);
+				if (!IS_ERR_OR_NULL(ihandle))
+					ion_free(qseecom.ion_clnt, ihandle);
+				return ret;
+			}
+		}
+		if (resp.result != QSEOS_RESULT_SUCCESS) {
+			pr_err("scm_call failed resp.result != QSEOS_RESULT_SUCCESS\n");
+			if (!IS_ERR_OR_NULL(ihandle))
+				ion_free(qseecom.ion_clnt, ihandle);
+			return -EFAULT;
+		}
+
+		app_id = resp.data;
+
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+		if (!entry) {
+			pr_err("kmalloc failed\n");
+			return -ENOMEM;
+		}
+		entry->app_id = app_id;
+		entry->ref_cnt = 1;
+
+		/* Deallocate the handle */
+		if (!IS_ERR_OR_NULL(ihandle))
+			ion_free(qseecom.ion_clnt, ihandle);
+
+		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+		list_add_tail(&entry->list, &qseecom.registered_app_list_head);
+		spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+					flags);
+	}
+	data->client.app_id = app_id;
+	load_img_req.app_id = app_id;
+	if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
+		pr_err("copy_to_user failed\n");
+		kzfree(entry);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static int __qseecom_cleanup_app(struct qseecom_dev_handle *data)
+{
+	wake_up_all(&qseecom.send_resp_wq);
+	while (atomic_read(&data->ioctl_count) > 1) {
+		if (wait_event_interruptible(data->abort_wq,
+					atomic_read(&data->ioctl_count) <= 1)) {
+			pr_err("Interrupted from abort\n");
+			return -ERESTARTSYS;
+			break;
+		}
+	}
+	/* Set unload app */
+	return 1;
+}
+
+static int qseecom_unload_app(struct qseecom_dev_handle *data)
+{
+	unsigned long flags;
+	int ret = 0;
+	struct qseecom_command_scm_resp resp;
+	struct qseecom_registered_app_list *ptr_app;
+	uint32_t unload = 0;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_14) {
+		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+		list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
+								list) {
+			if (ptr_app->app_id == data->client.app_id) {
+				if (ptr_app->ref_cnt == 1) {
+					unload = __qseecom_cleanup_app(data);
+					list_del(&ptr_app->list);
+					kzfree(ptr_app);
+					break;
+				} else {
+					ptr_app->ref_cnt--;
+					break;
+				}
+			}
+		}
+		spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+								flags);
+	}
+	if (!IS_ERR_OR_NULL(data->client.ihandle)) {
+		ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
+		ion_free(qseecom.ion_clnt, data->client.ihandle);
+	}
+
+	if ((unload) && (qseecom.qseos_version == QSEOS_VERSION_14)) {
+		struct qseecom_unload_app_ireq req;
+
+		/* Populate the structure for sending scm call to load image */
+		req.qsee_cmd_id = QSEOS_APP_SHUTDOWN_COMMAND;
+		req.app_id = data->client.app_id;
+
+		/* SCM_CALL to unload the app */
+		ret = scm_call(SCM_SVC_TZSCHEDULER, 1,  &req,
+				sizeof(struct qseecom_unload_app_ireq),
+				&resp, sizeof(resp));
+		if (ret) {
+			pr_err("Fail to unload APP\n");
+			return -EFAULT;
+		}
+		if (resp.result == QSEOS_RESULT_INCOMPLETE) {
+			ret = __qseecom_process_incomplete_cmd(data, &resp);
+			if (ret) {
+				pr_err("process_incomplete_cmd fail err: %d\n",
+						ret);
+				return ret;
+			}
+		}
+	}
+
+	if (qseecom.qseos_version == QSEOS_VERSION_13) {
+		data->abort = 1;
+		wake_up_all(&qseecom.send_resp_wq);
+		while (atomic_read(&data->ioctl_count) > 0) {
+			if (wait_event_interruptible(data->abort_wq,
+					atomic_read(&data->ioctl_count) <= 0)) {
+				pr_err("Interrupted from abort\n");
+				ret = -ERESTARTSYS;
+				break;
+			}
+		}
+		mutex_lock(&pil_access_lock);
+		if (pil_ref_cnt == 1)
+			pil_put(pil);
+		pil_ref_cnt--;
+		mutex_unlock(&pil_access_lock);
+	}
+	data->released = true;
+	return ret;
+}
+
+static uint32_t __qseecom_uvirt_to_kphys(struct qseecom_dev_handle *data,
+						uint32_t virt)
+{
+	return data->client.sb_phys + (virt - data->client.user_virt_sb_base);
+}
+
+static int __qseecom_send_cmd_legacy(struct qseecom_dev_handle *data,
+				struct qseecom_send_cmd_req *req)
+{
+	int ret = 0;
+	unsigned long flags;
+	u32 reqd_len_sb_in = 0;
+	struct qseecom_command cmd;
+	struct qseecom_response resp;
+
+
+	if (req->cmd_req_buf == NULL || req->resp_buf == NULL) {
+		pr_err("cmd buffer or response buffer is null\n");
+		return -EINVAL;
+	}
+
+	if (req->cmd_req_len <= 0 ||
+		req->resp_len <= 0 ||
+		req->cmd_req_len > data->client.sb_length ||
+		req->resp_len > data->client.sb_length) {
+		pr_err("cmd buffer length or "
+				"response buffer length not valid\n");
+		return -EINVAL;
+	}
+
+	reqd_len_sb_in = req->cmd_req_len + req->resp_len;
+	if (reqd_len_sb_in > data->client.sb_length) {
+		pr_debug("Not enough memory to fit cmd_buf and "
+			"resp_buf. Required: %u, Available: %u\n",
+				reqd_len_sb_in, data->client.sb_length);
+		return -ENOMEM;
+	}
+	cmd.cmd_type = TZ_SCHED_CMD_NEW;
+	cmd.sb_in_cmd_addr = (u8 *) data->client.sb_phys;
+	cmd.sb_in_cmd_len = req->cmd_req_len;
+
+	resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
+	resp.sb_in_rsp_addr = (u8 *)data->client.sb_phys + req->cmd_req_len;
+	resp.sb_in_rsp_len = req->resp_len;
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *)&cmd,
+					sizeof(cmd), &resp, sizeof(resp));
+
+	if (ret) {
+		pr_err("qseecom_scm_call_legacy failed with err: %d\n", ret);
+		return ret;
+	}
+
+	while (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
+		/*
+		 * If cmd is incomplete, get the callback cmd out from SB out
+		 * and put it on the list
+		 */
+		struct qseecom_registered_listener_list *ptr_svc = NULL;
+		/*
+		 * We don't know which service can handle the command. so we
+		 * wake up all blocking services and let them figure out if
+		 * they can handle the given command.
+		 */
+		spin_lock_irqsave(&qseecom.registered_listener_list_lock,
+					flags);
+		list_for_each_entry(ptr_svc,
+				&qseecom.registered_listener_list_head, list) {
+				ptr_svc->rcv_req_flag = 1;
+				wake_up_interruptible(&ptr_svc->rcv_req_wq);
+		}
+		spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
+				flags);
+
+		pr_debug("waking up rcv_req_wq and "
+				"waiting for send_resp_wq\n");
+		if (wait_event_interruptible(qseecom.send_resp_wq,
+				__qseecom_listener_has_sent_rsp(data))) {
+			pr_warning("qseecom Interrupted: exiting send_cmd loop\n");
+			return -ERESTARTSYS;
+		}
+
+		if (data->abort) {
+			pr_err("Aborting driver\n");
+			return -ENODEV;
+		}
+		qseecom.send_resp_flag = 0;
+		cmd.cmd_type = TZ_SCHED_CMD_PENDING;
+		ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *)&cmd,
+					sizeof(cmd), &resp, sizeof(resp));
+		if (ret) {
+			pr_err("qseecom_scm_call failed with err: %d\n", ret);
+			return ret;
+		}
+	}
+	return ret;
+}
+
+static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
+				struct qseecom_send_cmd_req *req)
+{
+	int ret = 0;
+	u32 reqd_len_sb_in = 0;
+	struct qseecom_client_send_data_ireq send_data_req;
+	struct qseecom_command_scm_resp resp;
+
+	if (req->cmd_req_buf == NULL || req->resp_buf == NULL) {
+		pr_err("cmd buffer or response buffer is null\n");
+		return -EINVAL;
+	}
+
+	if (req->cmd_req_len <= 0 ||
+		req->resp_len <= 0 ||
+		req->cmd_req_len > data->client.sb_length ||
+		req->resp_len > data->client.sb_length) {
+		pr_err("cmd buffer length or "
+				"response buffer length not valid\n");
+		return -EINVAL;
+	}
+
+	reqd_len_sb_in = req->cmd_req_len + req->resp_len;
+	if (reqd_len_sb_in > data->client.sb_length) {
+		pr_debug("Not enough memory to fit cmd_buf and "
+			"resp_buf. Required: %u, Available: %u\n",
+				reqd_len_sb_in, data->client.sb_length);
+		return -ENOMEM;
+	}
+
+	send_data_req.qsee_cmd_id = QSEOS_CLIENT_SEND_DATA_COMMAND;
+	send_data_req.app_id = data->client.app_id;
+	send_data_req.req_ptr = (void *)(__qseecom_uvirt_to_kphys(data,
+					(uint32_t)req->cmd_req_buf));
+	send_data_req.req_len = req->cmd_req_len;
+	send_data_req.rsp_ptr = (void *)(__qseecom_uvirt_to_kphys(data,
+					(uint32_t)req->resp_buf));
+	send_data_req.rsp_len = req->resp_len;
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *) &send_data_req,
+					sizeof(send_data_req),
+					&resp, sizeof(resp));
+	if (ret) {
+		pr_err("qseecom_scm_call failed with err: %d\n", ret);
+		return ret;
+	}
+
+	if (resp.result == QSEOS_RESULT_INCOMPLETE) {
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret) {
+			pr_err("process_incomplete_cmd failed err: %d\n", ret);
+			return ret;
+		}
+	}
+	return ret;
+}
+
+
+static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp)
+{
+	int ret = 0;
+	struct qseecom_send_cmd_req req;
+
+	ret = copy_from_user(&req, argp, sizeof(req));
+	if (ret) {
+		pr_err("copy_from_user failed\n");
+		return ret;
+	}
+	if (qseecom.qseos_version == QSEOS_VERSION_14)
+		ret = __qseecom_send_cmd(data, &req);
+	else
+		ret = __qseecom_send_cmd_legacy(data, &req);
+	if (ret)
+		return ret;
+
+	pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
+			req.resp_len, req.resp_buf);
+	return ret;
+}
+
+static int __qseecom_send_cmd_req_clean_up(
+			struct qseecom_send_modfd_cmd_req *req)
+{
+	char *field;
+	uint32_t *update;
+	int ret = 0;
+	int i = 0;
+
+	for (i = 0; i < MAX_ION_FD; i++) {
+		if (req->ifd_data[i].fd != 0) {
+			field = (char *)req->cmd_req_buf +
+					req->ifd_data[i].cmd_buf_offset;
+			update = (uint32_t *) field;
+			*update = 0;
+		}
+	}
+	return ret;
+}
+
+static int __qseecom_update_with_phy_addr(
+			struct qseecom_send_modfd_cmd_req *req)
+{
+	struct ion_handle *ihandle;
+	char *field;
+	uint32_t *update;
+	ion_phys_addr_t pa;
+	int ret = 0;
+	int i = 0;
+	uint32_t length;
+
+	for (i = 0; i < MAX_ION_FD; i++) {
+		if (req->ifd_data[i].fd != 0) {
+			/* Get the handle of the shared fd */
+			ihandle = ion_import_fd(qseecom.ion_clnt,
+						req->ifd_data[i].fd);
+			if (IS_ERR_OR_NULL(ihandle)) {
+				pr_err("Ion client can't retrieve the handle\n");
+				return -ENOMEM;
+			}
+			field = (char *) req->cmd_req_buf +
+						req->ifd_data[i].cmd_buf_offset;
+			update = (uint32_t *) field;
+
+			/* Populate the cmd data structure with the phys_addr */
+			ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &length);
+			if (ret)
+				return -ENOMEM;
+
+			*update = (uint32_t)pa;
+			/* Deallocate the handle */
+			if (!IS_ERR_OR_NULL(ihandle))
+				ion_free(qseecom.ion_clnt, ihandle);
+		}
+	}
+	return ret;
+}
+
+static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data,
+					void __user *argp)
+{
+	int ret = 0;
+	struct qseecom_send_modfd_cmd_req req;
+	struct qseecom_send_cmd_req send_cmd_req;
+
+	ret = copy_from_user(&req, argp, sizeof(req));
+	if (ret) {
+		pr_err("copy_from_user failed\n");
+		return ret;
+	}
+	send_cmd_req.cmd_req_buf = req.cmd_req_buf;
+	send_cmd_req.cmd_req_len = req.cmd_req_len;
+	send_cmd_req.resp_buf = req.resp_buf;
+	send_cmd_req.resp_len = req.resp_len;
+
+	ret = __qseecom_update_with_phy_addr(&req);
+	if (ret)
+		return ret;
+	if (qseecom.qseos_version == QSEOS_VERSION_14)
+		ret = __qseecom_send_cmd(data, &send_cmd_req);
+	else
+		ret = __qseecom_send_cmd_legacy(data, &send_cmd_req);
+	__qseecom_send_cmd_req_clean_up(&req);
+
+	if (ret)
+		return ret;
+
+	pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
+			req.resp_len, req.resp_buf);
+	return ret;
+}
+
+static int __qseecom_listener_has_rcvd_req(struct qseecom_dev_handle *data,
+		struct qseecom_registered_listener_list *svc)
+{
+	int ret;
+	ret = (svc->rcv_req_flag != 0);
+	return ret || data->abort;
+}
+
+static int qseecom_receive_req(struct qseecom_dev_handle *data)
+{
+	int ret = 0;
+	struct qseecom_registered_listener_list *this_lstnr;
+
+	this_lstnr = __qseecom_find_svc(data->listener.id);
+	while (1) {
+		if (wait_event_interruptible(this_lstnr->rcv_req_wq,
+				__qseecom_listener_has_rcvd_req(data,
+				this_lstnr))) {
+			pr_warning("Interrupted: exiting wait_rcv_req loop\n");
+			/* woken up for different reason */
+			return -ERESTARTSYS;
+		}
+
+		if (data->abort) {
+			pr_err("Aborting driver!\n");
+			return -ENODEV;
+		}
+		this_lstnr->rcv_req_flag = 0;
+		if (qseecom.qseos_version == QSEOS_VERSION_13) {
+			if (*((uint32_t *)this_lstnr->sb_virt) != 0)
+				break;
+		} else {
+			break;
+		}
+	}
+	return ret;
+}
+
+static int qseecom_send_resp(void)
+{
+	qseecom.send_resp_flag = 1;
+	wake_up_interruptible(&qseecom.send_resp_wq);
+	return 0;
+}
+
+static int qseecom_get_qseos_version(struct qseecom_dev_handle *data,
+						void __user *argp)
+{
+	struct qseecom_qseos_version_req req;
+
+	if (copy_from_user(&req, argp, sizeof(req))) {
+		pr_err("copy_from_user failed");
+		return -EINVAL;
+	}
+	req.qseos_version = qseecom.qseos_version;
+	if (copy_to_user(argp, &req, sizeof(req))) {
+		pr_err("copy_to_user failed");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int qsee_vote_for_clock(void)
+{
+	int ret = 0;
+
+	if (!qsee_perf_client)
+		return -EINVAL;
+
+	mutex_lock(&qsee_bw_mutex);
+	if (!qsee_bw_count) {
+		ret = msm_bus_scale_client_update_request(
+				qsee_perf_client, 1);
+		if (ret) {
+			pr_err("Bandwidth request failed (%d)\n", ret);
+		} else {
+			ret = clk_enable(qseecom_bus_clk);
+			if (ret)
+				pr_err("Clock enable failed\n");
+		}
+	}
+	if (ret)
+		msm_bus_scale_client_update_request(qsee_perf_client, 0);
+	else
+		qsee_bw_count++;
+
+	mutex_unlock(&qsee_bw_mutex);
+	return ret;
+}
+
+static void qsee_disable_clock_vote(void)
+{
+	if (!qsee_perf_client)
+		return ;
+
+	mutex_lock(&qsee_bw_mutex);
+	if (qsee_bw_count > 0) {
+		if (qsee_bw_count-- == 1) {
+			msm_bus_scale_client_update_request(qsee_perf_client,
+							0);
+			clk_disable(qseecom_bus_clk);
+		}
+	}
+	mutex_unlock(&qsee_bw_mutex);
+}
+
+
+static long qseecom_ioctl(struct file *file, unsigned cmd,
+		unsigned long arg)
+{
+	int ret = 0;
+	struct qseecom_dev_handle *data = file->private_data;
+	void __user *argp = (void __user *) arg;
+
+	if (data->abort) {
+		pr_err("Aborting qseecom driver\n");
+		return -ENODEV;
+	}
+
+	switch (cmd) {
+	case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: {
+		pr_debug("ioctl register_listener_req()\n");
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_register_listener(data, argp);
+		atomic_dec(&data->ioctl_count);
+		wake_up_all(&data->abort_wq);
+		if (ret)
+			pr_err("failed qseecom_register_listener: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ: {
+		pr_debug("ioctl unregister_listener_req()\n");
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_unregister_listener(data);
+		atomic_dec(&data->ioctl_count);
+		wake_up_all(&data->abort_wq);
+		if (ret)
+			pr_err("failed qseecom_unregister_listener: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_SEND_CMD_REQ: {
+		/* Only one client allowed here at a time */
+		mutex_lock(&send_msg_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_send_cmd(data, argp);
+		atomic_dec(&data->ioctl_count);
+		wake_up_all(&data->abort_wq);
+		mutex_unlock(&send_msg_lock);
+		if (ret)
+			pr_err("failed qseecom_send_cmd: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: {
+		/* Only one client allowed here at a time */
+		mutex_lock(&send_msg_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_send_modfd_cmd(data, argp);
+		atomic_dec(&data->ioctl_count);
+		wake_up_all(&data->abort_wq);
+		mutex_unlock(&send_msg_lock);
+		if (ret)
+			pr_err("failed qseecom_send_cmd: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_RECEIVE_REQ: {
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_receive_req(data);
+		atomic_dec(&data->ioctl_count);
+		wake_up_all(&data->abort_wq);
+		if (ret)
+			pr_err("failed qseecom_receive_req: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_SEND_RESP_REQ: {
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_send_resp();
+		atomic_dec(&data->ioctl_count);
+		wake_up_all(&data->abort_wq);
+		if (ret)
+			pr_err("failed qseecom_send_resp: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_SET_MEM_PARAM_REQ: {
+		ret = qseecom_set_client_mem_param(data, argp);
+		if (ret)
+			pr_err("failed Qqseecom_set_mem_param request: %d\n",
+								ret);
+		break;
+	}
+	case QSEECOM_IOCTL_LOAD_APP_REQ: {
+		mutex_lock(&app_access_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_load_app(data, argp);
+		atomic_dec(&data->ioctl_count);
+		mutex_unlock(&app_access_lock);
+		if (ret)
+			pr_err("failed load_app request: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_UNLOAD_APP_REQ: {
+		mutex_lock(&app_access_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_unload_app(data);
+		atomic_dec(&data->ioctl_count);
+		mutex_unlock(&app_access_lock);
+		if (ret)
+			pr_err("failed unload_app request: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ: {
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_get_qseos_version(data, argp);
+		if (ret)
+			pr_err("qseecom_get_qseos_version: %d\n", ret);
+		atomic_dec(&data->ioctl_count);
+		break;
+	}
+	case QSEECOM_IOCTL_PERF_ENABLE_REQ:{
+		atomic_inc(&data->ioctl_count);
+		ret = qsee_vote_for_clock();
+		if (ret)
+			pr_err("Failed to vote for clock%d\n", ret);
+		atomic_dec(&data->ioctl_count);
+		break;
+	}
+	case QSEECOM_IOCTL_PERF_DISABLE_REQ:{
+		atomic_inc(&data->ioctl_count);
+		qsee_disable_clock_vote();
+		atomic_dec(&data->ioctl_count);
+		break;
+	}
+	default:
+		return -EINVAL;
+	}
+	return ret;
+}
+
+static int qseecom_open(struct inode *inode, struct file *file)
+{
+	int ret = 0;
+	struct qseecom_dev_handle *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		pr_err("kmalloc failed\n");
+		return -ENOMEM;
+	}
+	file->private_data = data;
+	data->abort = 0;
+	data->service = false;
+	data->released = false;
+	init_waitqueue_head(&data->abort_wq);
+	atomic_set(&data->ioctl_count, 0);
+	return ret;
+}
+
+static int qseecom_release(struct inode *inode, struct file *file)
+{
+	struct qseecom_dev_handle *data = file->private_data;
+	int ret = 0;
+
+	if (data->released == false) {
+		pr_warn("data->released == false\n");
+		if (data->service)
+			ret = qseecom_unregister_listener(data);
+		else
+			ret = qseecom_unload_app(data);
+		if (ret) {
+			pr_err("Close failed\n");
+			return ret;
+		}
+	}
+	kfree(data);
+	return ret;
+}
+
+/* qseecom bus scaling */
+static struct msm_bus_paths qsee_bw_table[] = {
+	{
+		.vectors = (struct msm_bus_vectors[]){
+			{
+				.src = MSM_BUS_MASTER_SPS,
+				.dst = MSM_BUS_SLAVE_EBI_CH0,
+			},
+		},
+		.num_paths = 1,
+	},
+	{
+		.vectors = (struct msm_bus_vectors[]){
+			{
+				.src = MSM_BUS_MASTER_SPS,
+				.dst = MSM_BUS_SLAVE_EBI_CH0,
+				.ib = (492 * 8) * 1000000UL,
+				.ab = (492 * 8) *  100000UL,
+			},
+		},
+		.num_paths = 1,
+	},
+};
+
+static struct msm_bus_scale_pdata qsee_bus_pdata = {
+	.usecase = qsee_bw_table,
+	.num_usecases = ARRAY_SIZE(qsee_bw_table),
+	.name = "qsee",
+};
+
+static const struct file_operations qseecom_fops = {
+		.owner = THIS_MODULE,
+		.unlocked_ioctl = qseecom_ioctl,
+		.open = qseecom_open,
+		.release = qseecom_release
+};
+
+static int __init qseecom_init(void)
+{
+	int rc;
+	int ret = 0;
+	struct device *class_dev;
+	char qsee_not_legacy = 0;
+	uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
+
+	rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
+	if (rc < 0) {
+		pr_err("alloc_chrdev_region failed %d\n", rc);
+		return rc;
+	}
+
+	driver_class = class_create(THIS_MODULE, QSEECOM_DEV);
+	if (IS_ERR(driver_class)) {
+		rc = -ENOMEM;
+		pr_err("class_create failed %d\n", rc);
+		goto unregister_chrdev_region;
+	}
+
+	class_dev = device_create(driver_class, NULL, qseecom_device_no, NULL,
+			QSEECOM_DEV);
+	if (!class_dev) {
+		pr_err("class_device_create failed %d\n", rc);
+		rc = -ENOMEM;
+		goto class_destroy;
+	}
+
+	cdev_init(&qseecom_cdev, &qseecom_fops);
+	qseecom_cdev.owner = THIS_MODULE;
+
+	rc = cdev_add(&qseecom_cdev, MKDEV(MAJOR(qseecom_device_no), 0), 1);
+	if (rc < 0) {
+		pr_err("cdev_add failed %d\n", rc);
+		goto err;
+	}
+
+	INIT_LIST_HEAD(&qseecom.registered_listener_list_head);
+	spin_lock_init(&qseecom.registered_listener_list_lock);
+	INIT_LIST_HEAD(&qseecom.registered_app_list_head);
+	spin_lock_init(&qseecom.registered_app_list_lock);
+	init_waitqueue_head(&qseecom.send_resp_wq);
+	qseecom.send_resp_flag = 0;
+
+	rc = scm_call(6, 1, &system_call_id, sizeof(system_call_id),
+				&qsee_not_legacy, sizeof(qsee_not_legacy));
+	if (rc) {
+		pr_err("Failed to retrieve QSEE version information %d\n", rc);
+		goto err;
+	}
+	if (qsee_not_legacy)
+		qseecom.qseos_version = QSEOS_VERSION_14;
+	else {
+		qseecom.qseos_version = QSEOS_VERSION_13;
+		pil = NULL;
+		pil_ref_cnt = 0;
+	}
+	/* Create ION msm client */
+	qseecom.ion_clnt = msm_ion_client_create(0x03, "qseecom-kernel");
+	if (qseecom.ion_clnt == NULL) {
+		pr_err("Ion client cannot be created\n");
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	/* register client for bus scaling */
+	qsee_perf_client = msm_bus_scale_register_client(&qsee_bus_pdata);
+	if (!qsee_perf_client)
+		pr_err("Unable to register bus client\n");
+
+	qseecom_bus_clk = clk_get_sys("scm", "bus_clk");
+	if (!IS_ERR(qseecom_bus_clk)) {
+		ret = clk_set_rate(qseecom_bus_clk, 64000000);
+		if (ret) {
+			qseecom_bus_clk = NULL;
+			pr_err("Unable to set clock rate\n");
+		}
+	} else {
+		qseecom_bus_clk = NULL;
+		pr_warn("Unable to get bus clk\n");
+	}
+	return 0;
+err:
+	device_destroy(driver_class, qseecom_device_no);
+class_destroy:
+	class_destroy(driver_class);
+unregister_chrdev_region:
+	unregister_chrdev_region(qseecom_device_no, 1);
+	return rc;
+}
+
+static void __exit qseecom_exit(void)
+{
+	device_destroy(driver_class, qseecom_device_no);
+	class_destroy(driver_class);
+	unregister_chrdev_region(qseecom_device_no, 1);
+	ion_client_destroy(qseecom.ion_clnt);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm Secure Execution Environment Communicator");
+
+module_init(qseecom_init);
+module_exit(qseecom_exit);
diff --git a/drivers/misc/qseecom_legacy.h b/drivers/misc/qseecom_legacy.h
new file mode 100644
index 0000000..66f87e9
--- /dev/null
+++ b/drivers/misc/qseecom_legacy.h
@@ -0,0 +1,79 @@
+/* Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
+ *
+ * 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 __QSEECOM_LEGACY_H_
+#define __QSEECOM_LEGACY_H_
+
+#include <linux/types.h>
+
+#define TZ_SCHED_CMD_ID_REGISTER_LISTENER    0x04
+
+enum tz_sched_cmd_type {
+	TZ_SCHED_CMD_INVALID = 0,
+	TZ_SCHED_CMD_NEW,      /* New TZ Scheduler Command */
+	TZ_SCHED_CMD_PENDING,  /* Pending cmd...sched will restore stack */
+	TZ_SCHED_CMD_COMPLETE, /* TZ sched command is complete */
+	TZ_SCHED_CMD_MAX     = 0x7FFFFFFF
+};
+
+enum tz_sched_cmd_status {
+	TZ_SCHED_STATUS_INCOMPLETE = 0,
+	TZ_SCHED_STATUS_COMPLETE,
+	TZ_SCHED_STATUS_MAX  = 0x7FFFFFFF
+};
+/* Command structure for initializing shared buffers */
+__packed struct qse_pr_init_sb_req_s {
+	/* First 4 bytes should always be command id */
+	uint32_t                  pr_cmd;
+	/* Pointer to the physical location of sb buffer */
+	uint32_t                  sb_ptr;
+	/* length of shared buffer */
+	uint32_t                  sb_len;
+	uint32_t                  listener_id;
+};
+
+__packed struct qse_pr_init_sb_rsp_s {
+	/* First 4 bytes should always be command id */
+	uint32_t                  pr_cmd;
+	/* Return code, 0 for success, Approp error code otherwise */
+	int32_t                   ret;
+};
+
+/*
+ * struct QSEECom_command - QSECom command buffer
+ * @cmd_type: value from enum tz_sched_cmd_type
+ * @sb_in_cmd_addr: points to physical location of command
+ *                buffer
+ * @sb_in_cmd_len: length of command buffer
+ */
+__packed struct qseecom_command {
+	uint32_t               cmd_type;
+	uint8_t                *sb_in_cmd_addr;
+	uint32_t               sb_in_cmd_len;
+};
+
+/*
+ * struct QSEECom_response - QSECom response buffer
+ * @cmd_status: value from enum tz_sched_cmd_status
+ * @sb_in_rsp_addr: points to physical location of response
+ *                buffer
+ * @sb_in_rsp_len: length of command response
+ */
+__packed struct qseecom_response {
+	uint32_t                 cmd_status;
+	uint8_t                  *sb_in_rsp_addr;
+	uint32_t                 sb_in_rsp_len;
+};
+
+#endif /* __QSEECOM_LEGACY_H_ */
diff --git a/drivers/misc/tzcom.c b/drivers/misc/tzcom.c
index e662f43..2b1484c 100644
--- a/drivers/misc/tzcom.c
+++ b/drivers/misc/tzcom.c
@@ -1002,7 +1002,10 @@
 	}
 	spin_unlock_irqrestore(&tzcom_data->registered_svc_list_lock, flags);
 	PDEBUG("After removing svc list");
-
+	if (pil != NULL) {
+		pil_put(pil);
+		pil = NULL;
+	}
 	PDEBUG("Freeing tzcom data");
 	kfree(tzcom_data);
 	return 0;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 3ae639e..e364eac 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1042,8 +1042,6 @@
 	host->curr.got_dataend = 0;
 	host->curr.got_auto_prog_done = 0;
 
-	memset(&host->pio, 0, sizeof(host->pio));
-
 	datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
 
 	if (host->curr.wait_for_auto_prog_done)
@@ -1078,17 +1076,21 @@
 
 	/* Is data transfer in PIO mode required? */
 	if (!(datactrl & MCI_DPSM_DMAENABLE)) {
-		host->pio.sg = data->sg;
-		host->pio.sg_len = data->sg_len;
-		host->pio.sg_off = 0;
+		unsigned int sg_miter_flags = SG_MITER_ATOMIC;
 
 		if (data->flags & MMC_DATA_READ) {
+			sg_miter_flags |= SG_MITER_TO_SG;
 			pio_irqmask = MCI_RXFIFOHALFFULLMASK;
 			if (host->curr.xfer_remain < MCI_FIFOSIZE)
 				pio_irqmask |= MCI_RXDATAAVLBLMASK;
-		} else
+		} else {
+			sg_miter_flags |= SG_MITER_FROM_SG;
 			pio_irqmask = MCI_TXFIFOHALFEMPTYMASK |
 					MCI_TXFIFOEMPTYMASK;
+		}
+
+		sg_miter_start(&host->sg_miter, data->sg, data->sg_len,
+				sg_miter_flags);
 	}
 
 	if (data->flags & MMC_DATA_READ)
@@ -1254,6 +1256,7 @@
 	struct msmsdcc_host	*host = dev_id;
 	void __iomem		*base = host->base;
 	uint32_t		status;
+	unsigned long flags;
 
 	spin_lock(&host->lock);
 
@@ -1268,9 +1271,10 @@
 #if IRQ_DEBUG
 	msmsdcc_print_status(host, "irq1-r", status);
 #endif
+	local_irq_save(flags);
 
-	do {
-		unsigned long flags;
+	while (sg_miter_next(&host->sg_miter)) {
+
 		unsigned int remain, len;
 		char *buffer;
 
@@ -1278,12 +1282,8 @@
 				| MCI_RXDATAAVLBL)))
 			break;
 
-		/* Map the current scatter buffer */
-		local_irq_save(flags);
-		buffer = kmap_atomic(sg_page(host->pio.sg),
-				     KM_BIO_SRC_IRQ) + host->pio.sg->offset;
-		buffer += host->pio.sg_off;
-		remain = host->pio.sg->length - host->pio.sg_off;
+		buffer = host->sg_miter.addr;
+		remain = host->sg_miter.length;
 
 		len = 0;
 		if (status & MCI_RXACTIVE)
@@ -1294,11 +1294,7 @@
 		if (len > remain)
 			len = remain;
 
-		/* Unmap the buffer */
-		kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
-		local_irq_restore(flags);
-
-		host->pio.sg_off += len;
+		host->sg_miter.consumed = len;
 		host->curr.xfer_remain -= len;
 		host->curr.data_xfered += len;
 		remain -= len;
@@ -1306,20 +1302,11 @@
 		if (remain) /* Done with this page? */
 			break; /* Nope */
 
-		if (status & MCI_RXACTIVE && host->curr.user_pages)
-			flush_dcache_page(sg_page(host->pio.sg));
-
-		if (!--host->pio.sg_len) {
-			memset(&host->pio, 0, sizeof(host->pio));
-			break;
-		}
-
-		/* Advance to next sg */
-		host->pio.sg++;
-		host->pio.sg_off = 0;
-
 		status = readl_relaxed(base + MMCISTATUS);
-	} while (1);
+	}
+
+	sg_miter_stop(&host->sg_miter);
+	local_irq_restore(flags);
 
 	if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
 		writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
@@ -2300,6 +2287,10 @@
 	/* Select free running MCLK as input clock of cm_dll_sdc4 */
 	clk |= (2 << 23);
 
+	/* Clear IO_PAD_PWR_SWITCH while powering off the card */
+	if (!ios->vdd)
+		host->io_pad_pwr_switch = 0;
+
 	if (host->io_pad_pwr_switch)
 		clk |= IO_PAD_PWR_SWITCH;
 
@@ -2575,6 +2566,10 @@
 	unsigned long flags;
 	int rc = 0;
 
+	spin_lock_irqsave(&host->lock, flags);
+	host->io_pad_pwr_switch = 0;
+	spin_unlock_irqrestore(&host->lock, flags);
+
 	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
 		/* Change voltage level of VDDPX to high voltage */
 		rc = msmsdcc_set_vddp_high_vol(host);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index ee7a3e5..319d721 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -361,7 +361,7 @@
 	struct msmsdcc_sps_data sps;
 	bool			is_dma_mode;
 	bool			is_sps_mode;
-	struct msmsdcc_pio_data	pio;
+	struct sg_mapping_iter sg_miter;
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	struct early_suspend early_suspend;
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 4be8373..167efd9 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -318,6 +318,17 @@
 	  The driver provides wear leveling by storing erase counter into the
 	  OOB.
 
+config MTD_LAZYECCSTATS
+	bool "MTD Lazy ECC Stats collection support"
+	default y
+	help
+	  Normally bad block counts for ECC stats are collected at boot time.
+	  This option delays the badblock stats collection until ECCGETSTATS
+	  ioctl is invoked on the partition.
+
+	  This can significantly decrease boot times depending on the size of
+	  the partition.  If unsure, say 'N'.
+
 source "drivers/mtd/chips/Kconfig"
 
 source "drivers/mtd/maps/Kconfig"
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f1af222..ed9468c 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -34,6 +34,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
 
 #include <asm/uaccess.h>
 
@@ -904,6 +905,9 @@
 
 	case ECCGETSTATS:
 	{
+#ifdef CONFIG_MTD_LAZYECCSTATS
+		part_fill_badblockstats(mtd);
+#endif
 		if (copy_to_user(argp, &mtd->ecc_stats,
 				 sizeof(struct mtd_ecc_stats)))
 			return -EFAULT;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 630be3e..4c75f32 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -353,6 +353,21 @@
 	kfree(p);
 }
 
+void part_fill_badblockstats(struct mtd_info *mtd)
+{
+	struct mtd_part *part = PART(mtd);
+	if (part->master->block_isbad) {
+		uint64_t offs = 0;
+		mtd->ecc_stats.badblocks = 0;
+		while (offs < mtd->size) {
+			if (part->master->block_isbad(part->master,
+						offs + part->offset))
+				mtd->ecc_stats.badblocks++;
+			offs += mtd->erasesize;
+		}
+	}
+}
+
 /*
  * This function unregisters and destroy all slave MTD objects which are
  * attached to the given master MTD object.
@@ -542,16 +557,10 @@
 	}
 
 	slave->mtd.ecclayout = master->ecclayout;
-	if (master->block_isbad) {
-		uint64_t offs = 0;
 
-		while (offs < slave->mtd.size) {
-			if (master->block_isbad(master,
-						offs + slave->offset))
-				slave->mtd.ecc_stats.badblocks++;
-			offs += slave->mtd.erasesize;
-		}
-	}
+#ifndef CONFIG_MTD_LAZYECCSTATS
+	part_fill_badblockstats(&(slave->mtd));
+#endif
 
 out_register:
 	return slave;
diff --git a/drivers/net/qfec.c b/drivers/net/qfec.c
index fc27837..e1f4be2 100644
--- a/drivers/net/qfec.c
+++ b/drivers/net/qfec.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
@@ -1899,6 +1899,11 @@
 	setup_timer(&priv->phy_tmr, qfec_phy_monitor, (unsigned long)dev);
 	mod_timer(&priv->phy_tmr, jiffies + HZ);
 
+	/* driver supports AN capable PHY only */
+	qfec_mdio_write(dev, priv->phy_id, MII_BMCR, BMCR_RESET);
+	res = (BMCR_ANENABLE|BMCR_ANRESTART);
+	qfec_mdio_write(dev, priv->phy_id, MII_BMCR, res);
+
 	/* initialize interrupts */
 	QFEC_LOG(QFEC_LOG_DBG, " %s: request irq %d\n", __func__, dev->irq);
 	res = request_irq(dev->irq, qfec_int, 0, dev->name, dev);
diff --git a/drivers/net/wireless/libra/qcomwlan_pwrif.c b/drivers/net/wireless/libra/qcomwlan_pwrif.c
index 8268f24..6a0c78f 100644
--- a/drivers/net/wireless/libra/qcomwlan_pwrif.c
+++ b/drivers/net/wireless/libra/qcomwlan_pwrif.c
@@ -72,7 +72,7 @@
 	static const int vregs_qwlan_peek_current[] = {
 		4000,
 		150000,
-		200000,
+		60000,
 		0,
 		32000,
 		130000,
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 93de829..3104daf 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -29,6 +29,7 @@
 #define BMS_CONTROL		0x224
 #define BMS_OUTPUT0		0x230
 #define BMS_OUTPUT1		0x231
+#define BMS_TOLERANCES		0x232
 #define BMS_TEST1		0x237
 
 #define ADC_ARB_SECP_CNTRL	0x190
@@ -1268,6 +1269,10 @@
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_get_fcc);
 
+#define IBAT_TOL_MASK		0x0F
+#define OCV_TOL_MASK			0xF0
+#define IBAT_TOL_DEFAULT	0x03
+#define IBAT_TOL_NOCHG		0x0F
 void pm8921_bms_charging_began(void)
 {
 	int batt_temp, rc;
@@ -1291,7 +1296,8 @@
 	bms_start_percent = the_chip->start_percent;
 	bms_start_ocv_uv = raw.last_good_ocv_uv;
 	calculate_cc_uah(the_chip, raw.cc, &bms_start_cc_uah);
-
+	pm_bms_masked_write(the_chip, BMS_TOLERANCES,
+			IBAT_TOL_MASK, IBAT_TOL_DEFAULT);
 	pr_debug("start_percent = %u%%\n", the_chip->start_percent);
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_charging_began);
@@ -1373,6 +1379,8 @@
 			last_chargecycles);
 	the_chip->start_percent = -EINVAL;
 	the_chip->end_percent = -EINVAL;
+	pm_bms_masked_write(the_chip, BMS_TOLERANCES,
+				IBAT_TOL_MASK, IBAT_TOL_NOCHG);
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_charging_end);
 
@@ -1514,6 +1522,9 @@
 				BMS_CONTROL, rc);
 	}
 
+	/* The charger will call start charge later if usb is present */
+	pm_bms_masked_write(chip, BMS_TOLERANCES,
+				IBAT_TOL_MASK, IBAT_TOL_NOCHG);
 	return 0;
 }
 
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index fa8f866..aca724a 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -415,14 +415,6 @@
 				disable ? CHG_CHARGE_DIS_BIT : 0);
 }
 
-static bool pm_is_chg_charge_dis_bit_set(struct pm8921_chg_chip *chip)
-{
-	u8 temp = 0;
-
-	pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
-	return !!(temp & CHG_CHARGE_DIS_BIT);
-}
-
 #define PM8921_CHG_V_MIN_MV	3240
 #define PM8921_CHG_V_STEP_MV	20
 #define PM8921_CHG_V_STEP_10_MV_BIT	BIT(7)
@@ -1024,24 +1016,34 @@
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 	case POWER_SUPPLY_PROP_ONLINE:
-		if (pm_is_chg_charge_dis_bit_set(the_chip) ||
-				!is_usb_chg_plugged_in(the_chip))
-			val->intval = 0;
-		else if (psy->type == POWER_SUPPLY_TYPE_USB ||
+		val->intval = 0;
+		if (charging_disabled)
+			return 0;
+
+		/* USB charging */
+		if (psy->type == POWER_SUPPLY_TYPE_USB ||
 				psy->type == POWER_SUPPLY_TYPE_USB_DCP ||
 				psy->type == POWER_SUPPLY_TYPE_USB_CDP ||
 				psy->type == POWER_SUPPLY_TYPE_USB_ACA) {
-			val->intval = 1;
-		} else if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
+			val->intval = is_usb_chg_plugged_in(the_chip);
+			return 0;
+		}
+
+		/* DC charging */
+		if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
+			/* external charger is connected */
+			if (the_chip->dc_present || is_ext_charging(the_chip)) {
+				val->intval = 1;
+				return 0;
+			}
+			/* USB with max current greater than 500 mA connected */
 			pm_chg_iusbmax_get(the_chip, &current_max);
 			if (current_max > USB_WALL_THRESHOLD_MA)
-				val->intval = 1;
-			else
-				val->intval = 0;
-		} else {
-			val->intval = 0;
-			pr_err("Unkown POWER_SUPPLY_TYPE %d\n", psy->type);
+				val->intval = is_usb_chg_plugged_in(the_chip);
+			return 0;
 		}
+
+		pr_err("Unkown POWER_SUPPLY_TYPE %d\n", psy->type);
 		break;
 	default:
 		return -EINVAL;
@@ -1592,6 +1594,7 @@
 
 	the_chip->usb_psy.type = type;
 	power_supply_changed(&the_chip->usb_psy);
+	power_supply_changed(&the_chip->dc_psy);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pm8921_set_usb_power_supply_type);
@@ -1639,6 +1642,7 @@
 	power_supply_set_charge_type(chip->ext_psy,
 					POWER_SUPPLY_CHARGE_TYPE_NONE);
 	pm8921_disable_source_current(false); /* release BATFET */
+	power_supply_changed(&chip->dc_psy);
 	chip->ext_charging = false;
 	chip->ext_charge_done = false;
 	bms_notify_check(chip);
@@ -1686,8 +1690,10 @@
 		return;
 	}
 
+	power_supply_set_online(chip->ext_psy, dc_present);
 	power_supply_set_charge_type(chip->ext_psy,
 					POWER_SUPPLY_CHARGE_TYPE_FAST);
+	power_supply_changed(&chip->dc_psy);
 	chip->ext_charging = true;
 	chip->ext_charge_done = false;
 	bms_notify_check(chip);
@@ -1768,6 +1774,7 @@
 
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
+	power_supply_changed(&chip->dc_psy);
 
 	return IRQ_HANDLED;
 }
@@ -1819,6 +1826,7 @@
 
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
+	power_supply_changed(&chip->dc_psy);
 
 	bms_notify_check(chip);
 
@@ -1841,6 +1849,7 @@
 
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
+	power_supply_changed(&chip->dc_psy);
 	return IRQ_HANDLED;
 }
 
@@ -1851,6 +1860,7 @@
 	pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
+	power_supply_changed(&chip->dc_psy);
 
 	bms_notify_check(chip);
 
diff --git a/drivers/regulator/pm8xxx-regulator.c b/drivers/regulator/pm8xxx-regulator.c
index 94b028d..fa17449 100644
--- a/drivers/regulator/pm8xxx-regulator.c
+++ b/drivers/regulator/pm8xxx-regulator.c
@@ -401,6 +401,19 @@
 #define NCP_SET_POINTS			((NCP_UV_MAX - NCP_UV_MIN) \
 						/ NCP_UV_STEP + 1)
 
+/* Boost masks and values */
+#define BOOST_ENABLE_MASK		0x80
+#define BOOST_DISABLE			0x00
+#define BOOST_ENABLE			0x80
+#define BOOST_VPROG_MASK		0x1F
+
+#define BOOST_UV_MIN			4000000
+#define BOOST_UV_MAX			5550000
+#define BOOST_UV_STEP			50000
+
+#define BOOST_SET_POINTS		((BOOST_UV_MAX - BOOST_UV_MIN) \
+						/ BOOST_UV_STEP + 1)
+
 #define vreg_err(vreg, fmt, ...) \
 	pr_err("%s: " fmt, vreg->rdesc.name, ##__VA_ARGS__)
 
@@ -1424,6 +1437,64 @@
 	return rc;
 }
 
+static int pm8xxx_boost_get_voltage(struct regulator_dev *rdev)
+{
+	struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
+	u8 vprog;
+
+	vprog = vreg->ctrl_reg & BOOST_VPROG_MASK;
+
+	return BOOST_UV_STEP * vprog + BOOST_UV_MIN;
+}
+
+static int pm8xxx_boost_list_voltage(struct regulator_dev *rdev,
+				    unsigned selector)
+{
+	if (selector >= BOOST_SET_POINTS)
+		return 0;
+
+	return selector * BOOST_UV_STEP + BOOST_UV_MIN;
+}
+
+static int pm8xxx_boost_set_voltage(struct regulator_dev *rdev, int min_uV,
+				   int max_uV, unsigned *selector)
+{
+	struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
+	int rc;
+	int uV = min_uV;
+	u8 val;
+
+	if (uV < BOOST_UV_MIN && max_uV >= BOOST_UV_MIN)
+		uV = BOOST_UV_MIN;
+
+	if (uV < BOOST_UV_MIN || uV > BOOST_UV_MAX) {
+		vreg_err(vreg,
+			"request v=[%d, %d] is outside possible v=[%d, %d]\n",
+			 min_uV, max_uV, BOOST_UV_MIN, BOOST_UV_MAX);
+		return -EINVAL;
+	}
+
+	val = (uV - BOOST_UV_MIN + BOOST_UV_STEP - 1) / BOOST_UV_STEP;
+	uV = val * BOOST_UV_STEP + BOOST_UV_MIN;
+
+	if (uV > max_uV) {
+		vreg_err(vreg,
+			"request v=[%d, %d] cannot be met by any set point\n",
+			min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	/* voltage setting */
+	rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, val,
+			BOOST_VPROG_MASK, &vreg->ctrl_reg);
+	if (rc)
+		vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc);
+	else
+		pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE);
+
+	return rc;
+}
+
 static unsigned int pm8xxx_ldo_get_mode(struct regulator_dev *rdev)
 {
 	struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
@@ -2066,6 +2137,38 @@
 	return rc;
 }
 
+static int pm8xxx_boost_enable(struct regulator_dev *rdev)
+{
+	struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
+	int rc;
+
+	rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, BOOST_ENABLE,
+		BOOST_ENABLE_MASK, &vreg->ctrl_reg);
+
+	if (rc)
+		vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc);
+	else
+		pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE);
+
+	return rc;
+}
+
+static int pm8xxx_boost_disable(struct regulator_dev *rdev)
+{
+	struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
+	int rc;
+
+	rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, BOOST_DISABLE,
+		BOOST_ENABLE_MASK, &vreg->ctrl_reg);
+
+	if (rc)
+		vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc);
+	else
+		pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE);
+
+	return rc;
+}
+
 static int pm8xxx_ldo_pin_control_enable(struct regulator_dev *rdev)
 {
 	struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
@@ -2506,6 +2609,11 @@
 		pr_info("%s %-9s: %s, v=%7d uV\n",
 			action_label, vreg->rdesc.name, enable_label, uV);
 		break;
+	case PM8XXX_REGULATOR_TYPE_BOOST:
+		uV = pm8xxx_boost_get_voltage(rdev);
+		pr_info("%s %-9s: %s, v=%7d uV\n",
+			action_label, vreg->rdesc.name, enable_label, uV);
+		break;
 	default:
 		break;
 	}
@@ -2601,6 +2709,16 @@
 	.enable_time		= pm8xxx_enable_time,
 };
 
+static struct regulator_ops pm8xxx_boost_ops = {
+	.enable			= pm8xxx_boost_enable,
+	.disable		= pm8xxx_boost_disable,
+	.is_enabled		= pm8xxx_vreg_is_enabled,
+	.set_voltage		= pm8xxx_boost_set_voltage,
+	.get_voltage		= pm8xxx_boost_get_voltage,
+	.list_voltage		= pm8xxx_boost_list_voltage,
+	.enable_time		= pm8xxx_enable_time,
+};
+
 /* Pin control regulator operations. */
 static struct regulator_ops pm8xxx_ldo_pc_ops = {
 	.enable			= pm8xxx_ldo_pin_control_enable,
@@ -2629,6 +2747,7 @@
 	[PM8XXX_REGULATOR_TYPE_VS]		= &pm8xxx_vs_ops,
 	[PM8XXX_REGULATOR_TYPE_VS300]		= &pm8xxx_vs300_ops,
 	[PM8XXX_REGULATOR_TYPE_NCP]		= &pm8xxx_ncp_ops,
+	[PM8XXX_REGULATOR_TYPE_BOOST]		= &pm8xxx_boost_ops,
 };
 
 static struct regulator_ops *pm8xxx_reg_pc_ops[PM8XXX_REGULATOR_TYPE_MAX] = {
@@ -2647,6 +2766,7 @@
 	[PM8XXX_REGULATOR_TYPE_VS]		= 0,
 	[PM8XXX_REGULATOR_TYPE_VS300]		= 0,
 	[PM8XXX_REGULATOR_TYPE_NCP]		= NCP_SET_POINTS,
+	[PM8XXX_REGULATOR_TYPE_BOOST]		= BOOST_SET_POINTS,
 };
 
 static int pm8xxx_init_ldo(struct pm8xxx_vreg *vreg, bool is_real)
@@ -2937,6 +3057,20 @@
 	return rc;
 }
 
+static int pm8xxx_init_boost(struct pm8xxx_vreg *vreg)
+{
+	int rc;
+
+	/* Save the current control register state. */
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg);
+	if (rc) {
+		vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
 static int __devinit pm8xxx_vreg_probe(struct platform_device *pdev)
 {
 	struct pm8xxx_regulator_core_platform_data *core_data;
@@ -3058,6 +3192,9 @@
 	case PM8XXX_REGULATOR_TYPE_NCP:
 		rc = pm8xxx_init_ncp(vreg);
 		break;
+	case PM8XXX_REGULATOR_TYPE_BOOST:
+		rc = pm8xxx_init_boost(vreg);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 02d1c39..22297be 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1171,6 +1171,27 @@
 			}
 			slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
 			sat->satcl.laddr = laddr;
+			/*
+			 * Since capability message is already sent, present
+			 * message will indicate subsystem hosting this
+			 * satellite has restarted.
+			 * Remove all active channels of this satellite
+			 * when this is detected
+			 */
+			if (sat->sent_capability) {
+				for (i = 0; i < sat->nsatch; i++) {
+					enum slim_ch_state chs =
+						slim_get_ch_state(&sat->satcl,
+							sat->satch[i].chanh);
+					pr_err("Slim-SSR, sat:%d, rm chan:%d",
+							laddr,
+							sat->satch[i].chan);
+					if (chs == SLIM_CH_ACTIVE)
+						slim_control_ch(&sat->satcl,
+							sat->satch[i].chanh,
+							SLIM_CH_REMOVE, true);
+				}
+			}
 		} else if (mt != SLIM_MSG_MT_CORE &&
 				mc != SLIM_MSG_MC_REPORT_PRESENT) {
 			satv = msm_slim_get_ctrl(dev);
@@ -1886,7 +1907,7 @@
 	}
 
 
-	dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
+	dev->rclk = clk_get(dev->dev, "core_clk");
 	if (!dev->rclk) {
 		dev_err(dev->dev, "slimbus clock not found");
 		goto err_clk_get_failed;
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 6733396..cc008ab 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2730,15 +2730,19 @@
  * -EXFULL is returned if there is no space in TDM to reserve the bandwidth.
  * -EISCONN/-ENOTCONN is returned if the channel is already connected or not
  * yet defined.
+ * -EINVAL is returned if individual control of a grouped-channel is attempted.
  */
 int slim_control_ch(struct slim_device *sb, u16 chanh,
 			enum slim_ch_control chctrl, bool commit)
 {
 	struct slim_controller *ctrl = sb->ctrl;
-	struct slim_ich *slc;
 	int ret = 0;
 	/* Get rid of the group flag in MSB if any */
 	u8 chan = SLIM_HDL_TO_CHIDX(chanh);
+	struct slim_ich *slc = &ctrl->chans[chan];
+	if (!(slc->nextgrp & SLIM_START_GRP))
+		return -EINVAL;
+
 	mutex_lock(&sb->sldev_reconf);
 	mutex_lock(&ctrl->m_ctrl);
 	do {
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
new file mode 100644
index 0000000..7768eed
--- /dev/null
+++ b/drivers/spmi/Kconfig
@@ -0,0 +1,29 @@
+#
+# SPMI driver configuration
+#
+menuconfig SPMI
+	bool "SPMI support"
+	help
+	  SPMI (System Power Management Interface) is a two-wire
+	  serial interface between baseband and application processors
+	  and Power Management Integrated Circuits (PMIC).
+
+if SPMI
+config SPMI_MSM_PMIC_ARB
+	tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in SPMI PMIC Arbiter interface on Qualcomm MSM family
+	  processors.
+
+	  This is required for communicating with Qualcomm PMICs and
+	  other devices that have the SPMI interface.
+
+config MSM_QPNP
+	depends on ARCH_MSMCOPPER
+	depends on OF_SPMI
+	bool "MSM QPNP"
+	help
+	  Say 'y' here to include support for the Qualcomm QPNP
+	  support. QPNP is a SPMI based PMIC implementation.
+endif
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
new file mode 100644
index 0000000..659e886
--- /dev/null
+++ b/drivers/spmi/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for kernel SPMI framework.
+#
+obj-$(CONFIG_SPMI)			+= spmi.o
+obj-$(CONFIG_SPMI_MSM_PMIC_ARB)		+= spmi-pmic-arb.o
+obj-$(CONFIG_MSM_QPNP)                  += qpnp.o
diff --git a/drivers/spmi/qpnp.c b/drivers/spmi/qpnp.c
new file mode 100644
index 0000000..ddf9000
--- /dev/null
+++ b/drivers/spmi/qpnp.c
@@ -0,0 +1,55 @@
+/* Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ * 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.
+ *
+ * Resource handling based on platform.c.
+ */
+
+#include <mach/qpnp.h>
+
+/**
+ * qpnp_get_resource - get a resource for a device
+ * @dev: qpnp device
+ * @type: resource type
+ * @num: resource index
+ */
+struct resource *qpnp_get_resource(struct spmi_device *dev,
+				   unsigned int node_idx, unsigned int type,
+				   unsigned int res_num)
+{
+	int i;
+
+	for (i = 0; i < dev->dev_node[node_idx].num_resources; i++) {
+		struct resource *r = &dev->dev_node[node_idx].resource[i];
+
+		if (type == resource_type(r) && res_num-- == 0)
+			return r;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(qpnp_get_resource);
+
+/**
+ * qpnp_get_irq - get an IRQ for a device
+ * @dev: qpnp device
+ * @num: IRQ number index
+ */
+int qpnp_get_irq(struct spmi_device *dev, unsigned int node_idx,
+					  unsigned int res_num)
+{
+	struct resource *r = qpnp_get_resource(dev, node_idx,
+						IORESOURCE_IRQ, res_num);
+
+	return r ? r->start : -ENXIO;
+}
+EXPORT_SYMBOL_GPL(qpnp_get_irq);
+
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
new file mode 100644
index 0000000..e5a9d40
--- /dev/null
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -0,0 +1,733 @@
+/* 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/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/of_spmi.h>
+#include <mach/qpnp-int.h>
+
+#define SPMI_PMIC_ARB_NAME		"spmi_pmic_arb"
+
+/* PMIC Arbiter configuration registers */
+#define PMIC_ARB_VERSION		0x0000
+#define PMIC_ARB_INT_EN			0x0004
+
+/* PMIC Arbiter channel registers */
+#define PMIC_ARB_CMD(N)			(0x0800 + (0x80 * (N)))
+#define PMIC_ARB_CONFIG(N)		(0x0804 + (0x80 * (N)))
+#define PMIC_ARB_STATUS(N)		(0x0808 + (0x80 * (N)))
+#define PMIC_ARB_WDATA0(N)		(0x0810 + (0x80 * (N)))
+#define PMIC_ARB_WDATA1(N)		(0x0814 + (0x80 * (N)))
+#define PMIC_ARB_RDATA0(N)		(0x0818 + (0x80 * (N)))
+#define PMIC_ARB_RDATA1(N)		(0x081C + (0x80 * (N)))
+
+/* Interrupt Controller */
+#define SPMI_PIC_OWNER_ACC_STATUS(M, N)	(0x0000 + ((32 * (M)) + (4 * (N))))
+#define SPMI_PIC_ACC_ENABLE(N)		(0x0200 + (4 * (N)))
+#define SPMI_PIC_IRQ_STATUS(N)		(0x0600 + (4 * (N)))
+#define SPMI_PIC_IRQ_CLEAR(N)		(0x0A00 + (4 * (N)))
+
+/* Channel Status fields */
+enum pmic_arb_chnl_status {
+	PMIC_ARB_STATUS_DONE	= (1 << 0),
+	PMIC_ARB_STATUS_FAILURE	= (1 << 1),
+	PMIC_ARB_STATUS_DENIED	= (1 << 2),
+	PMIC_ARB_STATUS_DROPPED	= (1 << 3),
+};
+
+/* Command register fields */
+#define PMIC_ARB_CMD_MAX_BYTE_COUNT	8
+
+/* Command Opcodes */
+enum pmic_arb_cmd_op_code {
+	PMIC_ARB_OP_EXT_WRITEL = 0,
+	PMIC_ARB_OP_EXT_READL = 1,
+	PMIC_ARB_OP_EXT_WRITE = 2,
+	PMIC_ARB_OP_RESET = 3,
+	PMIC_ARB_OP_SLEEP = 4,
+	PMIC_ARB_OP_SHUTDOWN = 5,
+	PMIC_ARB_OP_WAKEUP = 6,
+	PMIC_ARB_OP_AUTHENTICATE = 7,
+	PMIC_ARB_OP_MSTR_READ = 8,
+	PMIC_ARB_OP_MSTR_WRITE = 9,
+	PMIC_ARB_OP_EXT_READ = 13,
+	PMIC_ARB_OP_WRITE = 14,
+	PMIC_ARB_OP_READ = 15,
+	PMIC_ARB_OP_ZERO_WRITE = 16,
+};
+
+/* Maximum number of support PMIC peripherals */
+#define PMIC_ARB_MAX_PERIPHS		256
+#define PMIC_ARB_PERIPH_ID_VALID	(1 << 15)
+#define PMIC_ARB_TIMEOUT_US		100
+#define PMIC_ARB_APID_MASK		0xFF
+#define PMIC_ARB_PPID_MASK		0xFFF
+
+/**
+ * base - base address of the PMIC Arbiter core registers.
+ * intr - base address of the SPMI interrupt control registers
+ */
+struct spmi_pmic_arb_dev {
+	struct spmi_controller	controller;
+	struct device		*dev;
+	struct device		*slave;
+	void __iomem		*base;
+	void __iomem		*intr;
+	int			pic_irq;
+	int			pic_enable_cnt;
+	spinlock_t		lock;
+	u8			owner;
+	u8			channel;
+	u8			min_apid;
+	u8			max_apid;
+	u16			periph_id_map[PMIC_ARB_MAX_PERIPHS];
+};
+
+static u32 pmic_arb_read(struct spmi_pmic_arb_dev *dev, u32 offset)
+{
+	u32 val = readl_relaxed(dev->base + offset);
+	pr_debug("address 0x%p, val 0x%x\n", dev->base + offset, val);
+	return val;
+}
+
+static void pmic_arb_write(struct spmi_pmic_arb_dev *dev, u32 offset, u32 val)
+{
+	pr_debug("address 0x%p, val 0x%x\n", dev->base + offset, val);
+	writel_relaxed(val, dev->base + offset);
+}
+
+static int pmic_arb_wait_for_done(struct spmi_pmic_arb_dev *dev)
+{
+	u32 status = 0;
+	u32 timeout = PMIC_ARB_TIMEOUT_US;
+	u32 offset = PMIC_ARB_STATUS(dev->channel);
+
+	while (timeout--) {
+		status = pmic_arb_read(dev, offset);
+
+		if (status & PMIC_ARB_STATUS_DONE) {
+			if (status & PMIC_ARB_STATUS_DENIED) {
+				dev_err(dev->dev,
+					"%s: transaction denied (0x%x)\n",
+					__func__, status);
+				return -EPERM;
+			}
+
+			if (status & PMIC_ARB_STATUS_FAILURE) {
+				dev_err(dev->dev,
+					"%s: transaction failed (0x%x)\n",
+					__func__, status);
+				return -EIO;
+			}
+
+			if (status & PMIC_ARB_STATUS_DROPPED) {
+				dev_err(dev->dev,
+					"%s: transaction dropped (0x%x)\n",
+					__func__, status);
+				return -EIO;
+			}
+
+			return 0;
+		}
+		udelay(1);
+	}
+
+	dev_err(dev->dev, "%s: timeout, status 0x%x\n", __func__, status);
+	return -ETIMEDOUT;
+}
+
+static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+{
+	u32 data = pmic_arb_read(dev, reg);
+
+	switch (bc & 0x3) {
+	case 3:
+		*buf++ = data & 0xff;
+		data >>= 8;
+	case 2:
+		*buf++ = data & 0xff;
+		data >>= 8;
+	case 1:
+		*buf++ = data & 0xff;
+		data >>= 8;
+	case 0:
+		*buf++ = data & 0xff;
+	default:
+		break;
+	}
+}
+
+static void
+pa_write_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+{
+	u32 data = 0;
+
+	switch (bc & 0x3) {
+	case 3:
+		data = (buf[0]|buf[1]<<8|buf[2]<<16|buf[3]<<24);
+		break;
+	case 2:
+		data = (buf[0]|buf[1]<<8|buf[2]<<16);
+		break;
+	case 1:
+		data = (buf[0]|buf[1]<<8);
+		break;
+	case 0:
+		data = (buf[0]);
+		break;
+	default:
+		break;
+	}
+
+	pmic_arb_write(dev, reg, data);
+}
+
+/* Non-data command */
+static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	unsigned long flags;
+	u32 cmd;
+	int rc;
+
+	pr_debug("op:0x%x sid:%d\n", opc, sid);
+
+	/* Check for valid non-data command */
+	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
+		return -EINVAL;
+
+	cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
+
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(pmic_arb);
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+	return rc;
+}
+
+static int pmic_arb_read_cmd(struct spmi_controller *ctrl,
+				u8 opc, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	unsigned long flags;
+	u32 cmd;
+	int rc;
+
+	pr_debug("op:0x%x sid:%d bc:%d addr:0x%x\n", opc, sid, bc, addr);
+
+	/* Check the opcode */
+	if (opc >= 0x60 && opc <= 0x7F)
+		opc = PMIC_ARB_OP_READ;
+	else if (opc >= 0x20 && opc <= 0x2F)
+		opc = PMIC_ARB_OP_EXT_READ;
+	else if (opc >= 0x38 && opc <= 0x3F)
+		opc = PMIC_ARB_OP_EXT_READL;
+	else
+		return -EINVAL;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(pmic_arb);
+	if (rc)
+		goto done;
+
+	/* Read from FIFO, note 'bc' is actually number of bytes minus 1 */
+	pa_read_data(pmic_arb, buf, PMIC_ARB_RDATA0(pmic_arb->channel), bc);
+
+	if (bc > 3)
+		pa_read_data(pmic_arb, buf + 4,
+				PMIC_ARB_RDATA1(pmic_arb->channel), bc);
+
+done:
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	return rc;
+}
+
+static int pmic_arb_write_cmd(struct spmi_controller *ctrl,
+				u8 opc, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	unsigned long flags;
+	u32 cmd;
+	int rc;
+
+	pr_debug("op:0x%x sid:%d bc:%d addr:0x%x\n", opc, sid, bc, addr);
+
+	/* Check the opcode */
+	if (opc >= 0x40 && opc <= 0x5F)
+		opc = PMIC_ARB_OP_WRITE;
+	else if (opc >= 0x00 && opc <= 0x0F)
+		opc = PMIC_ARB_OP_EXT_WRITE;
+	else if (opc >= 0x30 && opc <= 0x37)
+		opc = PMIC_ARB_OP_EXT_WRITEL;
+	else if (opc >= 0x80 && opc <= 0xFF)
+		opc = PMIC_ARB_OP_ZERO_WRITE;
+	else
+		return -EINVAL;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+	/* Write data to FIFOs */
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	pa_write_data(pmic_arb, buf, PMIC_ARB_WDATA0(pmic_arb->channel), bc);
+
+	if (bc > 3)
+		pa_write_data(pmic_arb, buf + 4,
+				PMIC_ARB_WDATA1(pmic_arb->channel), bc);
+
+	/* Start the transaction */
+	pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(pmic_arb);
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+	return rc;
+}
+
+/* APID to PPID */
+static u16 get_peripheral_id(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+	return pmic_arb->periph_id_map[apid] & PMIC_ARB_PPID_MASK;
+}
+
+/* APID to PPID, returns valid flag */
+static int is_apid_valid(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+	return pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID;
+}
+
+/* PPID to APID */
+static uint32_t map_peripheral_id(struct spmi_pmic_arb_dev *pmic_arb, u16 ppid)
+{
+	int first = pmic_arb->min_apid;
+	int last = pmic_arb->max_apid;
+	int i;
+
+	/* Search table for a matching PPID */
+	for (i = first; i <= last; ++i) {
+		if ((pmic_arb->periph_id_map[i] & PMIC_ARB_PPID_MASK) == ppid)
+			return i;
+	}
+
+	dev_err(pmic_arb->dev, "Unknown ppid 0x%x\n", ppid);
+	return PMIC_ARB_MAX_PERIPHS;
+}
+
+/* Enable interrupt at the PMIC Arbiter PIC */
+static int pmic_arb_pic_enable(struct spmi_controller *ctrl,
+				struct qpnp_irq_spec *spec, uint32_t data)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	u8 apid = data & PMIC_ARB_APID_MASK;
+	unsigned long flags;
+	u32 status;
+
+	dev_dbg(pmic_arb->dev, "PIC enable, apid:0x%x, sid:0x%x, pid:0x%x\n",
+				apid, spec->slave, spec->per);
+
+	if (data < pmic_arb->min_apid || data > pmic_arb->max_apid) {
+		dev_err(pmic_arb->dev, "int enable: invalid APID %d\n", data);
+		return -EINVAL;
+	}
+
+	if (!is_apid_valid(pmic_arb, apid)) {
+		dev_err(pmic_arb->dev, "int enable: int not supported\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	status = readl_relaxed(pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+	if (!status) {
+		if (pmic_arb->pic_enable_cnt++ == 0)
+			enable_irq(pmic_arb->pic_irq);
+		writel_relaxed(0x1, pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+		/* Interrupt needs to be enabled before returning to caller */
+		wmb();
+	}
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	return 0;
+}
+
+/* Disable interrupt at the PMIC Arbiter PIC */
+static int pmic_arb_pic_disable(struct spmi_controller *ctrl,
+				struct qpnp_irq_spec *spec, uint32_t data)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	u8 apid = data & PMIC_ARB_APID_MASK;
+	unsigned long flags;
+	u32 status;
+
+	dev_dbg(pmic_arb->dev, "PIC disable, apid:0x%x, sid:0x%x, pid:0x%x\n",
+				apid, spec->slave, spec->per);
+
+	if (data < pmic_arb->min_apid || data > pmic_arb->max_apid) {
+		dev_err(pmic_arb->dev, "int disable: invalid APID %d\n", data);
+		return -EINVAL;
+	}
+
+	if (!is_apid_valid(pmic_arb, apid)) {
+		dev_err(pmic_arb->dev, "int disable: int not supported\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	status = readl_relaxed(pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+	if (status) {
+		if (pmic_arb->pic_enable_cnt-- == 1)
+			disable_irq(pmic_arb->pic_irq);
+		writel_relaxed(0x0, pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+		/* Interrupt needs to be disabled before returning to caller */
+		wmb();
+	}
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	return 0;
+}
+
+static irqreturn_t
+periph_interrupt(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+	u16 ppid = get_peripheral_id(pmic_arb, apid);
+	void __iomem *base = pmic_arb->intr;
+	u8 sid = (ppid >> 8) & 0x0F;
+	u8 pid = ppid & 0xFF;
+	u32 status;
+	int i;
+
+	if (!is_apid_valid(pmic_arb, apid)) {
+		dev_err(pmic_arb->dev, "unknown peripheral id 0x%x\n", ppid);
+		/* return IRQ_NONE; */
+	}
+
+	/* Read the peripheral specific interrupt bits */
+	status = readl_relaxed(base + SPMI_PIC_IRQ_STATUS(apid));
+
+	/* Clear the peripheral interrupts */
+	writel_relaxed(status, base + SPMI_PIC_IRQ_CLEAR(apid));
+	/* Interrupt needs to be cleared/acknowledged before exiting ISR */
+	mb();
+
+	dev_dbg(pmic_arb->dev,
+		"interrupt, apid:0x%x, sid:0x%x, pid:0x%x, intr:0x%x\n",
+						apid, sid, pid, status);
+
+	/* Send interrupt notification */
+	for (i = 0; status && i < 8; ++i, status >>= 1) {
+		if (status & 0x1) {
+			struct qpnp_irq_spec irq_spec = {
+				.slave = sid,
+				.per = pid,
+				.irq = i,
+			};
+			qpnpint_handle_irq(&pmic_arb->controller, &irq_spec);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+/* Peripheral interrupt handler */
+static irqreturn_t pmic_arb_periph_irq(int irq, void *dev_id)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = dev_id;
+	void __iomem *intr = pmic_arb->intr;
+	u8 ee = pmic_arb->owner;
+	u32 ret = IRQ_NONE;
+	u32 status;
+
+	int first = pmic_arb->min_apid >> 5;
+	int last = pmic_arb->max_apid >> 5;
+	int i, j;
+
+	dev_dbg(pmic_arb->dev, "Peripheral interrupt detected\n");
+
+	/* Check the accumulated interrupt status */
+	for (i = first; i <= last; ++i) {
+		status = readl_relaxed(intr + SPMI_PIC_OWNER_ACC_STATUS(ee, i));
+
+		for (j = 0; status && j < 32; ++j, status >>= 1) {
+			if (status & 0x1) {
+				u8 id = (i * 32) + j;
+				ret |= periph_interrupt(pmic_arb, id);
+			}
+		}
+	}
+
+	return ret;
+}
+
+/* Callback to register an APID for specific slave/peripheral */
+static int pmic_arb_intr_priv_data(struct spmi_controller *ctrl,
+				struct qpnp_irq_spec *spec, uint32_t *data)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	u16 ppid = ((spec->slave & 0x0F) << 8) | (spec->per & 0xFF);
+	*data = map_peripheral_id(pmic_arb, ppid);
+	return 0;
+}
+
+static int __devinit
+spmi_pmic_arb_get_property(struct platform_device *pdev, char *pname, u32 *prop)
+{
+	int ret = of_property_read_u32(pdev->dev.of_node, pname, prop);
+
+	if (ret)
+		dev_err(&pdev->dev, "missing property: %s\n", pname);
+	else
+		pr_debug("%s = 0x%x\n", pname, *prop);
+
+	return ret;
+}
+
+static int __devinit spmi_pmic_arb_get_map_data(struct platform_device *pdev,
+					struct spmi_pmic_arb_dev *pmic_arb)
+{
+	int i;
+	int ret;
+	int map_size;
+	u32 *map_data;
+	const int map_width = 2 * sizeof(*map_data);
+	const struct device_node *of_node = pdev->dev.of_node;
+
+	/* Get size of the mapping table (in bytes) */
+	if (!of_get_property(of_node, "qcom,pmic-arb-ppid-map", &map_size)) {
+		dev_err(&pdev->dev, "missing ppid mapping table\n");
+		return -ENODEV;
+	}
+
+	/* Map size can't exceed the maximum number of peripherals */
+	if (map_size == 0 || map_size % map_width ||
+				map_size > map_width * PMIC_ARB_MAX_PERIPHS) {
+		dev_err(&pdev->dev, "map size of %d is not valid\n", map_size);
+		return -ENODEV;
+	}
+
+	map_data = kzalloc(map_size, GFP_KERNEL);
+	if (!map_data) {
+		dev_err(&pdev->dev, "can not allocate map data\n");
+		return -ENOMEM;
+	}
+
+	ret = of_property_read_u32_array(of_node,
+		"qcom,pmic-arb-ppid-map", map_data, map_size/sizeof(u32));
+	if (ret) {
+		dev_err(&pdev->dev, "invalid or missing property: ppid-map\n");
+		goto err;
+	};
+
+	pmic_arb->max_apid = 0;
+	pmic_arb->min_apid = PMIC_ARB_MAX_PERIPHS - 1;
+
+	/* Build the mapping table from the data */
+	for (i = 0; i < map_size/sizeof(u32);) {
+		u32 ppid = map_data[i++];
+		u32 apid = map_data[i++];
+
+		if (apid > PMIC_ARB_APID_MASK) {
+			ret = -ENODEV;
+			dev_err(&pdev->dev, "invalid APID: 0x%x\n", apid);
+			goto err;
+		}
+
+		if (ppid > PMIC_ARB_PPID_MASK) {
+			ret = -ENODEV;
+			dev_err(&pdev->dev, "invalid PPID: 0x%x\n", ppid);
+			goto err;
+		}
+
+		if (pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID)
+			dev_warn(&pdev->dev, "duplicate APID 0x%x\n", apid);
+
+		pmic_arb->periph_id_map[apid] = ppid | PMIC_ARB_PERIPH_ID_VALID;
+
+		if (apid > pmic_arb->max_apid)
+			pmic_arb->max_apid = apid;
+
+		if (apid < pmic_arb->min_apid)
+			pmic_arb->min_apid = apid;
+	}
+
+	pr_debug("%d value(s) mapped, min:%d, max:%d\n",
+		map_size/map_width, pmic_arb->min_apid, pmic_arb->max_apid);
+
+err:
+	kfree(map_data);
+	return ret;
+}
+
+static struct qpnp_local_int spmi_pmic_arb_intr_cb = {
+	.mask = pmic_arb_pic_disable,
+	.unmask = pmic_arb_pic_enable,
+	.register_priv_data = pmic_arb_intr_priv_data,
+};
+
+static int __devinit spmi_pmic_arb_probe(struct platform_device *pdev)
+{
+	struct spmi_pmic_arb_dev *pmic_arb;
+	struct resource *mem_res;
+	u32 cell_index;
+	u32 prop;
+	int ret = 0;
+
+	pr_debug("SPMI PMIC Arbiter\n");
+
+	pmic_arb = devm_kzalloc(&pdev->dev,
+				sizeof(struct spmi_pmic_arb_dev), GFP_KERNEL);
+	if (!pmic_arb) {
+		dev_err(&pdev->dev, "can not allocate pmic_arb data\n");
+		return -ENOMEM;
+	}
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res) {
+		dev_err(&pdev->dev, "missing base memory resource\n");
+		return -ENODEV;
+	}
+
+	pmic_arb->base = devm_ioremap(&pdev->dev,
+					mem_res->start, resource_size(mem_res));
+	if (!pmic_arb->base) {
+		dev_err(&pdev->dev, "ioremap of 'base' failed\n");
+		return -ENOMEM;
+	}
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mem_res) {
+		dev_err(&pdev->dev, "missing mem resource (interrupts)\n");
+		return -ENODEV;
+	}
+
+	pmic_arb->intr = devm_ioremap(&pdev->dev,
+					mem_res->start, resource_size(mem_res));
+	if (!pmic_arb->intr) {
+		dev_err(&pdev->dev, "ioremap of 'intr' failed\n");
+		return -ENOMEM;
+	}
+
+	pmic_arb->pic_irq = platform_get_irq(pdev, 0);
+	if (!pmic_arb->pic_irq) {
+		dev_err(&pdev->dev, "missing IRQ resource\n");
+		return -ENODEV;
+	}
+
+	ret = devm_request_irq(&pdev->dev, pmic_arb->pic_irq,
+		pmic_arb_periph_irq, IRQF_TRIGGER_HIGH, pdev->name, pmic_arb);
+	if (ret) {
+		dev_err(&pdev->dev, "request IRQ failed\n");
+		return ret;
+	}
+	disable_irq(pmic_arb->pic_irq);
+
+	/* Get properties from the device tree */
+	ret = spmi_pmic_arb_get_property(pdev, "cell-index", &cell_index);
+	if (ret)
+		return -ENODEV;
+
+	ret = spmi_pmic_arb_get_map_data(pdev, pmic_arb);
+	if (ret)
+		return ret;
+
+	ret = spmi_pmic_arb_get_property(pdev, "qcom,pmic-arb-ee", &prop);
+	if (ret)
+		return -ENODEV;
+	pmic_arb->owner = (u8)prop;
+
+	ret = spmi_pmic_arb_get_property(pdev, "qcom,pmic-arb-channel", &prop);
+	if (ret)
+		return -ENODEV;
+	pmic_arb->channel = (u8)prop;
+
+	pmic_arb->dev = &pdev->dev;
+	platform_set_drvdata(pdev, pmic_arb);
+	spmi_set_ctrldata(&pmic_arb->controller, pmic_arb);
+
+	spin_lock_init(&pmic_arb->lock);
+
+	pmic_arb->controller.nr = cell_index;
+	pmic_arb->controller.dev.parent = pdev->dev.parent;
+	pmic_arb->controller.dev.of_node = of_node_get(pdev->dev.of_node);
+
+	/* Callbacks */
+	pmic_arb->controller.cmd = pmic_arb_cmd;
+	pmic_arb->controller.read_cmd = pmic_arb_read_cmd;
+	pmic_arb->controller.write_cmd =  pmic_arb_write_cmd;
+
+	ret = spmi_add_controller(&pmic_arb->controller);
+	if (ret)
+		goto err_add_controller;
+
+	/* Register the interrupt enable/disable functions */
+	qpnpint_register_controller(cell_index, &spmi_pmic_arb_intr_cb);
+
+	/* Register device(s) from the device tree */
+	of_spmi_register_devices(&pmic_arb->controller);
+
+	pr_debug("PMIC Arb Version 0x%x\n",
+			pmic_arb_read(pmic_arb, PMIC_ARB_VERSION));
+
+	return 0;
+
+err_add_controller:
+	platform_set_drvdata(pdev, NULL);
+	return ret;
+}
+
+static int __devexit spmi_pmic_arb_remove(struct platform_device *pdev)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = platform_get_drvdata(pdev);
+
+	free_irq(pmic_arb->pic_irq, pmic_arb);
+	platform_set_drvdata(pdev, NULL);
+	spmi_del_controller(&pmic_arb->controller);
+	return 0;
+}
+
+static struct of_device_id spmi_pmic_arb_match_table[] = {
+	{	.compatible = "qcom,spmi-pmic-arb",
+	},
+	{}
+};
+
+static struct platform_driver spmi_pmic_arb_driver = {
+	.probe		= spmi_pmic_arb_probe,
+	.remove		= __exit_p(spmi_pmic_arb_remove),
+	.driver		= {
+		.name	= SPMI_PMIC_ARB_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = spmi_pmic_arb_match_table,
+	},
+};
+
+static int __init spmi_pmic_arb_init(void)
+{
+	return platform_driver_register(&spmi_pmic_arb_driver);
+}
+postcore_initcall(spmi_pmic_arb_init);
+
+static void __exit spmi_pmic_arb_exit(void)
+{
+	platform_driver_unregister(&spmi_pmic_arb_driver);
+}
+module_exit(spmi_pmic_arb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:spmi_pmic_arb");
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
new file mode 100644
index 0000000..2842cd8
--- /dev/null
+++ b/drivers/spmi/spmi.c
@@ -0,0 +1,789 @@
+/* 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spmi.h>
+
+struct spmii_boardinfo {
+	struct list_head	list;
+	struct spmi_boardinfo	board_info;
+};
+
+static DEFINE_MUTEX(board_lock);
+static LIST_HEAD(board_list);
+static LIST_HEAD(spmi_ctrl_list);
+static DEFINE_IDR(ctrl_idr);
+static struct device_type spmi_ctrl_type = { 0 };
+
+#define to_spmi(dev)	platform_get_drvdata(to_platform_device(dev))
+
+/* Forward declarations */
+struct bus_type spmi_bus_type;
+static int spmi_register_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_busnum_to_ctrl: Map bus number to controller
+ * @busnum: bus number
+ * Returns controller representing this bus number
+ */
+struct spmi_controller *spmi_busnum_to_ctrl(u32 bus_num)
+{
+	struct spmi_controller *ctrl;
+
+	mutex_lock(&board_lock);
+	list_for_each_entry(ctrl, &spmi_ctrl_list, list) {
+		if (bus_num == ctrl->nr) {
+			mutex_unlock(&board_lock);
+			return ctrl;
+		}
+	}
+	mutex_unlock(&board_lock);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(spmi_busnum_to_ctrl);
+
+/**
+ * spmi_add_controller: Controller bring-up.
+ * @ctrl: controller to be registered.
+ * A controller is registered with the framework using this API. ctrl->nr is the
+ * desired number with which SPMI framework registers the controller.
+ * Function will return -EBUSY if the number is in use.
+ */
+int spmi_add_controller(struct spmi_controller *ctrl)
+{
+	int	id;
+	int	status;
+
+	pr_debug("adding controller for bus %d (0x%p)\n", ctrl->nr, ctrl);
+
+	if (ctrl->nr & ~MAX_ID_MASK) {
+		pr_err("invalid bus identifier %d\n", ctrl->nr);
+		return -EINVAL;
+	}
+
+retry:
+	if (idr_pre_get(&ctrl_idr, GFP_KERNEL) == 0) {
+		pr_err("no free memory for idr\n");
+		return -ENOMEM;
+	}
+
+	mutex_lock(&board_lock);
+	status = idr_get_new_above(&ctrl_idr, ctrl, ctrl->nr, &id);
+	if (status == 0 && id != ctrl->nr) {
+		status = -EAGAIN;
+		idr_remove(&ctrl_idr, id);
+	}
+	mutex_unlock(&board_lock);
+	if (status == -EAGAIN)
+		goto retry;
+
+	if (status == 0)
+		status = spmi_register_controller(ctrl);
+	return status;
+}
+EXPORT_SYMBOL_GPL(spmi_add_controller);
+
+/**
+ * spmi_del_controller: Controller tear-down.
+ * @ctrl: controller to which this device is to be added to.
+ *
+ * Controller added with the above API is torn down using this API.
+ */
+int spmi_del_controller(struct spmi_controller *ctrl)
+{
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(spmi_del_controller);
+
+#define spmi_device_attr_gr NULL
+#define spmi_device_uevent NULL
+static void spmi_dev_release(struct device *dev)
+{
+	struct spmi_device *spmidev = to_spmi_device(dev);
+	kfree(spmidev);
+}
+
+static struct device_type spmi_dev_type = {
+	.groups		= spmi_device_attr_gr,
+	.uevent		= spmi_device_uevent,
+	.release	= spmi_dev_release,
+};
+
+/**
+ * spmi_alloc_device: Allocate a new SPMI devices.
+ * @ctrl: controller to which this device is to be added to.
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize a SPMI device without
+ * registering it immediately.  This allows a driver to directly fill
+ * the spmi_device structure before calling spmi_add_device().
+ *
+ * Caller is responsible to call spmi_add_device() on the returned
+ * spmi_device.  If the caller needs to discard the spmi_device without
+ * adding it, then spmi_dev_put() should be called.
+ */
+struct spmi_device *spmi_alloc_device(struct spmi_controller *ctrl)
+{
+	struct spmi_device *spmidev;
+
+	if (!ctrl) {
+		pr_err("Missing SPMI controller\n");
+		return NULL;
+	}
+
+	spmidev = kzalloc(sizeof(*spmidev), GFP_KERNEL);
+	if (!spmidev) {
+		dev_err(&ctrl->dev, "unable to allocate spmi_device\n");
+		return NULL;
+	}
+
+	spmidev->ctrl = ctrl;
+	spmidev->dev.parent = ctrl->dev.parent;
+	spmidev->dev.bus = &spmi_bus_type;
+	spmidev->dev.type = &spmi_dev_type;
+	device_initialize(&spmidev->dev);
+
+	return spmidev;
+}
+EXPORT_SYMBOL_GPL(spmi_alloc_device);
+
+/* Validate the SPMI device structure */
+static struct device *get_valid_device(struct spmi_device *spmidev)
+{
+	struct device *dev;
+
+	if (!spmidev)
+		return NULL;
+
+	dev = &spmidev->dev;
+	if (dev->bus != &spmi_bus_type || dev->type != &spmi_dev_type)
+		return NULL;
+
+	return dev;
+}
+
+/**
+ * spmi_add_device: Add a new device without register board info.
+ * @ctrl: controller to which this device is to be added to.
+ *
+ * Called when device doesn't have an explicit client-driver to be probed, or
+ * the client-driver is a module installed dynamically.
+ */
+int spmi_add_device(struct spmi_device *spmidev)
+{
+	int rc;
+	struct device *dev = get_valid_device(spmidev);
+
+	if (!dev) {
+		pr_err("%s: invalid SPMI device\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Set the device name */
+	dev_set_name(dev, "%s-%p", spmidev->name, spmidev);
+
+	/* Device may be bound to an active driver when this returns */
+	rc = device_add(dev);
+
+	if (rc < 0)
+		dev_err(dev, "Can't add %s, status %d\n", dev_name(dev), rc);
+	else
+		dev_dbg(dev, "device %s registered\n", dev_name(dev));
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(spmi_add_device);
+
+/**
+ * spmi_new_device: Instantiates a new SPMI device
+ * @ctrl: controller to which this device is to be added to.
+ * @info: board information for this device.
+ *
+ * Returns the new device or NULL.
+ */
+struct spmi_device *spmi_new_device(struct spmi_controller *ctrl,
+					struct spmi_boardinfo const *info)
+{
+	struct spmi_device *spmidev;
+	int rc;
+
+	if (!ctrl || !info)
+		return NULL;
+
+	spmidev = spmi_alloc_device(ctrl);
+	if (!spmidev)
+		return NULL;
+
+	spmidev->name = info->name;
+	spmidev->sid  = info->slave_id;
+	spmidev->dev.of_node = info->of_node;
+	spmidev->resource = info->resource;
+	spmidev->num_resources = info->num_resources;
+	spmidev->dev.platform_data = (void *)info->platform_data;
+
+	rc = spmi_add_device(spmidev);
+	if (rc < 0) {
+		spmi_dev_put(spmidev);
+		return NULL;
+	}
+
+	return spmidev;
+}
+EXPORT_SYMBOL_GPL(spmi_new_device);
+
+/* spmi_remove_device: Remove the effect of spmi_add_device() */
+void spmi_remove_device(struct spmi_device *spmi_dev)
+{
+	device_unregister(&spmi_dev->dev);
+}
+EXPORT_SYMBOL_GPL(spmi_remove_device);
+
+/* If controller is not present, only add to boards list */
+static void spmi_match_ctrl_to_boardinfo(struct spmi_controller *ctrl,
+				struct spmi_boardinfo *bi)
+{
+	struct spmi_device *spmidev;
+
+	spmidev = spmi_new_device(ctrl, bi);
+	if (!spmidev)
+		dev_err(ctrl->dev.parent, "can't create new device for %s\n",
+			bi->name);
+}
+
+/**
+ * spmi_register_board_info: Board-initialization routine.
+ * @bus_num: controller number (bus) on which this device will sit.
+ * @info: list of all devices on all controllers present on the board.
+ * @n: number of entries.
+ * API enumerates respective devices on corresponding controller.
+ * Called from board-init function.
+ */
+int spmi_register_board_info(int busnum,
+			struct spmi_boardinfo const *info, unsigned n)
+{
+	int i;
+	struct spmii_boardinfo *bi;
+
+	bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
+	if (!bi)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++, bi++, info++) {
+		struct spmi_controller *ctrl;
+
+		memcpy(&bi->board_info, info, sizeof(*info));
+		mutex_lock(&board_lock);
+		list_add_tail(&bi->list, &board_list);
+		list_for_each_entry(ctrl, &spmi_ctrl_list, list)
+			if (ctrl->nr == busnum)
+				spmi_match_ctrl_to_boardinfo(ctrl,
+							&bi->board_info);
+		mutex_unlock(&board_lock);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spmi_register_board_info);
+
+/* ------------------------------------------------------------------------- */
+
+static inline int
+spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid)
+{
+	BUG_ON(!ctrl || !ctrl->cmd);
+	return ctrl->cmd(ctrl, opcode, sid);
+}
+
+static inline int spmi_read_cmd(struct spmi_controller *ctrl,
+				u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+	BUG_ON(!ctrl || !ctrl->read_cmd);
+	return ctrl->read_cmd(ctrl, opcode, sid, addr, bc, buf);
+}
+
+static inline int spmi_write_cmd(struct spmi_controller *ctrl,
+				u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+	BUG_ON(!ctrl || !ctrl->write_cmd);
+	return ctrl->write_cmd(ctrl, opcode, sid, addr, bc, buf);
+}
+
+/*
+ * register read/write: 5-bit address, 1 byte of data
+ * extended register read/write: 8-bit address, up to 16 bytes of data
+ * extended register read/write long: 16-bit address, up to 8 bytes of data
+ */
+
+/**
+ * spmi_register_read() - register read
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads 1 byte of data from a Slave device register.
+ */
+int spmi_register_read(struct spmi_controller *ctrl, u8 sid, u8 addr, u8 *buf)
+{
+	/* 4-bit Slave Identifier, 5-bit register address */
+	if (sid > SPMI_MAX_SLAVE_ID || addr > 0x1F)
+		return -EINVAL;
+
+	return spmi_read_cmd(ctrl, SPMI_CMD_READ, sid, addr, 0, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_register_read);
+
+/**
+ * spmi_ext_register_read() - extended register read
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @len: the request number of bytes to read (up to 16 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 16 bytes of data from the extended register space on a
+ * Slave device.
+ */
+int spmi_ext_register_read(struct spmi_controller *ctrl,
+				u8 sid, u8 addr, u8 *buf, int len)
+{
+	/* 4-bit Slave Identifier, 8-bit register address, up to 16 bytes */
+	if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 16)
+		return -EINVAL;
+
+	return spmi_read_cmd(ctrl, SPMI_CMD_EXT_READ, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_read);
+
+/**
+ * spmi_ext_register_readl() - extended register read long
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @len: the request number of bytes to read (up to 8 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 8 bytes of data from the extended register space on a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_readl(struct spmi_controller *ctrl,
+				u8 sid, u16 addr, u8 *buf, int len)
+{
+	/* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */
+	if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 8)
+		return -EINVAL;
+
+	return spmi_read_cmd(ctrl, SPMI_CMD_EXT_READL, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_readl);
+
+/**
+ * spmi_register_write() - register write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ *
+ * Writes 1 byte of data to a Slave device register.
+ */
+int spmi_register_write(struct spmi_controller *ctrl, u8 sid, u8 addr, u8 *buf)
+{
+	u8 op = SPMI_CMD_WRITE;
+
+	/* 4-bit Slave Identifier, 5-bit register address */
+	if (sid > SPMI_MAX_SLAVE_ID || addr > 0x1F)
+		return -EINVAL;
+
+	return spmi_write_cmd(ctrl, op, sid, addr, 0, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_register_write);
+
+/**
+ * spmi_register_zero_write() - register zero write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @data: the data to be written to register 0 (7-bits).
+ *
+ * Writes data to register 0 of the Slave device.
+ */
+int spmi_register_zero_write(struct spmi_controller *ctrl, u8 sid, u8 data)
+{
+	u8 op = SPMI_CMD_ZERO_WRITE;
+
+	/* 4-bit Slave Identifier, 5-bit register address */
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+
+	return spmi_write_cmd(ctrl, op, sid, 0, 0, &data);
+}
+EXPORT_SYMBOL_GPL(spmi_register_zero_write);
+
+/**
+ * spmi_ext_register_write() - extended register write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 16 bytes).
+ *
+ * Writes up to 16 bytes of data to the extended register space of a
+ * Slave device.
+ */
+int spmi_ext_register_write(struct spmi_controller *ctrl,
+				u8 sid, u8 addr, u8 *buf, int len)
+{
+	u8 op = SPMI_CMD_EXT_WRITE;
+
+	/* 4-bit Slave Identifier, 8-bit register address, up to 16 bytes */
+	if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 16)
+		return -EINVAL;
+
+	return spmi_write_cmd(ctrl, op, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_write);
+
+/**
+ * spmi_ext_register_writel() - extended register write long
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 8 bytes).
+ *
+ * Writes up to 8 bytes of data to the extended register space of a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_writel(struct spmi_controller *ctrl,
+				u8 sid, u16 addr, u8 *buf, int len)
+{
+	u8 op = SPMI_CMD_EXT_WRITEL;
+
+	/* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */
+	if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 8)
+		return -EINVAL;
+
+	return spmi_write_cmd(ctrl, op, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_writel);
+
+/**
+ * spmi_command_reset() - sends RESET command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Reset command initializes the Slave and forces all registers to
+ * their reset values. The Slave shall enter the STARTUP state after
+ * receiving a Reset command.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_reset(struct spmi_controller *ctrl, u8 sid)
+{
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+	return spmi_cmd(ctrl, SPMI_CMD_RESET, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_reset);
+
+/**
+ * spmi_command_sleep() - sends SLEEP command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Sleep command causes the Slave to enter the user defined SLEEP state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_sleep(struct spmi_controller *ctrl, u8 sid)
+{
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+	return spmi_cmd(ctrl, SPMI_CMD_SLEEP, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_sleep);
+
+/**
+ * spmi_command_wakeup() - sends WAKEUP command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Wakeup command causes the Slave to move from the SLEEP state to
+ * the ACTIVE state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_wakeup(struct spmi_controller *ctrl, u8 sid)
+{
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+	return spmi_cmd(ctrl, SPMI_CMD_WAKEUP, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_wakeup);
+
+/**
+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Shutdown command causes the Slave to enter the SHUTDOWN state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_shutdown(struct spmi_controller *ctrl, u8 sid)
+{
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+	return spmi_cmd(ctrl, SPMI_CMD_SHUTDOWN, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_shutdown);
+
+/* ------------------------------------------------------------------------- */
+
+static const struct spmi_device_id *spmi_match(const struct spmi_device_id *id,
+		const struct spmi_device *spmi_dev)
+{
+	while (id->name[0]) {
+		if (strncmp(spmi_dev->name, id->name, SPMI_NAME_SIZE) == 0)
+			return id;
+		id++;
+	}
+	return NULL;
+}
+
+static int spmi_device_match(struct device *dev, struct device_driver *drv)
+{
+	struct spmi_device *spmi_dev;
+	struct spmi_driver *sdrv = to_spmi_driver(drv);
+
+	if (dev->type == &spmi_dev_type)
+		spmi_dev = to_spmi_device(dev);
+	else
+		return 0;
+
+	/* Attempt an OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	if (sdrv->id_table)
+		return spmi_match(sdrv->id_table, spmi_dev) != NULL;
+
+	if (drv->name)
+		return strncmp(spmi_dev->name, drv->name, SPMI_NAME_SIZE) == 0;
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int spmi_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct spmi_device *spmi_dev = NULL;
+	struct spmi_driver *driver;
+	if (dev->type == &spmi_dev_type)
+		spmi_dev = to_spmi_device(dev);
+
+	if (!spmi_dev || !dev->driver)
+		return 0;
+
+	driver = to_spmi_driver(dev->driver);
+	if (!driver->suspend)
+		return 0;
+
+	return driver->suspend(spmi_dev, mesg);
+}
+
+static int spmi_legacy_resume(struct device *dev)
+{
+	struct spmi_device *spmi_dev = NULL;
+	struct spmi_driver *driver;
+	if (dev->type == &spmi_dev_type)
+		spmi_dev = to_spmi_device(dev);
+
+	if (!spmi_dev || !dev->driver)
+		return 0;
+
+	driver = to_spmi_driver(dev->driver);
+	if (!driver->resume)
+		return 0;
+
+	return driver->resume(spmi_dev);
+}
+
+static int spmi_pm_suspend(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_suspend(dev);
+	else
+		return spmi_legacy_suspend(dev, PMSG_SUSPEND);
+}
+
+static int spmi_pm_resume(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_resume(dev);
+	else
+		return spmi_legacy_resume(dev);
+}
+
+#else
+#define spmi_pm_suspend		NULL
+#define spmi_pm_resume		NULL
+#endif
+
+static const struct dev_pm_ops spmi_pm_ops = {
+	.suspend = spmi_pm_suspend,
+	.resume = spmi_pm_resume,
+	SET_RUNTIME_PM_OPS(
+		pm_generic_suspend,
+		pm_generic_resume,
+		pm_generic_runtime_idle
+		)
+};
+struct bus_type spmi_bus_type = {
+	.name		= "spmi",
+	.match		= spmi_device_match,
+	.pm		= &spmi_pm_ops,
+};
+EXPORT_SYMBOL_GPL(spmi_bus_type);
+
+struct device spmi_dev = {
+	.init_name = "spmi",
+};
+
+static int spmi_drv_probe(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+	return sdrv->probe(to_spmi_device(dev));
+}
+
+static int spmi_drv_remove(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+	return sdrv->remove(to_spmi_device(dev));
+}
+
+static void spmi_drv_shutdown(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+	sdrv->shutdown(to_spmi_device(dev));
+}
+
+/**
+ * spmi_driver_register: Client driver registration with SPMI framework.
+ * @drv: client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the SPMI framework.
+ * It is called from the driver's module-init function.
+ */
+int spmi_driver_register(struct spmi_driver *drv)
+{
+	drv->driver.bus = &spmi_bus_type;
+
+	if (drv->probe)
+		drv->driver.probe = spmi_drv_probe;
+
+	if (drv->remove)
+		drv->driver.remove = spmi_drv_remove;
+
+	if (drv->shutdown)
+		drv->driver.shutdown = spmi_drv_shutdown;
+
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(spmi_driver_register);
+
+static int spmi_register_controller(struct spmi_controller *ctrl)
+{
+	int ret = 0;
+
+	/* Can't register until after driver model init */
+	if (WARN_ON(!spmi_bus_type.p)) {
+		ret = -EAGAIN;
+		goto exit;
+	}
+
+	dev_set_name(&ctrl->dev, "spmi-%d", ctrl->nr);
+	ctrl->dev.bus = &spmi_bus_type;
+	ctrl->dev.type = &spmi_ctrl_type;
+	ret = device_register(&ctrl->dev);
+	if (ret)
+		goto exit;
+
+	dev_dbg(&ctrl->dev, "Bus spmi-%d registered: dev:%x\n",
+					ctrl->nr, (u32)&ctrl->dev);
+
+	mutex_lock(&board_lock);
+	list_add_tail(&ctrl->list, &spmi_ctrl_list);
+	mutex_unlock(&board_lock);
+
+	return 0;
+
+exit:
+	mutex_lock(&board_lock);
+	idr_remove(&ctrl_idr, ctrl->nr);
+	mutex_unlock(&board_lock);
+	return ret;
+}
+
+static void __exit spmi_exit(void)
+{
+	device_unregister(&spmi_dev);
+	bus_unregister(&spmi_bus_type);
+}
+
+static int __init spmi_init(void)
+{
+	int retval;
+
+	retval = bus_register(&spmi_bus_type);
+	if (!retval)
+		retval = device_register(&spmi_dev);
+
+	if (retval)
+		bus_unregister(&spmi_bus_type);
+
+	return retval;
+}
+postcore_initcall(spmi_init);
+module_exit(spmi_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("SPMI module");
+MODULE_ALIAS("platform:spmi");
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
index d12c8e8..c900647 100644
--- a/drivers/staging/qcache/fmem.c
+++ b/drivers/staging/qcache/fmem.c
@@ -51,9 +51,11 @@
 {
 	struct fmem_platform_data *pdata = pdev->dev.platform_data;
 
-	fmem_data.phys = pdata->phys + pdata->reserved_size;
-	fmem_data.size = pdata->size - pdata->reserved_size;
-	fmem_data.reserved_size = pdata->reserved_size;
+	fmem_data.phys = pdata->phys + pdata->reserved_size_low;
+	fmem_data.size = pdata->size - pdata->reserved_size_low -
+					pdata->reserved_size_high;
+	fmem_data.reserved_size_low = pdata->reserved_size_low;
+	fmem_data.reserved_size_high = pdata->reserved_size_high;
 
 	if (!fmem_data.size)
 		return -ENODEV;
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index 2a2166a..c38b279 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/msm_tsens.h>
 #include <linux/io.h>
+#include <linux/err.h>
 
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
@@ -56,10 +57,12 @@
 #define SENSOR4_EN					BIT(7)
 #define SENSORS_EN			(SENSOR0_EN | SENSOR1_EN |	\
 					SENSOR2_EN | SENSOR3_EN | SENSOR4_EN)
-#define TSENS_MIN_STATUS_MASK				BIT(8)
-#define TSENS_LOWER_STATUS_CLR				BIT(9)
-#define TSENS_UPPER_STATUS_CLR				BIT(10)
-#define TSENS_MAX_STATUS_MASK				BIT(11)
+#define TSENS_STATUS_CNTL_OFFSET	8
+#define TSENS_MIN_STATUS_MASK		BIT((tsens_status_cntl_start))
+#define TSENS_LOWER_STATUS_CLR		BIT((tsens_status_cntl_start + 1))
+#define TSENS_UPPER_STATUS_CLR		BIT((tsens_status_cntl_start + 2))
+#define TSENS_MAX_STATUS_MASK		BIT((tsens_status_cntl_start + 3))
+
 #define TSENS_MEASURE_PERIOD				4 /* 1 sec. default */
 #define TSENS_8960_SLP_CLK_ENA				BIT(26)
 
@@ -86,6 +89,7 @@
 
 #define TSENS_S0_STATUS_ADDR			(MSM_CLK_CTL_BASE + 0x00003628)
 #define TSENS_STATUS_ADDR_OFFSET			2
+#define TSENS_SENSOR_STATUS_SIZE			4
 #define TSENS_INT_STATUS_ADDR			(MSM_CLK_CTL_BASE + 0x0000363c)
 
 #define TSENS_LOWER_INT_MASK				BIT(1)
@@ -113,6 +117,26 @@
 #define TSENS_8660_CONFIG_MASK			(3 << TSENS_8660_CONFIG_SHIFT)
 #define TSENS_8660_SLP_CLK_ENA				BIT(24)
 
+#define TSENS_8064_SENSOR5_EN				BIT(8)
+#define TSENS_8064_SENSOR6_EN				BIT(9)
+#define TSENS_8064_SENSOR7_EN				BIT(10)
+#define TSENS_8064_SENSOR8_EN				BIT(11)
+#define TSENS_8064_SENSOR9_EN				BIT(12)
+#define TSENS_8064_SENSOR10_EN				BIT(13)
+#define TSENS_8064_SENSORS_EN			(SENSORS_EN | \
+						TSENS_8064_SENSOR5_EN | \
+						TSENS_8064_SENSOR6_EN | \
+						TSENS_8064_SENSOR7_EN | \
+						TSENS_8064_SENSOR8_EN | \
+						TSENS_8064_SENSOR9_EN | \
+						TSENS_8064_SENSOR10_EN)
+#define TSENS_8064_STATUS_CNTL			(MSM_CLK_CTL_BASE + 0x00003660)
+#define TSENS_8064_S5_STATUS_ADDR		(MSM_CLK_CTL_BASE + 0x00003664)
+#define TSENS_8064_SEQ_SENSORS				5
+#define TSENS_8064_S4_S5_OFFSET				40
+
+static int tsens_status_cntl_start;
+
 struct tsens_tm_device_sensor {
 	struct thermal_zone_device	*tz_dev;
 	enum thermal_device_mode	mode;
@@ -121,11 +145,11 @@
 	int				offset;
 	int				calib_data;
 	int				calib_data_backup;
+	uint32_t			slope_mul_tsens_factor;
 };
 
 struct tsens_tm_device {
 	bool				prev_reading_avail;
-	int				slope_mul_tsens_factor;
 	int				tsens_factor;
 	uint32_t			tsens_num_sensor;
 	enum platform_type		hw_type;
@@ -137,26 +161,28 @@
 /* Temperature on y axis and ADC-code on x-axis */
 static int tsens_tz_code_to_degC(int adc_code, int sensor_num)
 {
-	int degC, degcbeforefactor;
-	degcbeforefactor = adc_code * tmdev->slope_mul_tsens_factor
-				+ tmdev->sensor[sensor_num].offset;
+	int degcbeforefactor, degc;
+	degcbeforefactor = (adc_code *
+			tmdev->sensor[sensor_num].slope_mul_tsens_factor
+			+ tmdev->sensor[sensor_num].offset);
+
 	if (degcbeforefactor == 0)
-		degC = degcbeforefactor;
+		degc = degcbeforefactor;
 	else if (degcbeforefactor > 0)
-		degC = (degcbeforefactor + tmdev->tsens_factor/2)
-						/ tmdev->tsens_factor;
-	else  /* rounding for negative degrees */
-		degC = (degcbeforefactor - tmdev->tsens_factor/2)
-						/ tmdev->tsens_factor;
-	return degC;
+		degc = (degcbeforefactor + tmdev->tsens_factor/2)
+				/ tmdev->tsens_factor;
+	else
+		degc = (degcbeforefactor - tmdev->tsens_factor/2)
+				/ tmdev->tsens_factor;
+	return degc;
 }
 
 static int tsens_tz_degC_to_code(int degC, int sensor_num)
 {
 	int code = (degC * tmdev->tsens_factor -
-			tmdev->sensor[sensor_num].offset
-			+ tmdev->slope_mul_tsens_factor/2)
-			/ tmdev->slope_mul_tsens_factor;
+		tmdev->sensor[sensor_num].offset
+		+ tmdev->sensor[sensor_num].slope_mul_tsens_factor/2)
+		/ tmdev->sensor[sensor_num].slope_mul_tsens_factor;
 
 	if (code > TSENS_THRESHOLD_MAX_CODE)
 		code = TSENS_THRESHOLD_MAX_CODE;
@@ -167,7 +193,7 @@
 
 static void tsens8960_get_temp(int sensor_num, unsigned long *temp)
 {
-	unsigned int code;
+	unsigned int code, offset = 0, sensor_addr;
 
 	if (!tmdev->prev_reading_avail) {
 		while (!(readl_relaxed(TSENS_INT_STATUS_ADDR)
@@ -176,7 +202,12 @@
 				TSENS_TRDY_RDY_MAX_TIME);
 		tmdev->prev_reading_avail = true;
 	}
-	code = readl_relaxed(TSENS_S0_STATUS_ADDR +
+
+	sensor_addr = (unsigned int)TSENS_S0_STATUS_ADDR;
+	if (tmdev->hw_type == APQ_8064 &&
+			sensor_num >= TSENS_8064_SEQ_SENSORS)
+		offset = TSENS_8064_S4_S5_OFFSET;
+	code = readl_relaxed(sensor_addr + offset +
 			(sensor_num << TSENS_STATUS_ADDR_OFFSET));
 	*temp = tsens_tz_code_to_degC(code, sensor_num);
 }
@@ -247,7 +278,8 @@
 			}
 			writel_relaxed(reg | TSENS_SW_RST, TSENS_CNTL_ADDR);
 			if (tmdev->hw_type == MSM_8960 ||
-						tmdev->hw_type == MSM_9615)
+				tmdev->hw_type == MSM_9615 ||
+				tmdev->hw_type == APQ_8064)
 				reg |= mask | TSENS_8960_SLP_CLK_ENA
 							| TSENS_EN;
 			else
@@ -257,7 +289,11 @@
 		} else {
 			reg &= ~mask;
 			if (!(reg & SENSOR0_EN)) {
-				if (tmdev->hw_type == MSM_8960 ||
+				if (tmdev->hw_type == APQ_8064)
+					reg &= ~(TSENS_8064_SENSORS_EN |
+						TSENS_8960_SLP_CLK_ENA |
+						TSENS_EN);
+				else if (tmdev->hw_type == MSM_8960 ||
 						tmdev->hw_type == MSM_9615)
 					reg &= ~(SENSORS_EN |
 						TSENS_8960_SLP_CLK_ENA |
@@ -319,7 +355,11 @@
 	lo_code = TSENS_THRESHOLD_MIN_CODE;
 	hi_code = TSENS_THRESHOLD_MAX_CODE;
 
-	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == APQ_8064)
+		reg_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+	else
+		reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+
 	reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR);
 	switch (trip) {
 	case TSENS_TRIP_STAGE3:
@@ -386,14 +426,21 @@
 		return -EINVAL;
 	}
 
-	if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
-		writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR);
-	else {
+	if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) {
+		if (tmdev->hw_type == APQ_8064)
+			writel_relaxed(reg_cntl | mask, TSENS_8064_STATUS_CNTL);
+		else
+			writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR);
+	} else {
 		if (code < lo_code || code > hi_code) {
 			pr_info("%s with invalid code %x\n", __func__, code);
 			return -EINVAL;
 		}
-		writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR);
+		if (tmdev->hw_type == APQ_8064)
+			writel_relaxed(reg_cntl & ~mask,
+					TSENS_8064_STATUS_CNTL);
+		else
+			writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR);
 	}
 	mb();
 	return 0;
@@ -465,7 +512,10 @@
 	lo_code = TSENS_THRESHOLD_MIN_CODE;
 	hi_code = TSENS_THRESHOLD_MAX_CODE;
 
-	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == APQ_8064)
+		reg_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+	else
+		reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
 	reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR);
 	switch (trip) {
 	case TSENS_TRIP_STAGE3:
@@ -561,25 +611,40 @@
 {
 	struct tsens_tm_device *tm = data;
 	unsigned int threshold, threshold_low, i, code, reg, sensor, mask;
+	unsigned int sensor_addr;
 	bool upper_th_x, lower_th_x;
 	int adc_code;
 
-	reg = readl_relaxed(TSENS_CNTL_ADDR);
-	writel_relaxed(reg | TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR,
-			TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == APQ_8064) {
+		reg = readl_relaxed(TSENS_8064_STATUS_CNTL);
+		writel_relaxed(reg | TSENS_LOWER_STATUS_CLR |
+			TSENS_UPPER_STATUS_CLR, TSENS_8064_STATUS_CNTL);
+	} else {
+		reg = readl_relaxed(TSENS_CNTL_ADDR);
+		writel_relaxed(reg | TSENS_LOWER_STATUS_CLR |
+			TSENS_UPPER_STATUS_CLR, TSENS_CNTL_ADDR);
+	}
 	mask = ~(TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR);
 	threshold = readl_relaxed(TSENS_THRESHOLD_ADDR);
 	threshold_low = (threshold & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
 					>> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
 	threshold = (threshold & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
 					>> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
-	reg = sensor = readl_relaxed(TSENS_CNTL_ADDR);
-	sensor &= (uint32_t) SENSORS_EN;
+	sensor = readl_relaxed(TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == APQ_8064) {
+		reg = readl_relaxed(TSENS_8064_STATUS_CNTL);
+		sensor &= (uint32_t) TSENS_8064_SENSORS_EN;
+	} else {
+		reg = sensor;
+		sensor &= (uint32_t) SENSORS_EN;
+	}
 	sensor >>= TSENS_SENSOR0_SHIFT;
+	sensor_addr = (unsigned int)TSENS_S0_STATUS_ADDR;
 	for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+		if (i == TSENS_8064_SEQ_SENSORS)
+			sensor_addr += TSENS_8064_S4_S5_OFFSET;
 		if (sensor & TSENS_MASK1) {
-			code = readl_relaxed(TSENS_S0_STATUS_ADDR +
-					(i << TSENS_STATUS_ADDR_OFFSET));
+			code = readl_relaxed(sensor_addr);
 			upper_th_x = code >= threshold;
 			lower_th_x = code <= threshold_low;
 			if (upper_th_x)
@@ -589,8 +654,7 @@
 			if (upper_th_x || lower_th_x) {
 				/* Notify user space */
 				schedule_work(&tm->sensor[i].work);
-				adc_code = readl_relaxed(TSENS_S0_STATUS_ADDR
-					+ (i << TSENS_STATUS_ADDR_OFFSET));
+				adc_code = readl_relaxed(sensor_addr);
 				pr_info("\nTrip point triggered by "
 					"current temperature (%d degrees) "
 					"measured by Temperature-Sensor %d\n",
@@ -598,18 +662,37 @@
 			}
 		}
 		sensor >>= 1;
+		sensor_addr += TSENS_SENSOR_STATUS_SIZE;
 	}
+	if (tmdev->hw_type == APQ_8064)
+		writel_relaxed(reg & mask, TSENS_8064_STATUS_CNTL);
+	else
 	writel_relaxed(reg & mask, TSENS_CNTL_ADDR);
 	mb();
 	return IRQ_HANDLED;
 }
 
+static void tsens8960_sensor_mode_init(void)
+{
+	unsigned int reg_cntl = 0;
+
+	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+			tmdev->hw_type == APQ_8064) {
+		writel_relaxed(reg_cntl &
+				~((((1 << tmdev->tsens_num_sensor) - 1) >> 1)
+				<< (TSENS_SENSOR0_SHIFT + 1)), TSENS_CNTL_ADDR);
+		tmdev->sensor[TSENS_MAIN_SENSOR].mode = THERMAL_DEVICE_ENABLED;
+	}
+}
+
 static void tsens_disable_mode(void)
 {
 	unsigned int reg_cntl = 0;
 
 	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
-	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615)
+	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+			tmdev->hw_type == APQ_8064)
 		writel_relaxed(reg_cntl &
 				~((((1 << tmdev->tsens_num_sensor) - 1) <<
 				TSENS_SENSOR0_SHIFT) | TSENS_8960_SLP_CLK_ENA
@@ -624,6 +707,7 @@
 static void tsens_hw_init(void)
 {
 	unsigned int reg_cntl = 0, reg_cfg = 0, reg_thr = 0;
+	unsigned int reg_status_cntl = 0;
 
 	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
 	writel_relaxed(reg_cntl | TSENS_SW_RST, TSENS_CNTL_ADDR);
@@ -657,6 +741,25 @@
 				(TSENS_8660_CONFIG << TSENS_8660_CONFIG_SHIFT);
 
 		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+	} else if (tmdev->hw_type == APQ_8064) {
+		reg_cntl |= TSENS_8960_SLP_CLK_ENA |
+			(TSENS_MEASURE_PERIOD << 18) |
+			(((1 << tmdev->tsens_num_sensor) - 1) <<
+			 TSENS_SENSOR0_SHIFT);
+		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+		reg_status_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+		reg_status_cntl |= TSENS_LOWER_STATUS_CLR |
+			TSENS_UPPER_STATUS_CLR |
+			TSENS_MIN_STATUS_MASK |
+			TSENS_MAX_STATUS_MASK;
+		writel_relaxed(reg_status_cntl, TSENS_8064_STATUS_CNTL);
+		reg_cntl |= TSENS_EN;
+		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+
+		reg_cfg = readl_relaxed(TSENS_8960_CONFIG_ADDR);
+		reg_cfg = (reg_cfg & ~TSENS_8960_CONFIG_MASK) |
+			(TSENS_8960_CONFIG << TSENS_8960_CONFIG_SHIFT);
+		writel_relaxed(reg_cfg, TSENS_8960_CONFIG_ADDR);
 	}
 
 	reg_thr |= (TSENS_LOWER_LIMIT_TH << TSENS_THRESHOLD_LOWER_LIMIT_SHIFT) |
@@ -692,8 +795,10 @@
 	}
 
 	tmdev->sensor[TSENS_MAIN_SENSOR].offset = tmdev->tsens_factor *
-		TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor *
+		TSENS_CAL_DEGC -
+		tmdev->sensor[TSENS_MAIN_SENSOR].slope_mul_tsens_factor *
 		tmdev->sensor[TSENS_MAIN_SENSOR].calib_data;
+
 	tmdev->prev_reading_avail = false;
 	INIT_WORK(&tmdev->sensor[TSENS_MAIN_SENSOR].work,
 						notify_uspace_tsens_fn);
@@ -703,35 +808,27 @@
 
 static int tsens_calib_sensors8960(void)
 {
-	uint32_t *main_sensor_addr, sensor_shift, *backup_sensor_addr;
-	uint32_t sensor_mask, i;
+	uint32_t i;
+	uint8_t *main_sensor_addr, *backup_sensor_addr;
 	for (i = 0; i < tmdev->tsens_num_sensor; i++) {
-		main_sensor_addr = TSENS_8960_QFPROM_ADDR0 +
-			(TSENS_8960_QFPROM_SHIFT *
-		((i & TSENS_8960_QFPROM_SHIFT) >> TSENS_SENSOR_QFPROM_SHIFT));
-		sensor_shift = (i % TSENS_8960_QFPROM_SHIFT) * TSENS_RED_SHIFT;
-		sensor_mask = TSENS_THRESHOLD_MAX_CODE << sensor_shift;
-		backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 +
-			(TSENS_8960_QFPROM_SHIFT *
-		((i & TSENS_8960_QFPROM_SHIFT) >> TSENS_SENSOR_QFPROM_SHIFT));
+		main_sensor_addr = TSENS_8960_QFPROM_ADDR0 + i;
+		backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 + i;
 
-		tmdev->sensor[i].calib_data = (readl_relaxed(main_sensor_addr)
-			& sensor_mask) >> sensor_shift;
+		tmdev->sensor[i].calib_data = readb_relaxed(main_sensor_addr);
 		tmdev->sensor[i].calib_data_backup =
-			(readl_relaxed(backup_sensor_addr) &
-				sensor_mask) >> sensor_shift;
+			readb_relaxed(backup_sensor_addr);
 		if (tmdev->sensor[i].calib_data_backup)
 			tmdev->sensor[i].calib_data =
 				tmdev->sensor[i].calib_data_backup;
-
 		if (!tmdev->sensor[i].calib_data) {
 			WARN(1, "%s: No temperature sensor:%d data for"
 			" calibration in QFPROM!\n", __func__, i);
 			return -ENODEV;
 		}
-		tmdev->sensor[i].offset = tmdev->tsens_factor *
-			TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor *
-			tmdev->sensor[i].calib_data;
+		tmdev->sensor[i].offset = (TSENS_CAL_DEGC *
+			tmdev->tsens_factor)
+			- (tmdev->sensor[i].calib_data *
+			tmdev->sensor[i].slope_mul_tsens_factor);
 		tmdev->prev_reading_avail = false;
 		INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
 	}
@@ -756,7 +853,8 @@
 
 	if (tmdev->hw_type == MSM_8660)
 		rc = tsens_calib_sensors8660();
-	else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615)
+	else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+		tmdev->hw_type == APQ_8064)
 		rc = tsens_calib_sensors8960();
 
 	return rc;
@@ -764,7 +862,7 @@
 
 int msm_tsens_early_init(struct tsens_platform_data *pdata)
 {
-	int rc = 0;
+	int rc = 0, i;
 
 	if (!pdata) {
 		pr_err("No TSENS Platform data\n");
@@ -780,7 +878,8 @@
 		return -ENOMEM;
 	}
 
-	tmdev->slope_mul_tsens_factor = pdata->slope;
+	for (i = 0; i < pdata->tsens_num_sensor; i++)
+		tmdev->sensor[i].slope_mul_tsens_factor = pdata->slope[i];
 	tmdev->tsens_factor = pdata->tsens_factor;
 	tmdev->tsens_num_sensor = pdata->tsens_num_sensor;
 	tmdev->hw_type = pdata->hw_type;
@@ -799,9 +898,14 @@
 		return rc;
 	}
 
+	if (tmdev->hw_type == APQ_8064)
+		tsens_status_cntl_start = 0;
+	else
+		tsens_status_cntl_start = TSENS_STATUS_CNTL_OFFSET;
+
 	tsens_hw_init();
 
-	pr_info("msm_tsens_early_init: done\n");
+	pr_debug("msm_tsens_early_init: done\n");
 
 	return rc;
 }
@@ -816,14 +920,14 @@
 	}
 
 	for (i = 0; i < tmdev->tsens_num_sensor; i++) {
-		char name[17];
+		char name[18];
 		snprintf(name, sizeof(name), "tsens_tz_sensor%d", i);
 		tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
 		tmdev->sensor[i].sensor_num = i;
 		tmdev->sensor[i].tz_dev = thermal_zone_device_register(name,
 				TSENS_TRIP_NUM, &tmdev->sensor[i],
 				&tsens_thermal_zone_ops, 0, 0, 0, 0);
-		if (tmdev->sensor[i].tz_dev == NULL) {
+		if (IS_ERR(tmdev->sensor[i].tz_dev)) {
 			pr_err("%s: thermal_zone_device_register() failed.\n",
 			__func__);
 			rc = -ENODEV;
@@ -832,6 +936,8 @@
 		tmdev->sensor[i].mode = THERMAL_DEVICE_DISABLED;
 	}
 
+	tsens8960_sensor_mode_init();
+
 	rc = request_irq(TSENS_UPPER_LOWER_INT, tsens_isr,
 		IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
 	if (rc < 0) {
@@ -841,7 +947,7 @@
 		goto fail;
 	}
 
-	pr_notice("%s: OK\n", __func__);
+	pr_debug("%s: OK\n", __func__);
 	mb();
 	return 0;
 fail:
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index ed80b1b..ef28844 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -51,10 +51,7 @@
 	cpu_policy->user_policy.max = max_freq;
 
 	ret = cpufreq_update_policy(cpu);
-	if (ret)
-		pr_err("msm_thermal: cpufreq update to core%d %d err:%d\n",
-				cpu, max_freq, ret);
-	else
+	if (!ret)
 		pr_info("msm_thermal: Limiting core%d max frequency to %d\n",
 			cpu, max_freq);
 
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 9e85eb5..32e9dc0 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -2,7 +2,7 @@
  * drivers/serial/msm_serial.c - driver for msm7k serial device and console
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Author: Robert Love <rlove@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -102,48 +102,32 @@
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr &= ~UART_IMR_TXLEV;
 	msm_write(port, msm_port->imr, UART_IMR);
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_start_tx(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr |= UART_IMR_TXLEV;
 	msm_write(port, msm_port->imr, UART_IMR);
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_stop_rx(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
 	msm_write(port, msm_port->imr, UART_IMR);
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_enable_ms(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr |= UART_IMR_DELTA_CTS;
 	msm_write(port, msm_port->imr, UART_IMR);
-
-	clk_disable(msm_port->clk);
 }
 
 #ifdef CONFIG_SERIAL_MSM_CLOCK_CONTROL
@@ -365,7 +349,6 @@
 	unsigned int misr;
 
 	spin_lock_irqsave(&port->lock, flags);
-	clk_enable(msm_port->clk);
 	misr = msm_read(port, UART_MISR);
 	msm_write(port, 0, UART_IMR); /* disable interrupt */
 
@@ -377,7 +360,6 @@
 		handle_delta_cts(port);
 
 	msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */
-	clk_disable(msm_port->clk);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	return IRQ_HANDLED;
@@ -386,12 +368,8 @@
 static unsigned int msm_tx_empty(struct uart_port *port)
 {
 	unsigned int ret;
-	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
 	ret = (msm_read(port, UART_SR) & UART_SR_TX_EMPTY) ? TIOCSER_TEMT : 0;
-	clk_disable(msm_port->clk);
-
 	return ret;
 }
 
@@ -403,9 +381,6 @@
 static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	unsigned int mr;
-	struct msm_port *msm_port = UART_TO_MSM(port);
-
-	clk_enable(msm_port->clk);
 
 	mr = msm_read(port, UART_MR1);
 
@@ -417,22 +392,14 @@
 		mr |= UART_MR1_RX_RDY_CTL;
 		msm_write(port, mr, UART_MR1);
 	}
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_break_ctl(struct uart_port *port, int break_ctl)
 {
-	struct msm_port *msm_port = UART_TO_MSM(port);
-
-	clk_enable(msm_port->clk);
-
 	if (break_ctl)
 		msm_write(port, UART_CR_CMD_START_BREAK, UART_CR);
 	else
 		msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR);
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_set_baud_rate(struct uart_port *port, unsigned int baud)
@@ -520,9 +487,14 @@
 
 static void msm_init_clock(struct uart_port *port)
 {
+	int ret;
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
+	ret = clk_prepare_enable(msm_port->clk);
+	if (ret) {
+		pr_err("%s(): Can't enable uartclk. ret:%d\n", __func__, ret);
+		return;
+	}
 
 #ifdef CONFIG_SERIAL_MSM_CLOCK_CONTROL
 	msm_port->clk_state = MSM_CLK_ON;
@@ -552,7 +524,7 @@
 		clk_disable(msm_port->clk);
 	msm_port->clk_state = MSM_CLK_PORT_OFF;
 #else
-	clk_disable(msm_port->clk);
+	clk_disable_unprepare(msm_port->clk);
 #endif
 
 }
@@ -631,13 +603,9 @@
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr = 0;
 	msm_write(port, 0, UART_IMR); /* disable interrupts */
 
-	clk_disable(msm_port->clk);
-
 	free_irq(port->irq, port);
 
 #ifdef CONFIG_SERIAL_MSM_RX_WAKEUP
@@ -657,10 +625,8 @@
 {
 	unsigned long flags;
 	unsigned int baud, mr;
-	struct msm_port *msm_port = UART_TO_MSM(port);
 
 	spin_lock_irqsave(&port->lock, flags);
-	clk_enable(msm_port->clk);
 
 	/* calculate and set baud rate */
 	baud = uart_get_baud_rate(port, termios, old, 300, 115200);
@@ -723,8 +689,6 @@
 		port->read_status_mask |= UART_SR_RX_BREAK;
 
 	uart_update_timeout(port, termios->c_cflag, baud);
-
-	clk_disable(msm_port->clk);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -792,20 +756,23 @@
 static void msm_power(struct uart_port *port, unsigned int state,
 		      unsigned int oldstate)
 {
-#ifndef CONFIG_SERIAL_MSM_CLOCK_CONTROL
+	int ret;
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
 	switch (state) {
 	case 0:
-		clk_enable(msm_port->clk);
+		ret = clk_prepare_enable(msm_port->clk);
+		if (ret)
+			pr_err("msm_serial: %s(): Can't enable uartclk.\n",
+						__func__);
 		break;
 	case 3:
-		clk_disable(msm_port->clk);
+		clk_disable_unprepare(msm_port->clk);
 		break;
 	default:
-		printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state);
+		pr_err("msm_serial: %s(): Unknown PM state %d\n",
+						__func__, state);
 	}
-#endif
 }
 
 static struct uart_ops msm_uart_pops = {
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index c893889..8ea4632 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -47,7 +47,6 @@
 	.flags			= CI13XXX_REGS_SHARED |
 				  CI13XXX_REQUIRE_TRANSCEIVER |
 				  CI13XXX_PULLUP_ON_VBUS |
-				  CI13XXX_DISABLE_STREAMING |
 				  CI13XXX_ZERO_ITC,
 
 	.notify_event		= ci13xxx_msm_notify_event,
diff --git a/drivers/usb/gadget/u_data_hsic.c b/drivers/usb/gadget/u_data_hsic.c
index 7b77a1d..818e2a6 100644
--- a/drivers/usb/gadget/u_data_hsic.c
+++ b/drivers/usb/gadget/u_data_hsic.c
@@ -85,8 +85,7 @@
 	unsigned		port_num;
 
 	/* gadget */
-	spinlock_t		port_lock;
-	void			*port_usb;
+	atomic_t		connected;
 	struct usb_ep		*in;
 	struct usb_ep		*out;
 
@@ -96,10 +95,12 @@
 	unsigned int		tx_q_size;
 	struct list_head	tx_idle;
 	struct sk_buff_head	tx_skb_q;
+	spinlock_t		tx_lock;
 
 	unsigned int		rx_q_size;
 	struct list_head	rx_idle;
 	struct sk_buff_head	rx_skb_q;
+	spinlock_t		rx_lock;
 
 	/* work */
 	struct workqueue_struct	*wq;
@@ -175,17 +176,16 @@
 	struct gdata_port	*port = ctx;
 	unsigned long		flags;
 
-	if (!port)
+	if (!port || !atomic_read(&port->connected))
 		return;
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb) {
-		port->tx_unthrottled_cnt++;
-		queue_work(port->wq, &port->write_tomdm_w);
-		pr_debug("%s: port num =%d unthrottled\n", __func__,
-			port->port_num);
-	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_lock_irqsave(&port->rx_lock, flags);
+	port->tx_unthrottled_cnt++;
+	spin_unlock_irqrestore(&port->rx_lock, flags);
+
+	queue_work(port->wq, &port->write_tomdm_w);
+	pr_debug("%s: port num =%d unthrottled\n", __func__,
+		port->port_num);
 }
 
 static void ghsic_data_write_tohost(struct work_struct *w)
@@ -200,14 +200,16 @@
 
 	port = container_of(w, struct gdata_port, write_tohost_w);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+	if (!port)
+		return;
+
+	spin_lock_irqsave(&port->tx_lock, flags);
+	ep = port->in;
+	if (!ep) {
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		return;
 	}
 
-	ep = port->in;
-
 	while (!list_empty(&port->tx_idle)) {
 		skb = __skb_dequeue(&port->tx_skb_q);
 		if (!skb)
@@ -231,9 +233,9 @@
 
 		info = (struct timestamp_info *)skb->cb;
 		info->tx_queued = get_timestamp();
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		ret = usb_ep_queue(ep, req, GFP_KERNEL);
-		spin_lock_irqsave(&port->port_lock, flags);
+		spin_lock_irqsave(&port->tx_lock, flags);
 		if (ret) {
 			pr_err("%s: usb epIn failed\n", __func__);
 			list_add(&req->list, &port->tx_idle);
@@ -252,7 +254,7 @@
 			data_bridge_unthrottle_rx(port->brdg.ch_id);
 		}
 	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
 }
 
 static int ghsic_data_receive(void *p, void *data, size_t len)
@@ -261,21 +263,15 @@
 	unsigned long		flags;
 	struct sk_buff		*skb = data;
 
-	if (!port) {
+	if (!port || !atomic_read(&port->connected)) {
 		dev_kfree_skb_any(skb);
-		return -EINVAL;
+		return -ENOTCONN;
 	}
 
 	pr_debug("%s: p:%p#%d skb_len:%d\n", __func__,
 			port, port->port_num, skb->len);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		dev_kfree_skb_any(skb);
-		return -ENOTCONN;
-	}
-
+	spin_lock_irqsave(&port->tx_lock, flags);
 	__skb_queue_tail(&port->tx_skb_q, skb);
 
 	if (ghsic_data_fctrl_support &&
@@ -284,12 +280,12 @@
 		port->rx_throttled_cnt++;
 		pr_debug_ratelimited("%s: flow ctrl enabled: tx skbq len: %u\n",
 					__func__, port->tx_skb_q.qlen);
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		queue_work(port->wq, &port->write_tohost_w);
 		return -EBUSY;
 	}
 
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
 
 	queue_work(port->wq, &port->write_tohost_w);
 
@@ -306,14 +302,12 @@
 
 	port = container_of(w, struct gdata_port, write_tomdm_w);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+	if (!port || !atomic_read(&port->connected))
 		return;
-	}
 
+	spin_lock_irqsave(&port->rx_lock, flags);
 	if (test_bit(TX_THROTTLED, &port->brdg.flags)) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		goto start_rx;
 	}
 
@@ -323,9 +317,9 @@
 
 		info = (struct timestamp_info *)skb->cb;
 		info->rx_done_sent = get_timestamp();
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		ret = data_bridge_write(port->brdg.ch_id, skb);
-		spin_lock_irqsave(&port->port_lock, flags);
+		spin_lock_irqsave(&port->rx_lock, flags);
 		if (ret < 0) {
 			if (ret == -EBUSY) {
 				/*flow control*/
@@ -340,7 +334,7 @@
 		}
 		port->to_modem++;
 	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 start_rx:
 	ghsic_data_start_rx(port);
 }
@@ -370,9 +364,9 @@
 
 	dev_kfree_skb_any(skb);
 
-	spin_lock(&port->port_lock);
+	spin_lock(&port->tx_lock);
 	list_add_tail(&req->list, &port->tx_idle);
-	spin_unlock(&port->port_lock);
+	spin_unlock(&port->tx_lock);
 
 	queue_work(port->wq, &port->write_tohost_w);
 }
@@ -406,14 +400,14 @@
 		break;
 	}
 
-	spin_lock(&port->port_lock);
+	spin_lock(&port->rx_lock);
 	if (queue) {
 		info->rx_done = get_timestamp();
 		__skb_queue_tail(&port->rx_skb_q, skb);
 		list_add_tail(&req->list, &port->rx_idle);
 		queue_work(port->wq, &port->write_tomdm_w);
 	}
-	spin_unlock(&port->port_lock);
+	spin_unlock(&port->rx_lock);
 }
 
 static void ghsic_data_start_rx(struct gdata_port *port)
@@ -427,15 +421,17 @@
 	unsigned int		created;
 
 	pr_debug("%s: port:%p\n", __func__, port);
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+	if (!port)
+		return;
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	ep = port->out;
+	if (!ep) {
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		return;
 	}
 
-	ep = port->out;
-
-	while (port->port_usb && !list_empty(&port->rx_idle)) {
+	while (atomic_read(&port->connected) && !list_empty(&port->rx_idle)) {
 		if (port->rx_skb_q.qlen > ghsic_data_pend_limit_with_bridge)
 			break;
 
@@ -454,22 +450,22 @@
 		req->context = skb;
 
 		info->rx_queued = get_timestamp();
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		ret = usb_ep_queue(ep, req, GFP_KERNEL);
-		spin_lock_irqsave(&port->port_lock, flags);
+		spin_lock_irqsave(&port->rx_lock, flags);
 		if (ret) {
 			dev_kfree_skb_any(skb);
 
 			pr_err_ratelimited("%s: rx queue failed\n", __func__);
 
-			if (port->port_usb)
+			if (atomic_read(&port->connected))
 				list_add(&req->list, &port->rx_idle);
 			else
 				usb_ep_free_request(ep, req);
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 }
 
 static void ghsic_data_start_io(struct gdata_port *port)
@@ -480,32 +476,41 @@
 
 	pr_debug("%s: port:%p\n", __func__, port);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+	if (!port)
+		return;
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	ep = port->out;
+	if (!ep) {
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		return;
 	}
 
-	ep = port->out;
 	ret = ghsic_data_alloc_requests(ep, &port->rx_idle,
 		port->rx_q_size, ghsic_data_epout_complete, GFP_ATOMIC);
 	if (ret) {
 		pr_err("%s: rx req allocation failed\n", __func__);
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&port->rx_lock, flags);
+
+	spin_lock_irqsave(&port->tx_lock, flags);
+	ep = port->in;
+	if (!ep) {
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		return;
 	}
 
-	ep = port->in;
 	ret = ghsic_data_alloc_requests(ep, &port->tx_idle,
 		port->tx_q_size, ghsic_data_epin_complete, GFP_ATOMIC);
 	if (ret) {
 		pr_err("%s: tx req allocation failed\n", __func__);
 		ghsic_data_free_requests(ep, &port->rx_idle);
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		return;
 	}
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
 
 	/* queue out requests */
 	ghsic_data_start_rx(port);
@@ -517,7 +522,8 @@
 		container_of(w, struct gdata_port, connect_w);
 	int			ret;
 
-	if (!port || !test_bit(CH_READY, &port->bridge_sts))
+	if (!port || !atomic_read(&port->connected) ||
+		!test_bit(CH_READY, &port->bridge_sts))
 		return;
 
 	pr_debug("%s: port:%p\n", __func__, port);
@@ -551,28 +557,37 @@
 	struct sk_buff	*skb;
 	unsigned long	flags;
 
-	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port)
+		return;
 
-	if (!port || !port->port_usb)
-		goto free_buf_out;
+	spin_lock_irqsave(&port->tx_lock, flags);
+	if (!port->in) {
+		spin_unlock_irqrestore(&port->tx_lock, flags);
+		return;
+	}
 
 	ghsic_data_free_requests(port->in, &port->tx_idle);
-	ghsic_data_free_requests(port->out, &port->rx_idle);
 
 	while ((skb = __skb_dequeue(&port->tx_skb_q)))
 		dev_kfree_skb_any(skb);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	if (!port->out) {
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+		return;
+	}
+
+	ghsic_data_free_requests(port->out, &port->rx_idle);
 
 	while ((skb = __skb_dequeue(&port->rx_skb_q)))
 		dev_kfree_skb_any(skb);
-
-free_buf_out:
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 }
 
 static int ghsic_data_probe(struct platform_device *pdev)
 {
 	struct gdata_port *port;
-	unsigned long flags;
 
 	pr_debug("%s: name:%s no_data_ports= %d\n",
 		__func__, pdev->name, no_data_ports);
@@ -585,11 +600,9 @@
 	port = gdata_ports[pdev->id].port;
 	set_bit(CH_READY, &port->bridge_sts);
 
-	spin_lock_irqsave(&port->port_lock, flags);
 	/* if usb is online, try opening bridge */
-	if (port->port_usb)
+	if (atomic_read(&port->connected))
 		queue_work(port->wq, &port->connect_w);
-	spin_unlock_irqrestore(&port->port_lock, flags);
 
 	return 0;
 }
@@ -598,9 +611,8 @@
 static int ghsic_data_remove(struct platform_device *pdev)
 {
 	struct gdata_port *port;
-	struct usb_ep *ep_in = NULL;
-	struct usb_ep *ep_out = NULL;
-	unsigned long flags;
+	struct usb_ep	*ep_in;
+	struct usb_ep	*ep_out;
 
 	pr_debug("%s: name:%s\n", __func__, pdev->name);
 
@@ -611,15 +623,11 @@
 
 	port = gdata_ports[pdev->id].port;
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb) {
-		ep_in = port->in;
-		ep_out = port->out;
-	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
+	ep_in = port->in;
 	if (ep_in)
 		usb_ep_fifo_flush(ep_in);
+
+	ep_out = port->out;
 	if (ep_out)
 		usb_ep_fifo_flush(ep_out);
 
@@ -663,7 +671,8 @@
 	port->port_num = port_num;
 
 	/* port initialization */
-	spin_lock_init(&port->port_lock);
+	spin_lock_init(&port->rx_lock);
+	spin_lock_init(&port->tx_lock);
 
 	INIT_WORK(&port->connect_w, ghsic_data_connect_w);
 	INIT_WORK(&port->disconnect_w, ghsic_data_disconnect_w);
@@ -724,14 +733,18 @@
 	if (port->out)
 		usb_ep_disable(port->in);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	port->port_usb = 0;
+	atomic_set(&port->connected, 0);
+
+	spin_lock_irqsave(&port->tx_lock, flags);
 	port->in = NULL;
-	port->out = NULL;
 	port->n_tx_req_queued = 0;
-	clear_bit(TX_THROTTLED, &port->brdg.flags);
 	clear_bit(RX_THROTTLED, &port->brdg.flags);
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	port->out = NULL;
+	clear_bit(TX_THROTTLED, &port->brdg.flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 
 	queue_work(port->wq, &port->disconnect_w);
 }
@@ -762,8 +775,15 @@
 
 	if (port->gtype == USB_GADGET_SERIAL) {
 		gser = gptr;
+
+		spin_lock_irqsave(&port->tx_lock, flags);
 		port->in = gser->in;
+		spin_unlock_irqrestore(&port->tx_lock, flags);
+
+		spin_lock_irqsave(&port->rx_lock, flags);
 		port->out = gser->out;
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+
 		port->tx_q_size = ghsic_data_serial_tx_q_size;
 		port->rx_q_size = ghsic_data_serial_rx_q_size;
 		gser->in->driver_data = port;
@@ -772,8 +792,15 @@
 		out_desc = gser->out_desc;
 	} else {
 		gr = gptr;
+
+		spin_lock_irqsave(&port->tx_lock, flags);
 		port->in = gr->in;
+		spin_unlock_irqrestore(&port->tx_lock, flags);
+
+		spin_lock_irqsave(&port->rx_lock, flags);
 		port->out = gr->out;
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+
 		port->tx_q_size = ghsic_data_rmnet_tx_q_size;
 		port->rx_q_size = ghsic_data_rmnet_rx_q_size;
 		gr->in->driver_data = port;
@@ -796,17 +823,22 @@
 		usb_ep_disable(port->in);
 		goto fail;
 	}
-	spin_lock_irqsave(&port->port_lock, flags);
-	port->port_usb = gptr;
+
+	atomic_set(&port->connected, 1);
+
+	spin_lock_irqsave(&port->tx_lock, flags);
 	port->to_host = 0;
-	port->to_modem = 0;
-	port->tomodem_drp_cnt = 0;
 	port->rx_throttled_cnt = 0;
 	port->rx_unthrottled_cnt = 0;
+	port->unthrottled_pnd_skbs = 0;
+	spin_unlock_irqrestore(&port->tx_lock, flags);
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	port->to_modem = 0;
+	port->tomodem_drp_cnt = 0;
 	port->tx_throttled_cnt = 0;
 	port->tx_unthrottled_cnt = 0;
-	port->unthrottled_pnd_skbs = 0;
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 
 	queue_work(port->wq, &port->connect_w);
 fail:
@@ -932,42 +964,49 @@
 		if (!port)
 			continue;
 		pdrv = &gdata_ports[i].pdrv;
-		spin_lock_irqsave(&port->port_lock, flags);
 
+		spin_lock_irqsave(&port->rx_lock, flags);
 		temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
 				"\nName:           %s\n"
 				"#PORT:%d port#:   %p\n"
-				"dpkts_to_usbhost: %lu\n"
+				"data_ch_open:	   %d\n"
+				"data_ch_ready:    %d\n"
+				"\n******UL INFO*****\n\n"
 				"dpkts_to_modem:   %lu\n"
 				"tomodem_drp_cnt:  %u\n"
-				"tx_buf_len:       %u\n"
 				"rx_buf_len:       %u\n"
-				"rx thld cnt       %u\n"
-				"rx unthld cnt     %u\n"
 				"tx thld cnt       %u\n"
 				"tx unthld cnt     %u\n"
-				"uthld pnd skbs    %u\n"
-				"RX_THROTTLED      %d\n"
-				"TX_THROTTLED      %d\n"
-				"data_ch_open:     %d\n"
-				"data_ch_ready:    %d\n",
+				"TX_THROTTLED      %d\n",
 				pdrv->driver.name,
 				i, port,
-				port->to_host, port->to_modem,
+				test_bit(CH_OPENED, &port->bridge_sts),
+				test_bit(CH_READY, &port->bridge_sts),
+				port->to_modem,
 				port->tomodem_drp_cnt,
-				port->tx_skb_q.qlen,
 				port->rx_skb_q.qlen,
-				port->rx_throttled_cnt,
-				port->rx_unthrottled_cnt,
 				port->tx_throttled_cnt,
 				port->tx_unthrottled_cnt,
-				port->unthrottled_pnd_skbs,
-				test_bit(RX_THROTTLED, &port->brdg.flags),
-				test_bit(TX_THROTTLED, &port->brdg.flags),
-				test_bit(CH_OPENED, &port->bridge_sts),
-				test_bit(CH_READY, &port->bridge_sts));
+				test_bit(TX_THROTTLED, &port->brdg.flags));
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_lock_irqsave(&port->tx_lock, flags);
+		temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+				"\n******DL INFO******\n\n"
+				"dpkts_to_usbhost: %lu\n"
+				"tx_buf_len:	   %u\n"
+				"rx thld cnt	   %u\n"
+				"rx unthld cnt	   %u\n"
+				"uthld pnd skbs    %u\n"
+				"RX_THROTTLED	   %d\n",
+				port->to_host,
+				port->tx_skb_q.qlen,
+				port->rx_throttled_cnt,
+				port->rx_unthrottled_cnt,
+				port->unthrottled_pnd_skbs,
+				test_bit(RX_THROTTLED, &port->brdg.flags));
+		spin_unlock_irqrestore(&port->tx_lock, flags);
+
 	}
 
 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
@@ -989,16 +1028,19 @@
 		if (!port)
 			continue;
 
-		spin_lock_irqsave(&port->port_lock, flags);
-		port->to_host = 0;
+		spin_lock_irqsave(&port->rx_lock, flags);
 		port->to_modem = 0;
 		port->tomodem_drp_cnt = 0;
-		port->rx_throttled_cnt = 0;
-		port->rx_unthrottled_cnt = 0;
 		port->tx_throttled_cnt = 0;
 		port->tx_unthrottled_cnt = 0;
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+
+		spin_lock_irqsave(&port->tx_lock, flags);
+		port->to_host = 0;
+		port->rx_throttled_cnt = 0;
+		port->rx_unthrottled_cnt = 0;
 		port->unthrottled_pnd_skbs = 0;
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 	}
 	return count;
 }
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index dc11eaf..97b0a2e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1274,6 +1274,7 @@
 
 #ifdef CONFIG_USB_EHCI_MSM
 #include "ehci-msm.c"
+#include "ehci-msm2.c"
 #define PLATFORM_DRIVER_PRESENT
 #endif
 
@@ -1391,7 +1392,11 @@
 #endif
 
 #ifdef CONFIG_USB_EHCI_MSM_HSIC
-	&ehci_msm_hsic_driver
+	&ehci_msm_hsic_driver,
+#endif
+
+#ifdef CONFIG_USB_EHCI_MSM
+	&ehci_msm2_driver,
 #endif
 
 };
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index af7f2cf..dd3ec34 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -72,6 +72,8 @@
 #define USB_PHY_VDD_DIG_VOL_MAX		1320000 /* uV */
 #define USB_PHY_VDD_DIG_LOAD		49360	/* uA */
 
+#define HSIC_DBG1_REG		0x38
+
 static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
 {
 	int ret = 0;
@@ -160,7 +162,7 @@
 	static struct regulator *hsic_hub_reg;
 
 	pdata = mehci->dev->platform_data;
-	if (!pdata->hub_reset)
+	if (!pdata || !pdata->hub_reset)
 		return ret;
 
 	if (!init)
@@ -233,7 +235,7 @@
 
 	pdata = mehci->dev->platform_data;
 
-	if (!pdata->strobe || !pdata->data)
+	if (!pdata || !pdata->strobe || !pdata->data)
 		return rc;
 
 	if (gpio_status == gpio_en)
@@ -270,16 +272,16 @@
 {
 	int ret;
 
-	clk_enable(mehci->alt_core_clk);
+	clk_prepare_enable(mehci->alt_core_clk);
 
 	ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
 	if (ret) {
-		clk_disable(mehci->alt_core_clk);
+		clk_disable_unprepare(mehci->alt_core_clk);
 		dev_err(mehci->dev, "usb phy clk assert failed\n");
 		return ret;
 	}
 	usleep_range(10000, 12000);
-	clk_disable(mehci->alt_core_clk);
+	clk_disable_unprepare(mehci->alt_core_clk);
 
 	ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
 	if (ret)
@@ -320,6 +322,7 @@
 	struct usb_hcd *hcd = hsic_to_hcd(mehci);
 	int cnt = 0;
 	int ret;
+	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
 
 	ret = msm_hsic_phy_reset(mehci);
 	if (ret) {
@@ -337,36 +340,59 @@
 	if (cnt >= LINK_RESET_TIMEOUT_USEC)
 		return -ETIMEDOUT;
 
-	/* select ULPI phy */
+	/* Reset PORTSC and select ULPI phy */
 	writel_relaxed(0x80000000, USB_PORTSC);
 
 	/* TODO: Need to confirm if HSIC PHY also requires delay after RESET */
 	msleep(100);
 
 	/* HSIC PHY Initialization */
-	/* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
-	writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
 
-	/*set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
-	ulpi_write(mehci, 0xFF, 0x33);
+	/* HSIC init sequence when HSIC signals (Strobe/Data) are
+	routed via GPIOs */
+	if (pdata && pdata->strobe && pdata->data) {
 
-	/* Enable periodic IO calibration in HSIC_CFG register */
-	ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
+		/* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
+		writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
 
-	/* Configure GPIO 150/151 pins for HSIC functionality mode */
-	ret = msm_hsic_config_gpios(mehci, 1);
-	if (ret) {
-		dev_err(mehci->dev, " gpio configuarion failed\n");
-		return ret;
+		/*set periodic calibration interval to ~2.048sec in
+		  HSIC_IO_CAL_REG */
+		ulpi_write(mehci, 0xFF, 0x33);
+
+		/* Enable periodic IO calibration in HSIC_CFG register */
+		ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
+
+		/* Configure GPIO 150/151 pins for HSIC functionality mode */
+		ret = msm_hsic_config_gpios(mehci, 1);
+		if (ret) {
+			dev_err(mehci->dev, " gpio configuarion failed\n");
+			return ret;
+		}
+		/* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL
+		   register */
+		writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
+		writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
+		/* Enable HSIC mode in HSIC_CFG register */
+		ulpi_write(mehci, 0x01, 0x31);
+	} else {
+		/* HSIC init sequence when HSIC signals (Strobe/Data) are routed
+		via dedicated I/O */
+
+		/* programmable length of connect signaling (33.2ns) */
+		ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
+		if (ret) {
+			pr_err("%s: Unable to program length of connect "
+			      "signaling\n", __func__);
+		}
+
+		/*set periodic calibration interval to ~2.048sec in
+		  HSIC_IO_CAL_REG */
+		ulpi_write(mehci, 0xFF, 0x33);
+
+		/* Enable HSIC mode in HSIC_CFG register */
+		ulpi_write(mehci, 0xA9, 0x30);
 	}
 
-	/* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL register */
-	writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
-	writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
-
-	/* Enable HSIC mode in HSIC_CFG register */
-	ulpi_write(mehci, 0x01, 0x31);
-
 	return 0;
 }
 
@@ -423,12 +449,12 @@
 	 */
 	mb();
 
-	clk_disable(mehci->core_clk);
-	clk_disable(mehci->phy_clk);
-	clk_disable(mehci->cal_clk);
-	clk_disable(mehci->ahb_clk);
+	clk_disable_unprepare(mehci->core_clk);
+	clk_disable_unprepare(mehci->phy_clk);
+	clk_disable_unprepare(mehci->cal_clk);
+	clk_disable_unprepare(mehci->ahb_clk);
 	pdata = mehci->dev->platform_data;
-	if (pdata->hub_reset) {
+	if (pdata && pdata->hub_reset) {
 		ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_OFF);
 		if (ret)
 			pr_err("%s failed to devote for"
@@ -471,16 +497,16 @@
 		dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
 
 	pdata = mehci->dev->platform_data;
-	if (pdata->hub_reset) {
+	if (pdata && pdata->hub_reset) {
 		ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
 		if (ret)
 			pr_err("%s failed to vote for"
 				"TCXO D1 buffer%d\n", __func__, ret);
 	}
-	clk_enable(mehci->core_clk);
-	clk_enable(mehci->phy_clk);
-	clk_enable(mehci->cal_clk);
-	clk_enable(mehci->ahb_clk);
+	clk_prepare_enable(mehci->core_clk);
+	clk_prepare_enable(mehci->phy_clk);
+	clk_prepare_enable(mehci->cal_clk);
+	clk_prepare_enable(mehci->ahb_clk);
 
 	temp = readl_relaxed(USB_USBCMD);
 	temp &= ~ASYNC_INTR_CTRL;
@@ -634,32 +660,32 @@
 	if (!init)
 		goto put_clocks;
 
-	/*core_clk is required for LINK protocol engine,it should be at 60MHz */
+	/*core_clk is required for LINK protocol engine
+	 *clock rate appropriately set by target specific clock driver */
 	mehci->core_clk = clk_get(mehci->dev, "core_clk");
 	if (IS_ERR(mehci->core_clk)) {
 		dev_err(mehci->dev, "failed to get core_clk\n");
 		ret = PTR_ERR(mehci->core_clk);
 		return ret;
 	}
-	clk_set_rate(mehci->core_clk, 60000000);
 
-	/* 60MHz alt_core_clk is for LINK to be used during PHY RESET  */
+	/* alt_core_clk is for LINK to be used during PHY RESET
+	 * clock rate appropriately set by target specific clock driver */
 	mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
 	if (IS_ERR(mehci->alt_core_clk)) {
 		dev_err(mehci->dev, "failed to core_clk\n");
 		ret = PTR_ERR(mehci->alt_core_clk);
 		goto put_core_clk;
 	}
-	clk_set_rate(mehci->alt_core_clk, 60000000);
 
-	/* 480MHz phy_clk is required for HSIC PHY operation */
+	/* phy_clk is required for HSIC PHY operation
+	 * clock rate appropriately set by target specific clock driver */
 	mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
 	if (IS_ERR(mehci->phy_clk)) {
 		dev_err(mehci->dev, "failed to get phy_clk\n");
 		ret = PTR_ERR(mehci->phy_clk);
 		goto put_alt_core_clk;
 	}
-	clk_set_rate(mehci->phy_clk, 480000000);
 
 	/* 10MHz cal_clk is required for calibration of I/O pads */
 	mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
@@ -678,18 +704,20 @@
 		goto put_cal_clk;
 	}
 
-	clk_enable(mehci->core_clk);
-	clk_enable(mehci->phy_clk);
-	clk_enable(mehci->cal_clk);
-	clk_enable(mehci->ahb_clk);
+	clk_prepare_enable(mehci->core_clk);
+	clk_prepare_enable(mehci->phy_clk);
+	clk_prepare_enable(mehci->cal_clk);
+	clk_prepare_enable(mehci->ahb_clk);
 
 	return 0;
 
 put_clocks:
-	clk_disable(mehci->core_clk);
-	clk_disable(mehci->phy_clk);
-	clk_disable(mehci->cal_clk);
-	clk_disable(mehci->ahb_clk);
+	if (!atomic_read(&mehci->in_lpm)) {
+		clk_disable_unprepare(mehci->core_clk);
+		clk_disable_unprepare(mehci->phy_clk);
+		clk_disable_unprepare(mehci->cal_clk);
+		clk_disable_unprepare(mehci->ahb_clk);
+	}
 	clk_put(mehci->ahb_clk);
 put_cal_clk:
 	clk_put(mehci->cal_clk);
@@ -778,7 +806,7 @@
 	}
 
 	pdata = mehci->dev->platform_data;
-	if (pdata->hub_reset) {
+	if (pdata && pdata->hub_reset) {
 		mehci->xo_handle = msm_xo_get(MSM_XO_TCXO_D1, "hsic");
 		if (IS_ERR(mehci->xo_handle)) {
 			pr_err(" %s not able to get the handle"
@@ -843,7 +871,7 @@
 deinit_hub:
 	msm_hsic_config_hub(mehci, 0);
 free_xo_handle:
-	if (pdata->hub_reset)
+	if (pdata && pdata->hub_reset)
 		msm_xo_put(mehci->xo_handle);
 deinit_vddcx:
 	msm_hsic_init_vddcx(mehci, 0);
@@ -867,14 +895,13 @@
 		free_irq(mehci->peripheral_status_irq, mehci);
 
 	device_init_wakeup(&pdev->dev, 0);
-	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
 	usb_remove_hcd(hcd);
 	msm_hsic_config_gpios(mehci, 0);
 	msm_hsic_config_hub(mehci, 0);
 	pdata = mehci->dev->platform_data;
-	if (pdata->hub_reset)
+	if (pdata && pdata->hub_reset)
 		msm_xo_put(mehci->xo_handle);
 	msm_hsic_init_vddcx(mehci, 0);
 
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
new file mode 100644
index 0000000..4f6fe3e
--- /dev/null
+++ b/drivers/usb/host/ehci-msm2.c
@@ -0,0 +1,1003 @@
+/* ehci-msm2.c - HSUSB Host Controller Driver Implementation
+ *
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ *
+ * Partly derived from ehci-fsl.c and ehci-hcd.c
+ * Copyright (c) 2000-2004 by David Brownell
+ * Copyright (c) 2005 MontaVista Software
+ *
+ * All source code in this file is licensed under the following license except
+ * where indicated.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can find it at http://www.fsf.org
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/wakelock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/usb/ulpi.h>
+#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb/msm_hsusb.h>
+#include <mach/clk.h>
+#include <mach/msm_iomap.h>
+
+#define MSM_USB_BASE (hcd->regs)
+
+struct msm_hcd {
+	struct ehci_hcd				ehci;
+	struct device				*dev;
+	struct clk				*iface_clk;
+	struct clk				*core_clk;
+	struct clk				*alt_core_clk;
+	struct regulator			*hsusb_vddcx;
+	struct regulator			*hsusb_3p3;
+	struct regulator			*hsusb_1p8;
+	struct regulator			*vbus;
+	bool					async_int;
+	atomic_t				in_lpm;
+	struct wake_lock			wlock;
+};
+
+static inline struct msm_hcd *hcd_to_mhcd(struct usb_hcd *hcd)
+{
+	return (struct msm_hcd *) (hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *mhcd_to_hcd(struct msm_hcd *mhcd)
+{
+	return container_of((void *) mhcd, struct usb_hcd, hcd_priv);
+}
+
+#define HSUSB_PHY_3P3_VOL_MIN		3050000 /* uV */
+#define HSUSB_PHY_3P3_VOL_MAX		3300000 /* uV */
+#define HSUSB_PHY_3P3_HPM_LOAD		50000	/* uA */
+
+#define HSUSB_PHY_1P8_VOL_MIN		1800000 /* uV */
+#define HSUSB_PHY_1P8_VOL_MAX		1800000 /* uV */
+#define HSUSB_PHY_1P8_HPM_LOAD		50000	/* uA */
+
+#define HSUSB_PHY_VDD_DIG_VOL_MIN	1045000	/* uV */
+#define HSUSB_PHY_VDD_DIG_VOL_MAX	1320000	/* uV */
+#define HSUSB_PHY_VDD_DIG_LOAD		49360	/* uA */
+
+static int msm_ehci_init_vddcx(struct msm_hcd *mhcd, int init)
+{
+	int ret = 0;
+
+	if (!init)
+		goto disable_reg;
+
+	mhcd->hsusb_vddcx = regulator_get(mhcd->dev, "HSUSB_VDDCX");
+	if (IS_ERR(mhcd->hsusb_vddcx)) {
+		dev_err(mhcd->dev, "unable to get ehci vddcx\n");
+		return PTR_ERR(mhcd->hsusb_vddcx);
+	}
+
+	ret = regulator_set_voltage(mhcd->hsusb_vddcx,
+			HSUSB_PHY_VDD_DIG_VOL_MIN,
+			HSUSB_PHY_VDD_DIG_VOL_MAX);
+	if (ret) {
+		dev_err(mhcd->dev, "unable to set the voltage"
+				"for ehci vddcx\n");
+		goto reg_set_voltage_err;
+	}
+
+	ret = regulator_set_optimum_mode(mhcd->hsusb_vddcx,
+				HSUSB_PHY_VDD_DIG_LOAD);
+	if (ret < 0) {
+		dev_err(mhcd->dev, "%s: Unable to set optimum mode of the"
+				" regulator: VDDCX\n", __func__);
+		goto reg_optimum_mode_err;
+	}
+
+	ret = regulator_enable(mhcd->hsusb_vddcx);
+	if (ret) {
+		dev_err(mhcd->dev, "unable to enable ehci vddcx\n");
+		goto reg_enable_err;
+	}
+
+	return 0;
+
+disable_reg:
+	regulator_disable(mhcd->hsusb_vddcx);
+reg_enable_err:
+	regulator_set_optimum_mode(mhcd->hsusb_vddcx, 0);
+reg_optimum_mode_err:
+	regulator_set_voltage(mhcd->hsusb_vddcx, 0,
+				HSUSB_PHY_VDD_DIG_VOL_MIN);
+reg_set_voltage_err:
+	regulator_put(mhcd->hsusb_vddcx);
+
+	return ret;
+
+}
+
+static int msm_ehci_ldo_init(struct msm_hcd *mhcd, int init)
+{
+	int rc = 0;
+
+	if (!init)
+		goto put_1p8;
+
+	mhcd->hsusb_3p3 = regulator_get(mhcd->dev, "HSUSB_3p3");
+	if (IS_ERR(mhcd->hsusb_3p3)) {
+		dev_err(mhcd->dev, "unable to get hsusb 3p3\n");
+		return PTR_ERR(mhcd->hsusb_3p3);
+	}
+
+	rc = regulator_set_voltage(mhcd->hsusb_3p3,
+			HSUSB_PHY_3P3_VOL_MIN, HSUSB_PHY_3P3_VOL_MAX);
+	if (rc) {
+		dev_err(mhcd->dev, "unable to set voltage level for"
+				"hsusb 3p3\n");
+		goto put_3p3;
+	}
+	mhcd->hsusb_1p8 = regulator_get(mhcd->dev, "HSUSB_1p8");
+	if (IS_ERR(mhcd->hsusb_1p8)) {
+		dev_err(mhcd->dev, "unable to get hsusb 1p8\n");
+		rc = PTR_ERR(mhcd->hsusb_1p8);
+		goto put_3p3_lpm;
+	}
+	rc = regulator_set_voltage(mhcd->hsusb_1p8,
+			HSUSB_PHY_1P8_VOL_MIN, HSUSB_PHY_1P8_VOL_MAX);
+	if (rc) {
+		dev_err(mhcd->dev, "unable to set voltage level for"
+				"hsusb 1p8\n");
+		goto put_1p8;
+	}
+
+	return 0;
+
+put_1p8:
+	regulator_set_voltage(mhcd->hsusb_1p8, 0, HSUSB_PHY_1P8_VOL_MAX);
+	regulator_put(mhcd->hsusb_1p8);
+put_3p3_lpm:
+	regulator_set_voltage(mhcd->hsusb_3p3, 0, HSUSB_PHY_3P3_VOL_MAX);
+put_3p3:
+	regulator_put(mhcd->hsusb_3p3);
+
+	return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+#define HSUSB_PHY_SUSP_DIG_VOL  500000
+static int msm_ehci_config_vddcx(struct msm_hcd *mhcd, int high)
+{
+	int max_vol = HSUSB_PHY_VDD_DIG_VOL_MAX;
+	int min_vol;
+	int ret;
+
+	if (high)
+		min_vol = HSUSB_PHY_VDD_DIG_VOL_MIN;
+	else
+		min_vol = HSUSB_PHY_SUSP_DIG_VOL;
+
+	ret = regulator_set_voltage(mhcd->hsusb_vddcx, min_vol, max_vol);
+	if (ret) {
+		dev_err(mhcd->dev, "%s: unable to set the voltage of regulator"
+			" HSUSB_VDDCX\n", __func__);
+		return ret;
+	}
+
+	dev_dbg(mhcd->dev, "%s: min_vol:%d max_vol:%d\n", __func__, min_vol,
+								max_vol);
+
+	return ret;
+}
+#else
+static int msm_ehci_config_vddcx(struct msm_hcd *mhcd, int high)
+{
+	return 0;
+}
+#endif
+
+static int msm_ehci_init_vbus(struct msm_hcd *mhcd, int init)
+{
+	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+	struct msm_usb_host_platform_data *pdata;
+
+	if (!init) {
+		regulator_put(mhcd->vbus);
+		return 0;
+	}
+
+	mhcd->vbus = regulator_get(mhcd->dev, "vbus");
+	if (IS_ERR(mhcd->vbus)) {
+		pr_err("Unable to get vbus\n");
+		return -ENODEV;
+	}
+
+	pdata = mhcd->dev->platform_data;
+	if (pdata)
+		hcd->power_budget = pdata->power_budget;
+
+	return 0;
+}
+
+static void msm_ehci_vbus_power(struct msm_hcd *mhcd, bool on)
+{
+	int ret;
+
+	if (!mhcd->vbus) {
+		pr_err("vbus is NULL.");
+		return;
+	}
+	if (on) {
+		ret = regulator_enable(mhcd->vbus);
+		if (ret) {
+			pr_err("unable to enable vbus\n");
+			return;
+		}
+	} else {
+		ret = regulator_disable(mhcd->vbus);
+		if (ret) {
+			pr_err("unable to disable vbus\n");
+			return;
+		}
+	}
+}
+
+static int msm_ehci_ldo_enable(struct msm_hcd *mhcd, int on)
+{
+	int ret = 0;
+
+	if (IS_ERR(mhcd->hsusb_1p8)) {
+		dev_err(mhcd->dev, "%s: HSUSB_1p8 is not initialized\n",
+								__func__);
+		return -ENODEV;
+	}
+
+	if (IS_ERR(mhcd->hsusb_3p3)) {
+		dev_err(mhcd->dev, "%s: HSUSB_3p3 is not initialized\n",
+								__func__);
+		return -ENODEV;
+	}
+
+	if (on) {
+		ret = regulator_set_optimum_mode(mhcd->hsusb_1p8,
+						HSUSB_PHY_1P8_HPM_LOAD);
+		if (ret < 0) {
+			dev_err(mhcd->dev, "%s: Unable to set HPM of the"
+				" regulator: HSUSB_1p8\n", __func__);
+			return ret;
+		}
+
+		ret = regulator_enable(mhcd->hsusb_1p8);
+		if (ret) {
+			dev_err(mhcd->dev, "%s: unable to enable the hsusb"
+						" 1p8\n", __func__);
+			regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
+			return ret;
+		}
+
+		ret = regulator_set_optimum_mode(mhcd->hsusb_3p3,
+						HSUSB_PHY_3P3_HPM_LOAD);
+		if (ret < 0) {
+			dev_err(mhcd->dev, "%s: Unable to set HPM of the "
+				"regulator: HSUSB_3p3\n", __func__);
+			regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
+			regulator_disable(mhcd->hsusb_1p8);
+			return ret;
+		}
+
+		ret = regulator_enable(mhcd->hsusb_3p3);
+		if (ret) {
+			dev_err(mhcd->dev, "%s: unable to enable the "
+					"hsusb 3p3\n", __func__);
+			regulator_set_optimum_mode(mhcd->hsusb_3p3, 0);
+			regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
+			regulator_disable(mhcd->hsusb_1p8);
+			return ret;
+		}
+
+	} else {
+		ret = regulator_disable(mhcd->hsusb_1p8);
+		if (ret) {
+			dev_err(mhcd->dev, "%s: unable to disable the "
+					"hsusb 1p8\n", __func__);
+			return ret;
+		}
+
+		ret = regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
+		if (ret < 0)
+			dev_err(mhcd->dev, "%s: Unable to set LPM of the "
+				"regulator: HSUSB_1p8\n", __func__);
+
+		ret = regulator_disable(mhcd->hsusb_3p3);
+		if (ret) {
+			dev_err(mhcd->dev, "%s: unable to disable the "
+					"hsusb 3p3\n", __func__);
+			return ret;
+		}
+		ret = regulator_set_optimum_mode(mhcd->hsusb_3p3, 0);
+		if (ret < 0)
+			dev_err(mhcd->dev, "%s: Unable to set LPM of the "
+					"regulator: HSUSB_3p3\n", __func__);
+	}
+
+	dev_dbg(mhcd->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+
+	return ret < 0 ? ret : 0;
+}
+
+
+#define ULPI_IO_TIMEOUT_USECS	(10 * 1000)
+static int msm_ulpi_read(struct msm_hcd *mhcd, u32 reg)
+{
+	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+	unsigned long timeout;
+
+	/* initiate read operation */
+	writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
+	       USB_ULPI_VIEWPORT);
+
+	/* wait for completion */
+	timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USECS);
+	while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
+		if (time_after(jiffies, timeout)) {
+			dev_err(mhcd->dev, "msm_ulpi_read: timeout %08x\n",
+				readl_relaxed(USB_ULPI_VIEWPORT));
+			return -ETIMEDOUT;
+		}
+		udelay(1);
+	}
+
+	return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
+}
+
+
+static int msm_ulpi_write(struct msm_hcd *mhcd, u32 val, u32 reg)
+{
+	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+	unsigned long timeout;
+
+	/* initiate write operation */
+	writel_relaxed(ULPI_RUN | ULPI_WRITE |
+	       ULPI_ADDR(reg) | ULPI_DATA(val),
+	       USB_ULPI_VIEWPORT);
+
+	/* wait for completion */
+	timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USECS);
+	while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
+		if (time_after(jiffies, timeout)) {
+			dev_err(mhcd->dev, "msm_ulpi_write: timeout\n");
+			return -ETIMEDOUT;
+		}
+		udelay(1);
+	}
+
+	return 0;
+}
+
+static int msm_ehci_link_clk_reset(struct msm_hcd *mhcd, bool assert)
+{
+	int ret;
+
+	if (assert) {
+		ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_ASSERT);
+		if (ret)
+			dev_err(mhcd->dev, "usb alt_core_clk assert failed\n");
+	} else {
+		ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_DEASSERT);
+		if (ret)
+			dev_err(mhcd->dev, "usb alt_core_clk deassert failed\n");
+	}
+
+	return ret;
+}
+
+static int msm_ehci_phy_reset(struct msm_hcd *mhcd)
+{
+	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+	u32 val;
+	int ret;
+	int retries;
+
+	ret = msm_ehci_link_clk_reset(mhcd, 1);
+	if (ret)
+		return ret;
+
+	udelay(1);
+
+	ret = msm_ehci_link_clk_reset(mhcd, 0);
+	if (ret)
+		return ret;
+
+	val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
+	writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
+
+	for (retries = 3; retries > 0; retries--) {
+		ret = msm_ulpi_write(mhcd, ULPI_FUNC_CTRL_SUSPENDM,
+				ULPI_CLR(ULPI_FUNC_CTRL));
+		if (!ret)
+			break;
+	}
+	if (!retries)
+		return -ETIMEDOUT;
+
+	/* Wakeup the PHY with a reg-access for calibration */
+	for (retries = 3; retries > 0; retries--) {
+		ret = msm_ulpi_read(mhcd, ULPI_DEBUG);
+		if (ret != -ETIMEDOUT)
+			break;
+	}
+	if (!retries)
+		return -ETIMEDOUT;
+
+	dev_info(mhcd->dev, "phy_reset: success\n");
+
+	return 0;
+}
+
+#define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
+static int msm_hsusb_reset(struct msm_hcd *mhcd)
+{
+	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+	unsigned long timeout;
+	int ret;
+
+	clk_prepare_enable(mhcd->alt_core_clk);
+	ret = msm_ehci_phy_reset(mhcd);
+	if (ret) {
+		dev_err(mhcd->dev, "phy_reset failed\n");
+		return ret;
+	}
+
+	writel_relaxed(USBCMD_RESET, USB_USBCMD);
+
+	timeout = jiffies + usecs_to_jiffies(LINK_RESET_TIMEOUT_USEC);
+	while (readl_relaxed(USB_USBCMD) & USBCMD_RESET) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		udelay(1);
+	}
+
+	/* select ULPI phy */
+	writel_relaxed(0x80000000, USB_PORTSC);
+
+	msleep(100);
+
+	writel_relaxed(0x0, USB_AHBBURST);
+	writel_relaxed(0x00, USB_AHBMODE);
+
+	/* Ensure that RESET operation is completed before turning off clock */
+	mb();
+	clk_disable_unprepare(mhcd->alt_core_clk);
+
+	/*rising edge interrupts with Dp rise and fall enabled*/
+	msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_RISE);
+	msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_FALL);
+
+	/*Clear the PHY interrupts by reading the PHY interrupt latch register*/
+	msm_ulpi_read(mhcd, ULPI_USB_INT_LATCH);
+
+	return 0;
+}
+
+#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
+#define PHY_RESUME_TIMEOUT_USEC		(100 * 1000)
+
+#ifdef CONFIG_PM_SLEEP
+static int msm_ehci_suspend(struct msm_hcd *mhcd)
+{
+	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+	unsigned long timeout;
+	u32 portsc;
+
+	if (atomic_read(&mhcd->in_lpm)) {
+		dev_dbg(mhcd->dev, "%s called in lpm\n", __func__);
+		return 0;
+	}
+
+	disable_irq(hcd->irq);
+
+	/* Set the PHCD bit, only if it is not set by the controller.
+	 * PHY may take some time or even fail to enter into low power
+	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
+	 * in failure case.
+	 */
+	portsc = readl_relaxed(USB_PORTSC);
+	if (!(portsc & PORTSC_PHCD)) {
+		writel_relaxed(portsc | PORTSC_PHCD,
+				USB_PORTSC);
+
+		timeout = jiffies + usecs_to_jiffies(PHY_SUSPEND_TIMEOUT_USEC);
+		while (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD)) {
+			if (time_after(jiffies, timeout)) {
+				dev_err(mhcd->dev, "Unable to suspend PHY\n");
+				msm_hsusb_reset(mhcd);
+				break;
+			}
+			udelay(1);
+		}
+	}
+
+	/*
+	 * PHY has capability to generate interrupt asynchronously in low
+	 * power mode (LPM). This interrupt is level triggered. So USB IRQ
+	 * line must be disabled till async interrupt enable bit is cleared
+	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
+	 * block data communication from PHY.
+	 */
+	writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
+				ULPI_STP_CTRL, USB_USBCMD);
+
+	/*
+	 * Ensure that hardware is put in low power mode before
+	 * clocks are turned OFF and VDD is allowed to minimize.
+	 */
+	mb();
+
+	clk_disable_unprepare(mhcd->iface_clk);
+	clk_disable_unprepare(mhcd->core_clk);
+
+	msm_ehci_config_vddcx(mhcd, 0);
+
+	atomic_set(&mhcd->in_lpm, 1);
+	enable_irq(hcd->irq);
+	wake_unlock(&mhcd->wlock);
+
+	dev_info(mhcd->dev, "EHCI USB in low power mode\n");
+
+	return 0;
+}
+
+static int msm_ehci_resume(struct msm_hcd *mhcd)
+{
+	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+	unsigned long timeout;
+	unsigned temp;
+
+	if (!atomic_read(&mhcd->in_lpm)) {
+		dev_dbg(mhcd->dev, "%s called in !in_lpm\n", __func__);
+		return 0;
+	}
+
+	wake_lock(&mhcd->wlock);
+
+	clk_prepare_enable(mhcd->core_clk);
+	clk_prepare_enable(mhcd->iface_clk);
+
+	msm_ehci_config_vddcx(mhcd, 1);
+
+	temp = readl_relaxed(USB_USBCMD);
+	temp &= ~ASYNC_INTR_CTRL;
+	temp &= ~ULPI_STP_CTRL;
+	writel_relaxed(temp, USB_USBCMD);
+
+	if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
+		goto skip_phy_resume;
+
+	temp = readl_relaxed(USB_PORTSC) & ~PORTSC_PHCD;
+	writel_relaxed(temp, USB_PORTSC);
+
+	timeout = jiffies + usecs_to_jiffies(PHY_RESUME_TIMEOUT_USEC);
+	while ((readl_relaxed(USB_PORTSC) & PORTSC_PHCD) ||
+			!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE)) {
+		if (time_after(jiffies, timeout)) {
+			/*This is a fatal error. Reset the link and PHY*/
+			dev_err(mhcd->dev, "Unable to resume USB. Resetting the h/w\n");
+			msm_hsusb_reset(mhcd);
+			break;
+		}
+		udelay(1);
+	}
+
+skip_phy_resume:
+
+	atomic_set(&mhcd->in_lpm, 0);
+
+	if (mhcd->async_int) {
+		mhcd->async_int = false;
+		pm_runtime_put_noidle(mhcd->dev);
+		enable_irq(hcd->irq);
+	}
+
+	dev_info(mhcd->dev, "EHCI USB exited from low power mode\n");
+
+	return 0;
+}
+#endif
+
+static irqreturn_t msm_ehci_irq(struct usb_hcd *hcd)
+{
+	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+	if (atomic_read(&mhcd->in_lpm)) {
+		disable_irq_nosync(hcd->irq);
+		mhcd->async_int = true;
+		pm_runtime_get(mhcd->dev);
+		return IRQ_HANDLED;
+	}
+
+	return ehci_irq(hcd);
+}
+
+static int msm_ehci_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	ehci->caps = USB_CAPLENGTH;
+	ehci->regs = USB_CAPLENGTH +
+		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache the data to minimize the chip reads*/
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	hcd->has_tt = 1;
+	ehci->sbrn = HCD_USB2;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	retval = ehci_reset(ehci);
+	if (retval)
+		return retval;
+
+	/* bursts of unspecified length. */
+	writel_relaxed(0, USB_AHBBURST);
+	/* Use the AHB transactor */
+	writel_relaxed(0, USB_AHBMODE);
+	/* Disable streaming mode and select host mode */
+	writel_relaxed(0x13, USB_USBMODE);
+
+	ehci_port_power(ehci, 1);
+	return 0;
+}
+
+static struct hc_driver msm_hc2_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Qualcomm EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct msm_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= msm_ehci_irq,
+	.flags			= HCD_USB2 | HCD_MEMORY,
+
+	.reset			= msm_ehci_reset,
+	.start			= ehci_run,
+
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+	.clear_tt_buffer_complete	 = ehci_clear_tt_buffer_complete,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	/*
+	 * PM support
+	 */
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+};
+
+static int msm_ehci_init_clocks(struct msm_hcd *mhcd, u32 init)
+{
+	int ret = 0;
+
+	if (!init)
+		goto put_clocks;
+
+	/* 60MHz alt_core_clk is for LINK to be used during PHY RESET  */
+	mhcd->alt_core_clk = clk_get(mhcd->dev, "alt_core_clk");
+	if (IS_ERR(mhcd->alt_core_clk)) {
+		dev_err(mhcd->dev, "failed to get alt_core_clk\n");
+		ret = PTR_ERR(mhcd->alt_core_clk);
+		return ret;
+	}
+	clk_set_rate(mhcd->alt_core_clk, 60000000);
+
+	/* iface_clk is required for data transfers */
+	mhcd->iface_clk = clk_get(mhcd->dev, "iface_clk");
+	if (IS_ERR(mhcd->iface_clk)) {
+		dev_err(mhcd->dev, "failed to get iface_clk\n");
+		ret = PTR_ERR(mhcd->iface_clk);
+		goto put_alt_core_clk;
+	}
+
+	/* Link's protocol engine is based on pclk which must
+	 * be running >55Mhz and frequency should also not change.
+	 * Hence, vote for maximum clk frequency on its source
+	 */
+	mhcd->core_clk = clk_get(mhcd->dev, "core_clk");
+	if (IS_ERR(mhcd->core_clk)) {
+		dev_err(mhcd->dev, "failed to get core_clk\n");
+		ret = PTR_ERR(mhcd->core_clk);
+		goto put_iface_clk;
+	}
+	clk_set_rate(mhcd->core_clk, INT_MAX);
+
+	clk_prepare_enable(mhcd->core_clk);
+	clk_prepare_enable(mhcd->iface_clk);
+
+	return 0;
+
+put_clocks:
+	clk_disable_unprepare(mhcd->iface_clk);
+	clk_disable_unprepare(mhcd->core_clk);
+	clk_put(mhcd->core_clk);
+put_iface_clk:
+	clk_put(mhcd->iface_clk);
+put_alt_core_clk:
+	clk_put(mhcd->alt_core_clk);
+
+	return ret;
+}
+
+static int __devinit ehci_msm2_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res;
+	struct msm_hcd *mhcd;
+	int ret;
+
+	dev_dbg(&pdev->dev, "ehci_msm2 probe\n");
+
+	hcd = usb_create_hcd(&msm_hc2_driver, &pdev->dev,
+				dev_name(&pdev->dev));
+	if (!hcd) {
+		dev_err(&pdev->dev, "Unable to create HCD\n");
+		return  -ENOMEM;
+	}
+
+	hcd->irq = platform_get_irq(pdev, 0);
+	if (hcd->irq < 0) {
+		dev_err(&pdev->dev, "Unable to get IRQ resource\n");
+		ret = hcd->irq;
+		goto put_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Unable to get memory resource\n");
+		ret = -ENODEV;
+		goto put_hcd;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto put_hcd;
+	}
+
+	mhcd = hcd_to_mhcd(hcd);
+	mhcd->dev = &pdev->dev;
+
+	ret = msm_ehci_init_clocks(mhcd, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to initialize clocks\n");
+		ret = -ENODEV;
+		goto unmap;
+	}
+
+	ret = msm_ehci_init_vddcx(mhcd, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to initialize VDDCX\n");
+		ret = -ENODEV;
+		goto deinit_clocks;
+	}
+
+	ret = msm_ehci_config_vddcx(mhcd, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+		goto deinit_vddcx;
+	}
+
+	ret = msm_ehci_ldo_init(mhcd, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+		goto deinit_vddcx;
+	}
+
+	ret = msm_ehci_ldo_enable(mhcd, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+		goto deinit_ldo;
+	}
+
+	ret = msm_ehci_init_vbus(mhcd, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to get vbus\n");
+		goto disable_ldo;
+	}
+
+	ret = msm_hsusb_reset(mhcd);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb PHY initialization failed\n");
+		goto vbus_deinit;
+	}
+
+	ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to register HCD\n");
+		goto vbus_deinit;
+	}
+
+	/*TBD:for now enable vbus here*/
+	msm_ehci_vbus_power(mhcd, 1);
+
+	device_init_wakeup(&pdev->dev, 1);
+	wake_lock_init(&mhcd->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
+	wake_lock(&mhcd->wlock);
+	/*
+	 * This pdev->dev is assigned parent of root-hub by USB core,
+	 * hence, runtime framework automatically calls this driver's
+	 * runtime APIs based on root-hub's state.
+	 */
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+
+vbus_deinit:
+	msm_ehci_init_vbus(mhcd, 0);
+disable_ldo:
+	msm_ehci_ldo_enable(mhcd, 0);
+deinit_ldo:
+	msm_ehci_ldo_init(mhcd, 0);
+deinit_vddcx:
+	msm_ehci_init_vddcx(mhcd, 0);
+deinit_clocks:
+	msm_ehci_init_clocks(mhcd, 0);
+unmap:
+	iounmap(hcd->regs);
+put_hcd:
+	usb_put_hcd(hcd);
+
+	return ret;
+}
+
+static int __devexit ehci_msm2_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+	device_init_wakeup(&pdev->dev, 0);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+
+	usb_remove_hcd(hcd);
+	msm_ehci_vbus_power(mhcd, 0);
+	msm_ehci_init_vbus(mhcd, 0);
+	msm_ehci_ldo_enable(mhcd, 0);
+	msm_ehci_ldo_init(mhcd, 0);
+	msm_ehci_init_vddcx(mhcd, 0);
+
+	msm_ehci_init_clocks(mhcd, 0);
+	wake_lock_destroy(&mhcd->wlock);
+	iounmap(hcd->regs);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ehci_msm2_pm_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+	dev_dbg(dev, "ehci-msm2 PM suspend\n");
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(hcd->irq);
+
+	return msm_ehci_suspend(mhcd);
+
+}
+
+static int ehci_msm2_pm_resume(struct device *dev)
+{
+	int ret;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+	dev_dbg(dev, "ehci-msm2 PM resume\n");
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(hcd->irq);
+
+	ret = msm_ehci_resume(mhcd);
+	if (ret)
+		return ret;
+
+	/* Bring the device to full powered state upon system resume */
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int ehci_msm2_runtime_idle(struct device *dev)
+{
+	dev_dbg(dev, "EHCI runtime idle\n");
+
+	return 0;
+}
+
+static int ehci_msm2_runtime_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+	dev_dbg(dev, "EHCI runtime suspend\n");
+	return msm_ehci_suspend(mhcd);
+}
+
+static int ehci_msm2_runtime_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+	dev_dbg(dev, "EHCI runtime resume\n");
+	return msm_ehci_resume(mhcd);
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops ehci_msm2_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(ehci_msm2_pm_suspend, ehci_msm2_pm_resume)
+	SET_RUNTIME_PM_OPS(ehci_msm2_runtime_suspend, ehci_msm2_runtime_resume,
+				ehci_msm2_runtime_idle)
+};
+#endif
+
+static struct platform_driver ehci_msm2_driver = {
+	.probe	= ehci_msm2_probe,
+	.remove	= __devexit_p(ehci_msm2_remove),
+	.driver = {
+		.name = "msm_ehci_host",
+#ifdef CONFIG_PM
+		.pm = &ehci_msm2_dev_pm_ops,
+#endif
+	},
+};
diff --git a/drivers/usb/host/ehci-msm72k.c b/drivers/usb/host/ehci-msm72k.c
index 87c75e7..b3939ef 100644
--- a/drivers/usb/host/ehci-msm72k.c
+++ b/drivers/usb/host/ehci-msm72k.c
@@ -79,9 +79,9 @@
 		return;
 
 	if (vote)
-		clk_enable(pdata->ebi1_clk);
+		clk_prepare_enable(pdata->ebi1_clk);
 	else
-		clk_disable(pdata->ebi1_clk);
+		clk_disable_unprepare(pdata->ebi1_clk);
 }
 
 static void msm_xusb_enable_clks(struct msmusb_hcd *mhcd)
@@ -96,8 +96,8 @@
 		/* OTG driver takes care of clock management */
 		break;
 	case USB_PHY_SERIAL_PMIC:
-		clk_enable(mhcd->alt_core_clk);
-		clk_enable(mhcd->iface_clk);
+		clk_prepare_enable(mhcd->alt_core_clk);
+		clk_prepare_enable(mhcd->iface_clk);
 		break;
 	default:
 		pr_err("%s: undefined phy type ( %X )\n", __func__,
@@ -119,8 +119,8 @@
 		/* OTG driver takes care of clock management */
 		break;
 	case USB_PHY_SERIAL_PMIC:
-		clk_disable(mhcd->alt_core_clk);
-		clk_disable(mhcd->iface_clk);
+		clk_disable_unprepare(mhcd->alt_core_clk);
+		clk_disable_unprepare(mhcd->iface_clk);
 		break;
 	default:
 		pr_err("%s: undefined phy type ( %X )\n", __func__,
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
index 59d9769..0ee1827 100644
--- a/drivers/usb/otg/msm72k_otg.c
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -562,9 +562,9 @@
 
 	if (on)
 		/* enable clocks */
-		clk_enable(dev->alt_core_clk);
+		clk_prepare_enable(dev->alt_core_clk);
 	else
-		clk_disable(dev->alt_core_clk);
+		clk_disable_unprepare(dev->alt_core_clk);
 
 	return 0;
 }
@@ -589,7 +589,7 @@
 		 * low power mode routine
 		 */
 		if (dev->pdata->pclk_required_during_lpm)
-			clk_enable(dev->iface_clk);
+			clk_prepare_enable(dev->iface_clk);
 
 		usb_gadget_vbus_connect(xceiv->gadget);
 	} else {
@@ -601,7 +601,7 @@
 		 * low power mode routine
 		 */
 		if (dev->pdata->pclk_required_during_lpm)
-			clk_disable(dev->iface_clk);
+			clk_disable_unprepare(dev->iface_clk);
 
 		otg_pm_qos_update_latency(dev, 0);
 		if (pdata->setup_gpio)
@@ -628,9 +628,9 @@
 		 */
 		if (dev->pdata->pclk_required_during_lpm) {
 			if (on)
-				clk_enable(dev->iface_clk);
+				clk_prepare_enable(dev->iface_clk);
 			else
-				clk_disable(dev->iface_clk);
+				clk_disable_unprepare(dev->iface_clk);
 		}
 
 		dev->start_host(xceiv->host, on);
@@ -759,9 +759,9 @@
 	mb();
 
 	if (dev->iface_clk)
-		clk_disable(dev->iface_clk);
+		clk_disable_unprepare(dev->iface_clk);
 
-	clk_disable(dev->core_clk);
+	clk_disable_unprepare(dev->core_clk);
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable*/
 	ret = msm_xo_mode_vote(dev->xo_handle, MSM_XO_MODE_OFF);
 	if (ret)
@@ -835,10 +835,10 @@
 		pr_err("%s failed to vote for"
 			"TCXO D1 buffer%d\n", __func__, ret);
 
-	clk_enable(dev->core_clk);
+	clk_prepare_enable(dev->core_clk);
 
 	if (dev->iface_clk)
-		clk_enable(dev->iface_clk);
+		clk_prepare_enable(dev->iface_clk);
 
 	temp = readl(USB_USBCMD);
 	temp &= ~ASYNC_INTR_CTRL;
@@ -1550,7 +1550,7 @@
 	unsigned long timeout;
 	u32 mode, work = 0;
 
-	clk_enable(dev->alt_core_clk);
+	clk_prepare_enable(dev->alt_core_clk);
 
 	if (!phy_reset)
 		goto reset_link;
@@ -1596,7 +1596,7 @@
 	/* Ensure that RESET operation is completed before turning off clock */
 	mb();
 
-	clk_disable(dev->alt_core_clk);
+	clk_disable_unprepare(dev->alt_core_clk);
 
 	if ((xceiv->gadget && xceiv->gadget->is_a_peripheral) ||
 			test_bit(ID, &dev->inputs))
@@ -2646,7 +2646,7 @@
 	 */
 	clk_set_rate(dev->core_clk, INT_MAX);
 
-	clk_enable(dev->core_clk);
+	clk_prepare_enable(dev->core_clk);
 
 	if (!dev->pdata->pclk_is_hw_gated) {
 		dev->iface_clk = clk_get(&pdev->dev, "iface_clk");
@@ -2655,7 +2655,7 @@
 			ret = PTR_ERR(dev->iface_clk);
 			goto put_core_clk;
 		}
-		clk_enable(dev->iface_clk);
+		clk_prepare_enable(dev->iface_clk);
 	}
 
 	if (!dev->pdata->phy_reset) {
@@ -2888,11 +2888,11 @@
 		clk_put(dev->phy_reset_clk);
 put_iface_clk:
 	if (dev->iface_clk) {
-		clk_disable(dev->iface_clk);
+		clk_disable_unprepare(dev->iface_clk);
 		clk_put(dev->iface_clk);
 	}
 put_core_clk:
-	clk_disable(dev->core_clk);
+	clk_disable_unprepare(dev->core_clk);
 	clk_put(dev->core_clk);
 put_alt_core_clk:
 	clk_put(dev->alt_core_clk);
@@ -2942,10 +2942,10 @@
 		dev->pdata->chg_init(0);
 	free_irq(dev->irq, pdev);
 	iounmap(dev->regs);
-	clk_disable(dev->core_clk);
+	clk_disable_unprepare(dev->core_clk);
 	clk_put(dev->core_clk);
 	if (dev->iface_clk) {
-		clk_disable(dev->iface_clk);
+		clk_disable_unprepare(dev->iface_clk);
 		clk_put(dev->iface_clk);
 	}
 	if (dev->alt_core_clk)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 4e1895f..6964835 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -538,7 +538,7 @@
 			motg->reset_counter++;
 	}
 
-	clk_enable(motg->clk);
+	clk_prepare_enable(motg->clk);
 	ret = msm_otg_phy_reset(motg);
 	if (ret) {
 		dev_err(otg->dev, "phy_reset failed\n");
@@ -558,7 +558,7 @@
 	/* Ensure that RESET operation is completed before turning off clock */
 	mb();
 
-	clk_disable(motg->clk);
+	clk_disable_unprepare(motg->clk);
 
 	if (pdata->otg_control == OTG_PHY_CONTROL) {
 		val = readl_relaxed(USB_OTGSC);
@@ -711,8 +711,8 @@
 
 	/* Ensure that above operation is completed before turning off clocks */
 	mb();
-	clk_disable(motg->pclk);
-	clk_disable(motg->core_clk);
+	clk_disable_unprepare(motg->pclk);
+	clk_disable_unprepare(motg->core_clk);
 
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
 	clk_disable_unprepare(motg->xo_handle);
@@ -765,9 +765,9 @@
 		dev_err(otg->dev, "%s failed to vote for "
 			"TCXO D0 buffer%d\n", __func__, ret);
 
-	clk_enable(motg->core_clk);
+	clk_prepare_enable(motg->core_clk);
 
-	clk_enable(motg->pclk);
+	clk_prepare_enable(motg->pclk);
 
 	if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
 		msm_hsusb_ldo_enable(motg, 1);
@@ -2529,7 +2529,7 @@
 		goto free_xo_handle;
 	}
 
-	clk_enable(motg->pclk);
+	clk_prepare_enable(motg->pclk);
 
 	ret = msm_hsusb_init_vddcx(motg, 1);
 	if (ret) {
@@ -2554,7 +2554,7 @@
 		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
 		goto free_ldo_init;
 	}
-	clk_enable(motg->core_clk);
+	clk_prepare_enable(motg->core_clk);
 
 	writel(0, USB_USBINTR);
 	writel(0, USB_OTGSC);
@@ -2652,14 +2652,14 @@
 	free_irq(motg->irq, motg);
 destroy_wlock:
 	wake_lock_destroy(&motg->wlock);
-	clk_disable(motg->core_clk);
+	clk_disable_unprepare(motg->core_clk);
 	msm_hsusb_ldo_enable(motg, 0);
 free_ldo_init:
 	msm_hsusb_ldo_init(motg, 0);
 free_init_vddcx:
 	msm_hsusb_init_vddcx(motg, 0);
 devote_xo_handle:
-	clk_disable(motg->pclk);
+	clk_disable_unprepare(motg->pclk);
 	clk_disable_unprepare(motg->xo_handle);
 free_xo_handle:
 	clk_put(motg->xo_handle);
@@ -2726,8 +2726,8 @@
 	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
 		dev_err(otg->dev, "Unable to suspend PHY\n");
 
-	clk_disable(motg->pclk);
-	clk_disable(motg->core_clk);
+	clk_disable_unprepare(motg->pclk);
+	clk_disable_unprepare(motg->core_clk);
 	clk_put(motg->xo_handle);
 	msm_hsusb_ldo_enable(motg, 0);
 	msm_hsusb_ldo_init(motg, 0);
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index d3f8b2b..0110df9 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -270,6 +270,11 @@
 	select FB_MSM_MIPI_DSI_TOSHIBA
 	default n
 
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+	bool
+	select FB_MSM_MIPI_DSI_TOSHIBA
+	default n
+
 config FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
 	bool
 	select FB_MSM_MIPI_DSI_NOVATEK
@@ -446,6 +451,7 @@
 	bool "MIPI Panel Detect"
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
 	select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
 	select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
 	select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
@@ -497,9 +503,20 @@
 
 config FB_MSM_LVDS_MIPI_PANEL_DETECT
 	bool "LVDS + MIPI Panel Auto Detect"
-	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
 	select FB_MSM_LVDS_CHIMEI_WXGA
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+	select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
+	select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
+	select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
+	select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+	select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+	select FB_MSM_MIPI_SIMULATOR_VIDEO
 	select FB_MSM_MIPI_CHIMEI_WXGA
+	select FB_MSM_MIPI_CHIMEI_WUXGA
 	---help---
 	  Support for LVDS + MIPI panel auto detect
 
@@ -541,6 +558,10 @@
 	bool "MIPI Toshiba WSVGA PT Panel"
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
 
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA_PANEL
+	bool "MIPI Toshiba WUXGA (1920x1200) Panel"
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+
 config FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT_PANEL
 	bool "MIPI NOVATEK VIDEO QHD PT Panel"
 	select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index bd7628d..2bdab74 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -114,7 +114,7 @@
 endif
 
 ifeq ($(CONFIG_FB_MSM_MIPI_PANEL_DETECT),y)
-obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o
+obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o mipi_toshiba_video_wuxga.o
 obj-y += mipi_novatek_video_qhd_pt.o mipi_novatek_cmd_qhd_pt.o
 obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
 obj-y += mipi_NT35510_video_wvga_pt.o mipi_NT35510_cmd_wvga_pt.o
@@ -124,6 +124,7 @@
 else
 obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT) += mipi_toshiba_video_wvga_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT) += mipi_toshiba_video_wsvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA) += mipi_toshiba_video_wuxga.o
 obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT) += mipi_novatek_video_qhd_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT) += mipi_novatek_cmd_qhd_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
diff --git a/drivers/video/msm/adv7520.c b/drivers/video/msm/adv7520.c
index b3b34bb..7386983 100644
--- a/drivers/video/msm/adv7520.c
+++ b/drivers/video/msm/adv7520.c
@@ -874,7 +874,11 @@
 	} else
 		DEV_ERR("adv7520_probe: failed to add fb device\n");
 
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+	external_common_state->sdev.name = "hdmi_as_primary";
+#else
 	external_common_state->sdev.name = "hdmi";
+#endif
 	if (switch_dev_register(&external_common_state->sdev) < 0)
 		DEV_ERR("Hdmi switch registration failed\n");
 
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 07a075c..0a86a50 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -480,16 +480,19 @@
 static ssize_t hdmi_msm_wta_cec_frame(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
+	int i;
 	int retry = ((struct hdmi_msm_cec_msg *) buf)->retransmit;
 
-	if (retry > 15)
-		retry = 15;
-	while (1) {
+	for (i = 0; i < RETRANSMIT_MAX_NUM; i++) {
 		hdmi_msm_cec_msg_send((struct hdmi_msm_cec_msg *) buf);
 		if (hdmi_msm_state->cec_frame_wr_status
-		    & CEC_STATUS_WR_ERROR && retry--)
+		    & CEC_STATUS_WR_ERROR && retry--) {
+			mutex_lock(&hdmi_msm_state_mutex);
+			if (hdmi_msm_state->fsm_reset_done)
+				retry++;
+			mutex_unlock(&hdmi_msm_state_mutex);
 			msleep(360);
-		else
+		} else
 			break;
 	}
 
@@ -911,8 +914,13 @@
 	uint32 offset = 4;
 
 	*len = 0;
-	if ((in_buf[2] == 4) && (type != 2)) { /* no non-DTD data present */
-		DEV_WARN("EDID: no non-DTD data present\n");
+
+	/*edid buffer 1, byte 2 being 4 means no non-DTD/Data block collection
+	  present.
+	  edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block collection
+	  present and no DTD data present.*/
+	if ((in_buf[2] == 0) || (in_buf[2] == 4)) {
+		DEV_WARN("EDID: no DTD or non-DTD data present\n");
 		return NULL;
 	}
 	while (offset < 0x80) {
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 93e6d40..ef357db 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -79,6 +79,8 @@
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 
+static void hdmi_msm_cec_line_latch_detect(void);
+
 #ifdef TOGGLE_CEC_HARDWARE_FSM
 static boolean msg_send_complete = TRUE;
 static boolean msg_recv_complete = TRUE;
@@ -111,7 +113,7 @@
 #define HDMI_MSM_CEC_INT_FRAME_WR_DONE_ACK		BIT(0)
 #define HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT		BIT(0)
 
-#define HDMI_MSM_CEC_FRAME_WR_SUCCESS(___st)         (((___st)&0xF) ==\
+#define HDMI_MSM_CEC_FRAME_WR_SUCCESS(___st)         (((___st)&0xB) ==\
 		(HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT |\
 			HDMI_MSM_CEC_INT_FRAME_WR_DONE_MASK |\
 			HDMI_MSM_CEC_INT_FRAME_ERROR_MASK))
@@ -142,8 +144,8 @@
 	 */
 	HDMI_OUTP(0x02A0, HDMI_MSM_CEC_ADDR_LOGICAL_ADDR(4));
 
-	/* 0x028C CEC_CTRL */
-	HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+	hdmi_msm_state->first_monitor = 0;
+	hdmi_msm_state->fsm_reset_done = false;
 
 	/* 0x029C CEC_INT */
 	/* Enable CEC interrupts */
@@ -161,7 +163,11 @@
 	 * BIT_1_ERR_RANGE_HI = 8 => 750us, the test used 775us,
 	 * so increased this to 9 which => 800us.
 	 */
-	HDMI_OUTP(0x02E0, 0x889788);
+	/*
+	 * CEC latch up issue - To fire monitor interrupt
+	 * for every start of message
+	 */
+	HDMI_OUTP(0x02E0, 0x880000);
 
 	/*
 	 * Slight adjustment to logic 0 low period on write
@@ -173,6 +179,8 @@
 	 */
 	HDMI_OUTP(0x02A4, 0x1 | (7 * 0x30) << 7);
 
+	/* 0x028C CEC_CTRL */
+	HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
 }
 
 void hdmi_msm_cec_write_logical_addr(int addr)
@@ -207,6 +215,9 @@
 
 	boolean frameType = (msg->recvr_id == 15 ? BIT(0) : 0);
 
+	mutex_lock(&hdmi_msm_state_mutex);
+	hdmi_msm_state->fsm_reset_done = false;
+	mutex_unlock(&hdmi_msm_state_mutex);
 #ifdef TOGGLE_CEC_HARDWARE_FSM
 	msg_send_complete = FALSE;
 #endif
@@ -278,9 +289,34 @@
 		msg_recv_complete = TRUE;
 	}
 	msg_send_complete = TRUE;
+#else
+	HDMI_OUTP(0x028C, 0x0);
+	HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
 #endif
 }
 
+void hdmi_msm_cec_line_latch_detect(void)
+{
+	/*
+	 * CECT 9-5-1
+	 * The timer period needs to be changed to appropriate value
+	 */
+	/*
+	 * Timedout without RD_DONE, WR_DONE or ERR_INT
+	 * Toggle CEC hardware FSM
+	 */
+	mutex_lock(&hdmi_msm_state_mutex);
+	if (hdmi_msm_state->first_monitor == 1) {
+		DEV_WARN("CEC line is probably latched up - CECT 9-5-1");
+		if (!msg_recv_complete)
+			hdmi_msm_state->fsm_reset_done = true;
+		HDMI_OUTP(0x028C, 0x0);
+		HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+		hdmi_msm_state->first_monitor = 0;
+	}
+	mutex_unlock(&hdmi_msm_state_mutex);
+}
+
 void hdmi_msm_cec_msg_recv(void)
 {
 	uint32 data;
@@ -476,6 +512,14 @@
 		temp_msg.frame_size = i + 2;
 		hdmi_msm_cec_msg_send(&temp_msg);
 		break;
+	case 0x44:
+		/* User Control Pressed */
+		DEV_INFO("User Control Pressed\n");
+		break;
+	case 0x45:
+		/* User Control Released */
+		DEV_INFO("User Control Released\n");
+		break;
 	default:
 		DEV_INFO("Recvd an unknown cmd = [%u]\n",
 			hdmi_msm_state->cec_queue_wr->opcode);
@@ -837,6 +881,13 @@
 	HDMI_OUTP(0x0254, 4 | (hpd_state ? 0 : 2));
 }
 
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_latch_work(struct work_struct *work)
+{
+	hdmi_msm_cec_line_latch_detect();
+}
+#endif
+
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 static void hdcp_deauthenticate(void);
 static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
@@ -1099,6 +1150,8 @@
 			HDMI_MSM_CEC_INT_FRAME_WR_DONE_ACK);
 		mutex_lock(&hdmi_msm_state_mutex);
 		hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_DONE;
+		hdmi_msm_state->first_monitor = 0;
+		del_timer(&hdmi_msm_state->cec_read_timer);
 		mutex_unlock(&hdmi_msm_state_mutex);
 		complete(&hdmi_msm_state->cec_frame_wr_done);
 		return IRQ_HANDLED;
@@ -1112,17 +1165,50 @@
 #endif
 		HDMI_OUTP(0x029C, cec_intr_status);
 		mutex_lock(&hdmi_msm_state_mutex);
+		hdmi_msm_state->first_monitor = 0;
+		del_timer(&hdmi_msm_state->cec_read_timer);
 		hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_ERROR;
 		mutex_unlock(&hdmi_msm_state_mutex);
 		complete(&hdmi_msm_state->cec_frame_wr_done);
 		return IRQ_HANDLED;
 	}
 
-	if ((cec_intr_status & (1 << 4)) && (cec_intr_status & (1 << 5)))
+	if ((cec_intr_status & (1 << 4)) && (cec_intr_status & (1 << 5))) {
 		DEV_DBG("CEC_IRQ_MONITOR\n");
+		HDMI_OUTP(0x029C, cec_intr_status |
+			  HDMI_MSM_CEC_INT_MONITOR_ACK);
+
+		/*
+		 * CECT 9-5-1
+		 * On the first occassion start a timer
+		 * for few hundred ms, if it expires then
+		 * reset the CEC block else go on with
+		 * frame transactions as usual.
+		 * Below adds hdmi_msm_cec_msg_recv() as an
+		 * item into the work queue instead of running in
+		 * interrupt context
+		 */
+		mutex_lock(&hdmi_msm_state_mutex);
+		if (hdmi_msm_state->first_monitor == 0) {
+			/* This timer might have to be changed
+			 * worst case theoritical =
+			 * 16 bytes * 8 * 2.7msec = 346 msec
+			 */
+			mod_timer(&hdmi_msm_state->cec_read_timer,
+					jiffies + HZ/2);
+			hdmi_msm_state->first_monitor = 1;
+		}
+		mutex_unlock(&hdmi_msm_state_mutex);
+		return IRQ_HANDLED;
+	}
 
 	if ((cec_intr_status & (1 << 6)) && (cec_intr_status & (1 << 7))) {
 		DEV_DBG("CEC_IRQ_FRAME_RD_DONE\n");
+
+		mutex_lock(&hdmi_msm_state_mutex);
+		hdmi_msm_state->first_monitor = 0;
+		del_timer(&hdmi_msm_state->cec_read_timer);
+		mutex_unlock(&hdmi_msm_state_mutex);
 		HDMI_OUTP(0x029C, cec_intr_status |
 			HDMI_MSM_CEC_INT_FRAME_RD_DONE_ACK);
 		hdmi_msm_cec_msg_recv();
@@ -1135,6 +1221,9 @@
 			HDMI_OUTP(0x028C, 0x0);
 			HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
 		}
+#else
+		HDMI_OUTP(0x028C, 0x0);
+		HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
 #endif
 
 		return IRQ_HANDLED;
@@ -2371,6 +2460,8 @@
 		[8] AN_0_READY
 		[9] AN_1_READY */
 		/* wait for an0 and an1 ready bits to be set in LINK0_STATUS */
+
+		mutex_lock(&hdcp_auth_state_mutex);
 		timeout_count = 100;
 		while (((HDMI_INP_ND(0x011C) & (0x3 << 8)) != (0x3 << 8))
 			&& timeout_count--)
@@ -2404,6 +2495,7 @@
 		   [31:0] LINK0_AN_1 */
 		/* read an1 calculation */
 		link0_an_1 = HDMI_INP(0x0150);
+		mutex_unlock(&hdcp_auth_state_mutex);
 
 		/* three bits 28..30 */
 		hdcp_key_state((HDMI_INP(0x011C) >> 28) & 0x7);
@@ -3867,7 +3959,11 @@
 			"AUDIO CFG is %08x", i, audio_pkt_ctrl, audio_cfg);
 		msleep(20);
 	}
+
+	mutex_lock(&hdcp_auth_state_mutex);
 	hdmi_msm_reset_core();
+	mutex_unlock(&hdcp_auth_state_mutex);
+
 	hdmi_msm_init_phy(external_common_state->video_resolution);
 	/* HDMI_USEC_REFTIMER[0x0208] */
 	HDMI_OUTP(0x0208, 0x0001001B);
@@ -3924,6 +4020,13 @@
 }
 #endif
 
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_read_timer_func(unsigned long data)
+{
+	queue_work(hdmi_work_queue, &hdmi_msm_state->cec_latch_detect_work);
+}
+#endif
+
 static void hdmi_msm_hpd_read_work(struct work_struct *work)
 {
 	uint32 hpd_ctrl;
@@ -3959,12 +4062,18 @@
 
 static void hdmi_msm_hpd_off(void)
 {
+	if (!hdmi_msm_state->hpd_initialized) {
+		DEV_DBG("%s: HPD is already OFF, returning\n", __func__);
+		return;
+	}
+
 	DEV_DBG("%s: (timer, clk, 5V, core, IRQ off)\n", __func__);
 	del_timer(&hdmi_msm_state->hpd_state_timer);
 	disable_irq(hdmi_msm_state->irq);
 
 	hdmi_msm_set_mode(FALSE);
 	hdmi_msm_state->hpd_initialized = FALSE;
+	hdmi_msm_powerdown_phy();
 	hdmi_msm_state->pd->cec_power(0);
 	hdmi_msm_state->pd->enable_5v(0);
 	hdmi_msm_state->pd->core_power(0, 1);
@@ -3983,6 +4092,12 @@
 static int hdmi_msm_hpd_on(bool trigger_handler)
 {
 	static int phy_reset_done;
+	uint32 hpd_ctrl;
+
+	if (hdmi_msm_state->hpd_initialized) {
+		DEV_DBG("%s: HPD is already ON, returning\n", __func__);
+		return 0;
+	}
 
 	hdmi_msm_clk(1);
 	hdmi_msm_state->pd->core_power(1, 1);
@@ -4000,36 +4115,34 @@
 	HDMI_OUTP(0x0208, 0x0001001B);
 
 	/* Check HPD State */
-	if (!hdmi_msm_state->hpd_initialized) {
-		uint32 hpd_ctrl;
-		enable_irq(hdmi_msm_state->irq);
+	enable_irq(hdmi_msm_state->irq);
 
-		/* set timeout to 4.1ms (max) for hardware debounce */
-		hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
+	/* set timeout to 4.1ms (max) for hardware debounce */
+	hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
 
-		/* Toggle HPD circuit to trigger HPD sense */
-		HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
-		HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
+	/* Toggle HPD circuit to trigger HPD sense */
+	HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
+	HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
 
-		DEV_DBG("%s: (clk, 5V, core, IRQ on) <trigger:%s>\n", __func__,
-			trigger_handler ? "true" : "false");
+	DEV_DBG("%s: (clk, 5V, core, IRQ on) <trigger:%s>\n", __func__,
+		trigger_handler ? "true" : "false");
 
-		if (trigger_handler) {
-			/* Set HPD state machine: ensure at least 2 readouts */
-			mutex_lock(&hdmi_msm_state_mutex);
-			hdmi_msm_state->hpd_stable = 0;
-			hdmi_msm_state->hpd_prev_state = TRUE;
-			mutex_lock(&external_common_state_hpd_mutex);
-			external_common_state->hpd_state = FALSE;
-			mutex_unlock(&external_common_state_hpd_mutex);
-			hdmi_msm_state->hpd_cable_chg_detected = TRUE;
-			mutex_unlock(&hdmi_msm_state_mutex);
-			mod_timer(&hdmi_msm_state->hpd_state_timer,
-				jiffies + HZ/2);
-		}
-
-		hdmi_msm_state->hpd_initialized = TRUE;
+	if (trigger_handler) {
+		/* Set HPD state machine: ensure at least 2 readouts */
+		mutex_lock(&hdmi_msm_state_mutex);
+		hdmi_msm_state->hpd_stable = 0;
+		hdmi_msm_state->hpd_prev_state = TRUE;
+		mutex_lock(&external_common_state_hpd_mutex);
+		external_common_state->hpd_state = FALSE;
+		mutex_unlock(&external_common_state_hpd_mutex);
+		hdmi_msm_state->hpd_cable_chg_detected = TRUE;
+		mutex_unlock(&hdmi_msm_state_mutex);
+		mod_timer(&hdmi_msm_state->hpd_state_timer,
+			jiffies + HZ/2);
 	}
+
+	hdmi_msm_state->hpd_initialized = TRUE;
+
 	hdmi_msm_set_mode(TRUE);
 
 	return 0;
@@ -4248,6 +4361,15 @@
 	add_timer(&hdmi_msm_state->hdcp_timer);
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+	init_timer(&hdmi_msm_state->cec_read_timer);
+	hdmi_msm_state->cec_read_timer.function =
+		hdmi_msm_cec_read_timer_func;
+	hdmi_msm_state->cec_read_timer.data = (uint32)NULL;
+
+	hdmi_msm_state->cec_read_timer.expires = 0xffffffffL;
+ #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+
 	fb_dev = msm_fb_add_device(pdev);
 	if (fb_dev) {
 		rc = external_common_state_create(fb_dev);
@@ -4285,7 +4407,11 @@
 	queue_work(hdmi_work_queue, &hdmi_msm_state->hpd_read_work);
 
 	/* Initialize hdmi node and register with switch driver */
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+	external_common_state->sdev.name = "hdmi_as_primary";
+#else
 	external_common_state->sdev.name = "hdmi";
+#endif
 	if (switch_dev_register(&external_common_state->sdev) < 0)
 		DEV_ERR("Hdmi switch registration failed\n");
 
@@ -4452,7 +4578,10 @@
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+	INIT_WORK(&hdmi_msm_state->cec_latch_detect_work,
+		  hdmi_msm_cec_latch_work);
 	init_completion(&hdmi_msm_state->cec_frame_wr_done);
+	init_completion(&hdmi_msm_state->cec_line_latch_wait);
 #endif
 
 	rc = platform_device_register(&this_device);
diff --git a/drivers/video/msm/hdmi_msm.h b/drivers/video/msm/hdmi_msm.h
index 6d19d157..9675fd5 100644
--- a/drivers/video/msm/hdmi_msm.h
+++ b/drivers/video/msm/hdmi_msm.h
@@ -75,8 +75,10 @@
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 	boolean cec_enabled;
+	unsigned int first_monitor;
 	int cec_logical_addr;
 	struct completion cec_frame_wr_done;
+	struct timer_list cec_read_timer;
 #define CEC_STATUS_WR_ERROR	0x0001
 #define CEC_STATUS_WR_DONE	0x0002
 #define CEC_STATUS_WR_TMOUT	0x0004
@@ -86,8 +88,17 @@
 	struct hdmi_msm_cec_msg *cec_queue_wr;
 	struct hdmi_msm_cec_msg *cec_queue_rd;
 	boolean cec_queue_full;
+	boolean fsm_reset_done;
+
+	/*
+	 * CECT 9-5-1
+	 */
+	struct completion cec_line_latch_wait;
+	struct work_struct cec_latch_detect_work;
+
 #define CEC_QUEUE_SIZE		16
 #define CEC_QUEUE_END	 (hdmi_msm_state->cec_queue_start + CEC_QUEUE_SIZE)
+#define RETRANSMIT_MAX_NUM	7
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
 
 	int irq;
diff --git a/drivers/video/msm/lcdc_gordon.c b/drivers/video/msm/lcdc_gordon.c
index f9532b4..8327c6c 100644
--- a/drivers/video/msm/lcdc_gordon.c
+++ b/drivers/video/msm/lcdc_gordon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-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
@@ -84,6 +84,7 @@
 static int spi_sdo;
 static int spi_sdi;
 static int spi_dac;
+static int bl_level;
 static unsigned char bit_shift[8] = { (1 << 7),	/* MSB */
 	(1 << 6),
 	(1 << 5),
@@ -313,6 +314,17 @@
 		spi_init();	/* LCD needs SPI */
 		gordon_disp_powerup();
 		gordon_disp_on();
+		if (bl_level <= 1) {
+			/* keep back light OFF */
+			serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+			udelay(15);
+			serigo(GORDON_REG_VALTRAN, 0x01);
+		} else {
+			/* keep back light ON */
+			serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+			udelay(15);
+			serigo(GORDON_REG_VALTRAN, 0x01);
+		}
 		gordon_state.disp_initialized = TRUE;
 	}
 	return 0;
@@ -351,18 +363,20 @@
 
 static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
 {
-		int bl_level = mfd->bl_level;
+		bl_level = mfd->bl_level;
 
-		if (bl_level <= 1) {
-			/* keep back light OFF */
-			serigo(GORDON_REG_LCDIFCTL2, 0x0B);
-			udelay(15);
-			serigo(GORDON_REG_VALTRAN, 0x01);
-		} else {
-			/* keep back light ON */
-			serigo(GORDON_REG_LCDIFCTL2, 0x7B);
-			udelay(15);
-			serigo(GORDON_REG_VALTRAN, 0x01);
+		if (gordon_state.disp_initialized) {
+			if (bl_level <= 1) {
+				/* keep back light OFF */
+				serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+				udelay(15);
+				serigo(GORDON_REG_VALTRAN, 0x01);
+			} else {
+				/* keep back light ON */
+				serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+				udelay(15);
+				serigo(GORDON_REG_VALTRAN, 0x01);
+			}
 		}
 }
 
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 43520e0..d8987e2 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -86,6 +86,9 @@
 struct workqueue_struct *mdp_dma_wq;	/*mdp dma wq */
 struct workqueue_struct *mdp_vsync_wq;	/*mdp vsync wq */
 
+struct workqueue_struct *mdp_hist_wq;	/*mdp histogram wq */
+struct work_struct mdp_histogram_worker;
+
 static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
 static struct delayed_work mdp_pipe_ctrl_worker;
 
@@ -211,8 +214,8 @@
 	}
 
 	/*mask off non LUT select bits*/
-	out = inpdw(MDP_BASE + 0x90070) & ~(0x1 << 10);
-	MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | out);
+	out = inpdw(MDP_BASE + 0x90070) & ~((0x1 << 10) | 0x7);
+	MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x7 | out);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 	mdp_lut_i = (mdp_lut_i + 1)%2;
 
@@ -225,9 +228,9 @@
 	if (mdp_lut_push) {
 		mutex_lock(&mdp_lut_push_sem);
 		mdp_lut_push = 0;
-		out = inpdw(MDP_BASE + 0x90070) & ~(0x1 << 10);
+		out = inpdw(MDP_BASE + 0x90070) & ~((0x1 << 10) | 0x7);
 		MDP_OUTP(MDP_BASE + 0x90070,
-				(mdp_lut_push_i << 10) | out);
+				(mdp_lut_push_i << 10) | 0x7 | out);
 		mutex_unlock(&mdp_lut_push_sem);
 	}
 }
@@ -237,20 +240,112 @@
 
 #ifdef CONFIG_FB_MSM_MDP40
 unsigned int mdp_hist_frame_cnt;
-struct completion mdp_hist_comp;
-boolean mdp_is_hist_start = FALSE;
 #else
 static unsigned int mdp_hist_frame_cnt;
-static struct completion mdp_hist_comp;
-static boolean mdp_is_hist_start = FALSE;
 #endif
+struct completion mdp_hist_comp;
 static DEFINE_MUTEX(mdp_hist_mutex);
 static boolean mdp_is_hist_data = FALSE;
+static boolean mdp_is_hist_start = FALSE;
+boolean mdp_is_hist_valid = FALSE;
+static boolean mdp_is_hist_init = FALSE;
+static uint32 mdp_hist_r[128];
+static uint32 mdp_hist_g[128];
+static uint32 mdp_hist_b[128];
+
+void __mdp_histogram_kickoff()
+{
+	char *mdp_hist_base;
+
+	if (mdp_rev >= MDP_REV_40)
+		mdp_hist_base = MDP_BASE + 0x95000;
+	else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31)
+		mdp_hist_base = MDP_BASE + 0x94000;
+	else {
+		pr_err("%s(): Unsupported MDP rev. %u\n", __func__, mdp_rev);
+		return ;
+	}
+
+	if (mdp_is_hist_data == TRUE) {
+		MDP_OUTP(mdp_hist_base + 0x004,	mdp_hist_frame_cnt);
+		MDP_OUTP(mdp_hist_base, 1);
+	}
+}
+
+void __mdp_histogram_reset()
+{
+	char *mdp_hist_base;
+
+	if (mdp_rev >= MDP_REV_40)
+		mdp_hist_base = MDP_BASE + 0x95000;
+	else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31)
+		mdp_hist_base = MDP_BASE + 0x94000;
+	else {
+		pr_err("%s(): Unsupported MDP rev %u\n", __func__, mdp_rev);
+		return ;
+	}
+
+	MDP_OUTP(mdp_hist_base + 0x00C, 1);
+}
+
+static void mdp_hist_read_work(struct work_struct *data)
+{
+	char *mdp_hist_base;
+	uint32 r_data_offset = 0x100, g_data_offset = 0x200;
+	uint32 b_data_offset = 0x300;
+	int num_bins, i = 0;
+
+	if (mdp_rev >= MDP_REV_42) {
+		mdp_hist_base = MDP_BASE + 0x95000;
+		r_data_offset = 0x400;
+		g_data_offset = 0x800;
+		b_data_offset = 0xc00;
+		num_bins = 128;
+	} else if (mdp_rev >= MDP_REV_40 && mdp_rev <= MDP_REV_41) {
+		mdp_hist_base = MDP_BASE + 0x95000;
+		num_bins = 32;
+	} else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31) {
+		mdp_hist_base = MDP_BASE + 0x94000;
+		num_bins = 32;
+	} else {
+		pr_err("%s(): Unsupported MDP rev %u\n", __func__, mdp_rev);
+		return ;
+	}
+
+	mutex_lock(&mdp_hist_mutex);
+	if (mdp_is_hist_data == FALSE) {
+		pr_debug("%s, Histogram disabled before read.\n", __func__);
+		goto error;
+	}
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	for (i = 0; i < num_bins; i++) {
+		mdp_hist_r[i] = inpdw(mdp_hist_base + r_data_offset + (4*i));
+		mdp_hist_g[i] = inpdw(mdp_hist_base + g_data_offset + (4*i));
+		mdp_hist_b[i] = inpdw(mdp_hist_base + b_data_offset + (4*i));
+	}
+
+	__mdp_histogram_kickoff();
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	/* if read was triggered by an underrun, don't wake up readers*/
+	if (mdp_is_hist_valid && mdp_is_hist_init) {
+		complete(&mdp_hist_comp);
+	} else {
+		if (mdp_is_hist_valid == FALSE)
+			mdp_is_hist_valid = TRUE;
+
+		if (mdp_is_hist_init == FALSE)
+			mdp_is_hist_init = TRUE;
+	}
+error:
+	mutex_unlock(&mdp_hist_mutex);
+}
 
 /*should hold mdp_hist_mutex before calling this function*/
 int _mdp_histogram_ctrl(boolean en)
 {
-	unsigned long flag;
 	unsigned long hist_base;
 	uint32_t status;
 
@@ -266,34 +361,40 @@
 		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 		mdp_hist_frame_cnt = 1;
 		mdp_enable_irq(MDP_HISTOGRAM_TERM);
-		spin_lock_irqsave(&mdp_spin_lock, flag);
-		if (mdp_rev >= MDP_REV_40) {
-			MDP_OUTP(MDP_BASE + hist_base + 0x10, 1);
-			MDP_OUTP(MDP_BASE + hist_base + 0x1c, INTR_HIST_DONE);
-		}
-		spin_unlock_irqrestore(&mdp_spin_lock, flag);
-		MDP_OUTP(MDP_BASE + hist_base + 0x4, mdp_hist_frame_cnt);
-		MDP_OUTP(MDP_BASE + hist_base, 1);
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+		INIT_COMPLETION(mdp_hist_comp);
+
+		/*Clear the interrupts before enabling them*/
+		MDP_OUTP(MDP_BASE + hist_base + 0x18, INTR_HIST_DONE |
+						INTR_HIST_RESET_SEQ_DONE);
+		MDP_OUTP(MDP_BASE + hist_base + 0x10, 1);
+		MDP_OUTP(MDP_BASE + hist_base + 0x1c, INTR_HIST_DONE |
+						INTR_HIST_RESET_SEQ_DONE);
+
 		mdp_is_hist_data = TRUE;
+		mdp_is_hist_valid = TRUE;
+		mdp_is_hist_init = FALSE;
+
+		__mdp_histogram_reset();
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
 	} else {
 		if (!mdp_is_hist_data)
 			return -EINVAL;
 
 		mdp_is_hist_data = FALSE;
+		mdp_is_hist_valid = FALSE;
+		mdp_is_hist_init = FALSE;
+
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		status = inpdw(MDP_BASE + hist_base + 0x1C);
+		status &= ~(INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+		MDP_OUTP(MDP_BASE + hist_base + 0x1C, status);
+		MDP_OUTP(MDP_BASE + hist_base + 0x18, INTR_HIST_DONE |
+						INTR_HIST_RESET_SEQ_DONE);
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
 		complete(&mdp_hist_comp);
 
-		if (mdp_rev >= MDP_REV_40) {
-			mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-			status = inpdw(MDP_BASE + hist_base + 0x1C);
-			status &= ~INTR_HIST_DONE;
-			MDP_OUTP(MDP_BASE + hist_base + 0x1C, status);
-
-			MDP_OUTP(MDP_BASE + hist_base + 0x18, INTR_HIST_DONE);
-			mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
-									FALSE);
-		}
-
 		mdp_disable_irq(MDP_HISTOGRAM_TERM);
 	}
 
@@ -307,6 +408,10 @@
 	if (mdp_is_hist_start)
 		ret = _mdp_histogram_ctrl(en);
 	mutex_unlock(&mdp_hist_mutex);
+
+	if (en == false)
+		flush_workqueue(mdp_hist_wq);
+
 	return ret;
 }
 
@@ -361,6 +466,10 @@
 
 	ret = _mdp_histogram_ctrl(FALSE);
 
+	mutex_unlock(&mdp_hist_mutex);
+	flush_workqueue(mdp_hist_wq);
+	return ret;
+
 mdp_hist_stop_err:
 	mutex_unlock(&mdp_hist_mutex);
 	return ret;
@@ -369,55 +478,26 @@
 /*call from within mdp_hist_mutex*/
 static int _mdp_copy_hist_data(struct mdp_histogram *hist)
 {
-	char *mdp_hist_base;
-	uint32 r_data_offset = 0x100, g_data_offset = 0x200;
-	uint32 b_data_offset = 0x300;
 	int ret = 0;
 
-	if (mdp_rev >= MDP_REV_42) {
-		mdp_hist_base = MDP_BASE + 0x95000;
-		r_data_offset = 0x400;
-		g_data_offset = 0x800;
-		b_data_offset = 0xc00;
-	} else if (mdp_rev >= MDP_REV_40 && mdp_rev <= MDP_REV_41) {
-		mdp_hist_base = MDP_BASE + 0x95000;
-	} else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31) {
-		mdp_hist_base = MDP_BASE + 0x94000;
-	} else {
-		pr_err("%s(): Unsupported MDP rev %u\n", __func__, mdp_rev);
-		return -EPERM;
-	}
-
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	if (hist->r) {
-		ret = copy_to_user(hist->r, mdp_hist_base + r_data_offset,
-			hist->bin_cnt * 4);
+		ret = copy_to_user(hist->r, mdp_hist_r, hist->bin_cnt * 4);
 		if (ret)
 			goto hist_err;
 	}
 	if (hist->g) {
-		ret = copy_to_user(hist->g, mdp_hist_base + g_data_offset,
-			hist->bin_cnt * 4);
+		ret = copy_to_user(hist->g, mdp_hist_g, hist->bin_cnt * 4);
 		if (ret)
 			goto hist_err;
 	}
 	if (hist->b) {
-		ret = copy_to_user(hist->b, mdp_hist_base + b_data_offset,
-			hist->bin_cnt * 4);
+		ret = copy_to_user(hist->b, mdp_hist_b, hist->bin_cnt * 4);
 		if (ret)
 			goto hist_err;
 	}
-
-	if (mdp_is_hist_start == TRUE) {
-		MDP_OUTP(mdp_hist_base + 0x004,
-				mdp_hist_frame_cnt);
-		MDP_OUTP(mdp_hist_base, 1);
-	}
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 	return 0;
-
 hist_err:
-	printk(KERN_ERR "%s: invalid hist buffer\n", __func__);
+	pr_err("%s: invalid hist buffer\n", __func__);
 	return ret;
 }
 
@@ -435,17 +515,17 @@
 
 	mutex_lock(&mdp_hist_mutex);
 	if (!mdp_is_hist_data) {
-		ret = -EINVAL;
-		goto error;
-	}
-
-	if (!mdp_is_hist_start) {
-		printk(KERN_ERR "%s histogram not started\n", __func__);
+		pr_err("%s - histogram not ready\n", __func__);
 		ret = -EPERM;
 		goto error;
 	}
 
-	INIT_COMPLETION(mdp_hist_comp);
+	if (!mdp_is_hist_start) {
+		pr_err("%s histogram not started\n", __func__);
+		ret = -EPERM;
+		goto error;
+	}
+
 	mdp_hist_frame_cnt = hist->frame_cnt;
 	mutex_unlock(&mdp_hist_mutex);
 
@@ -455,8 +535,9 @@
 	}
 
 	mutex_lock(&mdp_hist_mutex);
-	if (mdp_is_hist_data)
+	if (mdp_is_hist_data && mdp_is_hist_init)
 		ret =  _mdp_copy_hist_data(hist);
+
 error:
 	mutex_unlock(&mdp_hist_mutex);
 	return ret;
@@ -818,7 +899,7 @@
 #ifndef CONFIG_FB_MSM_MDP40
 irqreturn_t mdp_isr(int irq, void *ptr)
 {
-	uint32 mdp_interrupt = 0;
+	uint32 hist_interrupt, mdp_interrupt = 0;
 	struct mdp_dma_data *dma;
 	unsigned long flag;
 
@@ -853,37 +934,48 @@
 	}
 #ifndef CONFIG_FB_MSM_MDP22
 	if (mdp_interrupt & MDP_HIST_DONE) {
+		hist_interrupt = inp32(MDP_DMA_P_HIST_INTR_STATUS);
 		outp32(MDP_BASE + 0x94018, 0x3);
 		outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
-		complete(&mdp_hist_comp);
+		if (hist_interrupt & INTR_HIST_RESET_SEQ_DONE)
+			__mdp_histogram_kickoff();
+
+		if (hist_interrupt & INTR_HIST_DONE) {
+			if (waitqueue_active(&mdp_hist_comp.wait)) {
+				if (!queue_work(mdp_hist_wq,
+						&mdp_histogram_worker)) {
+					pr_err("%s: can't queue hist_read\n",
+								__func__);
+				}
+			} else
+				__mdp_histogram_reset();
+		}
 	}
 
 	/* LCDC UnderFlow */
 	if (mdp_interrupt & LCDC_UNDERFLOW) {
 		mdp_lcdc_underflow_cnt++;
 		/*when underflow happens HW resets all the histogram
-		 registers that were set before so restore them back
-		 to normal.*/
+		  registers that were set before so restore them back
+		  to normal.*/
 		MDP_OUTP(MDP_BASE + 0x94010, 1);
-		MDP_OUTP(MDP_BASE + 0x9401c, 2);
-		if (mdp_is_hist_start == TRUE) {
-			MDP_OUTP(MDP_BASE + 0x94004,
-					 mdp_hist_frame_cnt);
-			MDP_OUTP(MDP_BASE + 0x94000, 1);
-		}
+		MDP_OUTP(MDP_BASE + 0x9401c, INTR_HIST_DONE);
+		mdp_is_hist_valid = FALSE;
+		__mdp_histogram_reset();
 	}
 
 	/* LCDC Frame Start */
 	if (mdp_interrupt & LCDC_FRAME_START) {
+		dma = &dma2_data;
+		spin_lock_irqsave(&mdp_spin_lock, flag);
 		/* let's disable LCDC interrupt */
 		mdp_intr_mask &= ~LCDC_FRAME_START;
 		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-
-		dma = &dma2_data;
 		if (dma->waiting) {
 			dma->waiting = FALSE;
 			complete(&dma->comp);
 		}
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	}
 
 	/* DMA2 LCD-Out Complete */
@@ -968,6 +1060,8 @@
 	spin_lock_init(&mdp_spin_lock);
 	mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
 	mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
+	mdp_hist_wq = create_singlethread_workqueue("mdp_hist_wq");
+	INIT_WORK(&mdp_histogram_worker, mdp_hist_read_work);
 	mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
 	INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
 			  mdp_pipe_ctrl_workqueue_handler);
@@ -1008,8 +1102,6 @@
 	mutex_init(&dma_wb_data.ov_mutex);
 #endif
 
-
-
 #ifndef CONFIG_FB_MSM_MDP22
 	init_completion(&mdp_hist_comp);
 #endif
@@ -1127,7 +1219,6 @@
 	}
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 #endif
-	mdp_histogram_ctrl(TRUE);
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	ret = panel_next_on(pdev);
@@ -1140,6 +1231,7 @@
 		mdp4_mddi_overlay_restore();
 #endif
 
+	mdp_histogram_ctrl(TRUE);
 	return ret;
 }
 
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 35a1453..3d3668e 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -44,6 +44,10 @@
 extern int mdp_rev;
 extern struct mdp_csc_cfg mdp_csc_convert[4];
 
+extern struct workqueue_struct *mdp_hist_wq;
+extern struct work_struct mdp_histogram_worker;
+extern boolean mdp_is_hist_valid;
+
 #define MDP4_REVISION_V1		0
 #define MDP4_REVISION_V2		1
 #define MDP4_REVISION_V2_1	2
@@ -606,6 +610,10 @@
 #define MDP_EBI2_LCD0		(msm_mdp_base + 0x003c)
 #define MDP_EBI2_LCD1		(msm_mdp_base + 0x0040)
 #define MDP_EBI2_PORTMAP_MODE	(msm_mdp_base + 0x005c)
+
+#define MDP_DMA_P_HIST_INTR_STATUS	(msm_mdp_base + 0x94014)
+#define MDP_DMA_P_HIST_INTR_CLEAR	(msm_mdp_base + 0x94018)
+#define MDP_DMA_P_HIST_INTR_ENABLE	(msm_mdp_base + 0x9401C)
 #endif
 
 #define MDP_FULL_BYPASS_WORD43  (msm_mdp_base + 0x101ac)
@@ -733,6 +741,8 @@
 int mdp_start_histogram(struct fb_info *info);
 int mdp_stop_histogram(struct fb_info *info);
 int mdp_histogram_ctrl(boolean en);
+void __mdp_histogram_kickoff(void);
+void __mdp_histogram_reset(void);
 void mdp_footswitch_ctrl(boolean on);
 
 #ifdef CONFIG_FB_MSM_MDP303
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 155bc54..77e8cd1 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -20,7 +20,6 @@
 extern struct mdp_dma_data dma_wb_data;
 extern unsigned int mdp_hist_frame_cnt;
 extern struct completion mdp_hist_comp;
-extern boolean mdp_is_hist_start;
 extern boolean mdp_is_in_isr;
 extern uint32 mdp_intr_mask;
 extern spinlock_t mdp_spin_lock;
@@ -713,6 +712,8 @@
 int mdp4_csc_config(struct mdp_csc_cfg_data *config);
 void mdp4_csc_write(struct mdp_csc_cfg *data, uint32_t base);
 int mdp4_csc_enable(struct mdp_csc_cfg_data *config);
+int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr);
+int mdp4_pgc_cfg(struct mdp_pgc_lut_data *pgc_ptr);
 
 u32  mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
 void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index bf53c73..a9efc1c 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -370,17 +370,18 @@
 
 static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
 {
-	uint32 val;
+	uint32 val, s;
 	int	n;
 
 	n = mdp4_leading_0(src);
 	if (n > f_num)
 		n = f_num;
-	val = src << n;	/* maximum to reduce lose of resolution */
-	val /= dst;
+	s = src << n;	/* maximum to reduce lose of resolution */
+	val = s / dst;
 	if (n < f_num) {
 		n = f_num - n;
 		val <<= n;
+		val |= ((s % dst) << n) / dst;
 	}
 
 	return val;
@@ -1303,6 +1304,11 @@
 	u32 data = 0, stage, flush_bits = 0, pipe_cnt = 0, pull_mode = 0;
 	u32 cfg[MDP4_MIXER_MAX];
 
+	if (mixer == MDP4_MIXER0)
+		flush_bits |= 0x1;
+	else if (mixer == MDP4_MIXER1)
+		flush_bits |= 0x2;
+
 	for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++) {
 		cfg[i] = 0;
 		for (j = MDP4_MIXER_STAGE_BASE; j < MDP4_MIXER_STAGE_MAX; j++) {
@@ -2031,7 +2037,8 @@
 	}
 }
 
-static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req)
+static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req,
+					  struct msm_fb_data_type *mfd)
 {
 	int is_fg;
 
@@ -2055,9 +2062,18 @@
 		return OVERLAY_PERF_LEVEL1;
 
 	if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE)
-		return OVERLAY_PERF_LEVEL3;
-	else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE)
-		return OVERLAY_PERF_LEVEL2;
+		return OVERLAY_PERF_LEVEL4;
+	else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE) {
+		u32 max, min;
+		max = (req->dst_rect.h > req->dst_rect.w) ?
+			req->dst_rect.h : req->dst_rect.w;
+		min = (mfd->panel_info.yres > mfd->panel_info.xres) ?
+			mfd->panel_info.xres : mfd->panel_info.yres;
+		if (max > min)	/* landscape mode */
+			return OVERLAY_PERF_LEVEL3;
+		else		/* potrait mode */
+			return OVERLAY_PERF_LEVEL2;
+	}
 	else
 		return OVERLAY_PERF_LEVEL1;
 }
@@ -2163,7 +2179,7 @@
 		return -EINTR;
 	}
 
-	perf_level = mdp4_overlay_get_perf_level(req);
+	perf_level = mdp4_overlay_get_perf_level(req, mfd);
 
 	mixer = mfd->panel_info.pdest;	/* DISPLAY_1 or DISPLAY_2 */
 
@@ -2342,6 +2358,9 @@
 	mdp4_stat.overlay_unset[pipe->mixer_num]++;
 
 	mdp4_overlay_pipe_free(pipe);
+
+	mdp4_set_perf_level();
+
 	mutex_unlock(&mfd->dma->ov_mutex);
 
 	return 0;
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index 5cdafe1..0b707d7 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -38,13 +38,16 @@
 {
 	uint8 *buf;
 	int bpp, ptype;
+	int yres, remainder;
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info;
 	int ret;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -55,10 +58,28 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	if (atv_pipe == NULL) {
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -150,16 +171,36 @@
 	uint8 *buf;
 	int bpp;
 	unsigned long flag;
+	int yres, remainder;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* no need to power on cmd block since it's lcdc mode */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	mutex_lock(&mfd->dma->ov_mutex);
 
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 3f12827..a3be2af 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -96,13 +96,16 @@
 	int hsync_end_x;
 	uint8 *buf;
 	int bpp, ptype;
+	int yres, remainder;
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info;
 	int ret;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -115,10 +118,28 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	if (dsi_pipe == NULL) {
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -295,7 +316,9 @@
 {
 	struct fb_info *fbi;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 	int bpp;
+	int yres, remainder;
 	uint8 *buf = NULL;
 
 	if (dsi_pipe == NULL)
@@ -314,10 +337,28 @@
 
 	fbi = mfd->fbi;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	if (pipe->is_3d) {
 		pipe->src_height = pipe->src_height_3d;
@@ -648,16 +689,36 @@
 	struct fb_info *fbi = mfd->fbi;
 	uint8 *buf;
 	int bpp;
+	int yres, remainder;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* no need to power on cmd block since it's dsi video mode */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	mutex_lock(&mfd->dma->ov_mutex);
 
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 3a1a9aa..590ad65 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -231,8 +231,15 @@
 		return -EINVAL;
 
 	mdp4_overlay_panel_mode(MDP4_MIXER1, MDP4_PANEL_DTV);
-	if (dtv_pipe != NULL)
-		ret = mdp4_dtv_start(mfd);
+
+	/* Allocate dtv_pipe at dtv_on*/
+	if (dtv_pipe == NULL) {
+		if (mdp4_overlay_dtv_set(mfd, NULL)) {
+			pr_warn("%s: dtv_pipe is NULL, dtv_set failed\n",
+				__func__);
+			return -EINVAL;
+		}
+	}
 
 	ret = panel_next_on(pdev);
 	if (ret != 0)
@@ -527,7 +534,7 @@
 	*/
 	temp_src_format = inpdw(rgb_base + 0x0050);
 	MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(dtv_pipe);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 #endif
@@ -604,14 +611,6 @@
 		return;
 
 	mutex_lock(&mfd->dma->ov_mutex);
-	if (dtv_pipe == NULL) {
-		if (mdp4_overlay_dtv_set(mfd, NULL)) {
-			pr_warn("%s: dtv_pipe == NULL\n", __func__);
-			mutex_unlock(&mfd->dma->ov_mutex);
-			return;
-		}
-	}
-
 	pipe = dtv_pipe;
 	if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
 		pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 3dece1f..ae498fc 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -84,8 +84,11 @@
 	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *pipe;
 	int ret;
+	int yres, remainder;
+	struct msm_panel_info *panel_info;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -98,6 +101,17 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	if (is_mdp4_hw_reset()) {
@@ -107,8 +121,15 @@
 
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	if (lcdc_pipe == NULL) {
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -552,16 +573,36 @@
 	struct fb_info *fbi = mfd->fbi;
 	uint8 *buf;
 	int bpp;
+	int yres, remainder;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* no need to power on cmd block since it's lcdc mode */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	mutex_lock(&mfd->dma->ov_mutex);
 
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index cd4afd0..7739837 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -394,20 +394,49 @@
 		temp = kzalloc(sizeof(struct msmfb_writeback_data_list),
 				GFP_KERNEL);
 		if (temp == NULL) {
-			pr_err("Out of memory\n");
-			goto err;
+			pr_err("%s: out of memory\n", __func__);
+			goto register_alloc_fail;
 		}
 
-		temp->addr = (void *)(data->iova + data->offset);
+		if (data->iova)
+			temp->addr = (void *)(data->iova + data->offset);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		else {
+			struct ion_handle *srcp_ihdl;
+			ulong len;
+			srcp_ihdl = ion_import_fd(mfd->iclient,
+						  data->memory_id);
+			if (IS_ERR_OR_NULL(srcp_ihdl)) {
+				pr_err("%s: ion import fd failed\n", __func__);
+				goto register_ion_fail;
+			}
+			if (ion_phys(mfd->iclient,
+				     srcp_ihdl,
+				     (ulong *)&temp->addr,
+				     (size_t *)&len)) {
+				pr_err("%s: unable to get ion phys\n",
+				       __func__);
+				goto register_ion_fail;
+			}
+			temp->addr += data->offset;
+		}
+#else
+		else {
+			pr_err("%s: only support ion memory\n", __func__);
+			goto register_ion_fail;
+		}
+#endif
 		memcpy(&temp->buf_info, data, sizeof(struct msmfb_data));
 		if (mdp4_overlay_writeback_register_buffer(mfd, temp)) {
-			pr_err("Error registering node\n");
-			kfree(temp);
-			temp = NULL;
+			pr_err("%s: error registering node\n", __func__);
+			goto register_ion_fail;
 		}
 	}
-err:
 	return temp;
+ register_ion_fail:
+	kfree(temp);
+ register_alloc_fail:
+	return NULL;
 }
 int mdp4_writeback_start(
 		struct fb_info *info)
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index d82672e..d8a55ed 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -24,6 +24,7 @@
 #include <linux/debugfs.h>
 #include <linux/semaphore.h>
 #include <linux/uaccess.h>
+#include <linux/msm_mdp.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
@@ -295,12 +296,6 @@
 	bits =  mdp_intr_mask;
 	outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
 
-	/* histogram */
-	MDP_OUTP(MDP_BASE + 0x95010, 1);	/* auto clear HIST */
-
-	/* enable histogram interrupts */
-	outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
-
 	/* For the max read pending cmd config below, if the MDP clock     */
 	/* is less than the AXI clock, then we must use 3 pending          */
 	/* pending requests.  Otherwise, we should use 8 pending requests. */
@@ -385,11 +380,8 @@
 		that histogram works.*/
 		MDP_OUTP(MDP_BASE + 0x95010, 1);
 		outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
-		if (mdp_is_hist_start == TRUE) {
-			MDP_OUTP(MDP_BASE + 0x95004,
-					mdp_hist_frame_cnt);
-			MDP_OUTP(MDP_BASE + 0x95000, 1);
-		}
+		mdp_is_hist_valid = FALSE;
+		__mdp_histogram_reset();
 	}
 
 	if (isr & INTR_EXTERNAL_INTF_UDERRUN)
@@ -568,16 +560,18 @@
 		outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
 		mb();
 		isr &= mask;
+		if (isr & INTR_HIST_RESET_SEQ_DONE)
+			__mdp_histogram_kickoff();
+
 		if (isr & INTR_HIST_DONE) {
-			if (waitqueue_active(&(mdp_hist_comp.wait))) {
-				complete(&mdp_hist_comp);
-			} else {
-				if (mdp_is_hist_start == TRUE) {
-					MDP_OUTP(MDP_BASE + 0x95004,
-							mdp_hist_frame_cnt);
-					MDP_OUTP(MDP_BASE + 0x95000, 1);
+			if (waitqueue_active(&mdp_hist_comp.wait)) {
+				if (!queue_work(mdp_hist_wq,
+						&mdp_histogram_worker)) {
+					pr_err("%s - can't queue hist_read\n",
+							__func__);
 				}
-			}
+			} else
+				__mdp_histogram_reset();
 		}
 	}
 
@@ -2617,3 +2611,381 @@
 	}
 	buf->phys_addr = 0;
 }
+
+static int mdp4_update_pcc_regs(uint32_t offset,
+				struct mdp_pcc_cfg_data *cfg_ptr)
+{
+	int ret = -1;
+
+	if (offset && cfg_ptr) {
+
+		outpdw(offset, cfg_ptr->r.c);
+		outpdw(offset + 0x30, cfg_ptr->g.c);
+		outpdw(offset + 0x60, cfg_ptr->b.c);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.r);
+		outpdw(offset + 0x30, cfg_ptr->g.r);
+		outpdw(offset + 0x60, cfg_ptr->b.r);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.g);
+		outpdw(offset + 0x30, cfg_ptr->g.g);
+		outpdw(offset + 0x60, cfg_ptr->b.g);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.b);
+		outpdw(offset + 0x30, cfg_ptr->g.b);
+		outpdw(offset + 0x60, cfg_ptr->b.b);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.rr);
+		outpdw(offset + 0x30, cfg_ptr->g.rr);
+		outpdw(offset + 0x60, cfg_ptr->b.rr);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.gg);
+		outpdw(offset + 0x30, cfg_ptr->g.gg);
+		outpdw(offset + 0x60, cfg_ptr->b.gg);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.bb);
+		outpdw(offset + 0x30, cfg_ptr->g.bb);
+		outpdw(offset + 0x60, cfg_ptr->b.bb);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.rg);
+		outpdw(offset + 0x30, cfg_ptr->g.rg);
+		outpdw(offset + 0x60, cfg_ptr->b.rg);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.gb);
+		outpdw(offset + 0x30, cfg_ptr->g.gb);
+		outpdw(offset + 0x60, cfg_ptr->b.gb);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.rb);
+		outpdw(offset + 0x30, cfg_ptr->g.rb);
+		outpdw(offset + 0x60, cfg_ptr->b.rb);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.rgb_0);
+		outpdw(offset + 0x30, cfg_ptr->g.rgb_0);
+		outpdw(offset + 0x60, cfg_ptr->b.rgb_0);
+		offset += 4;
+
+		outpdw(offset, cfg_ptr->r.rgb_1);
+		outpdw(offset + 0x30, cfg_ptr->g.rgb_1);
+		outpdw(offset + 0x60, cfg_ptr->b.rgb_1);
+
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int mdp4_read_pcc_regs(uint32_t offset,
+				struct mdp_pcc_cfg_data *cfg_ptr)
+{
+	int ret = -1;
+
+	if (offset && cfg_ptr) {
+		cfg_ptr->r.c = inpdw(offset);
+		cfg_ptr->g.c = inpdw(offset + 0x30);
+		cfg_ptr->b.c = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.r = inpdw(offset);
+		cfg_ptr->g.r = inpdw(offset + 0x30);
+		cfg_ptr->b.r = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.g = inpdw(offset);
+		cfg_ptr->g.g = inpdw(offset + 0x30);
+		cfg_ptr->b.g = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.b = inpdw(offset);
+		cfg_ptr->g.b = inpdw(offset + 0x30);
+		cfg_ptr->b.b = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.rr = inpdw(offset);
+		cfg_ptr->g.rr = inpdw(offset + 0x30);
+		cfg_ptr->b.rr = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.gg = inpdw(offset);
+		cfg_ptr->g.gg = inpdw(offset + 0x30);
+		cfg_ptr->b.gg = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.bb = inpdw(offset);
+		cfg_ptr->g.bb = inpdw(offset + 0x30);
+		cfg_ptr->b.bb = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.rg = inpdw(offset);
+		cfg_ptr->g.rg = inpdw(offset + 0x30);
+		cfg_ptr->b.rg = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.gb = inpdw(offset);
+		cfg_ptr->g.gb = inpdw(offset + 0x30);
+		cfg_ptr->b.gb = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.rb = inpdw(offset);
+		cfg_ptr->g.rb = inpdw(offset + 0x30);
+		cfg_ptr->b.rb = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.rgb_0 = inpdw(offset);
+		cfg_ptr->g.rgb_0 = inpdw(offset + 0x30);
+		cfg_ptr->b.rgb_0 = inpdw(offset + 0x60);
+		offset += 4;
+
+		cfg_ptr->r.rgb_1 = inpdw(offset);
+		cfg_ptr->g.rgb_1 = inpdw(offset + 0x30);
+		cfg_ptr->b.rgb_1 = inpdw(offset + 0x60);
+
+		ret = 0;
+	}
+
+	return ret;
+}
+
+#define MDP_DMA_P_BASE 0x90000
+#define MDP_DMA_S_BASE 0xA0000
+
+#define MDP_PCC_OFFSET 0xA000
+
+#define MDP_DMA_P_OP_MODE_OFFSET 0x70
+#define MDP_DMA_S_OP_MODE_OFFSET 0x28
+
+
+#define DMA_PCC_R2_OFFSET 0x100
+
+int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr)
+{
+	int ret = -1;
+	uint32_t pcc_offset = 0, mdp_cfg_offset = 0;
+	uint32_t mdp_dma_op_mode = 0;
+
+	switch (cfg_ptr->block) {
+	case MDP_BLOCK_DMA_P:
+		pcc_offset = (uint32_t) (MDP_BASE + MDP_DMA_P_BASE \
+				+ MDP_PCC_OFFSET);
+		mdp_cfg_offset = (uint32_t)(MDP_BASE + MDP_DMA_P_BASE);
+		mdp_dma_op_mode = (uint32_t)(MDP_BASE + MDP_DMA_P_BASE \
+				+ MDP_DMA_P_OP_MODE_OFFSET);
+		break;
+
+	case MDP_BLOCK_DMA_S:
+		pcc_offset = (uint32_t)(MDP_BASE + MDP_DMA_S_BASE \
+				+ MDP_PCC_OFFSET);
+		mdp_cfg_offset = (uint32_t)(MDP_BASE + MDP_DMA_S_BASE);
+		mdp_dma_op_mode = (uint32_t)(MDP_BASE + MDP_DMA_S_BASE \
+				+ MDP_DMA_S_OP_MODE_OFFSET);
+		break;
+
+	default:
+		break;
+	}
+
+	if (0x8 & cfg_ptr->ops)
+		pcc_offset += DMA_PCC_R2_OFFSET;
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	switch ((0x6 & cfg_ptr->ops)>>1) {
+	case 0x1:
+		ret = mdp4_read_pcc_regs(pcc_offset, cfg_ptr);
+		break;
+
+	case 0x2:
+		ret = mdp4_update_pcc_regs(pcc_offset, cfg_ptr);
+		break;
+
+	default:
+		break;
+	}
+
+	if (0x8 & cfg_ptr->ops)
+		outpdw(mdp_dma_op_mode,
+			(inpdw(mdp_dma_op_mode)|((0x8&cfg_ptr->ops)<<10)));
+
+	outpdw(mdp_cfg_offset,
+			(inpdw(mdp_cfg_offset)|((cfg_ptr->ops&0x1)<<29)));
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	return ret;
+}
+
+#define MDP_DMA_GC_OFFSET 0x8800
+
+#define MDP_LM_0_BASE 0x10004
+#define MDP_LM_1_BASE 0x18004
+#define MDP_LM_GC_OFFSET 0x47ec
+
+#define MDP_LM_OP_MODE_OFFSET 0x10
+
+#define MDP_DMA_P_CONFIG_OFFSET MDP_DMA_P_BASE
+#define MDP_DMA_S_CONFIG_OFFSET MDP_DMA_S_BASE
+#define MDP_LM_0_OP_MODE_OFFSET (MDP_LM_0_BASE + MDP_LM_OP_MODE_OFFSET)
+#define MDP_LM_1_OP_MODE_OFFSET (MDP_LM_1_BASE + MDP_LM_OP_MODE_OFFSET)
+
+#define MDP_GC_COLOR_OFFSET	0x100
+#define MDP_GC_PARMS_OFFSET	0x80
+
+#define MDP_AR_GC_MAX_STAGES	16
+
+static int update_ar_gc_lut(uint32_t *offset, struct mdp_pgc_lut_data *lut_data)
+{
+	int ret = -1, count = 0;
+
+	uint32_t *c0_offset = offset;
+	uint32_t *c0_params_offset = (uint32_t *)((uint32_t)c0_offset
+							+ MDP_GC_PARMS_OFFSET);
+
+	uint32_t *c1_offset = (uint32_t *)((uint32_t)offset
+							+ MDP_GC_COLOR_OFFSET);
+
+	uint32_t *c1_params_offset = (uint32_t *)((uint32_t)c1_offset
+							+ MDP_GC_PARMS_OFFSET);
+
+	uint32_t *c2_offset = (uint32_t *)((uint32_t)offset
+						+ 2*MDP_GC_COLOR_OFFSET);
+
+	uint32_t *c2_params_offset = (uint32_t *)((uint32_t)c2_offset
+						+MDP_GC_PARMS_OFFSET);
+
+
+	for (count = 0; count < MDP_AR_GC_MAX_STAGES; count++) {
+		if (count < lut_data->num_r_stages) {
+			outpdw(c0_offset+count,
+				((0xfff & lut_data->r_data[count].x_start)
+					| 0x10000));
+
+			outpdw(c0_params_offset+count,
+				((0x7fff & lut_data->r_data[count].slope)
+					| ((0xffff
+					& lut_data->r_data[count].offset)
+						<< 16)));
+		} else
+			outpdw(c0_offset+count, 0);
+
+		if (count < lut_data->num_b_stages) {
+			outpdw(c1_offset+count,
+				((0xfff & lut_data->b_data[count].x_start)
+					| 0x10000));
+
+			outpdw(c1_params_offset+count,
+				((0x7fff & lut_data->b_data[count].slope)
+					| ((0xffff
+					& lut_data->b_data[count].offset)
+						<< 16)));
+		} else
+			outpdw(c1_offset+count, 0);
+
+		if (count < lut_data->num_g_stages) {
+			outpdw(c2_offset+count,
+				((0xfff & lut_data->g_data[count].x_start)
+					| 0x10000));
+
+			outpdw(c2_params_offset+count,
+				((0x7fff & lut_data->g_data[count].slope)
+				| ((0xffff
+				& lut_data->g_data[count].offset)
+					<< 16)));
+		} else
+			outpdw(c2_offset+count, 0);
+	}
+
+	ret = 0;
+
+	return ret;
+}
+
+int mdp4_pgc_cfg(struct mdp_pgc_lut_data *pgc_ptr)
+{
+	int ret = 0;
+	uint32_t *offset = 0, *pgc_enable_offset = 0, lshift_bits = 0;
+	struct mdp_ar_gc_lut_data r[MDP_AR_GC_MAX_STAGES];
+	struct mdp_ar_gc_lut_data g[MDP_AR_GC_MAX_STAGES];
+	struct mdp_ar_gc_lut_data b[MDP_AR_GC_MAX_STAGES];
+
+	ret = copy_from_user(&r[0], pgc_ptr->r_data,
+		pgc_ptr->num_r_stages*sizeof(struct mdp_ar_gc_lut_data));
+	if (!ret) {
+		ret = copy_from_user(&g[0],
+			pgc_ptr->g_data,
+			pgc_ptr->num_g_stages
+			* sizeof(struct mdp_ar_gc_lut_data));
+		if (!ret)
+			ret = copy_from_user(&b[0],
+			pgc_ptr->b_data,
+			pgc_ptr->num_b_stages
+			* sizeof(struct mdp_ar_gc_lut_data));
+	}
+
+	if (ret)
+		return ret;
+
+	pgc_ptr->r_data = &r[0];
+	pgc_ptr->g_data = &g[0];
+	pgc_ptr->b_data = &b[0];
+
+	switch (pgc_ptr->block) {
+	case MDP_BLOCK_DMA_P:
+		offset = (uint32_t *)(MDP_BASE + MDP_DMA_P_BASE
+					+ MDP_DMA_GC_OFFSET);
+		pgc_enable_offset = (uint32_t *)(MDP_BASE
+					+ MDP_DMA_P_CONFIG_OFFSET);
+		lshift_bits = 28;
+		break;
+
+	case MDP_BLOCK_DMA_S:
+		offset = (uint32_t *)(MDP_BASE + MDP_DMA_S_BASE
+					+  MDP_DMA_GC_OFFSET);
+		pgc_enable_offset = (uint32_t *)(MDP_BASE
+					+ MDP_DMA_S_CONFIG_OFFSET);
+		lshift_bits = 28;
+		break;
+
+	case MDP_BLOCK_OVERLAY_0:
+		offset = (uint32_t *)(MDP_BASE + MDP_LM_0_BASE
+					+ MDP_LM_GC_OFFSET);
+		pgc_enable_offset = (uint32_t *)(MDP_BASE
+					+ MDP_LM_0_OP_MODE_OFFSET);
+		lshift_bits = 2;
+		break;
+
+	case MDP_BLOCK_OVERLAY_1:
+		offset = (uint32_t *)(MDP_BASE + MDP_LM_1_BASE
+					+ MDP_LM_GC_OFFSET);
+		pgc_enable_offset = (uint32_t *)(MDP_BASE
+					+ MDP_LM_0_OP_MODE_OFFSET);
+		lshift_bits = 2;
+		break;
+
+	default:
+		ret = -1;
+		break;
+	}
+
+	if (!ret) {
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+		ret = update_ar_gc_lut(offset, pgc_ptr);
+		if (!ret)
+			outpdw(pgc_enable_offset, (inpdw(pgc_enable_offset)
+						|(1<<lshift_bits)));
+
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
+
+	return ret;
+}
+
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index 3997814..e8b288f 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -522,14 +522,37 @@
 			  boolean sync)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct fb_info *fbi = mfd->fbi;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 	MDPIBUF *iBuf;
 	int bpp = info->var.bits_per_pixel / 8;
+	int yres, remainder;
+
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
 
 	down(&mfd->sem);
+
 	iBuf = &mfd->ibuf;
 	iBuf->buf = (uint8 *) info->fix.smem_start;
-	iBuf->buf += info->var.xoffset * bpp +
-			info->var.yoffset * info->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		iBuf->buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		iBuf->buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		iBuf->buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	iBuf->ibuf_width = info->var.xres_virtual;
 	iBuf->bpp = bpp;
diff --git a/drivers/video/msm/mdp_dma_dsi_video.c b/drivers/video/msm/mdp_dma_dsi_video.c
index 505eb74..0e76a07 100644
--- a/drivers/video/msm/mdp_dma_dsi_video.c
+++ b/drivers/video/msm/mdp_dma_dsi_video.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
@@ -67,14 +67,17 @@
 	int hsync_end_x;
 	uint8 *buf;
 	uint32 dma2_cfg_reg;
+	int yres, remainder;
 
 	int bpp;
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
+	struct msm_panel_info *panel_info;
 	int ret;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -85,10 +88,29 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_DSI_VIDEO;
 
@@ -239,17 +261,38 @@
 	uint8 *buf;
 	int bpp;
 	unsigned long flag;
+	int yres, remainder;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 	int irq_block = MDP_DMA2_TERM;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	down(&mfd->dma->mutex);
 
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 	/* no need to power on cmd block since it's dsi mode */
 	/* starting address */
 	MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x8, (uint32) buf);
diff --git a/drivers/video/msm/mdp_dma_lcdc.c b/drivers/video/msm/mdp_dma_lcdc.c
index 9ce7e13..5dada35 100644
--- a/drivers/video/msm/mdp_dma_lcdc.c
+++ b/drivers/video/msm/mdp_dma_lcdc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -89,12 +89,15 @@
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
+	struct msm_panel_info *panel_info;
 	uint32 dma_base;
 	uint32 timer_base = LCDC_BASE;
 	uint32 block = MDP_DMA2_BLOCK;
 	int ret;
+	int yres, remainder;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -105,12 +108,32 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_LCDC;
 
@@ -299,6 +322,7 @@
 	}
 #endif
 
+	down(&mfd->dma->mutex);
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	MDP_OUTP(MDP_BASE + timer_base, 0);
@@ -307,6 +331,7 @@
 	mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
 
 	ret = panel_next_off(pdev);
+	up(&mfd->dma->mutex);
 
 	/* delay to make sure the last frame finishes */
 	msleep(16);
@@ -317,23 +342,45 @@
 void mdp_lcdc_update(struct msm_fb_data_type *mfd)
 {
 	struct fb_info *fbi = mfd->fbi;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 	uint8 *buf;
 	int bpp;
 	unsigned long flag;
 	uint32 dma_base;
+	int yres, remainder;
 	int irq_block = MDP_DMA2_TERM;
 #ifdef CONFIG_FB_MSM_MDP40
 	int intr = INTR_DMA_P_DONE;
 #endif
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	if (!mfd->panel_power_on)
 		return;
 
+	down(&mfd->dma->mutex);
 	/* no need to power on cmd block since it's lcdc mode */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	dma_base = DMA_P_BASE;
 
@@ -365,4 +412,5 @@
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	wait_for_completion_killable(&mfd->dma->comp);
 	mdp_disable_irq(irq_block);
+	up(&mfd->dma->mutex);
 }
diff --git a/drivers/video/msm/mdp_dma_tv.c b/drivers/video/msm/mdp_dma_tv.c
index 66d9422..1305e03 100644
--- a/drivers/video/msm/mdp_dma_tv.c
+++ b/drivers/video/msm/mdp_dma_tv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,12 +39,15 @@
 int mdp_dma3_on(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd;
+	struct msm_panel_info *panel_info;
 	struct fb_info *fbi;
 	uint8 *buf;
 	int bpp;
 	int ret = 0;
+	int yres, remainder;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -53,13 +56,33 @@
 		return -EINVAL;
 
 	fbi = mfd->fbi;
+
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	/* starting address[31..8] of Video frame buffer is CS0 */
 	MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
@@ -112,15 +135,37 @@
 	uint8 *buf;
 	int bpp;
 	unsigned long flag;
+	int yres, remainder;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* no need to power on cmd block since dma3 is running */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
+
 	MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
diff --git a/drivers/video/msm/mdp_hw_init.c b/drivers/video/msm/mdp_hw_init.c
index 8f8b4d3..ff3ad41 100644
--- a/drivers/video/msm/mdp_hw_init.c
+++ b/drivers/video/msm/mdp_hw_init.c
@@ -635,8 +635,6 @@
 	MDP_OUTP(MDP_BASE + 0xE0000, 0);
 	MDP_OUTP(MDP_BASE + 0x100, 0xffffffff);
 	MDP_OUTP(MDP_BASE + 0x90070, 0);
-	MDP_OUTP(MDP_BASE + 0x94010, 1);
-	MDP_OUTP(MDP_BASE + 0x9401c, 2);
 #endif
 
 	/*
diff --git a/drivers/video/msm/mipi_chimei_wuxga.c b/drivers/video/msm/mipi_chimei_wuxga.c
index c63df46..7abb0d4 100644
--- a/drivers/video/msm/mipi_chimei_wuxga.c
+++ b/drivers/video/msm/mipi_chimei_wuxga.c
@@ -55,12 +55,12 @@
 	/* DSIPHY_TIMING_CTRL */
 	.timing = { 0xC9, 0x92, 0x29, /* panel specific */
 	0, /* DSIPHY_TIMING_CTRL_3 = 0 */
-	0x2E, 0x9B, 0x2C, 0x94, 0x2E, 0x03, 0x04},  /* panel specific */
+	0x2D, 0x9B, 0x2B, 0x94, 0x2D, 0x03, 0x04},  /* panel specific */
 
 	/* DSIPHY_PLL_CTRL */
 	.pll = { 0x00, /* common 8960 */
 	/* VCO */
-	0x32, (0x01 | 0x30) , (0x19 | 0xC0), /* panel specific */
+	0x30, (0x01 | 0x30) , (0x19 | 0xC0), /* panel specific */
 	0x00, 0x50, 0x48, 0x63,
 	0x77, 0x88, 0x99, /* Auto update by dsi-mipi driver */
 	0x00, 0x14, 0x03, 0x00, 0x02, /* common 8960 */
@@ -104,19 +104,19 @@
 	 * LVDS-CLK = DSI-CLK/4 , 320 MHZ/4= 80 MHZ.
 	 */
 
-	pinfo->clk_rate = 640 * MHZ ; /* bitclk Calculated */
+	pinfo->clk_rate = 635 * MHZ ; /* bitclk Calculated */
 
 	/*
 	 * this panel is operated by DE,
 	 * vsycn and hsync are ignored
 	 */
 
-	pinfo->lcdc.h_front_porch = 16;	/* thfp */
-	pinfo->lcdc.h_back_porch = 160;	/* thb */
+	pinfo->lcdc.h_front_porch = 160-48-32;	/* thfp */
+	pinfo->lcdc.h_back_porch = 48;	/* thb */
 	pinfo->lcdc.h_pulse_width = 32;	/* thpw */
 
-	pinfo->lcdc.v_front_porch = 0;	/* tvfp */
-	pinfo->lcdc.v_back_porch = 26;	/* tvb */
+	pinfo->lcdc.v_front_porch = 26-3-6;	/* tvfp */
+	pinfo->lcdc.v_back_porch = 3;	/* tvb */
 	pinfo->lcdc.v_pulse_width = 6;	/* tvpw */
 
 	pinfo->lcdc.border_clr = 0;		/* black */
@@ -138,7 +138,7 @@
 	pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
 
 	/* Four lanes are recomended for 1920x1200 at 60 frames per second */
-	pinfo->mipi.frame_rate = 45; /* 45 frames per second */
+	pinfo->mipi.frame_rate = 60;
 	pinfo->mipi.data_lane0 = true;
 	pinfo->mipi.data_lane1 = true;
 	pinfo->mipi.data_lane2 = true;
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 9907109..4fbb044 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -50,7 +50,8 @@
 #define MIPI_DSI_PANEL_WSVGA_PT	4
 #define MIPI_DSI_PANEL_QHD_PT 5
 #define MIPI_DSI_PANEL_WXGA	6
-#define DSI_PANEL_MAX	6
+#define MIPI_DSI_PANEL_WUXGA	7
+#define DSI_PANEL_MAX	7
 
 enum {		/* mipi dsi panel */
 	DSI_VIDEO_MODE,
diff --git a/drivers/video/msm/mipi_toshiba.c b/drivers/video/msm/mipi_toshiba.c
index 5788f27..2db8bcf 100644
--- a/drivers/video/msm/mipi_toshiba.c
+++ b/drivers/video/msm/mipi_toshiba.c
@@ -196,7 +196,8 @@
 		mipi_dsi_cmds_tx(mfd, &toshiba_tx_buf,
 			toshiba_wvga_display_on_cmds,
 			ARRAY_SIZE(toshiba_wvga_display_on_cmds));
-	else if (TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WSVGA_PT)
+	else if (TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WSVGA_PT ||
+		TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WUXGA)
 		mipi_dsi_cmds_tx(mfd, &toshiba_tx_buf,
 			toshiba_wsvga_display_on_cmds,
 			ARRAY_SIZE(toshiba_wsvga_display_on_cmds));
diff --git a/drivers/video/msm/mipi_toshiba_video_wuxga.c b/drivers/video/msm/mipi_toshiba_video_wuxga.c
new file mode 100644
index 0000000..297248f
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba_video_wuxga.c
@@ -0,0 +1,97 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_toshiba.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+	/* 1920*1200, RGB888, 4 Lane 60 fps video mode */
+	/* regulator */
+	{0x03, 0x0a, 0x04, 0x00, 0x20},
+	/* timing */
+	{0x66, 0x26, 0x1F, 0x00, 0x55, 0x9C, 0x16, 0x90,
+	0x23, 0x03, 0x04, 0xa0},
+	/* phy ctrl */
+	{0x5f, 0x00, 0x00, 0x10},
+	/* strength */
+	{0xff, 0x00, 0x06, 0x00},
+	/* pll control */
+	{0x0, 0xD7, 0x1, 0x19, 0x00, 0x50, 0x48, 0x63,
+	0x41, 0x0f, 0x01,
+	0x00, 0x14, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01 },
+};
+
+static int __init mipi_video_toshiba_wuxga_init(void)
+{
+	int ret;
+
+	if (msm_fb_detect_client("mipi_video_toshiba_wuxga"))
+		return 0;
+
+	pinfo.xres = 1920;
+	pinfo.yres = 1200;
+
+	pinfo.type = MIPI_VIDEO_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.lcdc.h_back_porch = 50;
+	pinfo.lcdc.h_front_porch = 50;
+	pinfo.lcdc.h_pulse_width = 170;
+	pinfo.lcdc.v_back_porch = 7;
+	pinfo.lcdc.v_front_porch = 8;
+	pinfo.lcdc.v_pulse_width = 30;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+	pinfo.bl_max = MIPI_TOSHIBA_PWM_LEVEL;
+	pinfo.bl_min = 1;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 981560000;
+
+	pinfo.mipi.mode = DSI_VIDEO_MODE;
+	pinfo.mipi.pulse_mode_hsa_he = TRUE;
+	pinfo.mipi.hfp_power_stop = FALSE;
+	pinfo.mipi.hbp_power_stop = FALSE;
+	pinfo.mipi.hsa_power_stop = FALSE;
+	pinfo.mipi.eof_bllp_power_stop = TRUE;
+	pinfo.mipi.bllp_power_stop = TRUE;
+	pinfo.mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+	pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+	pinfo.mipi.vc = 0;
+	pinfo.mipi.rgb_swap = DSI_RGB_SWAP_BGR;
+	pinfo.mipi.data_lane0 = TRUE;
+	pinfo.mipi.data_lane1 = TRUE;
+	pinfo.mipi.data_lane2 = TRUE;
+	pinfo.mipi.data_lane3 = TRUE;
+	pinfo.mipi.tx_eot_append = TRUE;
+	pinfo.mipi.t_clk_post = 0x04;
+	pinfo.mipi.t_clk_pre = 0x1c;
+	pinfo.mipi.stream = 0; /* dma_p */
+	pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.frame_rate = 60;
+	pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+	ret = mipi_toshiba_device_register(&pinfo, MIPI_DSI_PRIM,
+						MIPI_DSI_PANEL_WUXGA);
+	if (ret)
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mipi_video_toshiba_wuxga_init);
diff --git a/drivers/video/msm/mipi_truly_video_wvga_pt.c b/drivers/video/msm/mipi_truly_video_wvga_pt.c
index 931c564..03ef32b 100644
--- a/drivers/video/msm/mipi_truly_video_wvga_pt.c
+++ b/drivers/video/msm/mipi_truly_video_wvga_pt.c
@@ -38,10 +38,8 @@
 {
 	int ret;
 
-#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
 	if (msm_fb_detect_client("mipi_video_truly_wvga"))
 		return 0;
-#endif
 
 	pinfo.xres = 480;
 	pinfo.yres = 800;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 489e6d2..69e0423 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -606,6 +606,7 @@
 	return 0;
 }
 
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
 static int msm_fb_ext_suspend(struct device *dev)
 {
 	struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
@@ -635,13 +636,16 @@
 
 	return ret;
 }
+#endif
 
 static struct dev_pm_ops msm_fb_dev_pm_ops = {
 	.runtime_suspend = msm_fb_runtime_suspend,
 	.runtime_resume = msm_fb_runtime_resume,
 	.runtime_idle = msm_fb_runtime_idle,
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
 	.suspend = msm_fb_ext_suspend,
 	.resume = msm_fb_ext_resume,
+#endif
 };
 
 static struct platform_driver msm_fb_driver = {
@@ -969,6 +973,7 @@
 	struct fb_var_screeninfo *var;
 	int *id;
 	int fbram_offset;
+	int remainder, remainder_mode2;
 
 	/*
 	 * fb info initialization
@@ -1105,15 +1110,28 @@
 
 	fix->line_length = msm_fb_line_length(mfd->index, panel_info->xres,
 					      bpp);
+
+	/* Make sure all buffers can be addressed on a page boundary by an x
+	 * and y offset */
+
+	remainder = (fix->line_length * panel_info->yres) % PAGE_SIZE;
+	if (!remainder)
+		remainder = PAGE_SIZE;
+	remainder_mode2 = (fix->line_length *
+				panel_info->mode2_yres) % PAGE_SIZE;
+	if (!remainder_mode2)
+		remainder_mode2 = PAGE_SIZE;
+
 	/* calculate smem_len based on max size of two supplied modes */
-	fix->smem_len = roundup(MAX(msm_fb_line_length(mfd->index,
-					       panel_info->xres,
-					       bpp) *
-			    panel_info->yres * mfd->fb_page,
-			    msm_fb_line_length(mfd->index,
+	fix->smem_len = MAX((msm_fb_line_length(mfd->index, panel_info->xres,
+					      bpp) *
+			    panel_info->yres + PAGE_SIZE -
+				remainder) * mfd->fb_page,
+			    (msm_fb_line_length(mfd->index,
 					       panel_info->mode2_xres,
 					       bpp) *
-			    panel_info->mode2_yres * mfd->fb_page), PAGE_SIZE);
+			    panel_info->mode2_yres + PAGE_SIZE -
+				remainder_mode2) * mfd->fb_page);
 
 
 
@@ -2914,6 +2932,50 @@
 	return 0;
 }
 
+static int msmfb_handle_pp_ioctl(struct msmfb_mdp_pp *pp_ptr)
+{
+	int ret = -1;
+
+	if (!pp_ptr)
+		return ret;
+
+	switch (pp_ptr->op) {
+#ifdef CONFIG_FB_MSM_MDP40
+	case mdp_op_csc_cfg:
+		ret = mdp4_csc_config(&(pp_ptr->data.csc_cfg_data));
+		break;
+
+	case mdp_op_pcc_cfg:
+		ret = mdp4_pcc_cfg(&(pp_ptr->data.pcc_cfg_data));
+		break;
+
+	case mdp_op_lut_cfg:
+		switch (pp_ptr->data.lut_cfg_data.lut_type) {
+		case mdp_lut_igc:
+			break;
+
+		case mdp_lut_pgc:
+			ret = mdp4_pgc_cfg(
+				&pp_ptr->data.lut_cfg_data.data.pgc_lut_data);
+			break;
+
+		case mdp_lut_hist:
+			break;
+
+		default:
+			break;
+		}
+		break;
+#endif
+	default:
+		pr_warn("Unsupported request to MDP_PP IOCTL.\n");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
 static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
 			unsigned long arg)
 {
@@ -3207,28 +3269,15 @@
 		ret = -EINVAL;
 #endif
 		break;
+
 	case MSMFB_MDP_PP:
 		ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
 		if (ret)
 			return ret;
 
-		switch (mdp_pp.op) { /*Add PCC and LUT op handling here*/
-#ifdef CONFIG_FB_MSM_MDP40
-		case mdp_op_csc_cfg:
-			ret = mdp4_csc_config((struct mdp_csc_cfg_data *)
-					&(mdp_pp.data));
-			break;
-		case mdp_op_pcc_cfg:
-		case mdp_op_lut_cfg:
-#endif
-		default:
-			pr_warn("%s: Only CSC supported by MDP_PP IOCTL.\n",
-					__func__);
-			ret = -EINVAL;
-			break;
-		}
-
+		ret = msmfb_handle_pp_ioctl(&mdp_pp);
 		break;
+
 	default:
 		MSM_FB_INFO("MDP: unknown ioctl (cmd=%x) received!\n", cmd);
 		ret = -EINVAL;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
index 51a0d13..433dad4 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.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
@@ -14,8 +14,8 @@
 #ifndef _VCD_DDL_API_H_
 #define _VCD_DDL_API_H_
 
+#include <media/msm/vcd_api.h>
 #include "vidc.h"
-#include "vcd_api.h"
 
 #define VCD_EVT_RESP_DDL_BASE             0x3000
 #define VCD_EVT_RESP_DEVICE_INIT          (VCD_EVT_RESP_DDL_BASE + 0x1)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
index 42a991c..10b3404 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,7 +15,7 @@
 #define _VCD_DDL_UTILS_H_
 
 #include <linux/delay.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 
 extern u32 vidc_msg_pmem;
 extern u32 vidc_msg_timing;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
index f63ebcd..a5a8e57 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
@@ -24,8 +24,8 @@
 #define VIDC_REG_IN(x...)
 #endif
 
-#define __inpdw(port) (*((u32 *) (port)))
-#define __outpdw(port, val) (*((u32 *) (port)) = ((u32) (val)))
+#define __inpdw(port) __raw_readl(port)
+#define __outpdw(port, val) __raw_writel(val, port)
 
 #define in_dword(addr) (__inpdw(addr))
 #define in_dword_masked(addr, mask) (__inpdw(addr) & (mask))
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index c32ac81..8851b52 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -21,9 +21,9 @@
 #include <linux/interrupt.h>
 #include <linux/memory_alloc.h>
 #include <asm/sizes.h>
+#include <media/msm/vidc_init.h>
 #include "vidc.h"
 #include "vcd_res_tracker.h"
-#include "vidc_init.h"
 
 static unsigned int vidc_clk_table[3] = {
 	48000000, 133330000, 200000000
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
index 7c68d63..02b2369 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl_metadata.h"
 #include "vcd_res_tracker_api.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
index eb08b7e..ac5bce9 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl.h"
 
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
index 25aa6bc..965c3aa 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd_ddl_firmware.h"
 #include "vcd_ddl_utils.h"
 
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
index 7952dfb..a136de8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
  */
 #ifndef _VCD_DDL_FIRMWARE_H_
 #define _VCD_DDL_FIRMWARE_H_
-#include "vcd_property.h"
+#include <media/msm/vcd_property.h>
 
 #define VCD_FW_BIG_ENDIAN     0x0
 #define VCD_FW_LITTLE_ENDIAN  0x1
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
index f09bd71..6a69955 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl_metadata.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
index 2ec8419..15adf21 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd_ddl_utils.h"
 
 DDL_INLINE struct ddl_context *ddl_get_context(void)
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
index 00c00cd..9dc495b 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
  */
 #ifndef _VCD_DDL_INTERNAL_PROPERTY_H_
 #define _VCD_DDL_INTERNAL_PROPERTY_H_
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
 
 #define VCD_EVT_RESP_DDL_BASE          0x3000
 #define VCD_EVT_RESP_DEVICE_INIT       (VCD_EVT_RESP_DDL_BASE + 0x1)
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
index ece4c30..fe71dc1 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vidc.h"
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl_metadata.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
index 376ea6d..2a74da8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl_metadata.h"
 
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
index 6d3c666..3aebdaf 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl_metadata.h"
 
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index c8ea83f..17dedb8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 #include <linux/memory_alloc.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd_ddl_utils.h"
 
 #if DEBUG
diff --git a/drivers/video/msm/vidc/720p/ddl/vidc.c b/drivers/video/msm/vidc/720p/ddl/vidc.c
index 0f5932a..de6cbbb 100644
--- a/drivers/video/msm/vidc/720p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/720p/ddl/vidc.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
@@ -12,8 +12,8 @@
  */
 
 #include <linux/unistd.h>
+#include <media/msm/vidc_type.h>
 #include "vidc.h"
-#include "vidc_type.h"
 
 #if DEBUG
 #define DBG(x...) printk(KERN_DEBUG x)
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index 522ff16..86bf397 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -16,9 +16,9 @@
 #include <linux/regulator/consumer.h>
 #include <mach/clk.h>
 #include <linux/interrupt.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_init.h>
+#include <media/msm/vidc_type.h>
 #include "vcd_res_tracker.h"
-#include "vidc_init.h"
 
 #define MSM_AXI_QOS_NAME "msm_vidc_reg"
 #define AXI_CLK_SCALING
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index b300fbc..bfaac82 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -29,11 +29,11 @@
 #include <linux/clk.h>
 #include <linux/timer.h>
 #include <mach/msm_subsystem_map.h>
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
 #include "vcd_res_tracker_api.h"
-#include "vidc_type.h"
-#include "vcd_api.h"
 #include "vdec_internal.h"
-#include "vidc_init.h"
 
 
 
@@ -2111,8 +2111,10 @@
 	struct video_client_ctx *client_ctx = file->private_data;
 
 	INFO("msm_vidc_dec: Inside %s()", __func__);
-	res_trk_close_secure_session();
+	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
+	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
 	vid_dec_close_client(client_ctx);
+	res_trk_close_secure_session();
 	vidc_release_firmware();
 #ifndef USE_RES_TRACKER
 	vidc_disable_clk();
@@ -2125,13 +2127,15 @@
 {
 	struct video_client_ctx *client_ctx = file->private_data;
 
-	DBG("msm_vidc_dec: Inside %s()", __func__);
+	INFO("msm_vidc_dec: Inside %s()", __func__);
+	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
+	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
 	vid_dec_close_client(client_ctx);
 	vidc_release_firmware();
 #ifndef USE_RES_TRACKER
 	vidc_disable_clk();
 #endif
-	DBG("msm_vidc_dec: Return from %s()", __func__);
+	INFO("msm_vidc_dec: Return from %s()", __func__);
 	return 0;
 }
 
diff --git a/drivers/video/msm/vidc/common/dec/vdec_internal.h b/drivers/video/msm/vidc/common/dec/vdec_internal.h
index f310e25..89da9a2 100644
--- a/drivers/video/msm/vidc/common/dec/vdec_internal.h
+++ b/drivers/video/msm/vidc/common/dec/vdec_internal.h
@@ -16,7 +16,7 @@
 
 #include <linux/msm_vidc_dec.h>
 #include <linux/cdev.h>
-#include "vidc_init.h"
+#include <media/msm/vidc_init.h>
 
 #define NUM_OF_DRIVER_NODES 2
 
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index cc6606c..6d6dcdc 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -27,11 +27,11 @@
 #include <linux/workqueue.h>
 #include <linux/android_pmem.h>
 #include <linux/clk.h>
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
 
-#include "vidc_type.h"
-#include "vcd_api.h"
 #include "venc_internal.h"
-#include "vidc_init.h"
 #include "vcd_res_tracker_api.h"
 
 #define VID_ENC_NAME	"msm_vidc_enc"
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index e3bb9db..f362f7b 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -28,10 +28,10 @@
 #include <linux/android_pmem.h>
 #include <linux/clk.h>
 #include <mach/msm_subsystem_map.h>
-#include "vidc_type.h"
-#include "vcd_api.h"
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
 #include "venc_internal.h"
-#include "vidc_init.h"
 
 #if DEBUG
 #define DBG(x...) printk(KERN_DEBUG x)
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h
index 2b5a532..a07f7ab 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.h
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.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
@@ -16,8 +16,7 @@
 
 #include <linux/msm_vidc_enc.h>
 #include <linux/cdev.h>
-
-#include "vidc_init.h"
+#include <media/msm/vidc_init.h>
 
 #define VID_ENC_MAX_NUM_OF_BUFF 100
 
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index cd3f954..0ea64d4 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -31,9 +31,9 @@
 #include <mach/clk.h>
 #include <linux/pm_runtime.h>
 #include <mach/msm_subsystem_map.h>
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
 #include "vidc_init_internal.h"
-#include "vidc_init.h"
 #include "vcd_res_tracker_api.h"
 
 #if DEBUG
@@ -384,6 +384,59 @@
 }
 EXPORT_SYMBOL(vidc_get_fd_info);
 
+void vidc_cleanup_addr_table(struct video_client_ctx *client_ctx,
+				enum buffer_dir buffer)
+{
+	u32 *num_of_buffers = NULL;
+	u32 i = 0;
+	struct buf_addr_table *buf_addr_table;
+	if (buffer == BUFFER_TYPE_INPUT) {
+		buf_addr_table = client_ctx->input_buf_addr_table;
+		num_of_buffers = &client_ctx->num_of_input_buffers;
+		DBG("%s(): buffer = INPUT\n", __func__);
+
+	} else {
+		buf_addr_table = client_ctx->output_buf_addr_table;
+		num_of_buffers = &client_ctx->num_of_output_buffers;
+		DBG("%s(): buffer = OUTPUT\n", __func__);
+	}
+
+	if (!*num_of_buffers)
+		goto bail_out_cleanup;
+	if (!client_ctx->user_ion_client)
+		goto bail_out_cleanup;
+	for (i = 0; i < *num_of_buffers; ++i) {
+		if (buf_addr_table[i].client_data) {
+			msm_subsystem_unmap_buffer(
+			(struct msm_mapped_buffer *)
+			buf_addr_table[i].client_data);
+			buf_addr_table[i].client_data = NULL;
+		}
+		if (buf_addr_table[i].buff_ion_handle) {
+			ion_unmap_kernel(client_ctx->user_ion_client,
+					buf_addr_table[i].buff_ion_handle);
+			ion_free(client_ctx->user_ion_client,
+					buf_addr_table[i].buff_ion_handle);
+			buf_addr_table[i].buff_ion_handle = NULL;
+		}
+	}
+	if (client_ctx->vcd_h264_mv_buffer.client_data) {
+		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+		client_ctx->vcd_h264_mv_buffer.client_data);
+		client_ctx->vcd_h264_mv_buffer.client_data = NULL;
+	}
+	if (client_ctx->h264_mv_ion_handle) {
+		ion_unmap_kernel(client_ctx->user_ion_client,
+				client_ctx->h264_mv_ion_handle);
+		ion_free(client_ctx->user_ion_client,
+				client_ctx->h264_mv_ion_handle);
+		client_ctx->h264_mv_ion_handle = NULL;
+	}
+bail_out_cleanup:
+	return;
+}
+EXPORT_SYMBOL(vidc_cleanup_addr_table);
+
 u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
 	enum buffer_dir buffer,
 	u32 search_with_user_vaddr,
@@ -540,9 +593,10 @@
 				client_ctx->user_ion_client,
 				buff_ion_handle,
 				ionflag);
-			if (!(*kernel_vaddr)) {
+			if (IS_ERR_OR_NULL((void *)*kernel_vaddr)) {
 				ERR("%s():ION virtual addr fail\n",
 				 __func__);
+				*kernel_vaddr = (unsigned long)NULL;
 				goto ion_error;
 			}
 			if (ion_phys(client_ctx->user_ion_client,
@@ -587,7 +641,7 @@
 	mutex_unlock(&client_ctx->enrty_queue_lock);
 	return true;
 ion_error:
-	if (*kernel_vaddr)
+	if (*kernel_vaddr && buff_ion_handle)
 		ion_unmap_kernel(client_ctx->user_ion_client, buff_ion_handle);
 	if (!IS_ERR_OR_NULL(buff_ion_handle))
 		ion_free(client_ctx->user_ion_client, buff_ion_handle);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.h b/drivers/video/msm/vidc/common/init/vidc_init.h
deleted file mode 100644
index ced99ff..0000000
--- a/drivers/video/msm/vidc/common/init/vidc_init.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef VIDC_INIT_H
-#define VIDC_INIT_H
-#include <linux/ion.h>
-#include "vidc_type.h"
-
-#define VIDC_MAX_NUM_CLIENTS 4
-#define MAX_VIDEO_NUM_OF_BUFF 100
-
-enum buffer_dir {
-	BUFFER_TYPE_INPUT,
-	BUFFER_TYPE_OUTPUT
-};
-
-struct buf_addr_table {
-	unsigned long user_vaddr;
-	unsigned long kernel_vaddr;
-	unsigned long phy_addr;
-	unsigned long buff_ion_flag;
-	struct ion_handle *buff_ion_handle;
-	int pmem_fd;
-	struct file *file;
-	unsigned long dev_addr;
-	void *client_data;
-};
-
-struct video_client_ctx {
-	void *vcd_handle;
-	u32 num_of_input_buffers;
-	u32 num_of_output_buffers;
-	struct buf_addr_table input_buf_addr_table[MAX_VIDEO_NUM_OF_BUFF];
-	struct buf_addr_table output_buf_addr_table[MAX_VIDEO_NUM_OF_BUFF];
-	struct list_head msg_queue;
-	struct mutex msg_queue_lock;
-	struct mutex enrty_queue_lock;
-	wait_queue_head_t msg_wait;
-	struct completion event;
-	struct vcd_property_h264_mv_buffer vcd_h264_mv_buffer;
-	struct vcd_property_enc_recon_buffer recon_buffer[4];
-	u32 event_status;
-	u32 seq_header_set;
-	u32 stop_msg;
-	u32 stop_called;
-	u32 stop_sync_cb;
-	struct ion_client *user_ion_client;
-	struct ion_handle *seq_hdr_ion_handle;
-	struct ion_handle *h264_mv_ion_handle;
-	struct ion_handle *recon_buffer_ion_handle[4];
-	u32 dmx_disable;
-};
-
-void __iomem *vidc_get_ioaddr(void);
-int vidc_load_firmware(void);
-void vidc_release_firmware(void);
-u32 vidc_get_fd_info(struct video_client_ctx *client_ctx,
-		enum buffer_dir buffer, int pmem_fd,
-		unsigned long kvaddr, int index);
-u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
-	enum buffer_dir buffer, u32 search_with_user_vaddr,
-	unsigned long *user_vaddr, unsigned long *kernel_vaddr,
-	unsigned long *phy_addr, int *pmem_fd, struct file **file,
-	s32 *buffer_index);
-u32 vidc_insert_addr_table(struct video_client_ctx *client_ctx,
-	enum buffer_dir buffer, unsigned long user_vaddr,
-	unsigned long *kernel_vaddr, int pmem_fd,
-	unsigned long buffer_addr_offset,
-	unsigned int max_num_buffers, unsigned long length);
-u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
-	enum buffer_dir buffer, unsigned long user_vaddr,
-	unsigned long *kernel_vaddr);
-
-u32 vidc_timer_create(void (*timer_handler)(void *),
-	void *user_data, void **timer_handle);
-void  vidc_timer_release(void *timer_handle);
-void  vidc_timer_start(void *timer_handle, u32 time_out);
-void  vidc_timer_stop(void *timer_handle);
-
-
-#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index b557752..9fc76d8 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.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
@@ -13,10 +13,10 @@
 #ifndef _VCD_H_
 #define _VCD_H_
 
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
+#include "vcd_util.h"
 #include "vcd_ddl_api.h"
 #include "vcd_res_tracker_api.h"
-#include "vcd_util.h"
 #include "vcd_client_sm.h"
 #include "vcd_core.h"
 #include "vcd_device_sm.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
index 5e9fd55..e0ef3af 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd.h"
 
 u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle)
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.h b/drivers/video/msm/vidc/common/vcd/vcd_api.h
deleted file mode 100644
index 9580ece..0000000
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#ifndef _VCD_API_H_
-#define _VCD_API_H_
-#include "vcd_property.h"
-#include "vcd_status.h"
-
-#define VCD_FRAME_FLAG_EOS 0x00000001
-#define VCD_FRAME_FLAG_DECODEONLY   0x00000004
-#define VCD_FRAME_FLAG_DATACORRUPT 0x00000008
-#define VCD_FRAME_FLAG_ENDOFFRAME 0x00000010
-#define VCD_FRAME_FLAG_SYNCFRAME 0x00000020
-#define VCD_FRAME_FLAG_EXTRADATA 0x00000040
-#define VCD_FRAME_FLAG_CODECCONFIG  0x00000080
-#define VCD_FRAME_FLAG_BFRAME 0x00100000
-#define VCD_FRAME_FLAG_EOSEQ 0x00200000
-
-#define VCD_FLUSH_INPUT   0x0001
-#define VCD_FLUSH_OUTPUT  0x0002
-#define VCD_FLUSH_ALL     0x0003
-
-#define VCD_FRAMETAG_INVALID  0xffffffff
-
-struct vcd_handle_container {
-	void *handle;
-};
-struct vcd_flush_cmd {
-	u32 mode;
-};
-
-enum vcd_frame {
-	VCD_FRAME_YUV = 1,
-	VCD_FRAME_I,
-	VCD_FRAME_P,
-	VCD_FRAME_B,
-	VCD_FRAME_NOTCODED,
-	VCD_FRAME_IDR,
-	VCD_FRAME_32BIT = 0x7fffffff
-};
-
-enum vcd_power_state {
-	VCD_PWR_STATE_ON = 1,
-	VCD_PWR_STATE_SLEEP,
-};
-
-struct vcd_frame_data {
-	u8 *virtual;
-	u8 *physical;
-	u32 ion_flag;
-	u32 alloc_len;
-	u32 data_len;
-	u32 offset;
-	s64 time_stamp;
-	u32 flags;
-	u32 frm_clnt_data;
-	struct vcd_property_dec_output_buffer dec_op_prop;
-	u32 interlaced;
-	enum vcd_frame frame;
-	u32 ip_frm_tag;
-	u32 intrlcd_ip_frm_tag;
-	u8 *desc_buf;
-	u32 desc_size;
-};
-
-struct vcd_sequence_hdr {
-	u8 *sequence_header;
-	u32 sequence_header_len;
-
-};
-
-enum vcd_buffer_type {
-	VCD_BUFFER_INPUT = 0x1,
-	VCD_BUFFER_OUTPUT = 0x2,
-	VCD_BUFFER_INVALID = 0x3,
-	VCD_BUFFER_32BIT = 0x7FFFFFFF
-};
-
-struct vcd_buffer_requirement {
-	u32 min_count;
-	u32 actual_count;
-	u32 max_count;
-	size_t sz;
-	u32 align;
-	u32 buf_pool_id;
-};
-
-struct vcd_init_config {
-	void *device_name;
-	void *(*map_dev_base_addr) (void *device_name);
-	void (*un_map_dev_base_addr) (void);
-	void (*interrupt_clr) (void);
-	void (*register_isr) (void *device_name);
-	void (*deregister_isr) (void);
-	u32  (*timer_create) (void (*timer_handler)(void *),
-		void *user_data, void **timer_handle);
-	void (*timer_release) (void *timer_handle);
-	void (*timer_start) (void *timer_handle, u32 time_out);
-	void (*timer_stop) (void *timer_handle);
-};
-
-u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle);
-u32 vcd_term(s32 driver_handle);
-u32 vcd_open(s32 driver_handle, u32 decoding,
-	void (*callback) (u32 event, u32 status, void *info, size_t sz,
-	void *handle, void *const client_data), void *client_data);
-u32 vcd_close(void *handle);
-u32 vcd_encode_start(void *handle);
-u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame);
-u32 vcd_decode_start(void *handle, struct vcd_sequence_hdr *seq_hdr);
-u32 vcd_decode_frame(void *handle, struct vcd_frame_data *input_frame);
-u32 vcd_pause(void *handle);
-u32 vcd_resume(void *handle);
-u32 vcd_flush(void *handle, u32 mode);
-u32 vcd_stop(void *handle);
-u32 vcd_set_property(void *handle, struct vcd_property_hdr *prop_hdr,
-					void *prop_val);
-u32 vcd_get_property(void *handle, struct vcd_property_hdr *prop_hdr,
-					 void *prop_val);
-u32 vcd_set_buffer_requirements(void *handle, enum vcd_buffer_type buffer,
-		struct vcd_buffer_requirement *buffer_req);
-u32 vcd_get_buffer_requirements(void *handle, enum vcd_buffer_type buffer,
-		struct vcd_buffer_requirement *buffer_req);
-u32 vcd_set_buffer(void *handle, enum vcd_buffer_type buffer_type,
-		u8 *buffer, u32 buf_size);
-u32 vcd_allocate_buffer(void *handle, enum vcd_buffer_type buffer,
-		u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr);
-
-u32 vcd_free_buffer(void *handle, enum vcd_buffer_type buffer_type, u8 *buffer);
-u32 vcd_fill_output_buffer(void *handle, struct vcd_frame_data *buffer);
-u32 vcd_set_device_power(s32 driver_handle,
-		enum vcd_power_state pwr_state);
-void vcd_read_and_clear_interrupt(void);
-void vcd_response_handler(void);
-u8 vcd_get_num_of_clients(void);
-u32 vcd_get_ion_status(void);
-struct ion_client *vcd_get_ion_client(void);
-#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index e00e85f..9376900 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd.h"
 
 static const struct vcd_clnt_state_table *vcd_clnt_state_table[];
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
index e9ab41c..9f2d63d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
  */
 #ifndef _VCD_CLIENT_SM_H_
 #define _VCD_CLIENT_SM_H_
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
 #include "vcd_ddl_api.h"
 
 struct vcd_clnt_state_table;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index 64dec2d..1f844e8 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.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
@@ -14,7 +14,7 @@
 #define _VCD_CORE_H_
 
 #include <linux/ion.h>
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
 #include "vcd_ddl_api.h"
 
 #include "vcd_util.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index 4c477cb..9576387 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd.h"
 
 static const struct vcd_dev_state_table *vcd_dev_state_table[];
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
index 8245966..2443c33 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,7 @@
 #ifndef _VCD_DEVICE_SM_H_
 #define _VCD_DEVICE_SM_H_
 
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
 #include "vcd_ddl_api.h"
 #include "vcd_core.h"
 
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
index 6a1cc80..01bd931 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd_power_sm.h"
 #include "vcd_core.h"
 #include "vcd.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_property.h b/drivers/video/msm/vidc/common/vcd/vcd_property.h
deleted file mode 100644
index a3069e3..0000000
--- a/drivers/video/msm/vidc/common/vcd/vcd_property.h
+++ /dev/null
@@ -1,350 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#ifndef _VCD_DRIVER_PROPERTY_H_
-#define _VCD_DRIVER_PROPERTY_H_
-
-#define VCD_START_BASE       0x0
-#define VCD_I_LIVE           (VCD_START_BASE + 0x1)
-#define VCD_I_CODEC          (VCD_START_BASE + 0x2)
-#define VCD_I_FRAME_SIZE     (VCD_START_BASE + 0x3)
-#define VCD_I_METADATA_ENABLE  (VCD_START_BASE + 0x4)
-#define VCD_I_METADATA_HEADER  (VCD_START_BASE + 0x5)
-#define VCD_I_PROFILE        (VCD_START_BASE + 0x6)
-#define VCD_I_LEVEL          (VCD_START_BASE + 0x7)
-#define VCD_I_BUFFER_FORMAT  (VCD_START_BASE + 0x8)
-#define VCD_I_FRAME_RATE  (VCD_START_BASE + 0x9)
-#define VCD_I_TARGET_BITRATE (VCD_START_BASE + 0xA)
-#define VCD_I_MULTI_SLICE    (VCD_START_BASE + 0xB)
-#define VCD_I_ENTROPY_CTRL   (VCD_START_BASE + 0xC)
-#define VCD_I_DEBLOCKING     (VCD_START_BASE + 0xD)
-#define VCD_I_RATE_CONTROL   (VCD_START_BASE + 0xE)
-#define VCD_I_QP_RANGE      (VCD_START_BASE + 0xF)
-#define VCD_I_SESSION_QP    (VCD_START_BASE + 0x10)
-#define VCD_I_INTRA_PERIOD   (VCD_START_BASE + 0x11)
-#define VCD_I_VOP_TIMING     (VCD_START_BASE + 0x12)
-#define VCD_I_SHORT_HEADER   (VCD_START_BASE + 0x13)
-#define VCD_I_SEQ_HEADER    (VCD_START_BASE + 0x14)
-#define VCD_I_HEADER_EXTENSION   (VCD_START_BASE + 0x15)
-#define VCD_I_INTRA_REFRESH  (VCD_START_BASE + 0x16)
-#define VCD_I_POST_FILTER    (VCD_START_BASE + 0x17)
-#define VCD_I_PROGRESSIVE_ONLY (VCD_START_BASE + 0x18)
-#define VCD_I_OUTPUT_ORDER (VCD_START_BASE + 0x19)
-#define VCD_I_RECON_BUFFERS   (VCD_START_BASE + 0x1A)
-#define VCD_I_FREE_RECON_BUFFERS   (VCD_START_BASE + 0x1B)
-#define VCD_I_GET_RECON_BUFFER_SIZE   (VCD_START_BASE + 0x1C)
-#define VCD_I_H264_MV_BUFFER   (VCD_START_BASE + 0x1D)
-#define VCD_I_FREE_H264_MV_BUFFER (VCD_START_BASE + 0x1E)
-#define VCD_I_GET_H264_MV_SIZE (VCD_START_BASE + 0x1F)
-#define VCD_I_DEC_PICTYPE (VCD_START_BASE + 0x20)
-#define VCD_I_CONT_ON_RECONFIG (VCD_START_BASE + 0x21)
-#define VCD_I_META_BUFFER_MODE (VCD_START_BASE + 0x22)
-#define VCD_I_DISABLE_DMX (VCD_START_BASE + 0x23)
-#define VCD_I_DISABLE_DMX_SUPPORT (VCD_START_BASE + 0x24)
-
-#define VCD_START_REQ      (VCD_START_BASE + 0x1000)
-#define VCD_I_REQ_IFRAME   (VCD_START_REQ + 0x1)
-
-#define VCD_I_RESERVED_BASE  (VCD_START_BASE + 0x10000)
-
-struct vcd_property_hdr {
-	u32    prop_id;
-	size_t sz;
-};
-
-struct vcd_property_live {
-	u32             live;
-};
-
-enum vcd_codec {
-	VCD_CODEC_H264      = 0x1,
-	VCD_CODEC_H263      = 0x2,
-	VCD_CODEC_MPEG1     = 0x3,
-	VCD_CODEC_MPEG2     = 0x4,
-	VCD_CODEC_MPEG4     = 0x5,
-	VCD_CODEC_DIVX_3    = 0x6,
-	VCD_CODEC_DIVX_4    = 0x7,
-	VCD_CODEC_DIVX_5    = 0x8,
-	VCD_CODEC_DIVX_6    = 0x9,
-	VCD_CODEC_XVID      = 0xA,
-	VCD_CODEC_VC1       = 0xB,
-	VCD_CODEC_VC1_RCV   = 0xC
-};
-
-struct vcd_property_codec {
-	enum vcd_codec       codec;
-};
-
-struct vcd_property_frame_size {
-	u32              width;
-	u32              height;
-	u32              stride;
-	u32              scan_lines;
-};
-
-
-#define VCD_METADATA_DATANONE       0x001
-#define VCD_METADATA_QCOMFILLER     0x002
-#define VCD_METADATA_QPARRAY        0x004
-#define VCD_METADATA_CONCEALMB      0x008
-#define VCD_METADATA_SEI            0x010
-#define VCD_METADATA_VUI            0x020
-#define VCD_METADATA_VC1            0x040
-#define VCD_METADATA_PASSTHROUGH    0x080
-#define VCD_METADATA_ENC_SLICE      0x100
-
-struct vcd_property_meta_data_enable {
-	u32 meta_data_enable_flag;
-};
-
-struct vcd_property_metadata_hdr {
-	u32 meta_data_id;
-	u32 version;
-	u32 port_index;
-	u32 type;
-};
-
-struct vcd_property_frame_rate {
-	u32              fps_denominator;
-	u32              fps_numerator;
-};
-
-struct vcd_property_target_bitrate {
-	u32             target_bitrate;
-};
-
-enum vcd_yuv_buffer_format {
-	VCD_BUFFER_FORMAT_NV12      = 0x1,
-	VCD_BUFFER_FORMAT_TILE_4x2    = 0x2,
-	VCD_BUFFER_FORMAT_NV12_16M2KA = 0x3,
-	VCD_BUFFER_FORMAT_TILE_1x1    = 0x4
-};
-
-struct vcd_property_buffer_format {
-	enum vcd_yuv_buffer_format  buffer_format;
-};
-
-struct vcd_property_post_filter {
-	u32           post_filter;
-};
-
-enum vcd_codec_profile {
-	VCD_PROFILE_UNKNOWN       = 0x0,
-	VCD_PROFILE_MPEG4_SP      = 0x1,
-	VCD_PROFILE_MPEG4_ASP     = 0x2,
-	VCD_PROFILE_H264_BASELINE = 0x3,
-	VCD_PROFILE_H264_MAIN     = 0x4,
-	VCD_PROFILE_H264_HIGH     = 0x5,
-	VCD_PROFILE_H263_BASELINE = 0x6,
-	VCD_PROFILE_VC1_SIMPLE    = 0x7,
-	VCD_PROFILE_VC1_MAIN      = 0x8,
-	VCD_PROFILE_VC1_ADVANCE   = 0x9,
-	VCD_PROFILE_MPEG2_MAIN    = 0xA,
-	VCD_PROFILE_MPEG2_SIMPLE  = 0xB
-};
-
-struct vcd_property_profile {
-	enum vcd_codec_profile       profile;
-};
-
-enum vcd_codec_level {
-   VCD_LEVEL_UNKNOWN       = 0x0,
-   VCD_LEVEL_MPEG4_0       = 0x1,
-   VCD_LEVEL_MPEG4_0b      = 0x2,
-   VCD_LEVEL_MPEG4_1       = 0x3,
-   VCD_LEVEL_MPEG4_2       = 0x4,
-   VCD_LEVEL_MPEG4_3       = 0x5,
-   VCD_LEVEL_MPEG4_3b      = 0x6,
-   VCD_LEVEL_MPEG4_4       = 0x7,
-   VCD_LEVEL_MPEG4_4a      = 0x8,
-   VCD_LEVEL_MPEG4_5       = 0x9,
-   VCD_LEVEL_MPEG4_6       = 0xA,
-   VCD_LEVEL_MPEG4_7       = 0xB,
-   VCD_LEVEL_MPEG4_X       = 0xC,
-   VCD_LEVEL_H264_1        = 0x10,
-   VCD_LEVEL_H264_1b       = 0x11,
-   VCD_LEVEL_H264_1p1      = 0x12,
-   VCD_LEVEL_H264_1p2      = 0x13,
-   VCD_LEVEL_H264_1p3      = 0x14,
-   VCD_LEVEL_H264_2        = 0x15,
-   VCD_LEVEL_H264_2p1      = 0x16,
-   VCD_LEVEL_H264_2p2      = 0x17,
-   VCD_LEVEL_H264_3        = 0x18,
-   VCD_LEVEL_H264_3p1      = 0x19,
-   VCD_LEVEL_H264_3p2      = 0x1A,
-   VCD_LEVEL_H264_4        = 0x1B,
-   VCD_LEVEL_H264_4p1      = 0x1C,
-   VCD_LEVEL_H264_4p2      = 0x1D,
-   VCD_LEVEL_H264_5        = 0x1E,
-   VCD_LEVEL_H264_5p1      = 0x1F,
-   VCD_LEVEL_H263_10       = 0x20,
-   VCD_LEVEL_H263_20       = 0x21,
-   VCD_LEVEL_H263_30       = 0x22,
-   VCD_LEVEL_H263_40       = 0x23,
-   VCD_LEVEL_H263_45       = 0x24,
-   VCD_LEVEL_H263_50       = 0x25,
-   VCD_LEVEL_H263_60       = 0x26,
-   VCD_LEVEL_H263_70       = 0x27,
-   VCD_LEVEL_H263_X        = 0x28,
-   VCD_LEVEL_MPEG2_LOW     = 0x30,
-   VCD_LEVEL_MPEG2_MAIN    = 0x31,
-   VCD_LEVEL_MPEG2_HIGH_14 = 0x32,
-   VCD_LEVEL_MPEG2_HIGH    = 0x33,
-   VCD_LEVEL_MPEG2_X       = 0x34,
-   VCD_LEVEL_VC1_S_LOW     = 0x40,
-   VCD_LEVEL_VC1_S_MEDIUM  = 0x41,
-   VCD_LEVEL_VC1_M_LOW     = 0x42,
-   VCD_LEVEL_VC1_M_MEDIUM  = 0x43,
-   VCD_LEVEL_VC1_M_HIGH    = 0x44,
-   VCD_LEVEL_VC1_A_0       = 0x45,
-   VCD_LEVEL_VC1_A_1       = 0x46,
-   VCD_LEVEL_VC1_A_2       = 0x47,
-   VCD_LEVEL_VC1_A_3       = 0x48,
-   VCD_LEVEL_VC1_A_4       = 0x49,
-   VCD_LEVEL_VC1_X         = 0x4A
-};
-
-struct vcd_property_level {
-	enum vcd_codec_level   level;
-};
-
-enum vcd_m_slice_sel {
-	VCD_MSLICE_OFF             = 0x1,
-	VCD_MSLICE_BY_MB_COUNT     = 0x2,
-	VCD_MSLICE_BY_BYTE_COUNT   = 0x3,
-	VCD_MSLICE_BY_GOB          = 0x4
-};
-
-struct vcd_property_multi_slice {
-	enum vcd_m_slice_sel   m_slice_sel;
-	u32             m_slice_size;
-};
-
-enum vcd_entropy_sel {
-	VCD_ENTROPY_SEL_CAVLC = 0x1,
-	VCD_ENTROPY_SEL_CABAC = 0x2
-};
-
-enum vcd_cabac_model {
-	VCD_CABAC_MODEL_NUMBER_0 = 0x1,
-	VCD_CABAC_MODEL_NUMBER_1 = 0x2,
-	VCD_CABAC_MODEL_NUMBER_2 = 0x3
-};
-
-struct vcd_property_entropy_control {
-	enum vcd_entropy_sel  entropy_sel;
-	enum vcd_cabac_model  cabac_model;
-};
-
-enum vcd_db_config {
-	VCD_DB_ALL_BLOCKING_BOUNDARY = 0x1,
-	VCD_DB_DISABLE               = 0x2,
-	VCD_DB_SKIP_SLICE_BOUNDARY   = 0x3
-};
-struct vcd_property_db_config {
-	enum vcd_db_config    db_config;
-	u32             slice_alpha_offset;
-	u32             slice_beta_offset;
-};
-
-enum vcd_rate_control {
-	VCD_RATE_CONTROL_OFF      = 0x1,
-	VCD_RATE_CONTROL_VBR_VFR  = 0x2,
-	VCD_RATE_CONTROL_VBR_CFR  = 0x3,
-	VCD_RATE_CONTROL_CBR_VFR  = 0x4,
-	VCD_RATE_CONTROL_CBR_CFR  = 0x5
-};
-
-struct vcd_property_rate_control {
-	enum vcd_rate_control     rate_control;
-};
-
-struct vcd_property_qp_range {
-	u32              max_qp;
-	u32              min_qp;
-};
-
-struct vcd_property_session_qp {
-	u32 i_frame_qp;
-	u32 p_frame_qp;
-	u32	b_frame_qp;
-};
-
-struct vcd_property_i_period {
-	u32 p_frames;
-	u32 b_frames;
-};
-
-struct vcd_property_vop_timing {
-	u32   vop_time_resolution;
-};
-
-struct vcd_property_short_header {
-	u32             short_header;
-};
-
-struct vcd_property_intra_refresh_mb_number {
-	u32            cir_mb_number;
-};
-
-struct vcd_property_req_i_frame {
-	u32        req_i_frame;
-};
-
-struct vcd_frame_rect{
-   u32   left;
-   u32   top;
-   u32   right;
-   u32   bottom;
-};
-
-struct vcd_property_dec_output_buffer {
-	struct vcd_frame_rect   disp_frm;
-	struct vcd_property_frame_size frm_size;
-};
-
-enum vcd_output_order {
-   VCD_DEC_ORDER_DISPLAY  = 0x0,
-   VCD_DEC_ORDER_DECODE   = 0x1
-};
-
-struct vcd_property_enc_recon_buffer{
-	u8 *user_virtual_addr;
-	u8 *kernel_virtual_addr;
-	u8 *physical_addr;
-	u8 *dev_addr;
-	u32 buffer_size;
-	u32 ysize;
-	int pmem_fd;
-	u32 offset;
-	void *client_data;
-};
-
-struct vcd_property_h264_mv_buffer{
-	u8 *kernel_virtual_addr;
-	u8 *physical_addr;
-	u32 size;
-	u32 count;
-	int pmem_fd;
-	u32 offset;
-	u8 *dev_addr;
-	void *client_data;
-};
-
-struct vcd_property_buffer_size{
-	int width;
-	int height;
-	int size;
-	int alignment;
-};
-
-#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
index 34a3445..dec9b4e 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  *
  */
 
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd.h"
 
 #define NORMALIZATION_FACTOR 3600
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_status.h b/drivers/video/msm/vidc/common/vcd/vcd_status.h
deleted file mode 100644
index 1a36167..0000000
--- a/drivers/video/msm/vidc/common/vcd/vcd_status.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _VCD_ERR_STATUS_H_
-#define _VCD_ERR_STATUS_H_
-
-#define VCD_EVT_RESP_BASE                 0x1000
-#define VCD_EVT_RESP_OPEN                 (VCD_EVT_RESP_BASE + 0x1)
-#define VCD_EVT_RESP_START                (VCD_EVT_RESP_BASE + 0x2)
-#define VCD_EVT_RESP_STOP                 (VCD_EVT_RESP_BASE + 0x3)
-#define VCD_EVT_RESP_PAUSE                (VCD_EVT_RESP_BASE + 0x4)
-#define VCD_EVT_RESP_FLUSH_INPUT_DONE     (VCD_EVT_RESP_BASE + 0x5)
-#define VCD_EVT_RESP_FLUSH_OUTPUT_DONE    (VCD_EVT_RESP_BASE + 0x6)
-#define VCD_EVT_RESP_INPUT_FLUSHED        (VCD_EVT_RESP_BASE + 0x7)
-#define VCD_EVT_RESP_OUTPUT_FLUSHED       (VCD_EVT_RESP_BASE + 0x8)
-#define VCD_EVT_RESP_INPUT_DONE           (VCD_EVT_RESP_BASE + 0x9)
-#define VCD_EVT_RESP_OUTPUT_DONE          (VCD_EVT_RESP_BASE + 0xa)
-
-#define VCD_EVT_IND_BASE                  0x2000
-#define VCD_EVT_IND_INPUT_RECONFIG        (VCD_EVT_IND_BASE + 0x1)
-#define VCD_EVT_IND_OUTPUT_RECONFIG       (VCD_EVT_IND_BASE + 0x2)
-#define VCD_EVT_IND_HWERRFATAL            (VCD_EVT_IND_BASE + 0x3)
-#define VCD_EVT_IND_RESOURCES_LOST        (VCD_EVT_IND_BASE + 0x4)
-#define VCD_EVT_IND_INFO_OUTPUT_RECONFIG  (VCD_EVT_IND_BASE + 0x5)
-#define VCD_EVT_IND_INFO_FIELD_DROPPED    (VCD_EVT_IND_BASE + 0x6)
-
-#define VCD_S_SUCCESS           0x0
-
-#define VCD_S_ERR_BASE                    0x80000000
-#define VCD_ERR_FAIL                      (VCD_S_ERR_BASE + 0x01)
-#define VCD_ERR_ALLOC_FAIL                (VCD_S_ERR_BASE + 0x02)
-#define VCD_ERR_ILLEGAL_OP                (VCD_S_ERR_BASE + 0x03)
-#define VCD_ERR_ILLEGAL_PARM              (VCD_S_ERR_BASE + 0x04)
-#define VCD_ERR_BAD_POINTER               (VCD_S_ERR_BASE + 0x05)
-#define VCD_ERR_BAD_HANDLE                (VCD_S_ERR_BASE + 0x06)
-#define VCD_ERR_NOT_SUPPORTED             (VCD_S_ERR_BASE + 0x07)
-#define VCD_ERR_BAD_STATE                 (VCD_S_ERR_BASE + 0x08)
-#define VCD_ERR_BUSY                      (VCD_S_ERR_BASE + 0x09)
-#define VCD_ERR_MAX_CLIENT                (VCD_S_ERR_BASE + 0x0a)
-#define VCD_ERR_IFRAME_EXPECTED           (VCD_S_ERR_BASE + 0x0b)
-#define VCD_ERR_INTRLCD_FIELD_DROP        (VCD_S_ERR_BASE + 0x0c)
-#define VCD_ERR_HW_FATAL                  (VCD_S_ERR_BASE + 0x0d)
-#define VCD_ERR_BITSTREAM_ERR             (VCD_S_ERR_BASE + 0x0e)
-#define VCD_ERR_QEMPTY                    (VCD_S_ERR_BASE + 0x0f)
-#define VCD_ERR_SEQHDR_PARSE_FAIL         (VCD_S_ERR_BASE + 0x10)
-#define VCD_ERR_INPUT_NOT_PROCESSED       (VCD_S_ERR_BASE + 0x11)
-#define VCD_ERR_INDEX_NOMORE              (VCD_S_ERR_BASE + 0x12)
-
-#define VCD_FAILED(rc)   ((rc > VCD_S_ERR_BASE) ? true : false)
-
-#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 509b897..ebc30fd 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -13,7 +13,7 @@
 #include <linux/memory_alloc.h>
 #include <mach/msm_subsystem_map.h>
 #include <asm/div64.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
 #include "vcd.h"
 #include "vdec_internal.h"
 
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_util.h b/drivers/video/msm/vidc/common/vcd/vcd_util.h
index 07ad651..7164029 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_util.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,8 +12,8 @@
  */
 #ifndef _VCD_UTIL_H_
 #define _VCD_UTIL_H_
-#include "vidc_type.h"
-#include "vcd_api.h"
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
 
 #if DEBUG
 
diff --git a/drivers/video/msm/vidc/common/vcd/vidc_type.h b/drivers/video/msm/vidc/common/vcd/vidc_type.h
deleted file mode 100644
index bd87c0d..0000000
--- a/drivers/video/msm/vidc/common/vcd/vidc_type.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#ifndef VIDC_TYPE_H
-#define VIDC_TYPE_H
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/list.h>
-#include <linux/time.h>
-#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
-
-#define DEBUG   0
-#define VIDC_ENABLE_DBGFS
-
-#define USE_RES_TRACKER
-#endif
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 9c43f56..79f7874 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -428,6 +428,7 @@
 header-y += msm_ipc.h
 header-y += msm_charm.h
 header-y += tzcom.h
+header-y += qseecom.h
 header-y += qcedev.h
 header-y += idle_stats_device.h
 header-y += genlock.h
diff --git a/include/linux/fmem.h b/include/linux/fmem.h
index aebeec4..44b7005 100644
--- a/include/linux/fmem.h
+++ b/include/linux/fmem.h
@@ -20,7 +20,8 @@
 struct fmem_platform_data {
 	unsigned long phys;
 	unsigned long size;
-	unsigned long reserved_size;
+	unsigned long reserved_size_low;
+	unsigned long reserved_size_high;
 };
 
 struct fmem_data {
@@ -28,7 +29,8 @@
 	void *virt;
 	struct vm_struct *area;
 	unsigned long size;
-	unsigned long reserved_size;
+	unsigned long reserved_size_low;
+	unsigned long reserved_size_high;
 };
 
 enum fmem_state {
diff --git a/include/linux/ion.h b/include/linux/ion.h
index ade87e6..caed2a2 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -64,12 +64,12 @@
 
 enum ion_heap_ids {
 	INVALID_HEAP_ID = -1,
-	ION_IOMMU_HEAP_ID = 4,
 	ION_CP_MM_HEAP_ID = 8,
 	ION_CP_MFC_HEAP_ID = 12,
 	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
 	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
 	ION_SF_HEAP_ID = 24,
+	ION_IOMMU_HEAP_ID = 25,
 	ION_QSECOM_HEAP_ID = 27,
 	ION_AUDIO_HEAP_ID = 28,
 
@@ -160,6 +160,8 @@
  *			of this heap in the case of a shared heap.
  * @reusable		Flag indicating whether this heap is reusable of not.
  *			(see FMEM)
+ * @mem_is_fmem		Flag indicating whether this memory is coming from fmem
+ *			or not.
  * @virt_addr:		Virtual address used when using fmem.
  * @request_region:	function to be called when the number of allocations
  *			goes from 0 -> 1
@@ -174,6 +176,7 @@
 	ion_phys_addr_t secure_base; /* Base addr used when heap is shared */
 	size_t secure_size; /* Size used for securing heap when heap is shared*/
 	int reusable;
+	int mem_is_fmem;
 	ion_virt_addr_t *virt_addr;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
@@ -184,6 +187,8 @@
  * struct ion_co_heap_pdata - defines a carveout heap in the given platform
  * @adjacent_mem_id:	Id of heap that this heap must be adjacent to.
  * @align:		Alignment requirement for the memory
+ * @mem_is_fmem		Flag indicating whether this memory is coming from fmem
+ *			or not.
  * @request_region:	function to be called when the number of allocations
  *			goes from 0 -> 1
  * @release_region:	function to be called when the number of allocations
@@ -194,6 +199,7 @@
 struct ion_co_heap_pdata {
 	int adjacent_mem_id;
 	unsigned int align;
+	int mem_is_fmem;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
 	void *(*setup_region)(void);
@@ -564,6 +570,7 @@
 			struct ion_handle *handle, int domain_num,
 			int partition_num, unsigned long align,
 			unsigned long iova_length, unsigned long *iova,
+			unsigned long *buffer_size,
 			unsigned long flags)
 {
 	return -ENODEV;
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index c4f601b..c90d8d1 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -73,6 +73,22 @@
 	PM8XXX_RESTART_ON_HARD_RESET,
 };
 
+enum pm8xxx_aux_clk_id {
+	CLK_MP3_1,
+	CLK_MP3_2,
+};
+
+enum pm8xxx_aux_clk_div {
+	X0_DIV_NONE,
+	XO_DIV_1,
+	XO_DIV_2,
+	XO_DIV_4,
+	XO_DIV_8,
+	XO_DIV_16,
+	XO_DIV_32,
+	XO_DIV_64,
+};
+
 #if defined(CONFIG_MFD_PM8XXX_MISC) || defined(CONFIG_MFD_PM8XXX_MISC_MODULE)
 
 /**
@@ -181,6 +197,19 @@
  */
 int pm8xxx_usb_id_pullup(int enable);
 
+/**
+ * pm8xxx_aux_clk_control - Control an auxiliary clock
+ * @clk_id: ID of clock to be programmed, registers of XO_CNTRL2
+ * @divider: divisor to use when configuring desired clock
+ * @enable: enable (1) the designated clock with the supplied division,
+ *		or disable (0) the designated clock
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+				enum pm8xxx_aux_clk_div divider,
+				bool enable);
+
 #else
 
 static inline int pm8xxx_reset_pwr_off(int reset)
@@ -225,6 +254,12 @@
 {
 	return -ENODEV;
 }
+static inline int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+			enum pm8xxx_aux_clk_div divider, bool enable)
+{
+	return -ENODEV;
+}
+
 #endif
 
 #endif
diff --git a/include/linux/mfd/pm8xxx/regulator.h b/include/linux/mfd/pm8xxx/regulator.h
index 9e0ce86..83492d2 100644
--- a/include/linux/mfd/pm8xxx/regulator.h
+++ b/include/linux/mfd/pm8xxx/regulator.h
@@ -30,6 +30,7 @@
  * %PM8XXX_REGULATOR_TYPE_VS:		voltage switch capable of sourcing 100mA
  * %PM8XXX_REGULATOR_TYPE_VS300:	voltage switch capable of sourcing 300mA
  * %PM8XXX_REGULATOR_TYPE_NCP:		negative charge pump
+ * %PM8XXX_REGULATOR_TYPE_BOOST:	boost regulator
  * %PM8XXX_REGULATOR_TYPE_MAX:		used internally for error checking; not
  *					a valid regulator type.
  *
@@ -44,6 +45,7 @@
 	PM8XXX_REGULATOR_TYPE_VS,
 	PM8XXX_REGULATOR_TYPE_VS300,
 	PM8XXX_REGULATOR_TYPE_NCP,
+	PM8XXX_REGULATOR_TYPE_BOOST,
 	PM8XXX_REGULATOR_TYPE_MAX,
 };
 
@@ -257,4 +259,13 @@
 		.prev_write_count = -1, \
 	}
 
+#define BOOST(_name, _ctrl_addr) \
+	{ \
+		.type		= PM8XXX_REGULATOR_TYPE_BOOST, \
+		.ctrl_addr	= _ctrl_addr, \
+		.rdesc.name	= _name, \
+		.write_count	= 0, \
+		.prev_write_count = -1, \
+	}
+
 #endif
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 18997d7..cb394e8 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -436,6 +436,15 @@
 			__attribute__((aligned(sizeof(kernel_ulong_t))));
 };
 
+#define SPMI_NAME_SIZE	32
+#define SPMI_MODULE_PREFIX "spmi:"
+
+struct spmi_device_id {
+	char name[SPMI_NAME_SIZE];
+	kernel_ulong_t driver_data	/* Data private to the driver */
+			__attribute__((aligned(sizeof(kernel_ulong_t))));
+};
+
 /* dmi */
 enum dmi_field {
 	DMI_NONE,
diff --git a/include/linux/msm_audio_mvs.h b/include/linux/msm_audio_mvs.h
index 2813c8f..8ec9796 100644
--- a/include/linux/msm_audio_mvs.h
+++ b/include/linux/msm_audio_mvs.h
@@ -24,7 +24,7 @@
 #define MVS_MODE_G729A 0xE
 #define MVS_MODE_G711A 0xF
 #define MVS_MODE_G722 0x10
-#define MVS_MODE_PCM_WB 0x80000000
+#define MVS_MODE_PCM_WB 0x12
 
 enum msm_audio_amr_mode {
 	MVS_AMR_MODE_0475, /* AMR 4.75 kbps */
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 9eb6dda..5e39f89 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -140,6 +140,13 @@
 #define KGSL_2D1_REG_MEMORY	"kgsl_2d1_reg_memory"
 #define KGSL_2D1_IRQ		"kgsl_2d1_irq"
 
+struct kgsl_device_iommu_data {
+	const char **iommu_ctx_names;
+	int iommu_ctx_count;
+	unsigned int physstart;
+	unsigned int physend;
+};
+
 struct kgsl_device_platform_data {
 	struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
 	int init_level;
@@ -148,9 +155,10 @@
 	unsigned int idle_timeout;
 	unsigned int nap_allowed;
 	unsigned int clk_map;
+	unsigned int idle_needed;
 	struct msm_bus_scale_pdata *bus_scale_table;
-	const char *iommu_user_ctx_name;
-	const char *iommu_priv_ctx_name;
+	struct kgsl_device_iommu_data *iommu_data;
+	int iommu_count;
 };
 
 #endif
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 189548c..99b5acd 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -22,14 +22,15 @@
 	MSM_8660 = 0,
 	MSM_8960,
 	MSM_9615,
+	APQ_8064,
 	MSM_TYPE
 };
 
 struct tsens_platform_data {
-	int				slope;
 	int				tsens_factor;
 	uint32_t			tsens_num_sensor;
 	enum platform_type		hw_type;
+	int				slope[11];
 };
 
 struct tsens_device {
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 3a6f037..cf58d27 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -49,6 +49,8 @@
 
 struct mtd_info;
 
+void part_fill_badblockstats(struct mtd_info *mtd);
+
 /*
  * Functions dealing with the various ways of partitioning the space
  */
diff --git a/include/linux/of.h b/include/linux/of.h
index 6a1272c..f904bf4 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -241,6 +241,16 @@
 	return false;
 }
 
+#define for_each_child_of_node(parent, child) \
+	while (0)
+
+static inline struct property *of_find_property(const struct device_node *np,
+						const char *name,
+						int *lenp)
+{
+	return NULL;
+}
+
 static inline int of_property_read_u32_array(const struct device_node *np,
 				char *propname, u32 *out_values, size_t sz)
 {
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3118623..01b925a 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -4,6 +4,7 @@
 #include <linux/errno.h>
 #include <linux/of.h>
 
+#ifdef CONFIG_OF_ADDRESS
 extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
 extern int of_address_to_resource(struct device_node *dev, int index,
 				  struct resource *r);
@@ -25,12 +26,37 @@
 #define pci_address_to_pio pci_address_to_pio
 #endif
 
-#ifdef CONFIG_PCI
+#else /* CONFIG_OF_ADDRESS */
+static inline int of_address_to_resource(struct device_node *dev, int index,
+					 struct resource *r)
+{
+	return -EINVAL;
+}
+static inline struct device_node *of_find_matching_node_by_address(
+					struct device_node *from,
+					const struct of_device_id *matches,
+					u64 base_address)
+{
+	return NULL;
+}
+static inline void __iomem *of_iomap(struct device_node *device, int index)
+{
+	return NULL;
+}
+static inline const u32 *of_get_address(struct device_node *dev, int index,
+					u64 *size, unsigned int *flags)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF_ADDRESS */
+
+
+#if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_PCI)
 extern const __be32 *of_get_pci_address(struct device_node *dev, int bar_no,
 			       u64 *size, unsigned int *flags);
 extern int of_pci_address_to_resource(struct device_node *dev, int bar,
 				      struct resource *r);
-#else /* CONFIG_PCI */
+#else /* CONFIG_OF_ADDRESS && CONFIG_PCI */
 static inline int of_pci_address_to_resource(struct device_node *dev, int bar,
 				             struct resource *r)
 {
@@ -42,8 +68,7 @@
 {
 	return NULL;
 }
-#endif /* CONFIG_PCI */
-
+#endif /* CONFIG_OF_ADDRESS && CONFIG_PCI */
 
 #endif /* __OF_ADDRESS_H */
 
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
new file mode 100644
index 0000000..6d39026
--- /dev/null
+++ b/include/linux/qseecom.h
@@ -0,0 +1,149 @@
+#ifndef __QSEECOM_H_
+#define __QSEECOM_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define MAX_ION_FD  4
+#define MAX_APP_NAME_SIZE  32
+
+/*
+ * struct qseecom_register_listener_req -
+ *      for register listener ioctl request
+ * @listener_id - service id (shared between userspace and QSE)
+ * @ifd_data_fd - ion handle
+ * @virt_sb_base - shared buffer base in user space
+ * @sb_size - shared buffer size
+ */
+struct qseecom_register_listener_req {
+	uint32_t listener_id; /* in */
+	int32_t ifd_data_fd; /* in */
+	uint32_t virt_sb_base; /* in */
+	uint32_t sb_size; /* in */
+};
+
+/*
+ * struct qseecom_send_cmd_req - for send command ioctl request
+ * @cmd_req_len - command buffer length
+ * @cmd_req_buf - command buffer
+ * @resp_len - response buffer length
+ * @resp_buf - response buffer
+ */
+struct qseecom_send_cmd_req {
+	void *cmd_req_buf; /* in */
+	unsigned int cmd_req_len; /* in */
+	void *resp_buf; /* in/out */
+	unsigned int resp_len; /* in/out */
+};
+
+
+/*
+ * struct qseecom_ion_fd_info - ion fd handle data information
+ * @fd - ion handle to some memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_ion_fd_info {
+	int32_t fd;
+	uint32_t cmd_buf_offset;
+};
+/*
+ * struct qseecom_send_modfd_cmd_req - for send command ioctl request
+ * @cmd_req_len - command buffer length
+ * @cmd_req_buf - command buffer
+ * @resp_len - response buffer length
+ * @resp_buf - response buffer
+ * @ifd_data_fd - ion handle to memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_send_modfd_cmd_req {
+	void *cmd_req_buf; /* in */
+	unsigned int cmd_req_len; /* in */
+	void *resp_buf; /* in/out */
+	unsigned int resp_len; /* in/out */
+	struct qseecom_ion_fd_info ifd_data[MAX_ION_FD];
+};
+/*
+ * struct qseecom_listener_send_resp_req - signal to continue the send_cmd req.
+ * Used as a trigger from HLOS service to notify QSEECOM that it's done with its
+ * operation and provide the response for QSEECOM can continue the incomplete
+ * command execution
+ * @resp_len - Length of the response
+ * @resp_buf - Response buffer where the response of the cmd should go.
+ */
+struct qseecom_send_resp_req {
+	void *resp_buf; /* in */
+	unsigned int resp_len; /* in */
+};
+
+/*
+ * struct qseecom_load_img_data - for sending image length information and
+ * ion file descriptor to the qseecom driver. ion file descriptor is used
+ * for retrieving the ion file handle and in turn the physical address of
+ * the image location.
+ * @mdt_len - Length of the .mdt file in bytes.
+ * @img_len - Length of the .mdt + .b00 +..+.bxx images files in bytes
+ * @ion_fd - Ion file descriptor used when allocating memory.
+ * @img_name - Name of the image.
+*/
+struct qseecom_load_img_req {
+	uint32_t mdt_len; /* in */
+	uint32_t img_len; /* in */
+	int32_t  ifd_data_fd; /* in */
+	char	 img_name[MAX_APP_NAME_SIZE]; /* in */
+	int app_id; /* out*/
+};
+
+struct qseecom_set_sb_mem_param_req {
+	int32_t ifd_data_fd; /* in */
+	uint32_t virt_sb_base; /* in */
+	uint32_t sb_len; /* in */
+};
+
+/*
+ * struct qseecom_qseos_version_req - get qseos version
+ * @qseos_version - version number
+ */
+struct qseecom_qseos_version_req {
+	unsigned int qseos_version; /* in */
+};
+
+#define QSEECOM_IOC_MAGIC    0x97
+
+
+#define QSEECOM_IOCTL_REGISTER_LISTENER_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 1, struct qseecom_register_listener_req)
+
+#define QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ \
+	_IO(QSEECOM_IOC_MAGIC, 2)
+
+#define QSEECOM_IOCTL_SEND_CMD_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 3, struct qseecom_send_cmd_req)
+
+#define QSEECOM_IOCTL_SEND_MODFD_CMD_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 4, struct qseecom_send_modfd_cmd_req)
+
+#define QSEECOM_IOCTL_RECEIVE_REQ \
+	_IO(QSEECOM_IOC_MAGIC, 5)
+
+#define QSEECOM_IOCTL_SEND_RESP_REQ \
+	_IO(QSEECOM_IOC_MAGIC, 6)
+
+#define QSEECOM_IOCTL_LOAD_APP_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 7, struct qseecom_load_img_req)
+
+#define QSEECOM_IOCTL_SET_MEM_PARAM_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 8, struct qseecom_set_sb_mem_param_req)
+
+#define QSEECOM_IOCTL_UNLOAD_APP_REQ \
+	_IO(QSEECOM_IOC_MAGIC, 9)
+
+#define QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 10, struct qseecom_qseos_version_req)
+
+#define QSEECOM_IOCTL_PERF_ENABLE_REQ \
+	_IO(QSEECOM_IOC_MAGIC, 11)
+
+#define QSEECOM_IOCTL_PERF_DISABLE_REQ \
+	_IO(QSEECOM_IOC_MAGIC, 12)
+
+#endif /* __QSEECOM_H_ */
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index 448d9ab..75b132b 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -877,6 +877,7 @@
  * -EXFULL is returned if there is no space in TDM to reserve the bandwidth.
  * -EISCONN/-ENOTCONN is returned if the channel is already connected or not
  * yet defined.
+ * -EINVAL is returned if individual control of a grouped-channel is attempted.
  */
 extern int slim_control_ch(struct slim_device *sb, u16 grpchanh,
 				enum slim_ch_control chctrl, bool commit);
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
new file mode 100644
index 0000000..ffcb24e
--- /dev/null
+++ b/include/linux/spmi.h
@@ -0,0 +1,408 @@
+/* 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 _LINUX_SPMI_H
+#define _LINUX_SPMI_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+/* Maximum slave identifier */
+#define SPMI_MAX_SLAVE_ID		16
+
+/* SPMI Commands */
+enum spmi_commands {
+	SPMI_CMD_EXT_WRITE = 0x00,
+	SPMI_CMD_RESET = 0x10,
+	SPMI_CMD_SLEEP = 0x11,
+	SPMI_CMD_SHUTDOWN = 0x12,
+	SPMI_CMD_WAKEUP = 0x13,
+	SPMI_CMD_AUTHENTICATE = 0x14,
+	SPMI_CMD_MSTR_READ = 0x15,
+	SPMI_CMD_MSTR_WRITE = 0x16,
+	SPMI_CMD_TRANSFER_BUS_OWNERSHIP = 0x1A,
+	SPMI_CMD_DDB_MASTER_READ = 0x1B,
+	SPMI_CMD_DDB_SLAVE_READ = 0x1C,
+	SPMI_CMD_EXT_READ = 0x20,
+	SPMI_CMD_EXT_WRITEL = 0x30,
+	SPMI_CMD_EXT_READL = 0x38,
+	SPMI_CMD_WRITE = 0x40,
+	SPMI_CMD_READ = 0x60,
+	SPMI_CMD_ZERO_WRITE = 0x80,
+};
+
+struct spmi_device;
+
+/**
+ * struct spmi_controller: interface to the SPMI master controller
+ * @nr: board-specific number identifier for this controller/bus
+ * @name: name for this controller
+ * @cmd: sends a non-data command sequence on the SPMI bus.
+ * @read_cmd: sends a register read command sequence on the SPMI bus.
+ * @write_cmd: sends a register write command sequence on the SPMI bus.
+ */
+struct spmi_controller {
+	struct device		dev;
+	unsigned int		nr;
+	struct list_head	list;
+	int		(*cmd)(struct spmi_controller *, u8 opcode, u8 sid);
+	int		(*read_cmd)(struct spmi_controller *,
+				u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);
+	int		(*write_cmd)(struct spmi_controller *,
+				u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);
+};
+#define to_spmi_controller(d) container_of(d, struct spmi_controller, dev)
+
+/**
+ * struct spmi_driver: Manage SPMI generic/slave device driver
+ * @probe: binds this driver to a SPMI device.
+ * @remove: unbinds this driver from the SPMI device.
+ * @shutdown: standard shutdown callback used during powerdown/halt.
+ * @suspend: standard suspend callback used during system suspend
+ * @resume: standard resume callback used during system resume
+ * @driver: SPMI device drivers should initialize name and owner field of
+ *	    this structure
+ * @id_table: list of SPMI devices supported by this driver
+ */
+struct spmi_driver {
+	int				(*probe)(struct spmi_device *dev);
+	int				(*remove)(struct spmi_device *dev);
+	void				(*shutdown)(struct spmi_device *dev);
+	int				(*suspend)(struct spmi_device *dev,
+					pm_message_t pmesg);
+	int				(*resume)(struct spmi_device *dev);
+
+	struct device_driver		driver;
+	const struct spmi_device_id	*id_table;
+};
+#define to_spmi_driver(d) container_of(d, struct spmi_driver, driver)
+
+/**
+ * Client/device handle (struct spmi_device):
+ * ------------------------------------------
+ * This is the client/device handle returned when a SPMI device
+ * is registered with a controller.
+ * Pointer to this structure is used by client-driver as a handle.
+ * @dev: driver model representation of the device.
+ * @name: name of driver to use with this device.
+ * @ctrl: SPMI controller managing the bus hosting this device.
+ * @resource: array of resources for this device_node
+ * @num_resources: number of resources for this device node
+ * @sid: slave identifier.
+ */
+struct spmi_device {
+	struct device		dev;
+	const char		*name;
+	struct spmi_controller	*ctrl;
+	struct resource		*resource;
+	u32			num_resources;
+	u8			sid;
+};
+#define to_spmi_device(d) container_of(d, struct spmi_device, dev)
+
+/**
+ * struct spmi_boardinfo: Declare board info for SPMI device bringup.
+ * @slave_id: slave identifier.
+ * @spmi_device: device to be registered with the SPMI framework.
+ * @of_node: pointer to the OpenFirmware device node.
+ * @num_resources: number of resources for this device node
+ * @resource: array of resources for this device_node
+ * @platform_data: goes to spmi_device.dev.platform_data
+ */
+struct spmi_boardinfo {
+	char			name[SPMI_NAME_SIZE];
+	uint8_t			slave_id;
+	struct device_node	*of_node;
+	u32			num_resources;
+	struct resource		*resource;
+	const void		*platform_data;
+};
+
+/**
+ * spmi_driver_register: Client driver registration with SPMI framework.
+ * @drv: client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the SPMI framework.
+ * It is called from the driver's module-init function.
+ */
+extern int spmi_driver_register(struct spmi_driver *drv);
+
+/**
+ * spmi_driver_unregister - reverse effect of spmi_driver_register
+ * @sdrv: the driver to unregister
+ * Context: can sleep
+ */
+static inline void spmi_driver_unregister(struct spmi_driver *sdrv)
+{
+	if (sdrv)
+		driver_unregister(&sdrv->driver);
+}
+
+/**
+ * spmi_add_controller: Controller bring-up.
+ * @ctrl: controller to be registered.
+ *
+ * A controller is registered with the framework using this API. ctrl->nr is the
+ * desired number with which SPMI framework registers the controller.
+ * Function will return -EBUSY if the number is in use.
+ */
+extern int spmi_add_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_del_controller: Controller tear-down.
+ * Controller added with the above API is teared down using this API.
+ */
+extern int spmi_del_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_busnum_to_ctrl: Map bus number to controller
+ * @busnum: bus number
+ *
+ * Returns controller device representing this bus number
+ */
+extern struct spmi_controller *spmi_busnum_to_ctrl(u32 bus_num);
+
+/**
+ * spmi_alloc_device: Allocate a new SPMI devices.
+ * @ctrl: controller to which this device is to be added to.
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize a SPMI device without
+ * registering it immediately.  This allows a driver to directly fill
+ * the spmi_device structure before calling spmi_add_device().
+ *
+ * Caller is responsible to call spmi_add_device() on the returned
+ * spmi_device.  If the caller needs to discard the spmi_device without
+ * adding it, then spmi_dev_put() should be called.
+ */
+extern struct spmi_device *spmi_alloc_device(struct spmi_controller *ctrl);
+
+/**
+ * spmi_add_device: Add spmi_device allocated with spmi_alloc_device().
+ * @spmi_dev: spmi_device to be added (registered).
+ */
+extern int spmi_add_device(struct spmi_device *spmi_dev);
+
+/**
+ * spmi_new_device: Instantiates a new SPMI device
+ * @ctrl: controller to which this device is to be added to.
+ * @info: board information for this device.
+ *
+ * Returns the new device or NULL.
+ */
+extern struct spmi_device *spmi_new_device(struct spmi_controller *ctrl,
+					struct spmi_boardinfo const *info);
+
+/* spmi_remove_device: Remove the effect of spmi_add_device() */
+extern void spmi_remove_device(struct spmi_device *spmi_dev);
+
+#ifdef CONFIG_SPMI
+/**
+ * spmi_register_board_info: Board-initialization routine.
+ * @bus_num: controller number (bus) on which this device will sit.
+ * @info: list of all devices on all controllers present on the board.
+ * @n: number of entries.
+ *
+ * API enumerates respective devices on corresponding controller.
+ * Called from board-init function.
+ */
+extern int spmi_register_board_info(int busnum,
+			struct spmi_boardinfo const *info, unsigned n);
+#else
+static inline int spmi_register_board_info(int busnum,
+			struct spmi_boardinfo const *info, unsigned n)
+{
+	return 0;
+}
+#endif
+
+static inline void *spmi_get_ctrldata(const struct spmi_controller *ctrl)
+{
+	return dev_get_drvdata(&ctrl->dev);
+}
+
+static inline void spmi_set_ctrldata(struct spmi_controller *ctrl, void *data)
+{
+	dev_set_drvdata(&ctrl->dev, data);
+}
+
+static inline void *spmi_get_devicedata(const struct spmi_device *dev)
+{
+	return dev_get_drvdata(&dev->dev);
+}
+
+static inline void spmi_set_devicedata(struct spmi_device *dev, void *data)
+{
+	dev_set_drvdata(&dev->dev, data);
+}
+
+static inline void spmi_dev_put(struct spmi_device *spmidev)
+{
+	if (spmidev)
+		put_device(&spmidev->dev);
+}
+
+/**
+ * spmi_register_read() - register read
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads 1 byte of data from a Slave device register.
+ */
+extern int spmi_register_read(struct spmi_controller *ctrl,
+					u8 sid, u8 ad, u8 *buf);
+
+/**
+ * spmi_ext_register_read() - extended register read
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @len: the request number of bytes to read (up to 16 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 16 bytes of data from the extended register space on a
+ * Slave device.
+ */
+extern int spmi_ext_register_read(struct spmi_controller *ctrl,
+					u8 sid, u8 ad, u8 *buf, int len);
+
+/**
+ * spmi_ext_register_readl() - extended register read long
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @len: the request number of bytes to read (up to 8 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 8 bytes of data from the extended register space on a
+ * Slave device using 16-bit address.
+ */
+extern int spmi_ext_register_readl(struct spmi_controller *ctrl,
+					u8 sid, u16 ad, u8 *buf, int len);
+
+/**
+ * spmi_register_write() - register write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ *
+ * Writes 1 byte of data to a Slave device register.
+ */
+extern int spmi_register_write(struct spmi_controller *ctrl,
+					u8 sid, u8 ad, u8 *buf);
+
+/**
+ * spmi_register_zero_write() - register zero write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @data: the data to be written to register 0 (7-bits).
+ *
+ * Writes data to register 0 of the Slave device.
+ */
+extern int spmi_register_zero_write(struct spmi_controller *ctrl,
+					u8 sid, u8 data);
+
+/**
+ * spmi_ext_register_write() - extended register write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 16 bytes).
+ *
+ * Writes up to 16 bytes of data to the extended register space of a
+ * Slave device.
+ */
+extern int spmi_ext_register_write(struct spmi_controller *ctrl,
+					u8 sid, u8 ad, u8 *buf, int len);
+
+/**
+ * spmi_ext_register_writel() - extended register write long
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 8 bytes).
+ *
+ * Writes up to 8 bytes of data to the extended register space of a
+ * Slave device using 16-bit address.
+ */
+extern int spmi_ext_register_writel(struct spmi_controller *ctrl,
+					u8 sid, u16 ad, u8 *buf, int len);
+
+/**
+ * spmi_command_reset() - sends RESET command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Reset command initializes the Slave and forces all registers to
+ * their reset values. The Slave shall enter the STARTUP state after
+ * receiving a Reset command.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_reset(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_sleep() - sends SLEEP command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Sleep command causes the Slave to enter the user defined SLEEP state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_sleep(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_wakeup() - sends WAKEUP command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Wakeup command causes the Slave to move from the SLEEP state to
+ * the ACTIVE state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_wakeup(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Shutdown command causes the Slave to enter the SHUTDOWN state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_shutdown(struct spmi_controller *ctrl, u8 sid);
+#endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 037cfe7..79fb177 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -277,6 +277,10 @@
 	unsigned hub_reset;
 };
 
+struct msm_usb_host_platform_data {
+	unsigned int power_budget;
+};
+
 struct usb_bam_pipe_connect {
 	u32 src_phy_addr;
 	int src_pipe_index;
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h
index 9595796..540a74c 100644
--- a/include/linux/usb/ulpi.h
+++ b/include/linux/usb/ulpi.h
@@ -145,6 +145,7 @@
 #define ULPI_INT_SESS_VALID			(1 << 2)
 #define ULPI_INT_SESS_END			(1 << 3)
 #define ULPI_INT_IDGRD				(1 << 4)
+#define ULPI_INT_DP				(1 << 7)
 
 /* Debug */
 #define ULPI_DEBUG_LINESTATE0			(1 << 0)
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 1cd8448..8bb2558 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -56,6 +56,7 @@
 struct vcd_frame_data {
 	u8 *virtual;
 	u8 *physical;
+	u32 ion_flag;
 	u32 alloc_len;
 	u32 data_len;
 	u32 offset;
diff --git a/include/media/msm/vidc_init.h b/include/media/msm/vidc_init.h
index 60cc35f..4e28c74 100644
--- a/include/media/msm/vidc_init.h
+++ b/include/media/msm/vidc_init.h
@@ -14,7 +14,8 @@
 #ifndef VIDC_INIT_H
 #define VIDC_INIT_H
 #include <linux/ion.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_property.h>
 
 #define VIDC_MAX_NUM_CLIENTS 4
 #define MAX_VIDEO_NUM_OF_BUFF 100
@@ -28,6 +29,7 @@
 	unsigned long user_vaddr;
 	unsigned long kernel_vaddr;
 	unsigned long phy_addr;
+	unsigned long buff_ion_flag;
 	struct ion_handle *buff_ion_handle;
 	int pmem_fd;
 	struct file *file;
@@ -63,6 +65,9 @@
 void __iomem *vidc_get_ioaddr(void);
 int vidc_load_firmware(void);
 void vidc_release_firmware(void);
+u32 vidc_get_fd_info(struct video_client_ctx *client_ctx,
+		enum buffer_dir buffer, int pmem_fd,
+		unsigned long kvaddr, int index);
 u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
 	enum buffer_dir buffer, u32 search_with_user_vaddr,
 	unsigned long *user_vaddr, unsigned long *kernel_vaddr,
@@ -76,6 +81,8 @@
 u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
 	enum buffer_dir buffer, unsigned long user_vaddr,
 	unsigned long *kernel_vaddr);
+void vidc_cleanup_addr_table(struct video_client_ctx *client_ctx,
+		enum buffer_dir buffer);
 
 u32 vidc_timer_create(void (*timer_handler)(void *),
 	void *user_data, void **timer_handle);
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 87fbbd2..867bd8a 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -184,10 +184,10 @@
 	_IOW(MSM_CAM_IOCTL_MAGIC, 51, uint32_t *)
 
 #define MSM_CAM_IOCTL_GET_MCTL_INFO \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 51, struct msm_mctl_node_info *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_mctl_node_info *)
 
 #define MSM_CAM_IOCTL_MCTL_DIVERT_DONE \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_cam_evt_divert_frame *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 53, struct msm_cam_evt_divert_frame *)
 
 struct msm_mctl_pp_cmd {
 	int32_t  id;
@@ -693,6 +693,9 @@
 #define MSM_V4L2_CAM_OP_ZSL             (MSM_V4L2_CAM_OP_DEFAULT+4)
 /* camera operation mode for raw snapshot - one frame output queue */
 #define MSM_V4L2_CAM_OP_RAW             (MSM_V4L2_CAM_OP_DEFAULT+5)
+/* camera operation mode for jpeg snapshot - one frame output queue */
+#define MSM_V4L2_CAM_OP_JPEG_CAPTURE    (MSM_V4L2_CAM_OP_DEFAULT+6)
+
 
 #define MSM_V4L2_VID_CAP_TYPE	0
 #define MSM_V4L2_STREAM_ON		1
@@ -762,8 +765,16 @@
 #define CFG_GET_OUTPUT_INFO		32
 #define CFG_GET_EEPROM_DATA		33
 #define CFG_SET_ACTUATOR_INFO		34
-#define CFG_GET_ACTUATOR_INFO		35
-#define CFG_MAX			36
+#define CFG_GET_ACTUATOR_INFO           35
+/* TBD: QRD */
+#define CFG_SET_SATURATION            36
+#define CFG_SET_SHARPNESS             37
+#define CFG_SET_TOUCHAEC              38
+#define CFG_SET_AUTO_FOCUS            39
+#define CFG_SET_AUTOFLASH             40
+#define CFG_SET_EXPOSURE_COMPENSATION 41
+#define CFG_SET_ISO                   42
+#define CFG_MAX			43
 
 
 #define MOVE_NEAR	0
@@ -854,14 +865,6 @@
 #define CAMERA_SETAE_AVERAGE		0
 #define CAMERA_SETAE_CENWEIGHT	1
 
-#define CFG_SET_SATURATION		30
-#define CFG_SET_SHARPNESS			31
-#define CFG_SET_TOUCHAEC            32
-#define CFG_SET_AUTO_FOCUS          33
-#define CFG_SET_AUTOFLASH 34
-/* QRD */
-#define CFG_SET_EXPOSURE_COMPENSATION 35
-
 #define  CAMERA_WB_AUTO               1 /* This list must match aeecamera.h */
 #define  CAMERA_WB_CUSTOM             2
 #define  CAMERA_WB_INCANDESCENT       3
@@ -945,6 +948,14 @@
 	MSM_V4L2_POWER_LINE_AUTO,
 };
 
+#define CAMERA_ISO_TYPE_AUTO           0
+#define CAMEAR_ISO_TYPE_HJR            1
+#define CAMEAR_ISO_TYPE_100            2
+#define CAMERA_ISO_TYPE_200            3
+#define CAMERA_ISO_TYPE_400            4
+#define CAMEAR_ISO_TYPE_800            5
+#define CAMERA_ISO_TYPE_1600           6
+
 struct sensor_pict_fps {
 	uint16_t prevfps;
 	uint16_t pictfps;
@@ -1080,6 +1091,7 @@
 		uint16_t pictp_pl;
 		uint32_t pict_max_exp_lc;
 		uint16_t p_fps;
+		uint8_t iso_type;
 		struct sensor_init_cfg init_info;
 		struct sensor_pict_fps gfps;
 		struct exp_gain_cfg exp_gain;
@@ -1125,6 +1137,10 @@
 	uint32_t f_pix_den;
 	uint32_t total_f_dist_num;
 	uint32_t total_f_dist_den;
+	uint32_t hor_view_angle_num;
+	uint32_t hor_view_angle_den;
+	uint32_t ver_view_angle_num;
+	uint32_t ver_view_angle_den;
 };
 
 struct msm_actuator_cfg_data {
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 5dd1445..07784e2 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -241,6 +241,9 @@
 #define VPE_SCALER_CONFIG_LEN           260
 #define VPE_DIS_OFFSET_CFG_LEN          12
 
+#define IMEM_Y_OFFSET  0x2E000000
+#define IMEM_CBCR_OFFSET  0x2E00FA00
+
 struct msm_vpe_op_mode_cfg {
 	uint8_t op_mode_cfg[VPE_OPERATION_MODE_CFG_LEN];
 };
@@ -311,6 +314,8 @@
 #define VFE_OUTPUTS_PREVIEW		BIT(6)
 #define VFE_OUTPUTS_VIDEO		BIT(7)
 #define VFE_OUTPUTS_RAW			BIT(8)
+#define VFE_OUTPUTS_JPEG_AND_THUMB	BIT(9)
+#define VFE_OUTPUTS_THUMB_AND_JPEG	BIT(10)
 
 #endif /*__MSM_ISP_H__*/
 
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 36139ba..de2b356 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -590,7 +590,8 @@
 	IRIS_EVT_NEW_SRCH_LIST,
 	IRIS_EVT_NEW_AF_LIST,
 	IRIS_EVT_TXRDSDAT,
-	IRIS_EVT_TXRDSDONE
+	IRIS_EVT_TXRDSDONE,
+	IRIS_EVT_RADIO_DISABLED
 };
 enum emphasis_type {
 	FM_RX_EMP75 = 0x0,
@@ -674,7 +675,7 @@
 
 /* Band limits */
 #define REGION_US_EU_BAND_LOW              87500
-#define REGION_US_EU_BAND_HIGH             107900
+#define REGION_US_EU_BAND_HIGH             108000
 #define REGION_JAPAN_STANDARD_BAND_LOW     76000
 #define REGION_JAPAN_STANDARD_BAND_HIGH    90000
 #define REGION_JAPAN_WIDE_BAND_LOW         90000
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8e66a25..164d3b4 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -931,7 +931,7 @@
 	if (conn->sec_level == BT_SECURITY_SDP)
 		conn->sec_level = BT_SECURITY_LOW;
 
-	if (conn->pending_sec_level > conn->sec_level)
+	if (!status && encrypt && conn->pending_sec_level > conn->sec_level)
 		conn->sec_level = conn->pending_sec_level;
 
 	hci_proto_encrypt_cfm(conn, status, encrypt);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 312de3f..d5c4189 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -489,6 +489,7 @@
 	__u8		fixed_channel;
 	__u8		num_conf_req;
 	__u8		num_conf_rsp;
+	__u8		incoming;
 
 	__u8		fcs;
 	__u8		sec_level;
@@ -648,6 +649,8 @@
 #define L2CAP_AMP_STATE_RESEGMENT		12
 
 #define L2CAP_ATT_ERROR				0x01
+#define L2CAP_ATT_MTU_REQ			0x02
+#define L2CAP_ATT_MTU_RSP			0x03
 #define L2CAP_ATT_RESPONSE_BIT			0x01
 #define L2CAP_ATT_INDICATE			0x1D
 #define L2CAP_ATT_NOT_SUPPORTED			0x06
@@ -689,6 +692,8 @@
 void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
+struct sock *l2cap_find_sock_by_fixed_cid_and_dir(__le16 cid, bdaddr_t *src,
+						bdaddr_t *dst, int server);
 void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err);
 void l2cap_chan_del(struct sock *sk, int err);
 int l2cap_do_connect(struct sock *sk);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 47bfde5..4c2bd37 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -561,6 +561,19 @@
 		goto done;
 	}
 
+	if (!skb_queue_empty(&hdev->cmd_q)) {
+		BT_ERR("command queue is not empty, purging");
+		skb_queue_purge(&hdev->cmd_q);
+	}
+	if (!skb_queue_empty(&hdev->rx_q)) {
+		BT_ERR("rx queue is not empty, purging");
+		skb_queue_purge(&hdev->rx_q);
+	}
+	if (!skb_queue_empty(&hdev->raw_q)) {
+		BT_ERR("raw queue is not empty, purging");
+		skb_queue_purge(&hdev->raw_q);
+	}
+
 	if (!test_bit(HCI_RAW, &hdev->flags)) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		set_bit(HCI_INIT, &hdev->flags);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b4dde4c..9662795 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -930,18 +930,24 @@
 }
 
 /* Find socket with fixed cid with given source and destination bdaddrs.
- * Returns closest match, locked.
+ * Direction of the req/rsp must match.
  */
-static struct sock *l2cap_get_sock_by_fixed_scid(int state,
-				__le16 cid, bdaddr_t *src, bdaddr_t *dst)
+struct sock *l2cap_find_sock_by_fixed_cid_and_dir(__le16 cid, bdaddr_t *src,
+						bdaddr_t *dst, int incoming)
 {
 	struct sock *sk = NULL, *sk1 = NULL;
 	struct hlist_node *node;
 
+	BT_DBG(" %d", incoming);
+
 	read_lock(&l2cap_sk_list.lock);
 
 	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		if (state && sk->sk_state != state)
+
+		if (incoming && !l2cap_pi(sk)->incoming)
+			continue;
+
+		if (!incoming && l2cap_pi(sk)->incoming)
 			continue;
 
 		if (l2cap_pi(sk)->scid == cid && !bacmp(&bt_sk(sk)->dst, dst)) {
@@ -1022,13 +1028,12 @@
 	l2cap_sock_init(sk, parent);
 	bacpy(&bt_sk(sk)->src, conn->src);
 	bacpy(&bt_sk(sk)->dst, conn->dst);
+	l2cap_pi(sk)->incoming = 1;
 
 	bt_accept_enqueue(parent, sk);
 
 	__l2cap_chan_add(conn, sk);
 
-	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-
 	sk->sk_state = BT_CONNECTED;
 	parent->sk_data_ready(parent, 0);
 
@@ -1061,10 +1066,10 @@
 				if (pending_sec > sec_level)
 					sec_level = pending_sec;
 
-				if (smp_conn_security(conn, sec_level)) {
+				if (smp_conn_security(conn, sec_level))
 					l2cap_chan_ready(sk);
-					hci_conn_put(conn->hcon);
-				}
+
+				hci_conn_put(conn->hcon);
 
 			} else if (sk->sk_type != SOCK_SEQPACKET &&
 					sk->sk_type != SOCK_STREAM) {
@@ -1081,6 +1086,9 @@
 	}
 
 	read_unlock(&l->lock);
+
+	if (conn->hcon->out && conn->hcon->type == LE_LINK)
+		l2cap_le_conn_ready(conn);
 }
 
 /* Notify sockets that we cannot guaranty reliability anymore */
@@ -3035,7 +3043,8 @@
 {
 	lock_sock(sk);
 
-	if (l2cap_pi(sk)->mode != L2CAP_MODE_ERTM) {
+	if (l2cap_pi(sk)->mode != L2CAP_MODE_ERTM ||
+			sk->sk_state != BT_CONNECTED) {
 		release_sock(sk);
 		return;
 	}
@@ -7209,15 +7218,24 @@
 	return 0;
 }
 
-static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
+static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid,
+							struct sk_buff *skb)
 {
 	struct sock *sk;
 	struct sk_buff *skb_rsp;
 	struct l2cap_hdr *lh;
+	int dir;
+	u8 mtu_rsp[] = {L2CAP_ATT_MTU_RSP, 23, 0};
 	u8 err_rsp[] = {L2CAP_ATT_ERROR, 0x00, 0x00, 0x00,
 						L2CAP_ATT_NOT_SUPPORTED};
 
-	sk = l2cap_get_sock_by_fixed_scid(0, cid, conn->src, conn->dst);
+	dir = (skb->data[0] & L2CAP_ATT_RESPONSE_BIT) ? 0 : 1;
+
+	sk = l2cap_find_sock_by_fixed_cid_and_dir(cid, conn->src,
+							conn->dst, dir);
+
+	BT_DBG("sk %p, dir:%d", sk, dir);
+
 	if (!sk)
 		goto drop;
 
@@ -7231,6 +7249,22 @@
 	if (l2cap_pi(sk)->imtu < skb->len)
 		goto drop;
 
+	if (skb->data[0] == L2CAP_ATT_MTU_REQ) {
+		skb_rsp = bt_skb_alloc(sizeof(mtu_rsp) + L2CAP_HDR_SIZE,
+								GFP_ATOMIC);
+		if (!skb_rsp)
+			goto drop;
+
+		lh = (struct l2cap_hdr *) skb_put(skb_rsp, L2CAP_HDR_SIZE);
+		lh->len = cpu_to_le16(sizeof(mtu_rsp));
+		lh->cid = cpu_to_le16(L2CAP_CID_LE_DATA);
+		memcpy(skb_put(skb_rsp, sizeof(mtu_rsp)), mtu_rsp,
+							sizeof(mtu_rsp));
+		hci_send_acl(conn->hcon, NULL, skb_rsp, 0);
+
+		goto free_skb;
+	}
+
 	if (!sock_queue_rcv_skb(sk, skb))
 		goto done;
 
@@ -7333,7 +7367,7 @@
 	struct hlist_node *node;
 
 	if (type != ACL_LINK)
-		return -EINVAL;
+		return 0;
 
 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
@@ -7424,6 +7458,7 @@
 	struct l2cap_chan_list *l;
 	struct l2cap_conn *conn = hcon->l2cap_data;
 	struct sock *sk;
+	int smp = 0;
 
 	if (!conn)
 		return 0;
@@ -7445,9 +7480,7 @@
 				l2cap_chan_ready(sk);
 			}
 
-			del_timer(&hcon->smp_timer);
-			smp_link_encrypt_cmplt(conn, status, encrypt);
-
+			smp = 1;
 			bh_unlock_sock(sk);
 			continue;
 		}
@@ -7511,6 +7544,11 @@
 
 	read_unlock(&l->lock);
 
+	if (smp) {
+		del_timer(&hcon->smp_timer);
+		smp_link_encrypt_cmplt(conn, status, encrypt);
+	}
+
 	return 0;
 }
 
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 94cacde..6a4a2f0 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -611,8 +611,16 @@
 		case L2CAP_MODE_BASIC:
 			l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
 			break;
-		case L2CAP_MODE_ERTM:
 		case L2CAP_MODE_STREAMING:
+			if (!disable_ertm) {
+				/* No fallback to ERTM or Basic mode */
+				l2cap_pi(sk)->conf_state |=
+						L2CAP_CONF_STATE2_DEVICE;
+				break;
+			}
+			err = -EINVAL;
+			break;
+		case L2CAP_MODE_ERTM:
 			if (!disable_ertm)
 				break;
 			/* fall through */
@@ -957,7 +965,8 @@
 	else
 		err = bt_sock_recvmsg(iocb, sock, msg, len, flags);
 
-	l2cap_ertm_recv_done(sk);
+	if (err >= 0)
+		l2cap_ertm_recv_done(sk);
 
 	return err;
 }
@@ -1096,6 +1105,7 @@
 static int l2cap_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
+	struct sock *srv_sk = NULL;
 	int err;
 
 	BT_DBG("sock %p, sk %p", sock, sk);
@@ -1103,6 +1113,16 @@
 	if (!sk)
 		return 0;
 
+	/* If this is an ATT Client socket, find the matching Server */
+	if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA && !l2cap_pi(sk)->incoming)
+		srv_sk = l2cap_find_sock_by_fixed_cid_and_dir(L2CAP_CID_LE_DATA,
+					&bt_sk(sk)->src, &bt_sk(sk)->dst, 1);
+
+	/* If server socket found, request tear down */
+	BT_DBG("client:%p server:%p", sk, srv_sk);
+	if (srv_sk)
+		l2cap_sock_set_timer(srv_sk, 1);
+
 	err = l2cap_sock_shutdown(sock, 2);
 
 	sock_orphan(sk);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 2e4c47a..910ef77 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -762,7 +762,7 @@
 	struct list_head *p;
 	size_t name_len;
 
-	name_len = strlen(hdev->dev_name);
+	name_len = strnlen(hdev->dev_name, HCI_MAX_EIR_LENGTH);
 
 	if (name_len > 0) {
 		/* EIR Data type */
@@ -890,13 +890,17 @@
 
 	list_add(&uuid->list, &hdev->uuids);
 
-	err = update_class(hdev);
-	if (err < 0)
-		goto failed;
+	if (test_bit(HCI_UP, &hdev->flags)) {
 
-	err = update_eir(hdev);
-	if (err < 0)
-		goto failed;
+		err = update_class(hdev);
+		if (err < 0)
+			goto failed;
+
+		err = update_eir(hdev);
+		if (err < 0)
+			goto failed;
+	} else
+		err = 0;
 
 	err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
 
@@ -950,13 +954,16 @@
 		goto unlock;
 	}
 
-	err = update_class(hdev);
-	if (err < 0)
-		goto unlock;
+	if (test_bit(HCI_UP, &hdev->flags)) {
+		err = update_class(hdev);
+		if (err < 0)
+			goto unlock;
 
-	err = update_eir(hdev);
-	if (err < 0)
-		goto unlock;
+		err = update_eir(hdev);
+		if (err < 0)
+			goto unlock;
+	} else
+		err = 0;
 
 	err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
 
@@ -991,7 +998,10 @@
 	hdev->major_class |= cp->major & MGMT_MAJOR_CLASS_MASK;
 	hdev->minor_class = cp->minor;
 
-	err = update_class(hdev);
+	if (test_bit(HCI_UP, &hdev->flags))
+		err = update_class(hdev);
+	else
+		err = 0;
 
 	if (err == 0)
 		err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
@@ -1027,9 +1037,12 @@
 		err = 0;
 	} else {
 		clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
-		err = update_class(hdev);
-		if (err == 0)
-			err = update_eir(hdev);
+		if (test_bit(HCI_UP, &hdev->flags)) {
+			err = update_class(hdev);
+			if (err == 0)
+				err = update_eir(hdev);
+		} else
+			err = 0;
 	}
 
 	if (err == 0)
@@ -1514,6 +1527,7 @@
 	}
 
 	pairing_complete(cmd, status);
+	hci_conn_put(conn);
 }
 
 static void pairing_security_complete_cb(struct hci_conn *conn, u8 status)
@@ -1936,12 +1950,14 @@
 	if (hdev->disco_state != SCAN_IDLE) {
 		struct hci_cp_le_set_scan_enable le_cp = {0, 0};
 
-		if (hdev->disco_state == SCAN_LE)
-			hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
+		if (test_bit(HCI_UP, &hdev->flags)) {
+			if (hdev->disco_state == SCAN_LE)
+				hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
 							sizeof(le_cp), &le_cp);
-		else
-			hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
-
+			else
+				hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0,
+									 NULL);
+		}
 		hdev->disco_state = SCAN_IDLE;
 	}
 
@@ -1969,18 +1985,20 @@
 
 	hci_dev_lock_bh(hdev);
 
-	if (hdev->disco_state == SCAN_LE)
-		hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
-				sizeof(le_cp), &le_cp);
+	if (test_bit(HCI_UP, &hdev->flags)) {
+		if (hdev->disco_state == SCAN_LE)
+			hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
+					sizeof(le_cp), &le_cp);
 
 	/* re-start BR scan */
-	if (hdev->disco_state != SCAN_IDLE) {
-		struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
-		hdev->disco_int_phase *= 2;
-		hdev->disco_int_count = 0;
-		cp.num_rsp = (u8) hdev->disco_int_phase;
-		hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
-		hdev->disco_state = SCAN_BR;
+		if (hdev->disco_state != SCAN_IDLE) {
+			struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
+			hdev->disco_int_phase *= 2;
+			hdev->disco_int_count = 0;
+			cp.num_rsp = (u8) hdev->disco_int_phase;
+			hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
+			hdev->disco_state = SCAN_BR;
+		}
 	}
 
 	hci_dev_unlock_bh(hdev);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 3b1e54c..99c4559 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -917,7 +917,7 @@
 	int lm = 0;
 
 	if (type != SCO_LINK && type != ESCO_LINK)
-		return -EINVAL;
+		return 0;
 
 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index e301edf..2484a9a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -652,6 +652,7 @@
 static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
 {
 	struct key_master_id *master;
+	u8 sec_level;
 	u8 zerobuf[8];
 
 	if (!hcon || !key || !key->data)
@@ -666,6 +667,17 @@
 
 	hcon->enc_key_size = key->pin_len;
 	hcon->sec_req = TRUE;
+	sec_level = authreq_to_seclevel(key->auth);
+
+	BT_DBG("cur %d, req: %d", hcon->sec_level, sec_level);
+
+	if (sec_level > hcon->sec_level)
+		hcon->pending_sec_level = sec_level;
+
+
+	if (!(hcon->link_mode & HCI_LM_ENCRYPT))
+		hci_conn_hold(hcon);
+
 	hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
 
 	return 0;
@@ -690,11 +702,6 @@
 		if (smp_encrypt_link(hcon, key) < 0)
 			goto invalid_key;
 
-		hcon->sec_level = authreq_to_seclevel(key->auth);
-
-		if (!(hcon->link_mode & HCI_LM_ENCRYPT))
-			hci_conn_hold(hcon);
-
 		return 0;
 	}
 
@@ -729,33 +736,26 @@
 	struct hci_conn *hcon = conn->hcon;
 	__u8 authreq;
 
-	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
+	BT_DBG("conn %p hcon %p %d req: %d",
+			conn, hcon, hcon->sec_level, sec_level);
 
-	if (IS_ERR(hcon->hdev->tfm)) {
-		BT_DBG("IS_ERR");
+	if (IS_ERR(hcon->hdev->tfm))
 		return 1;
-	}
 
-	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
-		BT_DBG("HCI_CONN_ENCRYPT_PEND");
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
 		return -EINPROGRESS;
-	}
 
-	if (sec_level == BT_SECURITY_LOW) {
-		BT_DBG("BT_SECURITY_LOW");
+	if (sec_level == BT_SECURITY_LOW)
 		return 1;
-	}
 
-	if (hcon->sec_level > sec_level) {
-		BT_DBG("hcon->sec_level > sec_level");
+
+	if (hcon->sec_level >= sec_level)
 		return 1;
-	}
 
 	authreq = seclevel_to_authreq(sec_level);
 
-	BT_ERR("conn = %p, sec: %d", conn, sec_level);
 	hcon->smp_conn = conn;
-	hcon->sec_level = sec_level;
+	hcon->pending_sec_level = sec_level;
 
 	if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
 		struct link_key *key;
@@ -785,6 +785,7 @@
 					msecs_to_jiffies(SMP_TIMEOUT));
 
 		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+		hci_conn_hold(hcon);
 	} else {
 		struct smp_cmd_security_req cp;
 		cp.auth_req = authreq;
@@ -792,7 +793,6 @@
 	}
 
 done:
-	hcon->pending_sec_level = sec_level;
 	set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 
 	return 0;
@@ -1045,15 +1045,17 @@
 
 	clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 
+	if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
+		hcon->sec_level = hcon->pending_sec_level;
+
 	if (!status && encrypt && !hcon->sec_req)
-		smp_distribute_keys(conn, 0);
+		return smp_distribute_keys(conn, 0);
 
 	/* Fall back to Pairing request if failed a Link Security request */
 	else if (hcon->sec_req  && (status || !encrypt))
-		smp_conn_security(conn, hcon->sec_level);
+		smp_conn_security(conn, hcon->pending_sec_level);
 
-	else
-		hci_conn_put(hcon);
+	hci_conn_put(hcon);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index ac7f050..46f6461 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -49,7 +49,8 @@
 
 #define AIF1_PB 1
 #define AIF1_CAP 2
-#define NUM_CODEC_DAIS 2
+#define AIF2_PB 3
+#define NUM_CODEC_DAIS 3
 
 struct tabla_codec_dai_data {
 	u32 rate;
@@ -570,6 +571,8 @@
 		-84, 40, digital_gain),
 	SOC_SINGLE_S8_TLV("RX6 Digital Volume", TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
 		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX7 Digital Volume", TABLA_A_CDC_RX7_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
 
 	SOC_SINGLE_S8_TLV("DEC1 Volume", TABLA_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
 		digital_gain),
@@ -2086,71 +2089,99 @@
 	{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX1 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"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", "RX6", "SLIM RX6"},
+	{"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX3 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX3 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX4 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX4 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX5 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX5 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX6 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX6 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX7 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX7 MIX1 INP2", "IIR1", "IIR1"},
 
 	/* Decimator Inputs */
@@ -2633,7 +2664,7 @@
 	}
 	pr_debug("%s: DAI-ID %x %d %d\n", __func__, dai->id, tx_num, rx_num);
 
-	if (dai->id == AIF1_PB) {
+	if (dai->id == AIF1_PB || dai->id == AIF2_PB) {
 		for (i = 0; i < rx_num; i++) {
 			tabla->dai[dai->id - 1].ch_num[i]  = rx_slot[i];
 			tabla->dai[dai->id - 1].ch_act = 0;
@@ -2681,6 +2712,12 @@
 			tx_slot[cnt] = tx_ch[6 + cnt];
 			cnt++;
 		}
+	} else if (dai->id == AIF2_PB) {
+		*rx_num = tabla_dai[dai->id - 1].playback.channels_max;
+		while (cnt < *rx_num) {
+			rx_slot[cnt] = rx_ch[5 + cnt];
+			cnt++;
+		}
 	}
 	return 0;
 }
@@ -2778,7 +2815,7 @@
 	 * 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) {
+	if (dai->id == AIF1_PB || dai->id == AIF2_PB) {
 
 		rx_state = snd_soc_read(codec,
 			TABLA_A_CDC_CLK_RX_B1_CTL);
@@ -2858,6 +2895,20 @@
 		},
 		.ops = &tabla_dai_ops,
 	},
+	{
+		.name = "tabla_rx2",
+		.id = AIF2_PB,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.rates = WCD9310_RATES,
+			.formats = TABLA_FORMATS,
+			.rate_min = 8000,
+			.rate_max = 48000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &tabla_dai_ops,
+	},
 };
 
 static struct snd_soc_dai_driver tabla_i2s_dai[] = {
@@ -2963,7 +3014,8 @@
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
-			if (tabla_dai[j].id == AIF1_PB)
+			if (tabla_dai[j].id == AIF1_PB ||
+				tabla_dai[j].id == AIF2_PB)
 				continue;
 			if (!strncmp(w->sname,
 				tabla_dai[j].capture.stream_name, 13)) {
@@ -2979,7 +3031,8 @@
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
-			if (tabla_dai[j].id == AIF1_PB)
+			if (tabla_dai[j].id == AIF1_PB ||
+				tabla_dai[j].id == AIF2_PB)
 				continue;
 			if (!strncmp(w->sname,
 				tabla_dai[j].capture.stream_name, 13)) {
@@ -3022,6 +3075,13 @@
 	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_E("SLIM RX6", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+				0, tabla_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX7", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+				0, tabla_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
 	/* Headphone */
 	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
 	SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
@@ -3789,19 +3849,15 @@
 	struct tabla_mbhc_general_cfg *generic;
 	struct tabla_mbhc_btn_detect_cfg *btn_det;
 	int n;
-	u8 tabla_ver;
 	u8 *n_cic, *gain;
+	struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
 
 	tabla = snd_soc_codec_get_drvdata(codec);
 	generic = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
 	btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
 
-	tabla_ver = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
-	tabla_ver &= 0x1F;
-
 	for (n = 0; n < 8; n++) {
-		if ((tabla_ver != TABLA_VERSION_1_0 &&
-		     tabla_ver != TABLA_VERSION_1_1) || n != 7) {
+		if ((!TABLA_IS_1_X(tabla_core->version)) || n != 7) {
 			snd_soc_update_bits(codec,
 					    TABLA_A_CDC_MBHC_FEATURE_B1_CFG,
 					    0x07, n);
@@ -5043,6 +5099,9 @@
 		case AIF1_CAP:
 			ch_cnt = tabla_dai[i].capture.channels_max;
 			break;
+		case AIF2_PB:
+			ch_cnt = tabla_dai[i].playback.channels_max;
+			break;
 		default:
 			continue;
 		}
@@ -5197,13 +5256,32 @@
 	},
 };
 
+static struct platform_driver tabla1x_codec_driver = {
+	.probe = tabla_probe,
+	.remove = tabla_remove,
+	.driver = {
+		.name = "tabla1x_codec",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &tabla_pm_ops,
+#endif
+	},
+};
+
 static int __init tabla_codec_init(void)
 {
-	return platform_driver_register(&tabla_codec_driver);
+	int rtn = platform_driver_register(&tabla_codec_driver);
+	if (rtn == 0) {
+		rtn = platform_driver_register(&tabla1x_codec_driver);
+		if (rtn != 0)
+			platform_driver_unregister(&tabla_codec_driver);
+	}
+	return rtn;
 }
 
 static void __exit tabla_codec_exit(void)
 {
+	platform_driver_unregister(&tabla1x_codec_driver);
 	platform_driver_unregister(&tabla_codec_driver);
 }
 
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 1b3014e..6f2d651 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -56,7 +56,7 @@
 
 obj-$(CONFIG_SND_SOC_MSM_QDSP6_INTF) += qdsp6/
 
-snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o msm-dai-stub.o
 obj-$(CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO) += msm-dai-q6-hdmi.o
 obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o
 snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index b515090..bcf6784 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -310,7 +310,6 @@
 		if (clk_users != 1)
 			return 0;
 
-		codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
 		if (codec_clk) {
 			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
 			clk_enable(codec_clk);
@@ -329,7 +328,6 @@
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
 			clk_disable(codec_clk);
-			clk_put(codec_clk);
 			tabla_mclk_enable(codec, 0);
 		}
 	}
@@ -350,7 +348,6 @@
 		if (clk_users != 1)
 			return 0;
 
-		codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
 		if (codec_clk) {
 			clk_set_rate(codec_clk, 12288000);
 			clk_enable(codec_clk);
@@ -376,7 +373,6 @@
 					__func__, clk_users);
 
 			clk_disable(codec_clk);
-			clk_put(codec_clk);
 			tabla_mclk_enable(w->codec, 0);
 		}
 		break;
@@ -736,8 +732,9 @@
 	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__);
+	pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
 
 	/*if (machine_is_msm_liquid()) {
 		top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
@@ -779,6 +776,8 @@
 		return err;
 	}
 
+	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+
 	tabla_hs_detect(codec, &hs_jack, &button_jack, tabla_mbhc_cal,
 			TABLA_MICBIAS2, msm_enable_codec_ext_clk, 0,
 			TABLA_EXT_CLK_RATE);
@@ -865,6 +864,23 @@
 	return 0;
 }
 
+static int msm_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);
+
+	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+			channels->min, channels->max);
+
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
 static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -1084,6 +1100,17 @@
 		.platform_name  = "msm-pcm-afe",
 		.ignore_suspend = 1,
 	},
+	{
+		.name = "Voice Stub",
+		.stream_name = "Voice Stub",
+		.cpu_dai_name = "VOICE_STUB",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* .be_id = do not care */
+	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
@@ -1160,14 +1187,14 @@
 	{
 		.name = LPASS_BE_HDMI,
 		.stream_name = "HDMI Playback",
-		.cpu_dai_name = "msm-dai-q6.8",
+		.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 = msm_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_hdmi_be_hw_params_fixup,
 	},
 	/* Backend AFE DAI Links */
 	{
@@ -1216,6 +1243,30 @@
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
 	},
+	{
+		.name = LPASS_BE_STUB_RX,
+		.stream_name = "Stub Playback",
+		.cpu_dai_name = "msm-dai-stub",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tabla_codec",
+		.codec_dai_name = "tabla_rx2",
+		.no_pcm = 1,
+		/* .be_id = do not care */
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm_be_ops,
+	},
+	{
+		.name = LPASS_BE_STUB_TX,
+		.stream_name = "Stub Capture",
+		.cpu_dai_name = "msm-dai-stub",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tabla_codec",
+		.codec_dai_name = "tabla_tx1",
+		.no_pcm = 1,
+		/* .be_id = do not care */
+		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm_be_ops,
+	},
 };
 
 struct snd_soc_card snd_soc_card_msm = {
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 8f71e83..14d9adf 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -271,6 +271,28 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "AUXPCM_HOSTLESS",
 	},
+	{
+		.playback = {
+			.stream_name = "Voice Stub Playback",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 48000,
+		},
+		.capture = {
+			.stream_name = "Voice Stub Capture",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "VOICE_STUB",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index aff87ae..070dc7b 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -100,6 +100,7 @@
 			break;
 		}
 	}
+	dai_data->rate = params_rate(params);
 	/* Q6 only supports 16 as now */
 	dai_data->port_config.mi2s.bitwidth = 16;
 
@@ -618,7 +619,7 @@
 	 * data to the cpu driver, since cpu drive is unaware of any
 	 * boarc specific configuration.
 	 */
-	pcm_clk = clk_get(NULL, auxpcm_pdata->clk);
+	pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
 	if (IS_ERR(pcm_clk)) {
 		pr_err("%s: could not get pcm_clk\n", __func__);
 		return PTR_ERR(pcm_clk);
diff --git a/sound/soc/msm/msm-dai-stub.c b/sound/soc/msm/msm-dai-stub.c
new file mode 100644
index 0000000..b2bfa2c
--- /dev/null
+++ b/sound/soc/msm/msm-dai-stub.c
@@ -0,0 +1,102 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+static int msm_dai_stub_set_channel_map(struct snd_soc_dai *dai,
+		unsigned int tx_num, unsigned int *tx_slot,
+		unsigned int rx_num, unsigned int *rx_slot)
+{
+	pr_debug("%s:\n", __func__);
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops msm_dai_stub_ops = {
+	.set_channel_map = msm_dai_stub_set_channel_map,
+};
+
+static struct snd_soc_dai_driver msm_dai_stub_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+			SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.capture = {
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+			SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &msm_dai_stub_ops,
+};
+
+static __devinit int msm_dai_stub_dev_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
+
+	rc = snd_soc_register_dai(&pdev->dev, &msm_dai_stub_dai);
+
+	return rc;
+}
+
+static __devexit int msm_dai_stub_dev_remove(struct platform_device *pdev)
+{
+	pr_debug("%s:\n", __func__);
+
+	snd_soc_unregister_dai(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver msm_dai_stub_driver = {
+	.probe  = msm_dai_stub_dev_probe,
+	.remove = msm_dai_stub_dev_remove,
+	.driver = {
+		.name = "msm-dai-stub",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_dai_stub_init(void)
+{
+	pr_debug("%s:\n", __func__);
+
+	return platform_driver_register(&msm_dai_stub_driver);
+}
+module_init(msm_dai_stub_init);
+
+static void __exit msm_dai_stub_exit(void)
+{
+	pr_debug("%s:\n", __func__);
+
+	platform_driver_unregister(&msm_dai_stub_driver);
+}
+module_exit(msm_dai_stub_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MSM Stub DSP DAI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 0a29016..0b7cc78 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,9 @@
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <linux/android_pmem.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
 
 #include "msm-pcm-q6.h"
 #include "msm-pcm-routing.h"
@@ -99,6 +102,8 @@
 			break;
 		} else
 			atomic_set(&prtd->pending_buffer, 0);
+		if (runtime->status->hw_ptr >= runtime->control->appl_ptr)
+			break;
 		pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
 				__func__, prtd->pcm_count);
 
@@ -134,6 +139,9 @@
 		case ASM_SESSION_CMD_RUN: {
 			if (!atomic_read(&prtd->pending_buffer))
 				break;
+			if (runtime->status->hw_ptr >=
+				runtime->control->appl_ptr)
+				break;
 			pr_debug("%s:writing %d bytes"
 				" of buffer to dsp\n",
 				__func__, prtd->pcm_count);
@@ -340,8 +348,26 @@
 	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct msm_audio *prtd = runtime->private_data;
 	int dir = 0;
+	int rc = 0;
 
-	pr_debug("%s\n", __func__);
+	/*
+	If routing is still enabled, we need to issue EOS to
+	the DSP
+	To issue EOS to dsp, we need to be run state otherwise
+	EOS is not honored.
+	*/
+	if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id)) {
+		rc = q6asm_run(prtd->audio_client, 0, 0, 0);
+		atomic_set(&prtd->pending_buffer, 0);
+		prtd->cmd_ack = 0;
+		q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+		pr_debug("%s\n", __func__);
+		rc = wait_event_timeout(the_locks.eos_wait,
+			prtd->cmd_ack, 5 * HZ);
+		if (rc < 0)
+			pr_err("EOS cmd timeout\n");
+		prtd->pcm_irq_pos = 0;
+	}
 
 	dir = IN;
 	atomic_set(&prtd->pending_buffer, 0);
@@ -436,7 +462,8 @@
 		return -ENOMEM;
 	}
 	buf = prtd->audio_client->port[dir].buf;
-	if (!buf && !buf[0].data)
+
+	if (buf == NULL || buf[0].data == NULL)
 		return -ENOMEM;
 
 	pr_debug("%s:buf = %p\n", __func__, buf);
@@ -459,9 +486,39 @@
 	int rc = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_audio *prtd = runtime->private_data;
+	uint64_t timestamp;
+	uint64_t temp;
 
 	switch (cmd) {
+	case SNDRV_COMPRESS_TSTAMP: {
+		struct snd_compr_tstamp tstamp;
+		pr_debug("SNDRV_COMPRESS_TSTAMP\n");
+
+		memset(&tstamp, 0x0, sizeof(struct snd_compr_tstamp));
+		timestamp = q6asm_get_session_time(prtd->audio_client);
+		if (timestamp < 0) {
+			pr_err("%s: Get Session Time return value =%lld\n",
+				__func__, timestamp);
+			return -EAGAIN;
+		}
+		temp = (timestamp * 2 * runtime->channels);
+		temp = temp * (runtime->rate/1000);
+		temp = div_u64(temp, 1000);
+		tstamp.sampling_rate = runtime->rate;
+		tstamp.rendered = (size_t)(temp & 0xFFFFFFFF);
+		tstamp.decoded  = (size_t)((temp >> 32) & 0xFFFFFFFF);
+		tstamp.timestamp = timestamp;
+		pr_debug("%s: bytes_consumed:lsb = %d, msb = %d,"
+			"timestamp = %lld,\n",
+			__func__, tstamp.rendered, tstamp.decoded,
+			tstamp.timestamp);
+		if (copy_to_user((void *) arg, &tstamp,
+			sizeof(struct snd_compr_tstamp)))
+			return -EFAULT;
+		return 0;
+	}
 	case SNDRV_PCM_IOCTL1_RESET:
+		prtd->cmd_ack = 0;
 		rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
 		if (rc < 0)
 			pr_err("%s: flush cmd failed rc=%d\n", __func__, rc);
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 8b6b5f1..b01c22c 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -46,6 +46,7 @@
 static struct mutex routing_lock;
 
 static int fm_switch_enable;
+
 #define INT_FM_RX_VOL_MAX_STEPS 100
 #define INT_FM_RX_VOL_GAIN 2000
 
@@ -1229,6 +1230,11 @@
 				0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("VOICE_STUB_UL", "VOICE_STUB Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("STUB_RX", "Stub Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("STUB_TX", "Stub Capture", 0, 0, 0, 0),
+
 	/* Switch Definitions */
 	SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
 				&fm_switch_mixer_controls),
@@ -1432,6 +1438,8 @@
 	{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
+	{"STUB_RX", NULL, "VOICE_STUB_DL"},
+	{"VOICE_STUB_UL", NULL, "STUB_TX"},
 };
 
 static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
@@ -1636,6 +1644,23 @@
 	.remove = __devexit_p(msm_routing_pcm_remove),
 };
 
+int msm_routing_check_backend_enabled(int fedai_id)
+{
+	int i;
+	if (fedai_id >= MSM_FRONTEND_DAI_MM_MAX_ID) {
+		/* bad ID assigned in machine driver */
+		pr_err("%s: bad MM ID\n", __func__);
+		return 0;
+	}
+	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+		if ((test_bit(fedai_id,
+			&msm_bedais[i].fe_sessions))) {
+			return msm_bedais[i].active;
+		}
+	}
+	return 0;
+}
+
 static int __init msm_soc_routing_platform_init(void)
 {
 	mutex_init(&routing_lock);
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 25efb58..9515ab3 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -32,6 +32,8 @@
 #define LPASS_BE_SEC_I2S_RX "(Backend) SECONDARY_I2S_RX"
 
 #define LPASS_BE_MI2S_RX "(Backend) MI2S_RX"
+#define LPASS_BE_STUB_RX "(Backend) STUB_RX"
+#define LPASS_BE_STUB_TX "(Backend) STUB_TX"
 
 /* For multimedia front-ends, asm session is allocated dynamically.
  * Hence, asm session/multimedia front-end mapping has to be maintained.
@@ -85,4 +87,6 @@
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
 
 int lpa_set_volume(unsigned volume);
+
+int msm_routing_check_backend_enabled(int fedai_id);
 #endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index eafe0f9..471284b 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -129,7 +129,7 @@
 
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_voice *prtd = runtime->private_data;
-	int ret;
+	int ret = 0;
 
 	mutex_lock(&prtd->lock);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index bedfd68..eb363e7 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -309,7 +309,6 @@
 		if (clk_users != 1)
 			return 0;
 
-		codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
 		if (codec_clk) {
 			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
 			clk_enable(codec_clk);
@@ -328,7 +327,6 @@
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
 			clk_disable(codec_clk);
-			clk_put(codec_clk);
 			tabla_mclk_enable(codec, 0);
 		}
 	}
@@ -708,8 +706,9 @@
 	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__);
+	pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
 
 	if (machine_is_msm8960_liquid()) {
 		top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
@@ -752,6 +751,8 @@
 		return err;
 	}
 
+	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+
 	tabla_hs_detect(codec, &hs_jack, &button_jack, tabla_mbhc_cal,
 			TABLA_MICBIAS2, msm8960_enable_codec_ext_clk, 0,
 			TABLA_EXT_CLK_RATE);
@@ -984,7 +985,7 @@
 };
 
 /* Digital audio interface glue - connects codec <---> CPU */
-static struct snd_soc_dai_link msm8960_dai[] = {
+static struct snd_soc_dai_link msm8960_dai_common[] = {
 	/* FrontEnd DAI Links */
 	{
 		.name = "MSM8960 Media1",
@@ -1105,32 +1106,6 @@
 		.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     = "tabla_codec",
-		.codec_dai_name	= "tabla_rx1",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
-		.init = &msm8960_audrx_init,
-		.be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
-		.ops = &msm8960_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     = "tabla_codec",
-		.codec_dai_name	= "tabla_tx1",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
-		.be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
-		.ops = &msm8960_be_ops,
-	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
@@ -1278,13 +1253,88 @@
 	},
 };
 
-struct snd_soc_card snd_soc_card_msm8960 = {
-	.name		= "msm8960-snd-card",
-	.dai_link	= msm8960_dai,
-	.num_links	= ARRAY_SIZE(msm8960_dai),
+static struct snd_soc_dai_link msm8960_dai_delta_tabla1x[] = {
+	/* 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     = "tabla1x_codec",
+		.codec_dai_name	= "tabla_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+		.init = &msm8960_audrx_init,
+		.be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8960_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     = "tabla1x_codec",
+		.codec_dai_name	= "tabla_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+		.be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8960_be_ops,
+	},
+};
+
+
+static struct snd_soc_dai_link msm8960_dai_delta_tabla2x[] = {
+	/* 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     = "tabla_codec",
+		.codec_dai_name	= "tabla_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+		.init = &msm8960_audrx_init,
+		.be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8960_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     = "tabla_codec",
+		.codec_dai_name	= "tabla_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+		.be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8960_be_ops,
+	},
+};
+
+static struct snd_soc_dai_link msm8960_tabla1x_dai[
+					 ARRAY_SIZE(msm8960_dai_common) +
+					 ARRAY_SIZE(msm8960_dai_delta_tabla1x)];
+
+
+static struct snd_soc_dai_link msm8960_dai[
+					 ARRAY_SIZE(msm8960_dai_common) +
+					 ARRAY_SIZE(msm8960_dai_delta_tabla2x)];
+
+static struct snd_soc_card snd_soc_tabla1x_card_msm8960 = {
+		.name		= "msm8960-tabla1x-snd-card",
+		.dai_link	= msm8960_tabla1x_dai,
+		.num_links	= ARRAY_SIZE(msm8960_tabla1x_dai),
+};
+
+static struct snd_soc_card snd_soc_card_msm8960 = {
+		.name		= "msm8960-snd-card",
+		.dai_link	= msm8960_dai,
+		.num_links	= ARRAY_SIZE(msm8960_dai),
 };
 
 static struct platform_device *msm8960_snd_device;
+static struct platform_device *msm8960_snd_tabla1x_device;
 
 static int msm8960_configure_headset_mic_gpios(void)
 {
@@ -1359,6 +1409,10 @@
 		return -ENOMEM;
 	}
 
+	memcpy(msm8960_dai, msm8960_dai_common, sizeof(msm8960_dai_common));
+	memcpy(msm8960_dai + ARRAY_SIZE(msm8960_dai_common),
+		msm8960_dai_delta_tabla2x, sizeof(msm8960_dai_delta_tabla2x));
+
 	platform_set_drvdata(msm8960_snd_device, &snd_soc_card_msm8960);
 	ret = platform_device_add(msm8960_snd_device);
 	if (ret) {
@@ -1367,6 +1421,27 @@
 		return ret;
 	}
 
+	msm8960_snd_tabla1x_device = platform_device_alloc("soc-audio", 1);
+	if (!msm8960_snd_tabla1x_device) {
+		pr_err("Platform device allocation failed\n");
+		kfree(tabla_mbhc_cal);
+		return -ENOMEM;
+	}
+
+	memcpy(msm8960_tabla1x_dai, msm8960_dai_common,
+		sizeof(msm8960_dai_common));
+	memcpy(msm8960_tabla1x_dai + ARRAY_SIZE(msm8960_dai_common),
+		msm8960_dai_delta_tabla1x, sizeof(msm8960_dai_delta_tabla1x));
+
+	platform_set_drvdata(msm8960_snd_tabla1x_device,
+		&snd_soc_tabla1x_card_msm8960);
+	ret = platform_device_add(msm8960_snd_tabla1x_device);
+	if (ret) {
+		platform_device_put(msm8960_snd_tabla1x_device);
+		kfree(tabla_mbhc_cal);
+		return ret;
+	}
+
 	if (msm8960_configure_headset_mic_gpios()) {
 		pr_err("%s Fail to configure headset mic gpios\n", __func__);
 		msm8960_headset_gpios_configured = 0;
@@ -1386,6 +1461,7 @@
 	}
 	msm8960_free_headset_mic_gpios();
 	platform_device_unregister(msm8960_snd_device);
+	platform_device_unregister(msm8960_snd_tabla1x_device);
 	kfree(tabla_mbhc_cal);
 }
 module_exit(msm8960_audio_exit);
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index dc49f12..d822af5 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -3211,7 +3211,7 @@
 {
 	pr_debug("%s\n", __func__);
 
-	if (session_id < 0) {
+	if (session_id < 0 || session_id > SESSION_MAX) {
 		pr_err("%s: invalid session_id = %d\n", __func__, session_id);
 		return -EINVAL;
 	}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c03f7ca7..3063f3e 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1318,7 +1318,7 @@
 		/* Do we need to apply any queued changes? */
 		if (sort[w->id] != cur_sort || w->reg != cur_reg ||
 		    w->dapm != cur_dapm || w->subseq != cur_subseq) {
-			if (!list_empty(&pending))
+			if (cur_dapm && !list_empty(&pending))
 				dapm_seq_run_coalesced(cur_dapm, &pending);
 
 			if (cur_dapm && cur_dapm->seq_notifier) {
@@ -1378,7 +1378,7 @@
 				"Failed to apply widget power: %d\n", ret);
 	}
 
-	if (!list_empty(&pending))
+	if (cur_dapm && !list_empty(&pending))
 		dapm_seq_run_coalesced(cur_dapm, &pending);
 
 	if (cur_dapm && cur_dapm->seq_notifier) {
diff --git a/tools/perf/builtin-periodic.c b/tools/perf/builtin-periodic.c
index 70a0e2b..060e909 100644
--- a/tools/perf/builtin-periodic.c
+++ b/tools/perf/builtin-periodic.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -194,6 +194,8 @@
 	if (p == NULL)
 		return PERF_PERIODIC_ERROR;
 	for (cpu = 0; cpu < cpus->nr; cpu++) {
+		if (((1 << cpu) & cpumask) == 0)
+			continue;
 		p->perf_fd[cpu] = sys_perf_event_open(p->attr, target_pid, cpu,
 					-1, 0);
 		if (p->perf_fd[cpu] < 0)