Merge "msm: sdio: Fix section mismatch" into msm-3.0
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
new file mode 100644
index 0000000..a33d833
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
@@ -0,0 +1,66 @@
+* MSM Subsystem Power Manager (spm-v2)
+
+S4 generation of MSMs have SPM hardware blocks to control the Application
+Processor Sub-System power. These SPM blocks run individual state machine
+to determine what the core (L2 or Krait/Scorpion) would do when the WFI
+instruction is executed by the core. The SAW hardware block handles SPM and
+AVS functionality for the cores.
+
+The devicetree representation of the SPM block should be:
+
+Required properties
+
+- compatible: "qcom,spm-v2"
+- reg: The physical address and the size of the SPM's memory mapped registers
+- qcom, core-id: The core id the SPM block is attached to.
+	{0..n} for cores {0..n}
+	{0xffff} for L2
+- qcom,saw2-ver-reg: The location of the version register
+- qcom,saw2-cfg: SAW2 configuration register
+- qcom,saw2-avs-ctl: The AVS control register
+- qcom,saw2-avs-hysterisis: The AVS hysterisis register to delay the AVS
+	controller requests
+- qcom,saw2-spm-dly: Provides the values for the SPM delay command in the SPM
+	sequence
+- qcom,saw2-spm-ctl: The SPM control register
+- qcom,saw2-vctl-timeout-us: The timeout value to wait for voltage to change
+	after sending the voltage command to the PMIC
+
+Optional properties
+
+- qcom,saw2-avs-limit: The AVS limit register
+- qcom,saw2-avs-dly: The AVS delay register is used to specify the delay values
+	between AVS controller requests
+- qcom,saw2-pmic-dly: The delay values for waiting on PMIC response
+- qcom,saw2-pmic-data0..7: Specify the pmic data value and the associated FTS
+	index to send the PMIC data to
+- qcom,saw2-vctl-port: The FTS port used for changing voltage
+- qcom,saw2-phase-port: The FTS port used for changing the number of phases
+- qcom,saw2-spm-cmd-wfi: The WFI command sequence
+- qcom,saw2-spm-cmd-ret: The Retention command sequence
+- qcom,saw2-spm-cmd-spc: The Standalone PC command sequence
+- qcom,saw2-spm-cmd-pc: The Power Collapse command sequence
+
+Example:
+	qcom,spm@f9089000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9089000 0x1000>;
+		qcom,core-id = <0>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x1b>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x20000400>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,spm-cmd-wfi = [03 0b 0f];
+		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+				a0 b0 03 68 70 3b 92 a0 b0
+				82 2b 50 10 30 02 22 30 0f];
+		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+				a0 b0 82 10 30 02 22 30 0f];
+	};
+
diff --git a/Documentation/devicetree/bindings/pil/pil-pronto.txt b/Documentation/devicetree/bindings/pil/pil-pronto.txt
new file mode 100644
index 0000000..6193b68
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-pronto.txt
@@ -0,0 +1,25 @@
+* Qualcomm WCNSS Pronto Peripheral Image Loader
+
+pil-pronto is a peripheral image loading (PIL) driver. It is used for loading
+Pronto firmware images for wireless connectivity subsystems into memory and
+preparing the subsystem's processor to execute code. It is also used for
+shutting down the processor when it's not needed.
+
+Required properties:
+- compatible: "pil-pronto"
+- reg: offset and length of the register set for the device. The first pair
+       corresponds to PRONTO_PMU, the second pair corresponds to CLK_CTL_WCNSS
+       the third pair corresponds to WCNSS_HALTREQ.
+- vdd_pronto_pll-supply: regulator to supply pronto pll.
+- qcom,firmware-name: Base name of the firmware image. Ex. "wcnss"
+
+Example:
+	qcom,pronto@fb21b000 {
+		compatible = "qcom,pil-pronto";
+		reg = <0xfb21b000 0x3000>,
+		      <0xfc401700 0x4>,
+		      <0xfd485300 0xc>;
+		vdd_pronto_pll-supply = <&pm8941_l12>;
+
+		qcom,firmware-name = "wcnss";
+	};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index c8a4ff9..2698ea7 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -17,6 +17,238 @@
 		interrupt-controller;
 		#interrupt-cells = <3>;
 
+		qcom,pm8941@0 {
+			spmi-slave-container;
+			reg = <0x0>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			pm8941_gpios {
+				spmi-dev-container;
+				compatible = "qcom,qpnp-gpio";
+				gpio-controller;
+				#gpio-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				gpio@c000 {
+					reg = <0xc000 0x100>;
+					qcom,gpio-num = <1>;
+					status = "disabled";
+				};
+
+				gpio@c100 {
+					reg = <0xc100 0x100>;
+					qcom,gpio-num = <2>;
+					status = "disabled";
+				};
+
+				gpio@c200 {
+					reg = <0xc200 0x100>;
+					qcom,gpio-num = <3>;
+					status = "disabled";
+				};
+
+				gpio@c300 {
+					reg = <0xc300 0x100>;
+					qcom,gpio-num = <4>;
+					status = "disabled";
+				};
+
+				gpio@c400 {
+					reg = <0xc400 0x100>;
+					qcom,gpio-num = <5>;
+					status = "disabled";
+				};
+
+				gpio@c500 {
+					reg = <0xc500 0x100>;
+					qcom,gpio-num = <6>;
+					status = "disabled";
+				};
+
+				gpio@c600 {
+					reg = <0xc600 0x100>;
+					qcom,gpio-num = <7>;
+					status = "disabled";
+				};
+
+				gpio@c700 {
+					reg = <0xc700 0x100>;
+					qcom,gpio-num = <8>;
+					status = "disabled";
+				};
+
+				gpio@c800 {
+					reg = <0xc800 0x100>;
+					qcom,gpio-num = <9>;
+					status = "disabled";
+				};
+
+				gpio@c900 {
+					reg = <0xc900 0x100>;
+					qcom,gpio-num = <10>;
+					status = "disabled";
+				};
+
+				gpio@ca00 {
+					reg = <0xca00 0x100>;
+					qcom,gpio-num = <11>;
+					status = "disabled";
+				};
+
+				gpio@cb00 {
+					reg = <0xcb00 0x100>;
+					qcom,gpio-num = <12>;
+					status = "disabled";
+				};
+
+				gpio@cc00 {
+					reg = <0xcc00 0x100>;
+					qcom,gpio-num = <13>;
+					status = "disabled";
+				};
+
+				gpio@cd00 {
+					reg = <0xcd00 0x100>;
+					qcom,gpio-num = <14>;
+					status = "disabled";
+				};
+
+				gpio@ce00 {
+					reg = <0xce00 0x100>;
+					qcom,gpio-num = <15>;
+					status = "disabled";
+				};
+
+				gpio@cf00 {
+					reg = <0xcf00 0x100>;
+					qcom,gpio-num = <16>;
+					status = "disabled";
+				};
+
+				gpio@d000 {
+					reg = <0xd000 0x100>;
+					qcom,gpio-num = <17>;
+					status = "disabled";
+				};
+
+				gpio@d100 {
+					reg = <0xd100 0x100>;
+					qcom,gpio-num = <18>;
+					status = "disabled";
+				};
+
+				gpio@d200 {
+					reg = <0xd200 0x100>;
+					qcom,gpio-num = <19>;
+					status = "disabled";
+				};
+
+				gpio@d300 {
+					reg = <0xd300 0x100>;
+					qcom,gpio-num = <20>;
+					status = "disabled";
+				};
+
+				gpio@d400 {
+					reg = <0xd400 0x100>;
+					qcom,gpio-num = <21>;
+					status = "disabled";
+				};
+
+				gpio@d500 {
+					reg = <0xd500 0x100>;
+					qcom,gpio-num = <22>;
+					status = "disabled";
+				};
+
+				gpio@d600 {
+					reg = <0xd600 0x100>;
+					qcom,gpio-num = <23>;
+					status = "disabled";
+				};
+
+				gpio@d700 {
+					reg = <0xd700 0x100>;
+					qcom,gpio-num = <24>;
+					status = "disabled";
+				};
+
+				gpio@d800 {
+					reg = <0xd800 0x100>;
+					qcom,gpio-num = <25>;
+					status = "disabled";
+				};
+
+				gpio@d900 {
+					reg = <0xd900 0x100>;
+					qcom,gpio-num = <26>;
+					status = "disabled";
+				};
+
+				gpio@da00 {
+					reg = <0xda00 0x100>;
+					qcom,gpio-num = <27>;
+					status = "disabled";
+				};
+
+				gpio@db00 {
+					reg = <0xdb00 0x100>;
+					qcom,gpio-num = <28>;
+					status = "disabled";
+				};
+
+				gpio@dc00 {
+					reg = <0xdc00 0x100>;
+					qcom,gpio-num = <29>;
+					status = "disabled";
+				};
+
+				gpio@dd00 {
+					reg = <0xdd00 0x100>;
+					qcom,gpio-num = <30>;
+					status = "disabled";
+				};
+
+				gpio@de00 {
+					reg = <0xde00 0x100>;
+					qcom,gpio-num = <31>;
+					status = "disabled";
+				};
+
+				gpio@df00 {
+					reg = <0xdf00 0x100>;
+					qcom,gpio-num = <32>;
+					status = "disabled";
+				};
+
+				gpio@e000 {
+					reg = <0xe000 0x100>;
+					qcom,gpio-num = <33>;
+					status = "disabled";
+				};
+
+				gpio@e100 {
+					reg = <0xe100 0x100>;
+					qcom,gpio-num = <34>;
+					status = "disabled";
+				};
+
+				gpio@e200 {
+					reg = <0xe200 0x100>;
+					qcom,gpio-num = <35>;
+					status = "disabled";
+				};
+
+				gpio@e300 {
+					reg = <0xe300 0x100>;
+					qcom,gpio-num = <36>;
+					status = "disabled";
+				};
+			};
+		};
+
 		qcom,pm8941@1 {
 			spmi-slave-container;
 			reg = <0x1>;
diff --git a/arch/arm/boot/dts/msmcopper-gpio.dtsi b/arch/arm/boot/dts/msmcopper-gpio.dtsi
new file mode 100644
index 0000000..7c3f5ce
--- /dev/null
+++ b/arch/arm/boot/dts/msmcopper-gpio.dtsi
@@ -0,0 +1,214 @@
+/* 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.
+ */
+
+/ {
+	qcom,spmi@fc4c0000 {
+
+		qcom,pm8941@0 {
+
+			pm8941_gpios: pm8941_gpios {
+
+				gpio@c000 {
+					qcom,gpio-num = <1>;
+					status = "ok";
+				};
+
+				gpio@c100 {
+					qcom,gpio-num = <2>;
+					status = "ok";
+				};
+
+				gpio@c200 {
+					qcom,gpio-num = <3>;
+					status = "ok";
+				};
+
+				gpio@c300 {
+					qcom,gpio-num = <4>;
+					status = "ok";
+				};
+
+				gpio@c400 {
+					qcom,gpio-num = <5>;
+					status = "ok";
+				};
+
+				gpio@c500 {
+					qcom,gpio-num = <6>;
+					status = "ok";
+				};
+
+				gpio@c600 {
+					qcom,gpio-num = <7>;
+					status = "ok";
+				};
+
+				gpio@c700 {
+					qcom,gpio-num = <8>;
+					status = "ok";
+				};
+
+				gpio@c800 {
+					qcom,gpio-num = <9>;
+					status = "ok";
+				};
+
+				gpio@c900 {
+					qcom,gpio-num = <10>;
+					status = "ok";
+				};
+
+				gpio@ca00 {
+					qcom,gpio-num = <11>;
+					status = "ok";
+				};
+
+				gpio@cb00 {
+					qcom,gpio-num = <12>;
+					status = "ok";
+				};
+
+				gpio@cc00 {
+					qcom,gpio-num = <13>;
+					status = "ok";
+				};
+
+				gpio@cd00 {
+					qcom,gpio-num = <14>;
+					status = "ok";
+				};
+
+				gpio@ce00 {
+					qcom,gpio-num = <15>;
+					status = "ok";
+				};
+
+				gpio@cf00 {
+					qcom,gpio-num = <16>;
+					status = "ok";
+				};
+
+				gpio@d000 {
+					qcom,gpio-num = <17>;
+					status = "ok";
+				};
+
+				gpio@d100 {
+					qcom,gpio-num = <18>;
+					status = "ok";
+				};
+
+				gpio@d200 {
+					qcom,gpio-num = <19>;
+					status = "ok";
+				};
+
+				gpio@d300 {
+					qcom,gpio-num = <20>;
+					status = "ok";
+				};
+
+				gpio@d400 {
+					qcom,gpio-num = <21>;
+					status = "ok";
+				};
+
+				gpio@d500 {
+					qcom,gpio-num = <22>;
+					status = "ok";
+				};
+
+				gpio@d600 {
+					qcom,gpio-num = <23>;
+					status = "ok";
+				};
+
+				gpio@d700 {
+					qcom,gpio-num = <24>;
+					status = "ok";
+				};
+
+				gpio@d800 {
+					qcom,gpio-num = <25>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@d900 {
+					qcom,gpio-num = <26>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@da00 {
+					qcom,gpio-num = <27>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@db00 {
+					qcom,gpio-num = <28>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@dc00 {
+					qcom,gpio-num = <29>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@dd00 {
+					qcom,gpio-num = <30>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@de00 {
+					qcom,gpio-num = <31>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@df00 {
+					qcom,gpio-num = <32>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@e000 {
+					qcom,gpio-num = <33>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@e100 {
+					qcom,gpio-num = <34>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@e200 {
+					qcom,gpio-num = <35>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@e300 {
+					qcom,gpio-num = <36>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 4821290..7dfa4df 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -11,9 +11,11 @@
  */
 
 /include/ "skeleton.dtsi"
+/include/ "msmcopper_pm.dtsi"
 /include/ "msm-pm8841.dtsi"
 /include/ "msm-pm8941.dtsi"
 /include/ "msmcopper-regulator.dtsi"
+/include/ "msmcopper-gpio.dtsi"
 
 / {
 	model = "Qualcomm MSM Copper";
@@ -252,4 +254,14 @@
 
 		qcom,firmware-name = "lpass";
 	};
+
+	qcom,pronto@fb21b000 {
+		compatible = "qcom,pil-pronto";
+		reg = <0xfb21b000 0x3000>,
+		      <0xfc401700 0x4>,
+		      <0xfd485300 0xc>;
+		vdd_pronto_pll-supply = <&pm8941_l12>;
+
+		qcom,firmware-name = "wcnss";
+	};
 };
diff --git a/arch/arm/boot/dts/msmcopper_pm.dtsi b/arch/arm/boot/dts/msmcopper_pm.dtsi
new file mode 100644
index 0000000..53ad0d1
--- /dev/null
+++ b/arch/arm/boot/dts/msmcopper_pm.dtsi
@@ -0,0 +1,134 @@
+/* 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/ "skeleton.dtsi"
+
+/ {
+	qcom,spm@f9089000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9089000 0x1000>;
+		qcom,core-id = <0>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x1b>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x20000400>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,spm-cmd-wfi = [03 0b 0f];
+		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+				a0 b0 03 68 70 3b 92 a0 b0
+				82 2b 50 10 30 02 22 30 0f];
+		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+				a0 b0 82 10 30 02 22 30 0f];
+	};
+
+	qcom,spm@f9099000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9099000 0x1000>;
+		qcom,core-id = <1>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x1b>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x20000400>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,spm-cmd-wfi = [03 0b 0f];
+		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+				a0 b0 03 68 70 3b 92 a0 b0
+				82 2b 50 10 30 02 22 30 0f];
+		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+				a0 b0 82 10 30 02 22 30 0f];
+	};
+
+	qcom,spm@f90a9000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf90a9000 0x1000>;
+		qcom,core-id = <2>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x1b>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x20000400>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,spm-cmd-wfi = [03 0b 0f];
+		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+				a0 b0 03 68 70 3b 92 a0 b0
+				82 2b 50 10 30 02 22 30 0f];
+		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+				a0 b0 82 10 30 02 22 30 0f];
+	};
+
+	qcom,spm@f90b9000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf90b9000 0x1000>;
+		qcom,core-id = <3>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x1b>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x20000400>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,spm-cmd-wfi = [03 0b 0f];
+		qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+				a0 b0 03 68 70 3b 92 a0 b0
+				82 2b 50 10 30 02 22 30 0f];
+		qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+				a0 b0 82 10 30 02 22 30 0f];
+	};
+
+	qcom,spm@f9012000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9012000 0x1000>;
+		qcom,core-id = <0xffff>; /* L2/APCS SAW */
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x1a>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x20000400>;
+		qcom,saw2-spm-ctl = <0x0>; /* TODO: Enable L2 SPM */
+		qcom,saw2-pmic-dly = <0x02020204>;
+		qcom,saw2-pmic-data0 = <0x0400009c>;
+		qcom,saw2-pmic-data1 = <0x00000060>;
+		qcom,saw2-pmic-data2 = <0x0000001c>;
+		qcom,saw2-pmic-data3 = <0x04000000>;
+		qcom,vctl-timeout-us = <50>;
+		qcom,vctl-port = <0x0>; /* TODO: */
+		qcom,phase-port = <0x1>; /* TODO: */
+		qcom,spm-cmd-ret = [0b 00 20 03 22 00 0f];
+		qcom,spm-cmd-spc = [00 20 32 60 70 80 42 03
+				78 80 44 22 50 3b 60 02 32
+				50 0f];
+		qcom,spm-cmd-pc = [00 10 32 60 70 80 b0 11 42
+				07 01 b0 78 80 12 44 a0 50
+				3b 60 02 32 a0 50 0f];
+	};
+};
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index b5a17cd..0c5aa8f 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -320,6 +320,7 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_IR_GPIO_CIR=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
 CONFIG_USB_VIDEO_CLASS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index e18f0ea..eee361a 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -244,6 +244,7 @@
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_PMIC8XXX_VIBRATOR=y
 CONFIG_QSEECOM=y
+CONFIG_USB_HSIC_SMSC_HUB=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
@@ -276,6 +277,7 @@
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_MATRIX=y
 CONFIG_KEYBOARD_PMIC8XXX=y
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_JOYSTICK_XPAD=y
@@ -327,6 +329,7 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_IR_GPIO_CIR=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
 CONFIG_USB_VIDEO_CLASS=y
@@ -435,7 +438,6 @@
 CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_USB_HSIC_SMSC_HUB=y
 CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 3f8ff74..11155d9 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -999,7 +999,7 @@
 		   cpu_name, read_cpuid_id() & 15, elf_platform);
 
 #if defined(CONFIG_SMP)
-	for_each_online_cpu(i) {
+	for_each_present_cpu(i) {
 		/*
 		 * glibc reads /proc/cpuinfo to determine the number of
 		 * online processors, looking for lines beginning with
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index ca3e459..7c7c0bb 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -35,6 +35,7 @@
 	select CLEANCACHE
 	select QCACHE
 	select MSM_PM2 if PM
+	select MSM_RUN_QUEUE_STATS if MSM_SOC_REV_A
 
 config ARCH_MSM7X30
 	bool "MSM7x30"
@@ -128,6 +129,7 @@
 	select MULTI_IRQ_HANDLER
 	select MSM_MULTIMEDIA_USE_ION
 	select MSM_PM8X60 if PM
+	select MSM_RUN_QUEUE_STATS
 
 config ARCH_MSM8960
 	bool "MSM8960"
@@ -169,6 +171,7 @@
 	select MULTI_IRQ_HANDLER
 	select MSM_PM8X60 if PM
 	select HOLES_IN_ZONE if SPARSEMEM
+	select MSM_RUN_QUEUE_STATS
 
 config ARCH_MSM8930
 	bool "MSM8930"
@@ -240,6 +243,8 @@
 	select MULTI_IRQ_HANDLER
 	select MSM_MULTIMEDIA_USE_ION
 	select MSM_PIL
+	select MSM_SPM_V2
+	select MSM_L2_SPM
 
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
@@ -281,6 +286,7 @@
 	select ARCH_MSM_CORTEXMP
 	select MULTI_IRQ_HANDLER
 	select ARM_TICKET_LOCKS
+	select MSM_RUN_QUEUE_STATS
 endmenu
 
 choice
@@ -500,6 +506,14 @@
 	help
 	  Support for the Qualcomm MSM8625 SURF.
 
+config MACH_MSM8625_FFA
+	depends on ARCH_MSM8625
+	depends on !MSM_STACKED_MEMORY
+	default y
+	bool "MSM8625 FFA"
+	help
+	  Support for the Qualcomm MSM8625 FFA.
+
 config MACH_MSM8625_EVB
 	depends on ARCH_MSM8625
 	depends on !MSM_STACKED_MEMORY
@@ -1818,6 +1832,14 @@
 	  Support for booting and shutting down Cortex A5 processors which run
 	  GPS subsystem firmware.
 
+config MSM_PIL_PRONTO
+	tristate "PRONTO (WCNSS) Boot Support"
+	depends on MSM_PIL
+	help
+	  Support for booting and shutting down the PRONTO processor (WCNSS).
+	  PRONTO is the wireless subsystem processor used in bluetooth, wireless
+	  LAN, and FM software applications.
+
 config MSM_SCM
 	bool "Secure Channel Manager (SCM) support"
 	default n
@@ -2049,7 +2071,11 @@
 
 config MSM_RUN_QUEUE_STATS
 	bool "Enable collection and exporting of MSM Run Queue stats to userspace"
-	default y
+	depends on (MSM_SOC_REV_A || ARCH_MSM8X60 || ARCH_MSM8960)
+	help
+	 This option enalbes statistics collection on Run Queue. A daemon
+         in user mode, called MPDecision will be using this data to decide
+         on when to switch off/on the other cores.
 
 config MSM_STANDALONE_POWER_COLLAPSE
        bool "Enable standalone power collapse"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 84af813..3c4b5a8 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -74,6 +74,7 @@
 obj-$(CONFIG_MSM_PIL_MODEM) += pil-modem.o
 obj-$(CONFIG_MSM_PIL_DSPS) += pil-dsps.o
 obj-$(CONFIG_MSM_PIL_GSS) += pil-gss.o
+obj-$(CONFIG_MSM_PIL_PRONTO) += pil-pronto.o
 obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
 obj-$(CONFIG_ARCH_FSM9XXX) += sirc-fsm9xxx.o
 obj-$(CONFIG_MSM_FIQ_SUPPORT) += fiq_glue.o
@@ -240,6 +241,7 @@
 obj-$(CONFIG_MACH_MSM8625_SURF) +=  board-msm7x27a.o board-7627a-all.o
 obj-$(CONFIG_MACH_MSM8625_EVB) +=  board-qrd7627a.o board-7627a-all.o
 obj-$(CONFIG_MACH_MSM8625_QRD7) +=  board-qrd7627a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM8625_FFA) += board-msm7x27a.o board-7627a-all.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o memory_topology.o
 obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o clock-7x30.o acpuclock-7x30.o clock-pll.o
 obj-$(CONFIG_MACH_MSM7X25_SURF) += board-msm7x27.o devices-msm7x25.o
@@ -274,7 +276,7 @@
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
 obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o board-copper-gpiomux.o
 obj-$(CONFIG_ARCH_MSMCOPPER) += acpuclock-krait.o acpuclock-copper.o
-obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o
+obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o clock-pll.o clock-copper.o
 
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 99a3fa1..3431cd0 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -433,6 +433,19 @@
 	.drv = GPIOMUX_DRV_12MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
+
+static struct gpiomux_setting sx150x_suspended_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sx150x_active_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct gpiomux_setting cyts_sleep_sus_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_6MA,
@@ -968,6 +981,16 @@
 	},
 };
 
+static struct msm_gpiomux_config sx150x_int_configs[] __initdata = {
+	{
+		.gpio      = 81,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &sx150x_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &sx150x_active_cfg,
+		},
+	},
+};
+
 void __init apq8064_init_gpiomux(void)
 {
 	int rc;
@@ -989,6 +1012,8 @@
 		msm_gpiomux_install(vcap_configs,
 				ARRAY_SIZE(vcap_configs));
 #endif
+		msm_gpiomux_install(sx150x_int_configs,
+				ARRAY_SIZE(sx150x_int_configs));
 	} else {
 		#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 		msm_gpiomux_install(apq8064_ethernet_configs,
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 2cab803..41dccac 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -148,26 +148,26 @@
 	},
 };
 
-static const char *kgsl_3d0_iommu0_ctx_names[] = {
-	"gfx3d_user",
-	/* priv_ctx goes here */
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu0_ctxs[] = {
+	{ "gfx3d_user", 0 },
+	{ "gfx3d_priv", 1 },
 };
 
-static const char *kgsl_3d0_iommu1_ctx_names[] = {
-	"gfx3d1_user",
-	/* priv_ctx goes here */
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu1_ctxs[] = {
+	{ "gfx3d1_user", 0 },
+	{ "gfx3d1_priv", 1 },
 };
 
 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),
+		.iommu_ctxs = kgsl_3d0_iommu0_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu0_ctxs),
 		.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),
+		.iommu_ctxs = kgsl_3d0_iommu1_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu1_ctxs),
 		.physstart = 0x07D00000,
 		.physend = 0x07D00000 + SZ_1M - 1,
 	},
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 7bb8af9..01665be 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -104,6 +104,9 @@
 VREG_CONSUMERS(L18) = {
 	REGULATOR_SUPPLY("8921_l18",		NULL),
 };
+VREG_CONSUMERS(L21) = {
+	REGULATOR_SUPPLY("8921_l21",		NULL),
+};
 VREG_CONSUMERS(L22) = {
 	REGULATOR_SUPPLY("8921_l22",		NULL),
 };
@@ -137,6 +140,9 @@
 	REGULATOR_SUPPLY("8921_l28",		NULL),
 	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.1"),
 };
+VREG_CONSUMERS(L29) = {
+	REGULATOR_SUPPLY("8921_l29",		NULL),
+};
 VREG_CONSUMERS(S1) = {
 	REGULATOR_SUPPLY("8921_s1",		NULL),
 };
@@ -180,6 +186,9 @@
 VREG_CONSUMERS(S7) = {
 	REGULATOR_SUPPLY("8921_s7",		NULL),
 };
+VREG_CONSUMERS(S8) = {
+	REGULATOR_SUPPLY("8921_s8",		NULL),
+};
 VREG_CONSUMERS(LVS1) = {
 	REGULATOR_SUPPLY("8921_lvs1",		NULL),
 	REGULATOR_SUPPLY("iris_vddio",		"wcnss_wlan.0"),
@@ -552,6 +561,7 @@
 	RPM_SMPS(S3, 0, 1, 1,  500000, 1150000, NULL, 100000, 4p80, NONE, NONE),
 	RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL, 100000, 1p60, NONE, NONE),
 	RPM_SMPS(S7, 0, 1, 0, 1300000, 1300000, NULL, 100000, 3p20, NONE, NONE),
+	RPM_SMPS(S8, 0, 1, 0, 2200000, 2200000, NULL,      0, 1p60, NONE, NONE),
 
 	/*	ID a_on pd ss min_uV   max_uV   supply    sys_uA init_ip */
 	RPM_LDO(L1,  1, 1, 0, 1100000, 1100000, "8921_s4",     0, 10000),
@@ -571,12 +581,14 @@
 	RPM_LDO(L16, 0, 1, 0, 2800000, 2800000, NULL,          0,     0),
 	RPM_LDO(L17, 0, 1, 0, 2000000, 2000000, NULL,          0,     0),
 	RPM_LDO(L18, 0, 1, 0, 1300000, 1800000, "8921_s4",     0,     0),
+	RPM_LDO(L21, 0, 1, 0, 1050000, 1050000, NULL,          0,     0),
 	RPM_LDO(L22, 0, 1, 0, 2600000, 2600000, NULL,          0,     0),
 	RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL,          0,     0),
 	RPM_LDO(L24, 0, 1, 1,  750000, 1150000, "8921_s1", 10000, 10000),
 	RPM_LDO(L25, 1, 1, 0, 1225000, 1225000, "8921_s1", 10000, 10000),
 	RPM_LDO(L27, 0, 1, 0, 1100000, 1100000, "8921_s7",     0,     0),
 	RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7",     0,     0),
+	RPM_LDO(L29, 0, 1, 0, 2000000, 2000000, NULL,          0,     0),
 
 	/*     ID  a_on pd ss                   supply */
 	RPM_VS(LVS1, 0, 1, 0,                   "8921_s4"),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 8135806..cfaa7da 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -198,31 +198,6 @@
 	},
 };
 
-#if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data apq8064_rtb_pdata = {
-	.size = SZ_1M,
-};
-
-static int __init msm_rtb_set_buffer_size(char *p)
-{
-	int s;
-
-	s = memparse(p, NULL);
-	apq8064_rtb_pdata.size = ALIGN(s, SZ_4K);
-	return 0;
-}
-early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-
-
-static struct platform_device apq8064_rtb_device = {
-	.name           = "msm_rtb",
-	.id             = -1,
-	.dev            = {
-		.platform_data = &apq8064_rtb_pdata,
-	},
-};
-#endif
-
 static void __init reserve_rtb_memory(void)
 {
 #if defined(CONFIG_MSM_RTB)
@@ -1490,6 +1465,11 @@
 			1132, 1132, 1199, 1132, 1199, 1132},
 };
 
+static struct platform_device msm_tsens_device = {
+	.name   = "tsens8960-tm",
+	.id = -1,
+};
+
 #define MSM_SHARED_RAM_PHYS 0x80000000
 static void __init apq8064_map_io(void)
 {
@@ -1963,9 +1943,7 @@
 	&msm_8960_q6_lpass,
 	&msm_pil_vidc,
 	&msm_gss,
-#ifdef CONFIG_MSM_RTB
 	&apq8064_rtb_device,
-#endif
 	&apq8064_cpu_idle_device,
 	&apq8064_msm_gov_device,
 	&apq8064_device_cache_erp,
@@ -1979,6 +1957,7 @@
 	&apq_cpudai_slim_4_tx,
 	&msm8960_gemini_device,
 	&apq8064_iommu_domain_device,
+	&msm_tsens_device,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -2291,6 +2270,92 @@
 	},
 };
 
+static struct gpio_keys_button mpq_keys[] = {
+	{
+		.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_VOLUMEUP,
+		.gpio           = GPIO_KEY_VOLUME_UP,
+		.desc           = "volume_up_key",
+		.active_low     = 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+};
+
+static struct gpio_keys_platform_data mpq_keys_data = {
+	.buttons        = mpq_keys,
+	.nbuttons       = ARRAY_SIZE(mpq_keys),
+};
+
+static struct platform_device mpq_gpio_keys_pdev = {
+	.name           = "gpio-keys",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &mpq_keys_data,
+	},
+};
+
+#define MPQ_KP_ROW_BASE		SX150X_EXP2_GPIO_BASE
+#define MPQ_KP_COL_BASE		(SX150X_EXP2_GPIO_BASE + 4)
+
+static unsigned int mpq_row_gpios[] = {MPQ_KP_ROW_BASE, MPQ_KP_ROW_BASE + 1,
+				MPQ_KP_ROW_BASE + 2, MPQ_KP_ROW_BASE + 3};
+static unsigned int mpq_col_gpios[] = {MPQ_KP_COL_BASE, MPQ_KP_COL_BASE + 1,
+				MPQ_KP_COL_BASE + 2};
+
+static const unsigned int mpq_keymap[] = {
+	KEY(0, 0, KEY_UP),
+	KEY(0, 1, KEY_ENTER),
+	KEY(0, 2, KEY_3),
+
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_EXIT),
+	KEY(1, 2, KEY_4),
+
+	KEY(2, 0, KEY_LEFT),
+	KEY(2, 1, KEY_1),
+	KEY(2, 2, KEY_5),
+
+	KEY(3, 0, KEY_RIGHT),
+	KEY(3, 1, KEY_2),
+	KEY(3, 2, KEY_6),
+};
+
+static struct matrix_keymap_data mpq_keymap_data = {
+	.keymap_size	= ARRAY_SIZE(mpq_keymap),
+	.keymap		= mpq_keymap,
+};
+
+static struct matrix_keypad_platform_data mpq_keypad_data = {
+	.keymap_data		= &mpq_keymap_data,
+	.row_gpios		= mpq_row_gpios,
+	.col_gpios		= mpq_col_gpios,
+	.num_row_gpios		= ARRAY_SIZE(mpq_row_gpios),
+	.num_col_gpios		= ARRAY_SIZE(mpq_col_gpios),
+	.col_scan_delay_us	= 32000,
+	.debounce_ms		= 20,
+	.wakeup			= 1,
+	.active_low		= 1,
+	.no_autorepeat		= 1,
+};
+
+static struct platform_device mpq_keypad_device = {
+	.name           = "matrix-keypad",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &mpq_keypad_data,
+	},
+};
+
 /* Sensors DSPS platform data */
 #define DSPS_PIL_GENERIC_NAME		"dsps"
 static void __init apq8064_init_dsps(void)
@@ -2356,6 +2421,7 @@
 };
 
 #define SX150X_EXP1_INT_N	PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9)
+#define SX150X_EXP2_INT_N	MSM_GPIO_TO_INT(81)
 
 struct sx150x_platform_data mpq8064_sx150x_pdata[] = {
 	[SX150X_EXP1] = {
@@ -2371,11 +2437,12 @@
 	[SX150X_EXP2] = {
 		.gpio_base	= SX150X_EXP2_GPIO_BASE,
 		.oscio_is_gpo	= false,
-		.io_pullup_ena	= 0x0,
-		.io_pulldn_ena	= 0x0,
+		.io_pullup_ena	= 0x0f,
+		.io_pulldn_ena	= 0x70,
 		.io_open_drain_ena = 0x0,
 		.io_polarity	= 0,
-		.irq_summary	= -1,
+		.irq_summary	= SX150X_EXP2_INT_N,
+		.irq_base	= SX150X_EXP2_IRQ_BASE,
 	},
 	[SX150X_EXP3] = {
 		.gpio_base	= SX150X_EXP3_GPIO_BASE,
@@ -2528,8 +2595,8 @@
 	if (machine_is_apq8064_liquid())
 		msm_otg_pdata.mhl_enable = true;
 
-	msm_otg_pdata.swfi_latency =
-		msm_rpmrs_levels[0].latency_us + 1;
+	android_usb_pdata.swfi_latency =
+		msm_rpmrs_levels[0].latency_us;
 
 	apq8064_device_otg.dev.platform_data = &msm_otg_pdata;
 	apq8064_ehci_host_init();
@@ -2609,6 +2676,11 @@
 		platform_device_register(&mtp_kp_pdev);
 
 	change_memory_power = &apq8064_change_memory_power;
+
+	if (machine_is_mpq8064_cdp()) {
+		platform_device_register(&mpq_gpio_keys_pdev);
+		platform_device_register(&mpq_keypad_device);
+	}
 }
 
 MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 3729385..67e0e6f 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -19,6 +19,7 @@
 #include <mach/msm_memtypes.h>
 #include <mach/irqs.h>
 #include <mach/rpm-regulator.h>
+#include <mach/msm_rtb.h>
 
 /* Macros assume PMIC GPIOs and MPPs start at 1 */
 #define PM8921_GPIO_BASE		NR_GPIO_IRQS
@@ -141,4 +142,5 @@
 	SX150X_EXP4,
 };
 
+extern struct msm_rtb_platform_data apq8064_rtb_pdata;
 #endif
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index 5ee480a..e23b76c 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -98,15 +98,15 @@
 	},
 };
 
-static const char *kgsl_3d0_iommu0_ctx_names[] = {
-	"gfx3d_user",
-	/* priv_ctx goes here */
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu0_ctxs[] = {
+	{ "gfx3d_user", 0 },
+	{ "gfx3d_priv", 1 },
 };
 
 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),
+		.iommu_ctxs = kgsl_3d0_iommu0_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu0_ctxs),
 		.physstart = 0x07C00000,
 		.physend = 0x07C00000 + SZ_1M - 1,
 	},
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 3c20add..cbb36a1 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -249,30 +249,6 @@
 	},
 };
 
-#if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data msm8930_rtb_pdata = {
-	.size = SZ_1M,
-};
-
-static int __init msm_rtb_set_buffer_size(char *p)
-{
-	int s;
-
-	s = memparse(p, NULL);
-	msm8930_rtb_pdata.size = ALIGN(s, SZ_4K);
-	return 0;
-}
-early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-
-
-static struct platform_device msm8930_rtb_device = {
-	.name           = "msm_rtb",
-	.id             = -1,
-	.dev            = {
-		.platform_data = &msm8930_rtb_pdata,
-	},
-};
-#endif
 
 static void __init reserve_rtb_memory(void)
 {
@@ -1286,30 +1262,35 @@
 	},
 };
 
-#/* TODO: Remove this once PM8038 physically becomes
- * available.
- */
 #define ISA1200_HAP_EN_GPIO	77
 #define ISA1200_HAP_LEN_GPIO	78
 #define ISA1200_HAP_CLK		PM8038_GPIO_PM_TO_SYS(7)
 
 static int isa1200_power(int on)
 {
+	int rc = 0;
+
 	gpio_set_value_cansleep(ISA1200_HAP_CLK, !!on);
 
-	return 0;
+	if (on)
+		rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_1, true);
+	else
+		rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_NONE, true);
+
+	if (rc) {
+		pr_err("%s: unable to write aux clock register(%d)\n",
+			__func__, rc);
+	}
+
+	return rc;
 }
 
 static int isa1200_dev_setup(bool enable)
 {
 	int rc = 0;
 
-	rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_1, enable);
-	if (rc) {
-		pr_err("%s: unable to write aux clock register(%d)\n",
-			__func__, rc);
-		return rc;
-	}
+	if (!enable)
+		goto fail_gpio_dir;
 
 	rc = gpio_request(ISA1200_HAP_CLK, "haptics_clk");
 	if (rc) {
@@ -1633,9 +1614,14 @@
 static struct tsens_platform_data msm_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},
+	.tsens_num_sensor	= 10,
+	.slope = {1132, 1135, 1137, 1135, 1157,
+			1142, 1124, 1153, 1175, 1166},
+};
+
+static struct platform_device msm_tsens_device = {
+	.name   = "tsens8960-tm",
+	.id = -1,
 };
 
 #ifdef CONFIG_MSM_FAKE_BATTERY
@@ -1780,9 +1766,7 @@
 #ifdef MSM8930_PHASE_2
 	&gpio_keys_8930,
 #endif
-#ifdef CONFIG_MSM_RTB
 	&msm8930_rtb_device,
-#endif
 	&msm8930_cpu_idle_device,
 	&msm8930_msm_gov_device,
 	&msm_bus_8930_apps_fabric,
@@ -1792,6 +1776,7 @@
 	&msm_bus_8930_cpss_fpb,
 	&msm8960_device_cache_erp,
 	&msm8930_iommu_domain_device,
+	&msm_tsens_device,
 };
 
 static struct platform_device *cdp_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8930.h b/arch/arm/mach-msm/board-8930.h
index a8fad72..2bbbf80 100644
--- a/arch/arm/mach-msm/board-8930.h
+++ b/arch/arm/mach-msm/board-8930.h
@@ -22,6 +22,7 @@
 #include <mach/irqs.h>
 #include <mach/rpm-regulator.h>
 #include <mach/msm_memtypes.h>
+#include <mach/msm_rtb.h>
 
 /*
  * TODO: When physical 8930/PM8038 hardware becomes
@@ -137,3 +138,5 @@
 #define MSM_8930_GSBI4_QUP_I2C_BUS_ID 4
 #define MSM_8930_GSBI9_QUP_I2C_BUS_ID 0
 #define MSM_8930_GSBI10_QUP_I2C_BUS_ID 10
+
+extern struct msm_rtb_platform_data msm8930_rtb_pdata;
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index defa33b..42dbbee 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -291,31 +291,6 @@
 	},
 };
 
-#if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data msm8960_rtb_pdata = {
-	.size = SZ_1M,
-};
-
-static int __init msm_rtb_set_buffer_size(char *p)
-{
-	int s;
-
-	s = memparse(p, NULL);
-	msm8960_rtb_pdata.size = ALIGN(s, SZ_4K);
-	return 0;
-}
-early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-
-
-static struct platform_device msm8960_rtb_device = {
-	.name           = "msm_rtb",
-	.id             = -1,
-	.dev            = {
-		.platform_data = &msm8960_rtb_pdata,
-	},
-};
-#endif
-
 static void __init reserve_rtb_memory(void)
 {
 #if defined(CONFIG_MSM_RTB)
@@ -2426,6 +2401,11 @@
 		.tsens_num_sensor	= 5,
 };
 
+static struct platform_device msm_tsens_device = {
+	.name   = "tsens8960-tm",
+	.id = -1,
+};
+
 #ifdef CONFIG_MSM_FAKE_BATTERY
 static struct platform_device fish_battery_device = {
 	.name = "fish_battery",
@@ -2582,9 +2562,7 @@
 #endif
 	&msm_device_dspcrashd_8960,
 	&msm8960_device_watchdog,
-#ifdef CONFIG_MSM_RTB
 	&msm8960_rtb_device,
-#endif
 	&msm8960_cpu_idle_device,
 	&msm8960_msm_gov_device,
 	&msm8960_device_cache_erp,
@@ -2592,6 +2570,7 @@
 	&msm8960_cache_dump_device,
 #endif
 	&msm8960_iommu_domain_device,
+	&msm_tsens_device,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -3125,7 +3104,7 @@
 			msm_otg_pdata.phy_init_seq =
 				liquid_v1_phy_init_seq;
 	}
-	msm_otg_pdata.swfi_latency =
+	android_usb_pdata.swfi_latency =
 		msm_rpmrs_levels[0].latency_us;
 	msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
 	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2 &&
diff --git a/arch/arm/mach-msm/board-8960.h b/arch/arm/mach-msm/board-8960.h
index 3824cfd..6a4c92e 100644
--- a/arch/arm/mach-msm/board-8960.h
+++ b/arch/arm/mach-msm/board-8960.h
@@ -20,6 +20,7 @@
 #include <mach/irqs.h>
 #include <mach/rpm-regulator.h>
 #include <mach/msm_memtypes.h>
+#include <mach/msm_rtb.h>
 
 /* Macros assume PMIC GPIOs and MPPs start at 1 */
 #define PM8921_GPIO_BASE		NR_GPIO_IRQS
@@ -92,3 +93,5 @@
 #define MSM_8960_GSBI4_QUP_I2C_BUS_ID 4
 #define MSM_8960_GSBI3_QUP_I2C_BUS_ID 3
 #define MSM_8960_GSBI10_QUP_I2C_BUS_ID 10
+
+extern struct msm_rtb_platform_data msm8960_rtb_pdata;
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 3389dea..b128223 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -620,18 +620,6 @@
 	return 0;
 }
 
-static struct android_usb_platform_data android_usb_pdata = {
-	.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
-};
-
-static struct platform_device android_usb_device = {
-	.name	= "android_usb",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &android_usb_pdata,
-	},
-};
-
 static struct platform_device msm_wlan_ar6000_pm_device = {
 	.name           = "wlan_ar6000_pm_dev",
 	.id             = -1,
@@ -656,7 +644,12 @@
 	.tsens_factor		= 1000,
 	.hw_type		= MDM_9615,
 	.tsens_num_sensor	= 5,
-	.slope = {1176, 1176, 1154, 1176, 1111},
+	.slope = {1176, 1162, 1162, 1149, 1176},
+};
+
+static struct platform_device msm_tsens_device = {
+	.name   = "tsens8960-tm",
+	.id = -1,
 };
 
 static struct platform_device *common_devices[] = {
@@ -673,7 +666,7 @@
 	&msm_device_hsusb_host,
 	&msm_device_hsic_host,
 	&msm_device_usb_bam,
-	&android_usb_device,
+	&msm_android_usb_device,
 	&msm9615_device_uart_gsbi4,
 	&msm9615_device_ext_2p95v_vreg,
 	&msm9615_device_ssbi_pmic1,
@@ -725,6 +718,7 @@
 	&msm_bus_def_fab,
 	&msm9615_rpm_log_device,
 	&msm9615_rpm_stat_device,
+	&msm_tsens_device,
 };
 
 static void __init msm9615_i2c_init(void)
@@ -743,6 +737,9 @@
 
 static void __init msm9615_common_init(void)
 {
+	struct android_usb_platform_data *android_pdata =
+				msm_android_usb_device.dev.platform_data;
+
 	msm9615_device_init();
 	msm9615_init_gpiomux();
 	msm9615_i2c_init();
@@ -770,6 +767,8 @@
 	msm9615_init_mmc();
 	slim_register_board_info(msm_slim_devices,
 		ARRAY_SIZE(msm_slim_devices));
+	android_pdata->update_pid_and_serial_num =
+					usb_diag_update_pid_and_serial_num;
 	msm_pm_boot_pdata.p_addr = allocate_contiguous_ebi_nomap(SZ_8, SZ_64K);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 	msm_tsens_early_init(&msm_tsens_pdata);
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index d1b62ae..e545f12 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -39,6 +39,7 @@
 #include <mach/msm_memtypes.h>
 #include <mach/msm_smd.h>
 #include <mach/qpnp-int.h>
+#include <mach/socinfo.h>
 #include "clock.h"
 #include "devices.h"
 
@@ -423,6 +424,7 @@
 
 static struct clk_lookup msm_clocks_dummy[] = {
 	CLK_DUMMY("xo",		XO_CLK,		NULL,	OFF),
+	CLK_DUMMY("xo",		XO_CLK,		"pil_pronto",		OFF),
 	CLK_DUMMY("core_clk",	BLSP2_UART_CLK,	"msm_serial_hsl.0",	OFF),
 	CLK_DUMMY("iface_clk",	BLSP2_UART_CLK,	"msm_serial_hsl.0",	OFF),
 	CLK_DUMMY("core_clk",	SDC1_CLK,	NULL,			OFF),
@@ -463,13 +465,19 @@
 			"msm_sdcc.3", NULL),
 	OF_DEV_AUXDATA("qcom,pil-q6v5-lpass",   0xFE200000, \
 			"pil-q6v5-lpass", NULL),
+	OF_DEV_AUXDATA("qcom,pil-pronto", 0xFB21B000, \
+			"pil_pronto", NULL),
 	{}
 };
 
 void __init msm_copper_init(struct of_dev_auxdata **adata)
 {
 	msm_copper_init_gpiomux();
-	msm_clock_init(&msm_dummy_clock_init_data);
+
+	if (machine_is_copper_rumi())
+		msm_clock_init(&msm_dummy_clock_init_data);
+	else
+		msm_clock_init(&msmcopper_clock_init_data);
 
 	*adata = msm_copper_auxdata_lookup;
 }
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 9d01d90..8e64a43 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -284,7 +284,8 @@
 static void __init msm7x27a_init_cam(void)
 {
 	if (!(machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
-				|| machine_is_msm7627a_qrd1())) {
+				|| machine_is_msm7627a_qrd1()
+				|| machine_is_msm8625_ffa())) {
 		sensor_board_info_s5k4e1.cam_vreg = NULL;
 		sensor_board_info_s5k4e1.num_vreg = 0;
 		sensor_board_info_mt9e013.cam_vreg = NULL;
@@ -523,7 +524,8 @@
 	int rc = 0;
 
 	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
-				|| machine_is_msm7627a_qrd1())
+				|| machine_is_msm7627a_qrd1()
+				|| machine_is_msm8625_ffa())
 		msm_camera_vreg_config(1);
 
 	rc = config_gpio_table(camera_on_gpio_table,
@@ -540,7 +542,8 @@
 static void config_camera_off_gpios_rear(void)
 {
 	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
-				|| machine_is_msm7627a_qrd1())
+				|| machine_is_msm7627a_qrd1()
+				|| machine_is_msm8625_ffa())
 		msm_camera_vreg_config(0);
 
 	config_gpio_table(camera_off_gpio_table,
@@ -552,7 +555,8 @@
 	int rc = 0;
 
 	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
-				|| machine_is_msm7627a_qrd1())
+				|| machine_is_msm7627a_qrd1()
+				|| machine_is_msm8625_ffa())
 		msm_camera_vreg_config(1);
 
 	rc = config_gpio_table(camera_on_gpio_table,
@@ -569,7 +573,8 @@
 static void config_camera_off_gpios_front(void)
 {
 	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
-				|| machine_is_msm7627a_qrd1())
+				|| machine_is_msm7627a_qrd1()
+				|| machine_is_msm8625_ffa())
 		msm_camera_vreg_config(0);
 
 	config_gpio_table(camera_off_gpio_table,
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 2a703f0..2de581b 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -487,7 +487,8 @@
 		if (!strncmp(name, "lcdc_toshiba_fwvga_pt", 21) ||
 				!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
 			ret = 0;
-	} else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()) {
+	} else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
+					|| machine_is_msm8625_ffa()) {
 		if (!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
 			ret = 0;
 	} else if (machine_is_msm7627a_qrd1()) {
@@ -1021,8 +1022,8 @@
 			machine_is_msm8625_surf()) {
 		gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
 		gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
-	} else if (machine_is_msm7x27a_ffa() ||
-			 machine_is_msm7625a_ffa()) {
+	} else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
+					|| machine_is_msm8625_ffa()) {
 		if (on) {
 			/* This line drives an active low pin on FFA */
 			rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, !on);
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index 7f84920..4df2232 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -701,7 +701,8 @@
 		platform_device_register(&led_pdev);
 
 	/* Vibrator */
-	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
+	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
+					|| machine_is_msm8625_ffa())
 		msm_init_pmic_vibrator();
 }
 
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 8941b6d..ab52665 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -1034,7 +1034,7 @@
 
 static void __init msm7x27a_add_platform_devices(void)
 {
-	if (machine_is_msm8625_surf()) {
+	if (machine_is_msm8625_surf() || machine_is_msm8625_ffa()) {
 		platform_add_devices(msm8625_surf_devices,
 			ARRAY_SIZE(msm8625_surf_devices));
 	} else {
@@ -1059,14 +1059,16 @@
 
 static void __init msm7x27a_otg_gadget(void)
 {
-	msm_otg_pdata.swfi_latency =
-		msm7x27a_pm_data[
-		MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
 	if (cpu_is_msm8625()) {
+		msm_otg_pdata.swfi_latency =
+		msm8625_pm_data[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
 		msm8625_device_otg.dev.platform_data = &msm_otg_pdata;
 		msm8625_device_gadget_peripheral.dev.platform_data =
 			&msm_gadget_pdata;
 	} else {
+		msm_otg_pdata.swfi_latency =
+		msm7x27a_pm_data[
+		MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
 		msm_device_otg.dev.platform_data = &msm_otg_pdata;
 		msm_device_gadget_peripheral.dev.platform_data =
 			&msm_gadget_pdata;
@@ -1075,7 +1077,7 @@
 
 static void __init msm7x27a_pm_init(void)
 {
-	if (machine_is_msm8625_surf()) {
+	if (machine_is_msm8625_surf() || machine_is_msm8625_ffa()) {
 		msm_pm_set_platform_data(msm8625_pm_data,
 				ARRAY_SIZE(msm8625_pm_data));
 		BUG_ON(msm_pm_boot_init(&msm_pm_8625_boot_pdata));
@@ -1198,3 +1200,13 @@
 	.init_early     = msm7x2x_init_early,
 	.handle_irq	= gic_handle_irq,
 MACHINE_END
+MACHINE_START(MSM8625_FFA, "QCT MSM8625 FFA")
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = msm8625_map_io,
+	.reserve        = msm8625_reserve,
+	.init_irq       = msm8625_init_irq,
+	.init_machine   = msm7x2x_init,
+	.timer          = &msm_timer,
+	.init_early     = msm7x2x_init_early,
+	.handle_irq	= gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 86bf205..782bb9e 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -839,15 +839,16 @@
 
 static void __init qrd7627a_otg_gadget(void)
 {
-	msm_otg_pdata.swfi_latency = msm7627a_pm_data
-		[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
-
 	if (cpu_is_msm8625()) {
+		msm_otg_pdata.swfi_latency = msm8625_pm_data
+		[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
 		msm8625_device_otg.dev.platform_data = &msm_otg_pdata;
 		msm8625_device_gadget_peripheral.dev.platform_data =
 					&msm_gadget_pdata;
 
 	} else {
+	msm_otg_pdata.swfi_latency = msm7627a_pm_data
+		[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
 		msm_device_otg.dev.platform_data = &msm_otg_pdata;
 		msm_device_gadget_peripheral.dev.platform_data =
 					&msm_gadget_pdata;
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 5ba3577..f51eb5b 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2796,8 +2796,8 @@
 	OWN(APPS1,  6, "iface_clk",	grp_2d_p_clk,	"kgsl-2d0.0"),
 	OWN(APPS1,  6, "iface_clk",	grp_2d_p_clk,	"footswitch-pcom.0"),
 	OWN(APPS1, 31, "hdmi_clk",	hdmi_clk,	"dtv.0"),
-	OWN(APPS1,  0, "jpeg_clk",	jpeg_clk,	"msm_gemini.0"),
-	OWN(APPS1,  0, "jpeg_pclk",	jpeg_p_clk,	"msm_gemini.0"),
+	OWN(APPS1,  0, "core_clk",	jpeg_clk,	"msm_gemini.0"),
+	OWN(APPS1,  0, "iface_clk",	jpeg_p_clk,	"msm_gemini.0"),
 	OWN(APPS1, 23, "lpa_codec_clk", lpa_codec_clk,	NULL),
 	OWN(APPS1, 23, "lpa_core_clk",	lpa_core_clk,	NULL),
 	OWN(APPS1, 23, "lpa_pclk",	lpa_p_clk,	NULL),
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 33e5b29..1035caf 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4932,8 +4932,6 @@
 	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	""),
 	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	""),
 	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	""),
-	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		""),
-	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		""),
 	CLK_LOOKUP("ref_clk",		sata_phy_ref_clk.c,	""),
 	CLK_LOOKUP("cfg_clk",		sata_phy_cfg_clk.c,	""),
 	CLK_LOOKUP("iface_clk",		ce3_p_clk.c,		"qce.0"),
@@ -5017,8 +5015,8 @@
 	CLK_LOOKUP("vcap_npl_clk",      vcap_npl_clk.c,         ""),
 	CLK_LOOKUP("vcap_npl_clk",      vcap_npl_clk.c,         "msm_vcap.0"),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
-	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		"msm_gemini.0"),
-	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,    "msm_gemini.0"),
+	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,	"msm_gemini.0"),
+	CLK_LOOKUP("core_clk",          ijpeg_clk.c,    "msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		jpegd_clk.c,		""),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
@@ -5063,7 +5061,7 @@
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,		"hdmi_msm.1"),
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,		"hdmi_msm.1"),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		"msm_gemini.0"),
+	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,		"msm_gemini.0"),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		""),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
@@ -5326,8 +5324,8 @@
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
-	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		"msm_gemini.0"),
-	CLK_LOOKUP("ijpeg_clk",     ijpeg_clk.c,    "msm_gemini.0"),
+	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,	"msm_gemini.0"),
+	CLK_LOOKUP("core_clk",          ijpeg_clk.c,    "msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		jpegd_clk.c,		""),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
@@ -5379,7 +5377,7 @@
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,	"hdmi_msm.1"),
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,	"hdmi_msm.1"),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		"msm_gemini.0"),
+	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"msm_gemini.0"),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		""),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
@@ -5617,8 +5615,8 @@
 	CLK_LOOKUP("bus_clk",
 			    gfx3d_axi_clk_8930.c, "footswitch-8x60.2"),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
-	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		"msm_gemini.0"),
-	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,    "msm_gemini.0"),
+	CLK_LOOKUP("mem_clk",		imem_axi_clk.c, "msm_gemini.0"),
+	CLK_LOOKUP("core_clk",          ijpeg_clk.c,    "msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,	"footswitch-8x60.4"),
@@ -5661,7 +5659,7 @@
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,	"hdmi_msm.1"),
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,	"hdmi_msm.1"),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		"msm_gemini.0"),
+	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"msm_gemini.0"),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,		"mdp.0"),
@@ -5749,32 +5747,82 @@
 	writel_relaxed(regval, reg);
 }
 
-static void __init set_fsm_mode(void __iomem *mode_reg)
-{
-	u32 regval = readl_relaxed(mode_reg);
+static struct pll_config_regs pll4_regs __initdata = {
+	.l_reg = LCC_PLL0_L_VAL_REG,
+	.m_reg = LCC_PLL0_M_VAL_REG,
+	.n_reg = LCC_PLL0_N_VAL_REG,
+	.config_reg = LCC_PLL0_CONFIG_REG,
+	.mode_reg = LCC_PLL0_MODE_REG,
+};
 
-	/*De-assert reset to FSM */
-	regval &= ~BIT(21);
-	writel_relaxed(regval, mode_reg);
+static struct pll_config pll4_config __initdata = {
+	.l = 0xE,
+	.m = 0x27A,
+	.n = 0x465,
+	.vco_val = 0x0,
+	.vco_mask = BM(17, 16),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BIT(19),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(21, 20),
+	.mn_ena_val = BIT(22),
+	.mn_ena_mask = BIT(22),
+	.main_output_val = BIT(23),
+	.main_output_mask = BIT(23),
+};
 
-	/* Program bias count */
-	regval &= ~BM(19, 14);
-	regval |= BVAL(19, 14, 0x1);
-	writel_relaxed(regval, mode_reg);
+static struct pll_config_regs pll15_regs __initdata = {
+	.l_reg = MM_PLL3_L_VAL_REG,
+	.m_reg = MM_PLL3_M_VAL_REG,
+	.n_reg = MM_PLL3_N_VAL_REG,
+	.config_reg = MM_PLL3_CONFIG_REG,
+	.mode_reg = MM_PLL3_MODE_REG,
+};
 
-	/* Program lock count */
-	regval &= ~BM(13, 8);
-	regval |= BVAL(13, 8, 0x8);
-	writel_relaxed(regval, mode_reg);
+static struct pll_config pll15_config __initdata = {
+	.l = (0x24 | BVAL(31, 7, 0x620)),
+	.m = 0x1,
+	.n = 0x9,
+	.vco_val = BVAL(17, 16, 0x2),
+	.vco_mask = BM(17, 16),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BIT(19),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(21, 20),
+	.mn_ena_val = BIT(22),
+	.mn_ena_mask = BIT(22),
+	.main_output_val = BIT(23),
+	.main_output_mask = BIT(23),
+};
 
-	/*Enable PLL FSM voting */
-	regval |= BIT(20);
-	writel_relaxed(regval, mode_reg);
-}
+static struct pll_config_regs pll14_regs __initdata = {
+	.l_reg = BB_PLL14_L_VAL_REG,
+	.m_reg = BB_PLL14_M_VAL_REG,
+	.n_reg = BB_PLL14_N_VAL_REG,
+	.config_reg = BB_PLL14_CONFIG_REG,
+	.mode_reg = BB_PLL14_MODE_REG,
+};
+
+static struct pll_config pll14_config __initdata = {
+	.l = (0x11 | BVAL(31, 7, 0x620)),
+	.m = 0x7,
+	.n = 0x9,
+	.vco_val = 0x0,
+	.vco_mask = BM(17, 16),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BIT(19),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(21, 20),
+	.mn_ena_val = BIT(22),
+	.mn_ena_mask = BIT(22),
+	.main_output_val = BIT(23),
+	.main_output_mask = BIT(23),
+};
 
 static void __init reg_init(void)
 {
 	void __iomem *imem_reg;
+
 	/* Deassert MM SW_RESET_ALL signal. */
 	writel_relaxed(0, SW_RESET_ALL_REG);
 
@@ -5915,40 +5963,18 @@
 
 		/* Check if PLL14 is active */
 		is_pll_enabled = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
-		if (!is_pll_enabled) {
+		if (!is_pll_enabled)
 			/* Ref clk = 27MHz and program pll14 to 480MHz */
-			writel_relaxed(0x00031011, BB_PLL14_L_VAL_REG);
-			writel_relaxed(0x7,  BB_PLL14_M_VAL_REG);
-			writel_relaxed(0x9,  BB_PLL14_N_VAL_REG);
-
-			/*
-			 * Enable the main output and the MN accumulator
-			 * Set pre-divider and post-divider values to 1 and 1
-			 */
-			writel_relaxed(0x00C00000, BB_PLL14_CONFIG_REG);
-
-			set_fsm_mode(BB_PLL14_MODE_REG);
-		}
+			configure_pll(&pll14_config, &pll14_regs, 1);
 
 		/* Program PLL15 to 975MHz with ref clk = 27MHz */
-		writel_relaxed(0x31024, MM_PLL3_L_VAL_REG);
-		writel_relaxed(0x1,	MM_PLL3_M_VAL_REG);
-		writel_relaxed(0x9,	MM_PLL3_N_VAL_REG);
-
-		writel_relaxed(0xC20000, MM_PLL3_CONFIG_REG);
+		configure_pll(&pll15_config, &pll15_regs, 0);
 
 		/* Check if PLL4 is active */
 		is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
-		if (!is_pll_enabled) {
+		if (!is_pll_enabled)
 			/* Ref clk = 27MHz and program pll4 to 393.2160MHz */
-			writel_relaxed(0xE,   LCC_PLL0_L_VAL_REG);
-			writel_relaxed(0x27A, LCC_PLL0_M_VAL_REG);
-			writel_relaxed(0x465, LCC_PLL0_N_VAL_REG);
-
-			writel_relaxed(0xC00000, LCC_PLL0_CONFIG_REG);
-
-			set_fsm_mode(LCC_PLL0_MODE_REG);
-		}
+			configure_pll(&pll4_config, &pll4_regs, 1);
 
 		/* Enable PLL4 source on the LPASS Primary PLL Mux */
 		writel_relaxed(0x1, LCC_PRI_PLL_CLK_CTL_REG);
@@ -5963,12 +5989,12 @@
 	 * only enable PLL main output.
 	 */
 	if (cpu_is_msm8930()) {
-		writel_relaxed(0x30021, MM_PLL3_L_VAL_REG);
-		writel_relaxed(0x1,	MM_PLL3_M_VAL_REG);
-		writel_relaxed(0x3,	MM_PLL3_N_VAL_REG);
-
-		writel_relaxed(0xC20000, MM_PLL3_CONFIG_REG);
-		writel_relaxed(0,	 MM_PLL3_TEST_CTL_REG);
+		pll15_config.l = 0x21 | BVAL(31, 7, 0x600);
+		pll15_config.m = 0x1;
+		pll15_config.n = 0x3;
+		configure_pll(&pll15_config, &pll15_regs, 0);
+		/* Disable AUX and BIST outputs */
+		writel_relaxed(0, MM_PLL3_TEST_CTL_REG);
 	}
 }
 
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 5bfd348..8d2b37a 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3591,7 +3591,7 @@
 	CLK_LOOKUP("core_clk",		gfx2d1_clk.c,	"footswitch-8x60.1"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"footswitch-8x60.2"),
-	CLK_LOOKUP("ijpeg_clk",		ijpeg_clk.c,		"msm_gemini.0"),
+	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		jpegd_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
@@ -3644,7 +3644,7 @@
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,	"hdmi_msm.1"),
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,	"hdmi_msm.1"),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		"msm_gemini.0"),
+	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"msm_gemini.0"),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		NULL),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 12d37ae..1fd9b4d 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1689,28 +1689,51 @@
 	CLK_LOOKUP("q6_func_clk",	q6_func_clk, NULL),
 };
 
-static void set_fsm_mode(void __iomem *mode_reg)
-{
-	u32 regval = readl_relaxed(mode_reg);
+static struct pll_config_regs pll0_regs __initdata = {
+	.l_reg = BB_PLL0_L_VAL_REG,
+	.m_reg = BB_PLL0_M_VAL_REG,
+	.n_reg = BB_PLL0_N_VAL_REG,
+	.config_reg = BB_PLL0_CONFIG_REG,
+	.mode_reg = BB_PLL0_MODE_REG,
+};
 
-	/* De-assert reset to FSM */
-	regval &= ~BIT(21);
-	writel_relaxed(regval, mode_reg);
+static struct pll_config pll0_config __initdata = {
+	.l = 0xE,
+	.m = 0x3,
+	.n = 0x8,
+	.vco_val = 0x0,
+	.vco_mask = BM(17, 16),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BIT(19),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(21, 20),
+	.mn_ena_val = BIT(22),
+	.mn_ena_mask = BIT(22),
+	.main_output_val = BIT(23),
+	.main_output_mask = BIT(23),
+};
 
-	/* Program bias count */
-	regval &= ~BM(19, 14);
-	regval |= BVAL(19, 14, 0x1);
-	writel_relaxed(regval, mode_reg);
+static struct pll_config_regs pll14_regs __initdata = {
+	.l_reg = BB_PLL14_L_VAL_REG,
+	.m_reg = BB_PLL14_M_VAL_REG,
+	.n_reg = BB_PLL14_N_VAL_REG,
+	.config_reg = BB_PLL14_CONFIG_REG,
+	.mode_reg = BB_PLL14_MODE_REG,
+};
 
-	/* Program lock count */
-	regval &= ~BM(13, 8);
-	regval |= BVAL(13, 8, 0x8);
-	writel_relaxed(regval, mode_reg);
-
-	/* Enable PLL FSM voting */
-	regval |= BIT(20);
-	writel_relaxed(regval, mode_reg);
-}
+static struct pll_config pll14_config __initdata = {
+	.l = 0x19,
+	.m = 0x0,
+	.n = 0x1,
+	.vco_val = 0x0,
+	.vco_mask = BM(17, 16),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BIT(19),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(21, 20),
+	.main_output_val = BIT(23),
+	.main_output_mask = BIT(23),
+};
 
 /*
  * Miscellaneous clock register initializations
@@ -1731,57 +1754,20 @@
 	is_pll_enabled = readl_relaxed(BB_PLL0_STATUS_REG) & BIT(16);
 
 	if (!is_pll_enabled) {
-		writel_relaxed(0xE, BB_PLL0_L_VAL_REG);
-		writel_relaxed(0x3, BB_PLL0_M_VAL_REG);
-		writel_relaxed(0x8, BB_PLL0_N_VAL_REG);
-
-		regval = readl_relaxed(BB_PLL0_CONFIG_REG);
-
-		/* Enable the main output and the MN accumulator  */
-		regval |= BIT(23) | BIT(22);
-
-		/* Set pre-divider and post-divider values to 1 and 1 */
-		regval &= ~BIT(19);
-		regval &= ~BM(21, 20);
-
-		/* Set VCO frequency */
-		regval &= ~BM(17, 16);
-
-		writel_relaxed(regval, BB_PLL0_CONFIG_REG);
-
 		/* Enable AUX output */
 		regval = readl_relaxed(BB_PLL0_TEST_CTL_REG);
 		regval |= BIT(12);
 		writel_relaxed(regval, BB_PLL0_TEST_CTL_REG);
 
-		set_fsm_mode(BB_PLL0_MODE_REG);
+		configure_pll(&pll0_config, &pll0_regs, 1);
 	}
 
 	/* Check if PLL14 is enabled in FSM mode */
 	is_pll_enabled  = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
 
-	if (!is_pll_enabled) {
-		writel_relaxed(0x19, BB_PLL14_L_VAL_REG);
-		writel_relaxed(0x0, BB_PLL14_M_VAL_REG);
-		writel_relaxed(0x1, BB_PLL14_N_VAL_REG);
-
-		regval = readl_relaxed(BB_PLL14_CONFIG_REG);
-
-		/* Enable main output and the MN accumulator */
-		regval |= BIT(23) | BIT(22);
-
-		/* Set pre-divider and post-divider values to 1 and 1 */
-		regval &= ~BIT(19);
-		regval &= ~BM(21, 20);
-
-		/* Set VCO frequency */
-		regval &= ~BM(17, 16);
-
-		writel_relaxed(regval, BB_PLL14_CONFIG_REG);
-
-		set_fsm_mode(BB_PLL14_MODE_REG);
-
-	} else if (!(readl_relaxed(BB_PLL14_MODE_REG) & BIT(20)))
+	if (!is_pll_enabled)
+		configure_pll(&pll14_config, &pll14_regs, 1);
+	else if (!(readl_relaxed(BB_PLL14_MODE_REG) & BIT(20)))
 		WARN(1, "PLL14 enabled in non-FSM mode!\n");
 
 	/* Detect PLL9 rate and fixup structure accordingly */
diff --git a/arch/arm/mach-msm/clock-copper.c b/arch/arm/mach-msm/clock-copper.c
new file mode 100644
index 0000000..7123ffa
--- /dev/null
+++ b/arch/arm/mach-msm/clock-copper.c
@@ -0,0 +1,5075 @@
+/* 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/err.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <mach/clk.h>
+
+#include "clock-local2.h"
+#include "clock-pll.h"
+
+enum {
+	GCC_BASE,
+	MMSS_BASE,
+	LPASS_BASE,
+	MSS_BASE,
+	N_BASES,
+};
+
+static void __iomem *virt_bases[N_BASES];
+
+#define GCC_REG_BASE(x) (void __iomem *)(virt_bases[GCC_BASE] + (x))
+#define MMSS_REG_BASE(x) (void __iomem *)(virt_bases[MMSS_BASE] + (x))
+#define LPASS_REG_BASE(x) (void __iomem *)(virt_bases[LPASS_BASE] + (x))
+#define MSS_REG_BASE(x) (void __iomem *)(virt_bases[MSS_BASE] + (x))
+
+#define GPLL0_MODE_REG                 0x0000
+#define GPLL0_L_REG                    0x0004
+#define GPLL0_M_REG                    0x0008
+#define GPLL0_N_REG                    0x000C
+#define GPLL0_USER_CTL_REG             0x0010
+#define GPLL0_CONFIG_CTL_REG           0x0014
+#define GPLL0_TEST_CTL_REG             0x0018
+#define GPLL0_STATUS_REG               0x001C
+
+#define GPLL1_MODE_REG                 0x0040
+#define GPLL1_L_REG                    0x0044
+#define GPLL1_M_REG                    0x0048
+#define GPLL1_N_REG                    0x004C
+#define GPLL1_USER_CTL_REG             0x0050
+#define GPLL1_CONFIG_CTL_REG           0x0054
+#define GPLL1_TEST_CTL_REG             0x0058
+#define GPLL1_STATUS_REG               0x005C
+
+#define MMPLL0_MODE_REG                0x0000
+#define MMPLL0_L_REG                   0x0004
+#define MMPLL0_M_REG                   0x0008
+#define MMPLL0_N_REG                   0x000C
+#define MMPLL0_USER_CTL_REG            0x0010
+#define MMPLL0_CONFIG_CTL_REG          0x0014
+#define MMPLL0_TEST_CTL_REG            0x0018
+#define MMPLL0_STATUS_REG              0x001C
+
+#define MMPLL1_MODE_REG                0x0040
+#define MMPLL1_L_REG                   0x0044
+#define MMPLL1_M_REG                   0x0048
+#define MMPLL1_N_REG                   0x004C
+#define MMPLL1_USER_CTL_REG            0x0050
+#define MMPLL1_CONFIG_CTL_REG          0x0054
+#define MMPLL1_TEST_CTL_REG            0x0058
+#define MMPLL1_STATUS_REG              0x005C
+
+#define MMPLL3_MODE_REG                0x0080
+#define MMPLL3_L_REG                   0x0084
+#define MMPLL3_M_REG                   0x0088
+#define MMPLL3_N_REG                   0x008C
+#define MMPLL3_USER_CTL_REG            0x0090
+#define MMPLL3_CONFIG_CTL_REG          0x0094
+#define MMPLL3_TEST_CTL_REG            0x0098
+#define MMPLL3_STATUS_REG              0x009C
+
+#define LPAPLL_MODE_REG                0x0000
+#define LPAPLL_L_REG                   0x0004
+#define LPAPLL_M_REG                   0x0008
+#define LPAPLL_N_REG                   0x000C
+#define LPAPLL_USER_CTL_REG            0x0010
+#define LPAPLL_CONFIG_CTL_REG          0x0014
+#define LPAPLL_TEST_CTL_REG            0x0018
+#define LPAPLL_STATUS_REG              0x001C
+
+#define GCC_DEBUG_CLK_CTL_REG          0x1880
+#define CLOCK_FRQ_MEASURE_CTL_REG      0x1884
+#define CLOCK_FRQ_MEASURE_STATUS_REG   0x1888
+#define GCC_XO_DIV4_CBCR_REG           0x10C8
+#define APCS_GPLL_ENA_VOTE_REG         0x1480
+#define MMSS_PLL_VOTE_APCS_REG         0x0100
+#define MMSS_DEBUG_CLK_CTL_REG         0x0900
+#define LPASS_DEBUG_CLK_CTL_REG        0x29000
+#define LPASS_LPA_PLL_VOTE_APPS_REG    0x2000
+
+#define USB30_MASTER_CMD_RCGR          0x03D4
+#define USB30_MOCK_UTMI_CMD_RCGR       0x03E8
+#define USB_HSIC_SYSTEM_CMD_RCGR       0x041C
+#define USB_HSIC_CMD_RCGR              0x0440
+#define USB_HSIC_IO_CAL_CMD_RCGR       0x0458
+#define USB_HS_SYSTEM_CMD_RCGR         0x0490
+#define SDCC1_APPS_CMD_RCGR            0x04D0
+#define SDCC2_APPS_CMD_RCGR            0x0510
+#define SDCC3_APPS_CMD_RCGR            0x0550
+#define SDCC4_APPS_CMD_RCGR            0x0590
+#define BLSP1_QUP1_SPI_APPS_CMD_RCGR   0x064C
+#define BLSP1_UART1_APPS_CMD_RCGR      0x068C
+#define BLSP1_QUP2_SPI_APPS_CMD_RCGR   0x06CC
+#define BLSP1_UART2_APPS_CMD_RCGR      0x070C
+#define BLSP1_QUP3_SPI_APPS_CMD_RCGR   0x074C
+#define BLSP1_UART3_APPS_CMD_RCGR      0x078C
+#define BLSP1_QUP4_SPI_APPS_CMD_RCGR   0x07CC
+#define BLSP1_UART4_APPS_CMD_RCGR      0x080C
+#define BLSP1_QUP5_SPI_APPS_CMD_RCGR   0x084C
+#define BLSP1_UART5_APPS_CMD_RCGR      0x088C
+#define BLSP1_QUP6_SPI_APPS_CMD_RCGR   0x08CC
+#define BLSP1_UART6_APPS_CMD_RCGR      0x090C
+#define BLSP2_QUP1_SPI_APPS_CMD_RCGR   0x098C
+#define BLSP2_UART1_APPS_CMD_RCGR      0x09CC
+#define BLSP2_QUP2_SPI_APPS_CMD_RCGR   0x0A0C
+#define BLSP2_UART2_APPS_CMD_RCGR      0x0A4C
+#define BLSP2_QUP3_SPI_APPS_CMD_RCGR   0x0A8C
+#define BLSP2_UART3_APPS_CMD_RCGR      0x0ACC
+#define BLSP2_QUP4_SPI_APPS_CMD_RCGR   0x0B0C
+#define BLSP2_UART4_APPS_CMD_RCGR      0x0B4C
+#define BLSP2_QUP5_SPI_APPS_CMD_RCGR   0x0B8C
+#define BLSP2_UART5_APPS_CMD_RCGR      0x0BCC
+#define BLSP2_QUP6_SPI_APPS_CMD_RCGR   0x0C0C
+#define BLSP2_UART6_APPS_CMD_RCGR      0x0C4C
+#define PDM2_CMD_RCGR                  0x0CD0
+#define TSIF_REF_CMD_RCGR              0x0D90
+#define CE1_CMD_RCGR                   0x1050
+#define CE2_CMD_RCGR                   0x1090
+#define GP1_CMD_RCGR                   0x1904
+#define GP2_CMD_RCGR                   0x1944
+#define GP3_CMD_RCGR                   0x1984
+#define LPAIF_SPKR_CMD_RCGR            0xA000
+#define LPAIF_PRI_CMD_RCGR             0xB000
+#define LPAIF_SEC_CMD_RCGR             0xC000
+#define LPAIF_TER_CMD_RCGR             0xD000
+#define LPAIF_QUAD_CMD_RCGR            0xE000
+#define LPAIF_PCM0_CMD_RCGR            0xF000
+#define LPAIF_PCM1_CMD_RCGR            0x10000
+#define RESAMPLER_CMD_RCGR             0x11000
+#define SLIMBUS_CMD_RCGR               0x12000
+#define LPAIF_PCMOE_CMD_RCGR           0x13000
+#define AHBFABRIC_CMD_RCGR             0x18000
+#define VCODEC0_CMD_RCGR               0x1000
+#define PCLK0_CMD_RCGR                 0x2000
+#define PCLK1_CMD_RCGR                 0x2020
+#define MDP_CMD_RCGR                   0x2040
+#define EXTPCLK_CMD_RCGR               0x2060
+#define VSYNC_CMD_RCGR                 0x2080
+#define EDPPIXEL_CMD_RCGR              0x20A0
+#define EDPLINK_CMD_RCGR               0x20C0
+#define EDPAUX_CMD_RCGR                0x20E0
+#define HDMI_CMD_RCGR                  0x2100
+#define BYTE0_CMD_RCGR                 0x2120
+#define BYTE1_CMD_RCGR                 0x2140
+#define ESC0_CMD_RCGR                  0x2160
+#define ESC1_CMD_RCGR                  0x2180
+#define CSI0PHYTIMER_CMD_RCGR          0x3000
+#define CSI1PHYTIMER_CMD_RCGR          0x3030
+#define CSI2PHYTIMER_CMD_RCGR          0x3060
+#define CSI0_CMD_RCGR                  0x3090
+#define CSI1_CMD_RCGR                  0x3100
+#define CSI2_CMD_RCGR                  0x3160
+#define CSI3_CMD_RCGR                  0x31C0
+#define CCI_CMD_RCGR                   0x3300
+#define MCLK0_CMD_RCGR                 0x3360
+#define MCLK1_CMD_RCGR                 0x3390
+#define MCLK2_CMD_RCGR                 0x33C0
+#define MCLK3_CMD_RCGR                 0x33F0
+#define MMSS_GP0_CMD_RCGR              0x3420
+#define MMSS_GP1_CMD_RCGR              0x3450
+#define JPEG0_CMD_RCGR                 0x3500
+#define JPEG1_CMD_RCGR                 0x3520
+#define JPEG2_CMD_RCGR                 0x3540
+#define VFE0_CMD_RCGR                  0x3600
+#define VFE1_CMD_RCGR                  0x3620
+#define CPP_CMD_RCGR                   0x3640
+#define GFX3D_CMD_RCGR                 0x4000
+#define RBCPR_CMD_RCGR                 0x4060
+#define AHB_CMD_RCGR                   0x5000
+#define AXI_CMD_RCGR                   0x5040
+#define OCMEMNOC_CMD_RCGR              0x5090
+
+#define MMSS_BCR                  0x0240
+#define USB_30_BCR                0x03C0
+#define USB3_PHY_BCR              0x03FC
+#define USB_HS_HSIC_BCR           0x0400
+#define USB_HS_BCR                0x0480
+#define SDCC1_BCR                 0x04C0
+#define SDCC2_BCR                 0x0500
+#define SDCC3_BCR                 0x0540
+#define SDCC4_BCR                 0x0580
+#define BLSP1_BCR                 0x05C0
+#define BLSP1_QUP1_BCR            0x0640
+#define BLSP1_UART1_BCR           0x0680
+#define BLSP1_QUP2_BCR            0x06C0
+#define BLSP1_UART2_BCR           0x0700
+#define BLSP1_QUP3_BCR            0x0740
+#define BLSP1_UART3_BCR           0x0780
+#define BLSP1_QUP4_BCR            0x07C0
+#define BLSP1_UART4_BCR           0x0800
+#define BLSP1_QUP5_BCR            0x0840
+#define BLSP1_UART5_BCR           0x0880
+#define BLSP1_QUP6_BCR            0x08C0
+#define BLSP1_UART6_BCR           0x0900
+#define BLSP2_BCR                 0x0940
+#define BLSP2_QUP1_BCR            0x0980
+#define BLSP2_UART1_BCR           0x09C0
+#define BLSP2_QUP2_BCR            0x0A00
+#define BLSP2_UART2_BCR           0x0A40
+#define BLSP2_QUP3_BCR            0x0A80
+#define BLSP2_UART3_BCR           0x0AC0
+#define BLSP2_QUP4_BCR            0x0B00
+#define BLSP2_UART4_BCR           0x0B40
+#define BLSP2_QUP5_BCR            0x0B80
+#define BLSP2_UART5_BCR           0x0BC0
+#define BLSP2_QUP6_BCR            0x0C00
+#define BLSP2_UART6_BCR           0x0C40
+#define PDM_BCR                   0x0CC0
+#define PRNG_BCR                  0x0D00
+#define BAM_DMA_BCR               0x0D40
+#define TSIF_BCR                  0x0D80
+#define CE1_BCR                   0x1040
+#define CE2_BCR                   0x1080
+#define AUDIO_CORE_BCR            0x4000
+#define VENUS0_BCR                0x1020
+#define MDSS_BCR                  0x2300
+#define CAMSS_PHY0_BCR            0x3020
+#define CAMSS_PHY1_BCR            0x3050
+#define CAMSS_PHY2_BCR            0x3080
+#define CAMSS_CSI0_BCR            0x30B0
+#define CAMSS_CSI0PHY_BCR         0x30C0
+#define CAMSS_CSI0RDI_BCR         0x30D0
+#define CAMSS_CSI0PIX_BCR         0x30E0
+#define CAMSS_CSI1_BCR            0x3120
+#define CAMSS_CSI1PHY_BCR         0x3130
+#define CAMSS_CSI1RDI_BCR         0x3140
+#define CAMSS_CSI1PIX_BCR         0x3150
+#define CAMSS_CSI2_BCR            0x3180
+#define CAMSS_CSI2PHY_BCR         0x3190
+#define CAMSS_CSI2RDI_BCR         0x31A0
+#define CAMSS_CSI2PIX_BCR         0x31B0
+#define CAMSS_CSI3_BCR            0x31E0
+#define CAMSS_CSI3PHY_BCR         0x31F0
+#define CAMSS_CSI3RDI_BCR         0x3200
+#define CAMSS_CSI3PIX_BCR         0x3210
+#define CAMSS_ISPIF_BCR           0x3220
+#define CAMSS_CCI_BCR             0x3340
+#define CAMSS_MCLK0_BCR           0x3380
+#define CAMSS_MCLK1_BCR           0x33B0
+#define CAMSS_MCLK2_BCR           0x33E0
+#define CAMSS_MCLK3_BCR           0x3410
+#define CAMSS_GP0_BCR             0x3440
+#define CAMSS_GP1_BCR             0x3470
+#define CAMSS_TOP_BCR             0x3480
+#define CAMSS_MICRO_BCR           0x3490
+#define CAMSS_JPEG_BCR            0x35A0
+#define CAMSS_VFE_BCR             0x36A0
+#define CAMSS_CSI_VFE0_BCR        0x3700
+#define CAMSS_CSI_VFE1_BCR        0x3710
+#define OCMEMNOC_BCR              0x50B0
+#define MMSSNOCAHB_BCR            0x5020
+#define MMSSNOCAXI_BCR            0x5060
+#define OXILI_GFX3D_CBCR          0x4028
+#define OXILICX_AHB_CBCR          0x403C
+#define OXILICX_AXI_CBCR          0x4038
+#define OXILI_BCR                 0x4020
+#define OXILICX_BCR               0x4030
+
+#define OCMEM_SYS_NOC_AXI_CBCR                   0x0244
+#define OCMEM_NOC_CFG_AHB_CBCR                   0x0248
+#define MMSS_NOC_CFG_AHB_CBCR                    0x024C
+
+#define USB30_MASTER_CBCR                        0x03C8
+#define USB30_MOCK_UTMI_CBCR                     0x03D0
+#define USB_HSIC_AHB_CBCR                        0x0408
+#define USB_HSIC_SYSTEM_CBCR                     0x040C
+#define USB_HSIC_CBCR                            0x0410
+#define USB_HSIC_IO_CAL_CBCR                     0x0414
+#define USB_HS_SYSTEM_CBCR                       0x0484
+#define USB_HS_AHB_CBCR                          0x0488
+#define SDCC1_APPS_CBCR                          0x04C4
+#define SDCC1_AHB_CBCR                           0x04C8
+#define SDCC2_APPS_CBCR                          0x0504
+#define SDCC2_AHB_CBCR                           0x0508
+#define SDCC3_APPS_CBCR                          0x0544
+#define SDCC3_AHB_CBCR                           0x0548
+#define SDCC4_APPS_CBCR                          0x0584
+#define SDCC4_AHB_CBCR                           0x0588
+#define BLSP1_AHB_CBCR                           0x05C4
+#define BLSP1_QUP1_SPI_APPS_CBCR                 0x0644
+#define BLSP1_QUP1_I2C_APPS_CBCR                 0x0648
+#define BLSP1_UART1_APPS_CBCR                    0x0684
+#define BLSP1_UART1_SIM_CBCR                     0x0688
+#define BLSP1_QUP2_SPI_APPS_CBCR                 0x06C4
+#define BLSP1_QUP2_I2C_APPS_CBCR                 0x06C8
+#define BLSP1_UART2_APPS_CBCR                    0x0704
+#define BLSP1_UART2_SIM_CBCR                     0x0708
+#define BLSP1_QUP3_SPI_APPS_CBCR                 0x0744
+#define BLSP1_QUP3_I2C_APPS_CBCR                 0x0748
+#define BLSP1_UART3_APPS_CBCR                    0x0784
+#define BLSP1_UART3_SIM_CBCR                     0x0788
+#define BLSP1_QUP4_SPI_APPS_CBCR                 0x07C4
+#define BLSP1_QUP4_I2C_APPS_CBCR                 0x07C8
+#define BLSP1_UART4_APPS_CBCR                    0x0804
+#define BLSP1_UART4_SIM_CBCR                     0x0808
+#define BLSP1_QUP5_SPI_APPS_CBCR                 0x0844
+#define BLSP1_QUP5_I2C_APPS_CBCR                 0x0848
+#define BLSP1_UART5_APPS_CBCR                    0x0884
+#define BLSP1_UART5_SIM_CBCR                     0x0888
+#define BLSP1_QUP6_SPI_APPS_CBCR                 0x08C4
+#define BLSP1_QUP6_I2C_APPS_CBCR                 0x08C8
+#define BLSP1_UART6_APPS_CBCR                    0x0904
+#define BLSP1_UART6_SIM_CBCR                     0x0908
+#define BLSP2_AHB_CBCR                           0x0944
+#define BLSP2_QUP1_SPI_APPS_CBCR                 0x0984
+#define BLSP2_QUP1_I2C_APPS_CBCR                 0x0988
+#define BLSP2_UART1_APPS_CBCR                    0x09C4
+#define BLSP2_UART1_SIM_CBCR                     0x09C8
+#define BLSP2_QUP2_SPI_APPS_CBCR                 0x0A04
+#define BLSP2_QUP2_I2C_APPS_CBCR                 0x0A08
+#define BLSP2_UART2_APPS_CBCR                    0x0A44
+#define BLSP2_UART2_SIM_CBCR                     0x0A48
+#define BLSP2_QUP3_SPI_APPS_CBCR                 0x0A84
+#define BLSP2_QUP3_I2C_APPS_CBCR                 0x0A88
+#define BLSP2_UART3_APPS_CBCR                    0x0AC4
+#define BLSP2_UART3_SIM_CBCR                     0x0AC8
+#define BLSP2_QUP4_SPI_APPS_CBCR                 0x0B04
+#define BLSP2_QUP4_I2C_APPS_CBCR                 0x0B08
+#define BLSP2_UART4_APPS_CBCR                    0x0B44
+#define BLSP2_UART4_SIM_CBCR                     0x0B48
+#define BLSP2_QUP5_SPI_APPS_CBCR                 0x0B84
+#define BLSP2_QUP5_I2C_APPS_CBCR                 0x0B88
+#define BLSP2_UART5_APPS_CBCR                    0x0BC4
+#define BLSP2_UART5_SIM_CBCR                     0x0BC8
+#define BLSP2_QUP6_SPI_APPS_CBCR                 0x0C04
+#define BLSP2_QUP6_I2C_APPS_CBCR                 0x0C08
+#define BLSP2_UART6_APPS_CBCR                    0x0C44
+#define BLSP2_UART6_SIM_CBCR                     0x0C48
+#define PDM_AHB_CBCR                             0x0CC4
+#define PDM_XO4_CBCR                             0x0CC8
+#define PDM2_CBCR                                0x0CCC
+#define PRNG_AHB_CBCR                            0x0D04
+#define BAM_DMA_AHB_CBCR                         0x0D44
+#define TSIF_AHB_CBCR                            0x0D84
+#define TSIF_REF_CBCR                            0x0D88
+#define MSG_RAM_AHB_CBCR                         0x0E44
+#define CE1_CBCR                                 0x1044
+#define CE1_AXI_CBCR                             0x1048
+#define CE1_AHB_CBCR                             0x104C
+#define CE2_CBCR                                 0x1084
+#define CE2_AXI_CBCR                             0x1088
+#define CE2_AHB_CBCR                             0x108C
+#define GCC_AHB_CBCR                             0x10C0
+#define GP1_CBCR                                 0x1900
+#define GP2_CBCR                                 0x1940
+#define GP3_CBCR                                 0x1980
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR     0xA014
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR    0xA018
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR    0xA01C
+#define AUDIO_CORE_LPAIF_PRI_OSR_CBCR            0xB014
+#define AUDIO_CORE_LPAIF_PRI_IBIT_CBCR           0xB018
+#define AUDIO_CORE_LPAIF_PRI_EBIT_CBCR           0xB01C
+#define AUDIO_CORE_LPAIF_SEC_OSR_CBCR            0xC014
+#define AUDIO_CORE_LPAIF_SEC_IBIT_CBCR           0xC018
+#define AUDIO_CORE_LPAIF_SEC_EBIT_CBCR           0xC01C
+#define AUDIO_CORE_LPAIF_TER_OSR_CBCR            0xD014
+#define AUDIO_CORE_LPAIF_TER_IBIT_CBCR           0xD018
+#define AUDIO_CORE_LPAIF_TER_EBIT_CBCR           0xD01C
+#define AUDIO_CORE_LPAIF_QUAD_OSR_CBCR           0xE014
+#define AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR          0xE018
+#define AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR          0xE01C
+#define AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR          0xF014
+#define AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR          0xF018
+#define AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR          0x10014
+#define AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR          0x10018
+#define AUDIO_CORE_RESAMPLER_CORE_CBCR           0x11014
+#define AUDIO_CORE_RESAMPLER_LFABIF_CBCR         0x11018
+#define AUDIO_CORE_SLIMBUS_CORE_CBCR             0x12014
+#define AUDIO_CORE_SLIMBUS_LFABIF_CBCR           0x12018
+#define AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR        0x13014
+#define VENUS0_VCODEC0_CBCR                      0x1028
+#define VENUS0_AHB_CBCR                          0x1030
+#define VENUS0_AXI_CBCR                          0x1034
+#define VENUS0_OCMEMNOC_CBCR                     0x1038
+#define MDSS_AHB_CBCR                            0x2308
+#define MDSS_HDMI_AHB_CBCR                       0x230C
+#define MDSS_AXI_CBCR                            0x2310
+#define MDSS_PCLK0_CBCR                          0x2314
+#define MDSS_PCLK1_CBCR                          0x2318
+#define MDSS_MDP_CBCR                            0x231C
+#define MDSS_MDP_LUT_CBCR                        0x2320
+#define MDSS_EXTPCLK_CBCR                        0x2324
+#define MDSS_VSYNC_CBCR                          0x2328
+#define MDSS_EDPPIXEL_CBCR                       0x232C
+#define MDSS_EDPLINK_CBCR                        0x2330
+#define MDSS_EDPAUX_CBCR                         0x2334
+#define MDSS_HDMI_CBCR                           0x2338
+#define MDSS_BYTE0_CBCR                          0x233C
+#define MDSS_BYTE1_CBCR                          0x2340
+#define MDSS_ESC0_CBCR                           0x2344
+#define MDSS_ESC1_CBCR                           0x2348
+#define CAMSS_PHY0_CSI0PHYTIMER_CBCR             0x3024
+#define CAMSS_PHY1_CSI1PHYTIMER_CBCR             0x3054
+#define CAMSS_PHY2_CSI2PHYTIMER_CBCR             0x3084
+#define CAMSS_CSI0_CBCR                          0x30B4
+#define CAMSS_CSI0_AHB_CBCR                      0x30BC
+#define CAMSS_CSI0PHY_CBCR                       0x30C4
+#define CAMSS_CSI0RDI_CBCR                       0x30D4
+#define CAMSS_CSI0PIX_CBCR                       0x30E4
+#define CAMSS_CSI1_CBCR                          0x3124
+#define CAMSS_CSI1_AHB_CBCR                      0x3128
+#define CAMSS_CSI1PHY_CBCR                       0x3134
+#define CAMSS_CSI1RDI_CBCR                       0x3144
+#define CAMSS_CSI1PIX_CBCR                       0x3154
+#define CAMSS_CSI2_CBCR                          0x3184
+#define CAMSS_CSI2_AHB_CBCR                      0x3188
+#define CAMSS_CSI2PHY_CBCR                       0x3194
+#define CAMSS_CSI2RDI_CBCR                       0x31A4
+#define CAMSS_CSI2PIX_CBCR                       0x31B4
+#define CAMSS_CSI3_CBCR                          0x31E4
+#define CAMSS_CSI3_AHB_CBCR                      0x31E8
+#define CAMSS_CSI3PHY_CBCR                       0x31F4
+#define CAMSS_CSI3RDI_CBCR                       0x3204
+#define CAMSS_CSI3PIX_CBCR                       0x3214
+#define CAMSS_ISPIF_AHB_CBCR                     0x3224
+#define CAMSS_CCI_CCI_CBCR                       0x3344
+#define CAMSS_CCI_CCI_AHB_CBCR                   0x3348
+#define CAMSS_MCLK0_CBCR                         0x3384
+#define CAMSS_MCLK1_CBCR                         0x33B4
+#define CAMSS_MCLK2_CBCR                         0x33E4
+#define CAMSS_MCLK3_CBCR                         0x3414
+#define CAMSS_GP0_CBCR                           0x3444
+#define CAMSS_GP1_CBCR                           0x3474
+#define CAMSS_TOP_AHB_CBCR                       0x3484
+#define CAMSS_MICRO_AHB_CBCR                     0x3494
+#define CAMSS_JPEG_JPEG0_CBCR                    0x35A8
+#define CAMSS_JPEG_JPEG1_CBCR                    0x35AC
+#define CAMSS_JPEG_JPEG2_CBCR                    0x35B0
+#define CAMSS_JPEG_JPEG_AHB_CBCR                 0x35B4
+#define CAMSS_JPEG_JPEG_AXI_CBCR                 0x35B8
+#define CAMSS_JPEG_JPEG_OCMEMNOC_CBCR            0x35BC
+#define CAMSS_VFE_VFE0_CBCR                      0x36A8
+#define CAMSS_VFE_VFE1_CBCR                      0x36AC
+#define CAMSS_VFE_CPP_CBCR                       0x36B0
+#define CAMSS_VFE_CPP_AHB_CBCR                   0x36B4
+#define CAMSS_VFE_VFE_AHB_CBCR                   0x36B8
+#define CAMSS_VFE_VFE_AXI_CBCR                   0x36BC
+#define CAMSS_VFE_VFE_OCMEMNOC_CBCR              0x36C0
+#define CAMSS_CSI_VFE0_CBCR                      0x3704
+#define CAMSS_CSI_VFE1_CBCR                      0x3714
+#define MMSS_MMSSNOC_AXI_CBCR                    0x506C
+#define MMSS_MMSSNOC_AHB_CBCR                    0x5024
+#define MMSS_MMSSNOC_BTO_AHB_CBCR                0x5028
+#define MMSS_MISC_AHB_CBCR                       0x502C
+#define MMSS_S0_AXI_CBCR                         0x5064
+#define OCMEMNOC_CBCR                            0x50B4
+
+#define APCS_CLOCK_BRANCH_ENA_VOTE 0x1484
+#define APCS_CLOCK_SLEEP_ENA_VOTE  0x1488
+
+/* Mux source select values */
+#define cxo_source_val	0
+#define gpll0_source_val 1
+#define gpll1_source_val 2
+#define gnd_source_val	5
+#define mmpll0_mm_source_val 1
+#define mmpll1_mm_source_val 2
+#define mmpll3_mm_source_val 3
+#define gpll0_mm_source_val 5
+#define cxo_mm_source_val 0
+#define mm_gnd_source_val 6
+#define gpll1_hsic_source_val 4
+#define cxo_lpass_source_val 0
+#define lpapll0_lpass_source_val 1
+#define gpll0_lpass_source_val 5
+#define edppll_270_mm_source_val 4
+#define edppll_350_mm_source_val 4
+#define dsipll_750_mm_source_val 1
+#define dsipll_250_mm_source_val 2
+#define hdmipll_297_mm_source_val 3
+
+#define F(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s##_clk_src.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
+			| BVAL(10, 8, s##_source_val), \
+	}
+
+#define F_MM(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s##_clk_src.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
+			| BVAL(10, 8, s##_mm_source_val), \
+	}
+
+#define F_MDSS(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
+			| BVAL(10, 8, s##_mm_source_val), \
+	}
+
+#define F_HSIC(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s##_clk_src.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
+			| BVAL(10, 8, s##_hsic_source_val), \
+	}
+
+#define F_LPASS(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s##_clk_src.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
+			| BVAL(10, 8, s##_lpass_source_val), \
+	}
+
+#define VDD_DIG_FMAX_MAP1(l1, f1) \
+	.vdd_class = &vdd_dig, \
+	.fmax[VDD_DIG_##l1] = (f1)
+#define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \
+	.vdd_class = &vdd_dig, \
+	.fmax[VDD_DIG_##l1] = (f1), \
+	.fmax[VDD_DIG_##l2] = (f2)
+#define VDD_DIG_FMAX_MAP3(l1, f1, l2, f2, l3, f3) \
+	.vdd_class = &vdd_dig, \
+	.fmax[VDD_DIG_##l1] = (f1), \
+	.fmax[VDD_DIG_##l2] = (f2), \
+	.fmax[VDD_DIG_##l3] = (f3)
+
+enum vdd_dig_levels {
+	VDD_DIG_NONE,
+	VDD_DIG_LOW,
+	VDD_DIG_NOMINAL,
+	VDD_DIG_HIGH
+};
+
+static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
+{
+	/* TODO: Actually call into regulator APIs to set VDD_DIG here. */
+	return 0;
+}
+
+static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig);
+
+static int cxo_clk_enable(struct clk *clk)
+{
+	/* TODO: Remove from here once the rpm xo clock is ready. */
+	return 0;
+}
+
+static void cxo_clk_disable(struct clk *clk)
+{
+	/* TODO: Remove from here once the rpm xo clock is ready. */
+	return;
+}
+
+static struct clk_ops clk_ops_cxo = {
+	.enable = cxo_clk_enable,
+	.disable = cxo_clk_disable,
+};
+
+static struct fixed_clk cxo_clk_src = {
+	.c = {
+		.rate = 19200000,
+		.dbg_name = "cxo_clk_src",
+		.ops = &clk_ops_cxo,
+		.warned = true,
+		CLK_INIT(cxo_clk_src.c),
+	},
+};
+
+static struct pll_vote_clk gpll0_clk_src = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)GPLL0_STATUS_REG,
+	.status_mask = BIT(17),
+	.parent = &cxo_clk_src.c,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.rate = 600000000,
+		.dbg_name = "gpll0_clk_src",
+		.ops = &clk_ops_pll_vote,
+		.warned = true,
+		CLK_INIT(gpll0_clk_src.c),
+	},
+};
+
+static struct pll_vote_clk gpll1_clk_src = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+	.en_mask = BIT(1),
+	.status_reg = (void __iomem *)GPLL1_STATUS_REG,
+	.status_mask = BIT(17),
+	.parent = &cxo_clk_src.c,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.rate = 480000000,
+		.dbg_name = "gpll1_clk_src",
+		.ops = &clk_ops_pll_vote,
+		.warned = true,
+		CLK_INIT(gpll1_clk_src.c),
+	},
+};
+
+static struct pll_vote_clk lpapll0_clk_src = {
+	.en_reg = (void __iomem *)LPASS_LPA_PLL_VOTE_APPS_REG,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)LPAPLL_STATUS_REG,
+	.status_mask = BIT(17),
+	.parent = &cxo_clk_src.c,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.rate = 491520000,
+		.dbg_name = "lpapll0_clk_src",
+		.ops = &clk_ops_pll_vote,
+		.warned = true,
+		CLK_INIT(lpapll0_clk_src.c),
+	},
+};
+
+static struct pll_vote_clk mmpll0_clk_src = {
+	.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS_REG,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)MMPLL0_STATUS_REG,
+	.status_mask = BIT(17),
+	.parent = &cxo_clk_src.c,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmpll0_clk_src",
+		.rate = 800000000,
+		.ops = &clk_ops_pll_vote,
+		.warned = true,
+		CLK_INIT(mmpll0_clk_src.c),
+	},
+};
+
+static struct pll_vote_clk mmpll1_clk_src = {
+	.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS_REG,
+	.en_mask = BIT(1),
+	.status_reg = (void __iomem *)MMPLL1_STATUS_REG,
+	.status_mask = BIT(17),
+	.parent = &cxo_clk_src.c,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmpll1_clk_src",
+		.rate = 1000000000,
+		.ops = &clk_ops_pll_vote,
+		.warned = true,
+		CLK_INIT(mmpll1_clk_src.c),
+	},
+};
+
+static struct pll_clk mmpll3_clk_src = {
+	.mode_reg = (void __iomem *)MMPLL3_MODE_REG,
+	.status_reg = (void __iomem *)MMPLL3_STATUS_REG,
+	.parent = &cxo_clk_src.c,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmpll3_clk_src",
+		.rate = 1000000000,
+		.ops = &clk_ops_local_pll,
+		CLK_INIT(mmpll3_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
+	F(125000000,  gpll0,   1,   5,  24),
+	F_END
+};
+
+static struct rcg_clk usb30_master_clk_src = {
+	.cmd_rcgr_reg = USB30_MASTER_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_usb30_master_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb30_master_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP1(NOMINAL, 125000000),
+		CLK_INIT(usb30_master_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk[] = {
+	F(  960000,    cxo,  10,   1,   2),
+	F( 4800000,    cxo,   4,   0,   0),
+	F( 9600000,    cxo,   2,   0,   0),
+	F(15000000,  gpll0,  10,   1,   4),
+	F(19200000,    cxo,   1,   0,   0),
+	F(25000000,  gpll0,  12,   1,   2),
+	F(50000000,  gpll0,  12,   0,   0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup1_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP1_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup1_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup1_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup2_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP2_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup2_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup2_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup3_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP3_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup3_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup3_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup4_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP4_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup4_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup4_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup5_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP5_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup5_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup5_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup6_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP6_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup6_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup6_spi_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_blsp1_2_uart1_6_apps_clk[] = {
+	F( 3686400,  gpll0,    1,  96,  15625),
+	F( 7372800,  gpll0,    1, 192,  15625),
+	F(14745600,  gpll0,    1, 384,  15625),
+	F(16000000,  gpll0,    5,   2,     15),
+	F(19200000,    cxo,    1,   0,      0),
+	F(24000000,  gpll0,    5,   1,      5),
+	F(32000000,  gpll0,    1,   4,     75),
+	F(40000000,  gpll0,   15,   0,      0),
+	F(46400000,  gpll0,    1,  29,    375),
+	F(48000000,  gpll0, 12.5,   0,      0),
+	F(51200000,  gpll0,    1,  32,    375),
+	F(56000000,  gpll0,    1,   7,     75),
+	F(58982400,  gpll0,    1, 1536, 15625),
+	F(60000000,  gpll0,   10,   0,      0),
+	F_END
+};
+
+static struct rcg_clk blsp1_uart1_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart1_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart1_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart2_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART2_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart2_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart2_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart3_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART3_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart3_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart3_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart4_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART4_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart4_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart4_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart5_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART5_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart5_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart5_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart6_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART6_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart6_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart6_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup1_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP1_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup1_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp2_qup1_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup2_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP2_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup2_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp2_qup2_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup3_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP3_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup3_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp2_qup3_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup4_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP4_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup4_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp2_qup4_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup5_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP5_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup5_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp2_qup5_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup6_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP6_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup6_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp2_qup6_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_uart1_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_UART1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_uart1_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp2_uart1_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_uart2_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_UART2_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_uart2_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp2_uart2_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_uart3_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_UART3_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_uart3_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp2_uart3_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_uart4_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_UART4_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_uart4_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp2_uart4_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_uart5_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_UART5_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_uart5_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp2_uart5_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_uart6_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_UART6_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_uart6_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp2_uart6_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = {
+	F( 50000000,  gpll0,  12,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F_END
+};
+
+static struct rcg_clk ce1_clk_src = {
+	.cmd_rcgr_reg = CE1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_ce1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "ce1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
+		CLK_INIT(ce1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_ce2_clk[] = {
+	F( 50000000,  gpll0,  12,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F_END
+};
+
+static struct rcg_clk ce2_clk_src = {
+	.cmd_rcgr_reg = CE2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_ce2_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "ce2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
+		CLK_INIT(ce2_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_gp_clk[] = {
+	F(19200000,  cxo,  1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk gp1_clk_src = {
+	.cmd_rcgr_reg = GP1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_gp_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp1_clk_src.c),
+	},
+};
+
+static struct rcg_clk gp2_clk_src = {
+	.cmd_rcgr_reg = GP2_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_gp_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp2_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp2_clk_src.c),
+	},
+};
+
+static struct rcg_clk gp3_clk_src = {
+	.cmd_rcgr_reg = GP3_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_gp_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp3_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp3_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_pdm2_clk[] = {
+	F(60000000,  gpll0,  10,   0,   0),
+	F_END
+};
+
+static struct rcg_clk pdm2_clk_src = {
+	.cmd_rcgr_reg = PDM2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_pdm2_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "pdm2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 60000000),
+		CLK_INIT(pdm2_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_sdcc1_2_apps_clk[] = {
+	F(   144000,    cxo,  16,   3,  25),
+	F(   400000,    cxo,  12,   1,   4),
+	F( 20000000,  gpll0,  15,   1,   2),
+	F( 25000000,  gpll0,  12,   1,   2),
+	F( 50000000,  gpll0,  12,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F(200000000,  gpll0,   3,   0,   0),
+	F_END
+};
+
+static struct clk_freq_tbl ftbl_gcc_sdcc3_4_apps_clk[] = {
+	F(   144000,    cxo,  16,   3,  25),
+	F(   400000,    cxo,  12,   1,   4),
+	F( 20000000,  gpll0,  15,   1,   2),
+	F( 25000000,  gpll0,  12,   1,   2),
+	F( 50000000,  gpll0,  12,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F_END
+};
+
+static struct rcg_clk sdcc1_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc1_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(sdcc1_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk sdcc2_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC2_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc2_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(sdcc2_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk sdcc3_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC3_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_sdcc3_4_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc3_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
+		CLK_INIT(sdcc3_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk sdcc4_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC4_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_sdcc3_4_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc4_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
+		CLK_INIT(sdcc4_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_tsif_ref_clk[] = {
+	F(105000,    cxo,   2,   1,  91),
+	F_END
+};
+
+static struct rcg_clk tsif_ref_clk_src = {
+	.cmd_rcgr_reg = TSIF_REF_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_tsif_ref_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "tsif_ref_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP1(LOW, 105500),
+		CLK_INIT(tsif_ref_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = {
+	F(60000000,  gpll0,   10,   0,   0),
+	F_END
+};
+
+static struct rcg_clk usb30_mock_utmi_clk_src = {
+	.cmd_rcgr_reg = USB30_MOCK_UTMI_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb30_mock_utmi_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb30_mock_utmi_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
+		CLK_INIT(usb30_mock_utmi_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
+	F(75000000,  gpll0,   8,   0,   0),
+	F_END
+};
+
+static struct rcg_clk usb_hs_system_clk_src = {
+	.cmd_rcgr_reg = USB_HS_SYSTEM_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb_hs_system_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hs_system_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 37500000, NOMINAL, 75000000),
+		CLK_INIT(usb_hs_system_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hsic_clk[] = {
+	F_HSIC(480000000,  gpll1,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb_hsic_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 480000000),
+		CLK_INIT(usb_hsic_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hsic_io_cal_clk[] = {
+	F(9600000,    cxo,   2,   0,   0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_io_cal_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_IO_CAL_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb_hsic_io_cal_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_io_cal_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 9600000),
+		CLK_INIT(usb_hsic_io_cal_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hsic_system_clk[] = {
+	F(75000000,  gpll0,   8,   0,   0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_system_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_SYSTEM_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb_hsic_system_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_system_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 37500000, NOMINAL, 75000000),
+		CLK_INIT(usb_hsic_system_clk_src.c),
+	},
+};
+
+static struct local_vote_clk gcc_bam_dma_ahb_clk = {
+	.cbcr_reg = BAM_DMA_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(12),
+	.bcr_reg = BAM_DMA_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_bam_dma_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_bam_dma_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_blsp1_ahb_clk = {
+	.cbcr_reg = BLSP1_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(17),
+	.bcr_reg = BLSP1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_blsp1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP1_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP1_QUP1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup1_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup1_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup1_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP1_SPI_APPS_CBCR,
+	.parent = &blsp1_qup1_spi_apps_clk_src.c,
+	.bcr_reg = BLSP1_QUP1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup1_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup1_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP2_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP1_QUP2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup2_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup2_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup2_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP2_SPI_APPS_CBCR,
+	.parent = &blsp1_qup2_spi_apps_clk_src.c,
+	.bcr_reg = BLSP1_QUP2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup2_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup2_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP1_QUP3_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup3_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup3_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP3_SPI_APPS_CBCR,
+	.parent = &blsp1_qup3_spi_apps_clk_src.c,
+	.bcr_reg = BLSP1_QUP3_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup3_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup3_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup4_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP4_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP1_QUP4_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup4_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup4_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup4_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP4_SPI_APPS_CBCR,
+	.parent = &blsp1_qup4_spi_apps_clk_src.c,
+	.bcr_reg = BLSP1_QUP4_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup4_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup4_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup5_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP5_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP1_QUP5_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup5_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup5_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup5_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP5_SPI_APPS_CBCR,
+	.parent = &blsp1_qup5_spi_apps_clk_src.c,
+	.bcr_reg = BLSP1_QUP5_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup5_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup5_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup6_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP6_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP1_QUP6_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup6_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup6_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup6_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP6_SPI_APPS_CBCR,
+	.parent = &blsp1_qup6_spi_apps_clk_src.c,
+	.bcr_reg = BLSP1_QUP6_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup6_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup6_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart1_apps_clk = {
+	.cbcr_reg = BLSP1_UART1_APPS_CBCR,
+	.parent = &blsp1_uart1_apps_clk_src.c,
+	.bcr_reg = BLSP1_UART1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart1_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart1_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart2_apps_clk = {
+	.cbcr_reg = BLSP1_UART2_APPS_CBCR,
+	.parent = &blsp1_uart2_apps_clk_src.c,
+	.bcr_reg = BLSP1_UART2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart2_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart2_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart3_apps_clk = {
+	.cbcr_reg = BLSP1_UART3_APPS_CBCR,
+	.parent = &blsp1_uart3_apps_clk_src.c,
+	.bcr_reg = BLSP1_UART3_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart3_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart3_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart4_apps_clk = {
+	.cbcr_reg = BLSP1_UART4_APPS_CBCR,
+	.parent = &blsp1_uart4_apps_clk_src.c,
+	.bcr_reg = BLSP1_UART4_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart4_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart4_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart5_apps_clk = {
+	.cbcr_reg = BLSP1_UART5_APPS_CBCR,
+	.parent = &blsp1_uart5_apps_clk_src.c,
+	.bcr_reg = BLSP1_UART5_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart5_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart5_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart6_apps_clk = {
+	.cbcr_reg = BLSP1_UART6_APPS_CBCR,
+	.parent = &blsp1_uart6_apps_clk_src.c,
+	.bcr_reg = BLSP1_UART6_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart6_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart6_apps_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_blsp2_ahb_clk = {
+	.cbcr_reg = BLSP2_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(15),
+	.bcr_reg = BLSP2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_blsp2_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup1_i2c_apps_clk = {
+	.cbcr_reg = BLSP2_QUP1_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP2_QUP1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup1_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup1_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup1_spi_apps_clk = {
+	.cbcr_reg = BLSP2_QUP1_SPI_APPS_CBCR,
+	.parent = &blsp2_qup1_spi_apps_clk_src.c,
+	.bcr_reg = BLSP2_QUP1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup1_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup1_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup2_i2c_apps_clk = {
+	.cbcr_reg = BLSP2_QUP2_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP2_QUP2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup2_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup2_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup2_spi_apps_clk = {
+	.cbcr_reg = BLSP2_QUP2_SPI_APPS_CBCR,
+	.parent = &blsp2_qup2_spi_apps_clk_src.c,
+	.bcr_reg = BLSP2_QUP2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup2_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup2_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup3_i2c_apps_clk = {
+	.cbcr_reg = BLSP2_QUP3_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP2_QUP3_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup3_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup3_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup3_spi_apps_clk = {
+	.cbcr_reg = BLSP2_QUP3_SPI_APPS_CBCR,
+	.parent = &blsp2_qup3_spi_apps_clk_src.c,
+	.bcr_reg = BLSP2_QUP3_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup3_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup3_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup4_i2c_apps_clk = {
+	.cbcr_reg = BLSP2_QUP4_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP2_QUP4_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup4_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup4_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup4_spi_apps_clk = {
+	.cbcr_reg = BLSP2_QUP4_SPI_APPS_CBCR,
+	.parent = &blsp2_qup4_spi_apps_clk_src.c,
+	.bcr_reg = BLSP2_QUP4_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup4_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup4_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup5_i2c_apps_clk = {
+	.cbcr_reg = BLSP2_QUP5_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP2_QUP5_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup5_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup5_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup5_spi_apps_clk = {
+	.cbcr_reg = BLSP2_QUP5_SPI_APPS_CBCR,
+	.parent = &blsp2_qup5_spi_apps_clk_src.c,
+	.bcr_reg = BLSP2_QUP5_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup5_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup5_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup6_i2c_apps_clk = {
+	.cbcr_reg = BLSP2_QUP6_I2C_APPS_CBCR,
+	.parent = &cxo_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = BLSP2_QUP6_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup6_i2c_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup6_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_qup6_spi_apps_clk = {
+	.cbcr_reg = BLSP2_QUP6_SPI_APPS_CBCR,
+	.parent = &blsp2_qup6_spi_apps_clk_src.c,
+	.bcr_reg = BLSP2_QUP6_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_qup6_spi_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_qup6_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_uart1_apps_clk = {
+	.cbcr_reg = BLSP2_UART1_APPS_CBCR,
+	.parent = &blsp2_uart1_apps_clk_src.c,
+	.bcr_reg = BLSP2_UART1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_uart1_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_uart1_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_uart2_apps_clk = {
+	.cbcr_reg = BLSP2_UART2_APPS_CBCR,
+	.parent = &blsp2_uart2_apps_clk_src.c,
+	.bcr_reg = BLSP2_UART2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_uart2_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_uart2_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_uart3_apps_clk = {
+	.cbcr_reg = BLSP2_UART3_APPS_CBCR,
+	.parent = &blsp2_uart3_apps_clk_src.c,
+	.bcr_reg = BLSP2_UART3_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_uart3_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_uart3_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_uart4_apps_clk = {
+	.cbcr_reg = BLSP2_UART4_APPS_CBCR,
+	.parent = &blsp2_uart4_apps_clk_src.c,
+	.bcr_reg = BLSP2_UART4_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_uart4_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_uart4_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_uart5_apps_clk = {
+	.cbcr_reg = BLSP2_UART5_APPS_CBCR,
+	.parent = &blsp2_uart5_apps_clk_src.c,
+	.bcr_reg = BLSP2_UART5_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_uart5_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_uart5_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp2_uart6_apps_clk = {
+	.cbcr_reg = BLSP2_UART6_APPS_CBCR,
+	.parent = &blsp2_uart6_apps_clk_src.c,
+	.bcr_reg = BLSP2_UART6_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp2_uart6_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp2_uart6_apps_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce1_clk = {
+	.cbcr_reg = CE1_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(5),
+	.bcr_reg = CE1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce1_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce1_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce1_ahb_clk = {
+	.cbcr_reg = CE1_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(3),
+	.bcr_reg = CE1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce1_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce1_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce1_axi_clk = {
+	.cbcr_reg = CE1_AXI_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(4),
+	.bcr_reg = CE1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce1_axi_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce1_axi_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce2_clk = {
+	.cbcr_reg = CE2_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(2),
+	.bcr_reg = CE2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce2_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce2_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce2_ahb_clk = {
+	.cbcr_reg = CE2_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(0),
+	.bcr_reg = CE2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce1_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce1_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce2_axi_clk = {
+	.cbcr_reg = CE2_AXI_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(1),
+	.bcr_reg = CE2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce1_axi_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce2_axi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp1_clk = {
+	.cbcr_reg = GP1_CBCR,
+	.parent = &gp1_clk_src.c,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp1_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp2_clk = {
+	.cbcr_reg = GP2_CBCR,
+	.parent = &gp2_clk_src.c,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp2_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp2_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp3_clk = {
+	.cbcr_reg = GP3_CBCR,
+	.parent = &gp3_clk_src.c,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp3_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp3_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm2_clk = {
+	.cbcr_reg = PDM2_CBCR,
+	.parent = &pdm2_clk_src.c,
+	.bcr_reg = PDM_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_pdm2_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm2_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm_ahb_clk = {
+	.cbcr_reg = PDM_AHB_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = PDM_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_pdm_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_prng_ahb_clk = {
+	.cbcr_reg = PRNG_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(13),
+	.bcr_reg = PRNG_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_prng_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_prng_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_ahb_clk = {
+	.cbcr_reg = SDCC1_AHB_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = SDCC1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc1_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_apps_clk = {
+	.cbcr_reg = SDCC1_APPS_CBCR,
+	.parent = &sdcc1_apps_clk_src.c,
+	.bcr_reg = SDCC1_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc1_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc2_ahb_clk = {
+	.cbcr_reg = SDCC2_AHB_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = SDCC2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc2_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc2_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc2_apps_clk = {
+	.cbcr_reg = SDCC2_APPS_CBCR,
+	.parent = &sdcc2_apps_clk_src.c,
+	.bcr_reg = SDCC2_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc2_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc2_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc3_ahb_clk = {
+	.cbcr_reg = SDCC3_AHB_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = SDCC3_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc3_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc3_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc3_apps_clk = {
+	.cbcr_reg = SDCC3_APPS_CBCR,
+	.parent = &sdcc3_apps_clk_src.c,
+	.bcr_reg = SDCC3_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc3_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc3_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc4_ahb_clk = {
+	.cbcr_reg = SDCC4_AHB_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = SDCC4_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc4_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc4_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc4_apps_clk = {
+	.cbcr_reg = SDCC4_APPS_CBCR,
+	.parent = &sdcc4_apps_clk_src.c,
+	.bcr_reg = SDCC4_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc4_apps_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc4_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_tsif_ahb_clk = {
+	.cbcr_reg = TSIF_AHB_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = TSIF_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_tsif_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_tsif_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_tsif_ref_clk = {
+	.cbcr_reg = TSIF_REF_CBCR,
+	.parent = &tsif_ref_clk_src.c,
+	.bcr_reg = TSIF_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_tsif_ref_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_tsif_ref_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb30_master_clk = {
+	.cbcr_reg = USB30_MASTER_CBCR,
+	.parent = &usb30_master_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = USB_30_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb30_master_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb30_master_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb30_mock_utmi_clk = {
+	.cbcr_reg = USB30_MOCK_UTMI_CBCR,
+	.parent = &usb30_mock_utmi_clk_src.c,
+	.bcr_reg = USB_30_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb30_mock_utmi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb30_mock_utmi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hs_ahb_clk = {
+	.cbcr_reg = USB_HS_AHB_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = USB_HS_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hs_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hs_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hs_system_clk = {
+	.cbcr_reg = USB_HS_SYSTEM_CBCR,
+	.parent = &usb_hs_system_clk_src.c,
+	.bcr_reg = USB_HS_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hs_system_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hs_system_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_ahb_clk = {
+	.cbcr_reg = USB_HSIC_AHB_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = USB_HS_HSIC_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_clk = {
+	.cbcr_reg = USB_HSIC_CBCR,
+	.parent = &usb_hsic_clk_src.c,
+	.bcr_reg = USB_HS_HSIC_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_io_cal_clk = {
+	.cbcr_reg = USB_HSIC_IO_CAL_CBCR,
+	.parent = &usb_hsic_io_cal_clk_src.c,
+	.bcr_reg = USB_HS_HSIC_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_io_cal_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_io_cal_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_system_clk = {
+	.cbcr_reg = USB_HSIC_SYSTEM_CBCR,
+	.parent = &usb_hsic_system_clk_src.c,
+	.bcr_reg = USB_HS_HSIC_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_system_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_system_clk.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mmss_ahb_clk[] = {
+	F_MM(19200000,    cxo,   1,   0,   0),
+	F_MM(40000000,  gpll0,  15,   0,   0),
+	F_MM(80000000, mmpll0,  10,   0,   0),
+	F_END,
+};
+
+/* TODO: This may go away (may be controlled by the RPM). */
+static struct rcg_clk ahb_clk_src = {
+	.cmd_rcgr_reg = 0x5000,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mmss_ahb_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "ahb_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 40000000, NOMINAL, 80000000),
+		CLK_INIT(ahb_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mmss_axi_clk[] = {
+	F_MM( 19200000,    cxo,   1,   0,   0),
+	F_MM(150000000,  gpll0,   4,   0,   0),
+	F_MM(333330000, mmpll1,   3,   0,   0),
+	F_MM(400000000, mmpll0,   2,   0,   0),
+	F_END
+};
+
+static struct rcg_clk axi_clk_src = {
+	.cmd_rcgr_reg = 0x5040,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mmss_axi_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "axi_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 150000000, NOMINAL, 333330000,
+				  HIGH, 400000000),
+		CLK_INIT(axi_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_csi0_3_clk[] = {
+	F_MM(100000000,  gpll0,   6,   0,   0),
+	F_MM(200000000, mmpll0,   4,   0,   0),
+	F_END
+};
+
+static struct rcg_clk csi0_clk_src = {
+	.cmd_rcgr_reg = CSI0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi0_clk_src.c),
+	},
+};
+
+static struct rcg_clk csi1_clk_src = {
+	.cmd_rcgr_reg = CSI1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi1_clk_src.c),
+	},
+};
+
+static struct rcg_clk csi2_clk_src = {
+	.cmd_rcgr_reg = CSI2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi2_clk_src.c),
+	},
+};
+
+static struct rcg_clk csi3_clk_src = {
+	.cmd_rcgr_reg = CSI3_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi3_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi3_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_vfe_vfe0_1_clk[] = {
+	F_MM( 37500000,  gpll0,  16,   0,   0),
+	F_MM( 50000000,  gpll0,  12,   0,   0),
+	F_MM( 60000000,  gpll0,  10,   0,   0),
+	F_MM( 80000000,  gpll0, 7.5,   0,   0),
+	F_MM(100000000,  gpll0,   6,   0,   0),
+	F_MM(109090000,  gpll0, 5.5,   0,   0),
+	F_MM(150000000,  gpll0,   4,   0,   0),
+	F_MM(200000000,  gpll0,   3,   0,   0),
+	F_MM(228570000, mmpll0, 3.5,   0,   0),
+	F_MM(266670000, mmpll0,   3,   0,   0),
+	F_MM(320000000, mmpll0, 2.5,   0,   0),
+	F_END
+};
+
+static struct rcg_clk vfe0_clk_src = {
+	.cmd_rcgr_reg = VFE0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "vfe0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000,
+				  HIGH, 320000000),
+		CLK_INIT(vfe0_clk_src.c),
+	},
+};
+
+static struct rcg_clk vfe1_clk_src = {
+	.cmd_rcgr_reg = VFE1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "vfe1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000,
+				  HIGH, 320000000),
+		CLK_INIT(vfe1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_mdp_clk[] = {
+	F_MM( 37500000,  gpll0,  16,   0,   0),
+	F_MM( 60000000,  gpll0,  10,   0,   0),
+	F_MM( 75000000,  gpll0,   8,   0,   0),
+	F_MM( 85710000,  gpll0,   7,   0,   0),
+	F_MM(100000000,  gpll0,   6,   0,   0),
+	F_MM(133330000, mmpll0,   6,   0,   0),
+	F_MM(160000000, mmpll0,   5,   0,   0),
+	F_MM(200000000, mmpll0,   4,   0,   0),
+	F_MM(266670000, mmpll0,   3,   0,   0),
+	F_MM(320000000, mmpll0, 2.5,   0,   0),
+	F_END
+};
+
+static struct rcg_clk mdp_clk_src = {
+	.cmd_rcgr_reg = MDP_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_mdp_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdp_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000,
+				  HIGH, 320000000),
+		CLK_INIT(mdp_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_cci_cci_clk[] = {
+	F_MM(19200000,    cxo,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk cci_clk_src = {
+	.cmd_rcgr_reg = CCI_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_cci_cci_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "cci_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(cci_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_gp0_1_clk[] = {
+	F_MM(   10000,    cxo,  16,   1, 120),
+	F_MM(   20000,    cxo,  16,   1,  50),
+	F_MM( 6000000,  gpll0,  10,   1,  10),
+	F_MM(12000000,  gpll0,  10,   1,   5),
+	F_MM(13000000,  gpll0,  10,  13,  60),
+	F_MM(24000000,  gpll0,   5,   1,   5),
+	F_END
+};
+
+static struct rcg_clk mmss_gp0_clk_src = {
+	.cmd_rcgr_reg = MMSS_GP0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_camss_gp0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_gp0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(mmss_gp0_clk_src.c),
+	},
+};
+
+static struct rcg_clk mmss_gp1_clk_src = {
+	.cmd_rcgr_reg = MMSS_GP1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_camss_gp0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_gp1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(mmss_gp1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_jpeg_jpeg0_2_clk[] = {
+	F_MM( 75000000,  gpll0,   8,   0,   0),
+	F_MM(150000000,  gpll0,   4,   0,   0),
+	F_MM(200000000,  gpll0,   3,   0,   0),
+	F_MM(228570000, mmpll0, 3.5,   0,   0),
+	F_MM(266670000, mmpll0,   3,   0,   0),
+	F_MM(320000000, mmpll0, 2.5,   0,   0),
+	F_END
+};
+
+static struct rcg_clk jpeg0_clk_src = {
+	.cmd_rcgr_reg = JPEG0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "jpeg0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000,
+				  HIGH, 320000000),
+		CLK_INIT(jpeg0_clk_src.c),
+	},
+};
+
+static struct rcg_clk jpeg1_clk_src = {
+	.cmd_rcgr_reg = JPEG1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "jpeg1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000,
+				  HIGH, 320000000),
+		CLK_INIT(jpeg1_clk_src.c),
+	},
+};
+
+static struct rcg_clk jpeg2_clk_src = {
+	.cmd_rcgr_reg = JPEG2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "jpeg2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000,
+				  HIGH, 320000000),
+		CLK_INIT(jpeg2_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_mclk0_3_clk[] = {
+	F_MM(66670000,  gpll0,   9,   0,   0),
+	F_END
+};
+
+static struct rcg_clk mclk0_clk_src = {
+	.cmd_rcgr_reg = MCLK0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mclk0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 66670000),
+		CLK_INIT(mclk0_clk_src.c),
+	},
+};
+
+static struct rcg_clk mclk1_clk_src = {
+	.cmd_rcgr_reg = MCLK1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mclk1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 66670000),
+		CLK_INIT(mclk1_clk_src.c),
+	},
+};
+
+static struct rcg_clk mclk2_clk_src = {
+	.cmd_rcgr_reg = MCLK2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mclk2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 66670000),
+		CLK_INIT(mclk2_clk_src.c),
+	},
+};
+
+static struct rcg_clk mclk3_clk_src = {
+	.cmd_rcgr_reg = MCLK3_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mclk3_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 66670000),
+		CLK_INIT(mclk3_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_phy0_2_csi0_2phytimer_clk[] = {
+	F_MM(100000000,  gpll0,   6,   0,   0),
+	F_MM(200000000, mmpll0,   4,   0,   0),
+	F_END
+};
+
+static struct rcg_clk csi0phytimer_clk_src = {
+	.cmd_rcgr_reg = CSI0PHYTIMER_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi0phytimer_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi0phytimer_clk_src.c),
+	},
+};
+
+static struct rcg_clk csi1phytimer_clk_src = {
+	.cmd_rcgr_reg = CSI1PHYTIMER_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi1phytimer_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi1phytimer_clk_src.c),
+	},
+};
+
+static struct rcg_clk csi2phytimer_clk_src = {
+	.cmd_rcgr_reg = CSI2PHYTIMER_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi2phytimer_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi2phytimer_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_vfe_cpp_clk[] = {
+	F_MM(150000000,  gpll0,   4,   0,   0),
+	F_MM(266670000, mmpll0,   3,   0,   0),
+	F_MM(320000000, mmpll0, 2.5,   0,   0),
+	F_END
+};
+
+static struct rcg_clk cpp_clk_src = {
+	.cmd_rcgr_reg = CPP_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_vfe_cpp_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "cpp_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000,
+				  HIGH, 320000000),
+		CLK_INIT(cpp_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_byte0_1_clk[] = {
+	F_MDSS( 93750000, dsipll_750,   8,   0,   0),
+	F_MDSS(187500000, dsipll_750,   4,   0,   0),
+	F_END
+};
+
+static struct rcg_clk byte0_clk_src = {
+	.cmd_rcgr_reg = BYTE0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_byte0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "byte0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 93800000, NOMINAL, 187500000,
+				  HIGH, 188000000),
+		CLK_INIT(byte0_clk_src.c),
+	},
+};
+
+static struct rcg_clk byte1_clk_src = {
+	.cmd_rcgr_reg = BYTE1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_byte0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "byte1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 93800000, NOMINAL, 187500000,
+				  HIGH, 188000000),
+		CLK_INIT(byte1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_edpaux_clk[] = {
+	F_MM(19200000,    cxo,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk edpaux_clk_src = {
+	.cmd_rcgr_reg = EDPAUX_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_edpaux_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "edpaux_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(edpaux_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_edplink_clk[] = {
+	F_MDSS(135000000, edppll_270,   2,   0,   0),
+	F_MDSS(270000000, edppll_270,  11,   0,   0),
+	F_END
+};
+
+static struct rcg_clk edplink_clk_src = {
+	.cmd_rcgr_reg = EDPLINK_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_edplink_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "edplink_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 135000000, NOMINAL, 270000000),
+		CLK_INIT(edplink_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_edppixel_clk[] = {
+	F_MDSS(175000000, edppll_350,   2,   0,   0),
+	F_MDSS(350000000, edppll_350,  11,   0,   0),
+	F_END
+};
+
+static struct rcg_clk edppixel_clk_src = {
+	.cmd_rcgr_reg = EDPPIXEL_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_mdss_edppixel_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "edppixel_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 175000000, NOMINAL, 350000000),
+		CLK_INIT(edppixel_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_esc0_1_clk[] = {
+	F_MM(19200000,    cxo,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk esc0_clk_src = {
+	.cmd_rcgr_reg = ESC0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "esc0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(esc0_clk_src.c),
+	},
+};
+
+static struct rcg_clk esc1_clk_src = {
+	.cmd_rcgr_reg = ESC1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "esc1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(esc1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_extpclk_clk[] = {
+	F_MDSS(148500000, hdmipll_297,   2,   0,   0),
+	F_END
+};
+
+static struct rcg_clk extpclk_clk_src = {
+	.cmd_rcgr_reg = EXTPCLK_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_extpclk_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "extpclk_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 148500000, NOMINAL, 297000000),
+		CLK_INIT(extpclk_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_hdmi_clk[] = {
+	F_MDSS(19200000,    cxo,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk hdmi_clk_src = {
+	.cmd_rcgr_reg = HDMI_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_hdmi_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "hdmi_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(hdmi_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_pclk0_1_clk[] = {
+	F_MDSS(125000000, dsipll_250,   2,   0,   0),
+	F_MDSS(250000000, dsipll_250,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk pclk0_clk_src = {
+	.cmd_rcgr_reg = PCLK0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_mdss_pclk0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "pclk0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 125000000, NOMINAL, 250000000),
+		CLK_INIT(pclk0_clk_src.c),
+	},
+};
+
+static struct rcg_clk pclk1_clk_src = {
+	.cmd_rcgr_reg = PCLK1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_mdss_pclk0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "pclk1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 125000000, NOMINAL, 250000000),
+		CLK_INIT(pclk1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_vsync_clk[] = {
+	F_MDSS(19200000,    cxo,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk vsync_clk_src = {
+	.cmd_rcgr_reg = VSYNC_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_vsync_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "vsync_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(vsync_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_venus0_vcodec0_clk[] = {
+	F_MM( 50000000,  gpll0,  12,   0,   0),
+	F_MM(100000000,  gpll0,   6,   0,   0),
+	F_MM(133330000, mmpll0,   6,   0,   0),
+	F_MM(200000000, mmpll0,   4,   0,   0),
+	F_MM(266670000, mmpll0,   3,   0,   0),
+	F_MM(410000000, mmpll3,   2,   0,   0),
+	F_END
+};
+
+static struct rcg_clk vcodec0_clk_src = {
+	.cmd_rcgr_reg = VCODEC0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_venus0_vcodec0_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "vcodec0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000,
+				  HIGH, 410000000),
+		CLK_INIT(vcodec0_clk_src.c),
+	},
+};
+
+static struct branch_clk camss_cci_cci_ahb_clk = {
+	.cbcr_reg = CAMSS_CCI_CCI_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CCI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_cci_cci_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_cci_cci_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_cci_cci_clk = {
+	.cbcr_reg = CAMSS_CCI_CCI_CBCR,
+	.parent = &cci_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_CCI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_cci_cci_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_cci_cci_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0_ahb_clk = {
+	.cbcr_reg = CAMSS_CSI0_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0_clk = {
+	.cbcr_reg = CAMSS_CSI0_CBCR,
+	.parent = &csi0_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0phy_clk = {
+	.cbcr_reg = CAMSS_CSI0PHY_CBCR,
+	.parent = &csi0_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI0PHY_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0phy_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0phy_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0pix_clk = {
+	.cbcr_reg = CAMSS_CSI0PIX_CBCR,
+	.parent = &csi0_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI0PIX_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0pix_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0pix_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0rdi_clk = {
+	.cbcr_reg = CAMSS_CSI0RDI_CBCR,
+	.parent = &csi0_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI0RDI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0rdi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0rdi_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1_ahb_clk = {
+	.cbcr_reg = CAMSS_CSI1_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI1_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1_clk = {
+	.cbcr_reg = CAMSS_CSI1_CBCR,
+	.parent = &csi1_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI1_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1phy_clk = {
+	.cbcr_reg = CAMSS_CSI1PHY_CBCR,
+	.parent = &csi1_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI1PHY_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1phy_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1phy_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1pix_clk = {
+	.cbcr_reg = CAMSS_CSI1PIX_CBCR,
+	.parent = &csi1_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI1PIX_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1pix_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1pix_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1rdi_clk = {
+	.cbcr_reg = CAMSS_CSI1RDI_CBCR,
+	.parent = &csi1_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI1RDI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1rdi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1rdi_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi2_ahb_clk = {
+	.cbcr_reg = CAMSS_CSI2_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI2_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi2_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi2_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi2_clk = {
+	.cbcr_reg = CAMSS_CSI2_CBCR,
+	.parent = &csi2_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI2_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi2_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi2_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi2phy_clk = {
+	.cbcr_reg = CAMSS_CSI2PHY_CBCR,
+	.parent = &csi2_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI2PHY_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi2phy_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi2phy_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi2pix_clk = {
+	.cbcr_reg = CAMSS_CSI2PIX_CBCR,
+	.parent = &csi2_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI2PIX_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi2pix_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi2pix_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi2rdi_clk = {
+	.cbcr_reg = CAMSS_CSI2RDI_CBCR,
+	.parent = &csi2_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI2RDI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi2rdi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi2rdi_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi3_ahb_clk = {
+	.cbcr_reg = CAMSS_CSI3_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI3_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi3_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi3_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi3_clk = {
+	.cbcr_reg = CAMSS_CSI3_CBCR,
+	.parent = &csi3_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI3_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi3_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi3_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi3phy_clk = {
+	.cbcr_reg = CAMSS_CSI3PHY_CBCR,
+	.parent = &csi3_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI3PHY_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi3phy_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi3phy_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi3pix_clk = {
+	.cbcr_reg = CAMSS_CSI3PIX_CBCR,
+	.parent = &csi3_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI3PIX_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi3pix_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi3pix_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi3rdi_clk = {
+	.cbcr_reg = CAMSS_CSI3RDI_CBCR,
+	.parent = &csi3_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI3RDI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi3rdi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi3rdi_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi_vfe0_clk = {
+	.cbcr_reg = CAMSS_CSI_VFE0_CBCR,
+	.parent = &vfe0_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI_VFE0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi_vfe0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi_vfe0_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi_vfe1_clk = {
+	.cbcr_reg = CAMSS_CSI_VFE1_CBCR,
+	.parent = &vfe1_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_CSI_VFE1_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi_vfe1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi_vfe1_clk.c),
+	},
+};
+
+static struct branch_clk camss_gp0_clk = {
+	.cbcr_reg = CAMSS_GP0_CBCR,
+	.parent = &mmss_gp0_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_GP0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_gp0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_gp0_clk.c),
+	},
+};
+
+static struct branch_clk camss_gp1_clk = {
+	.cbcr_reg = CAMSS_GP1_CBCR,
+	.parent = &mmss_gp1_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_GP1_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_gp1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_gp1_clk.c),
+	},
+};
+
+static struct branch_clk camss_ispif_ahb_clk = {
+	.cbcr_reg = CAMSS_ISPIF_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_ISPIF_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_ispif_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_ispif_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg0_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG0_CBCR,
+	.parent = &jpeg0_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_JPEG_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg0_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg1_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG1_CBCR,
+	.parent = &jpeg1_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_JPEG_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg1_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg2_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG2_CBCR,
+	.parent = &jpeg2_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_JPEG_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg2_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg2_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg_ahb_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_JPEG_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg_axi_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG_AXI_CBCR,
+	.parent = &axi_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_JPEG_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg_axi_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg_ocmemnoc_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG_OCMEMNOC_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_JPEG_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg_ocmemnoc_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg_ocmemnoc_clk.c),
+	},
+};
+
+static struct branch_clk camss_mclk0_clk = {
+	.cbcr_reg = CAMSS_MCLK0_CBCR,
+	.parent = &mclk0_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_MCLK0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_mclk0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_mclk0_clk.c),
+	},
+};
+
+static struct branch_clk camss_mclk1_clk = {
+	.cbcr_reg = CAMSS_MCLK1_CBCR,
+	.parent = &mclk1_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_MCLK1_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_mclk1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_mclk1_clk.c),
+	},
+};
+
+static struct branch_clk camss_mclk2_clk = {
+	.cbcr_reg = CAMSS_MCLK2_CBCR,
+	.parent = &mclk2_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_MCLK2_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_mclk2_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_mclk2_clk.c),
+	},
+};
+
+static struct branch_clk camss_mclk3_clk = {
+	.cbcr_reg = CAMSS_MCLK3_CBCR,
+	.parent = &mclk3_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_MCLK3_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_mclk3_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_mclk3_clk.c),
+	},
+};
+
+static struct branch_clk camss_micro_ahb_clk = {
+	.cbcr_reg = CAMSS_MICRO_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_MICRO_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_micro_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_micro_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_phy0_csi0phytimer_clk = {
+	.cbcr_reg = CAMSS_PHY0_CSI0PHYTIMER_CBCR,
+	.parent = &csi0phytimer_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_PHY0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_phy0_csi0phytimer_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_phy0_csi0phytimer_clk.c),
+	},
+};
+
+static struct branch_clk camss_phy1_csi1phytimer_clk = {
+	.cbcr_reg = CAMSS_PHY1_CSI1PHYTIMER_CBCR,
+	.parent = &csi1phytimer_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_PHY1_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_phy1_csi1phytimer_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_phy1_csi1phytimer_clk.c),
+	},
+};
+
+static struct branch_clk camss_phy2_csi2phytimer_clk = {
+	.cbcr_reg = CAMSS_PHY2_CSI2PHYTIMER_CBCR,
+	.parent = &csi2phytimer_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_PHY2_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_phy2_csi2phytimer_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_phy2_csi2phytimer_clk.c),
+	},
+};
+
+static struct branch_clk camss_top_ahb_clk = {
+	.cbcr_reg = CAMSS_TOP_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_TOP_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_top_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_top_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_cpp_ahb_clk = {
+	.cbcr_reg = CAMSS_VFE_CPP_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_VFE_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_cpp_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_cpp_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_cpp_clk = {
+	.cbcr_reg = CAMSS_VFE_CPP_CBCR,
+	.parent = &cpp_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = CAMSS_VFE_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_cpp_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_cpp_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_vfe0_clk = {
+	.cbcr_reg = CAMSS_VFE_VFE0_CBCR,
+	.parent = &vfe0_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_VFE_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_vfe0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_vfe0_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_vfe1_clk = {
+	.cbcr_reg = CAMSS_VFE_VFE1_CBCR,
+	.parent = &vfe1_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_VFE_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_vfe1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_vfe1_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_vfe_ahb_clk = {
+	.cbcr_reg = CAMSS_VFE_VFE_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_VFE_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_vfe_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_vfe_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_vfe_axi_clk = {
+	.cbcr_reg = CAMSS_VFE_VFE_AXI_CBCR,
+	.parent = &axi_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_VFE_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_vfe_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_vfe_axi_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_vfe_ocmemnoc_clk = {
+	.cbcr_reg = CAMSS_VFE_VFE_OCMEMNOC_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = CAMSS_VFE_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_vfe_ocmemnoc_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_vfe_ocmemnoc_clk.c),
+	},
+};
+
+static struct branch_clk mdss_ahb_clk = {
+	.cbcr_reg = MDSS_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mdss_axi_clk = {
+	.cbcr_reg = MDSS_AXI_CBCR,
+	.parent = &axi_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_axi_clk.c),
+	},
+};
+
+static struct branch_clk mdss_byte0_clk = {
+	.cbcr_reg = MDSS_BYTE0_CBCR,
+	.parent = &byte0_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_byte0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_byte0_clk.c),
+	},
+};
+
+static struct branch_clk mdss_byte1_clk = {
+	.cbcr_reg = MDSS_BYTE1_CBCR,
+	.parent = &byte1_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_byte1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_byte1_clk.c),
+	},
+};
+
+static struct branch_clk mdss_edpaux_clk = {
+	.cbcr_reg = MDSS_EDPAUX_CBCR,
+	.parent = &edpaux_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_edpaux_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_edpaux_clk.c),
+	},
+};
+
+static struct branch_clk mdss_edplink_clk = {
+	.cbcr_reg = MDSS_EDPLINK_CBCR,
+	.parent = &edplink_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_edplink_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_edplink_clk.c),
+	},
+};
+
+static struct branch_clk mdss_edppixel_clk = {
+	.cbcr_reg = MDSS_EDPPIXEL_CBCR,
+	.parent = &edppixel_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_edppixel_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_edppixel_clk.c),
+	},
+};
+
+static struct branch_clk mdss_esc0_clk = {
+	.cbcr_reg = MDSS_ESC0_CBCR,
+	.parent = &esc0_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_esc0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_esc0_clk.c),
+	},
+};
+
+static struct branch_clk mdss_esc1_clk = {
+	.cbcr_reg = MDSS_ESC1_CBCR,
+	.parent = &esc1_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_esc1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_esc1_clk.c),
+	},
+};
+
+static struct branch_clk mdss_extpclk_clk = {
+	.cbcr_reg = MDSS_EXTPCLK_CBCR,
+	.parent = &extpclk_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_extpclk_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_extpclk_clk.c),
+	},
+};
+
+static struct branch_clk mdss_hdmi_ahb_clk = {
+	.cbcr_reg = MDSS_HDMI_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_hdmi_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_hdmi_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mdss_hdmi_clk = {
+	.cbcr_reg = MDSS_HDMI_CBCR,
+	.parent = &hdmi_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_hdmi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_hdmi_clk.c),
+	},
+};
+
+static struct branch_clk mdss_mdp_clk = {
+	.cbcr_reg = MDSS_MDP_CBCR,
+	.parent = &mdp_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_mdp_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_mdp_clk.c),
+	},
+};
+
+static struct branch_clk mdss_mdp_lut_clk = {
+	.cbcr_reg = MDSS_MDP_LUT_CBCR,
+	.parent = &mdp_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_mdp_lut_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_mdp_lut_clk.c),
+	},
+};
+
+static struct branch_clk mdss_pclk0_clk = {
+	.cbcr_reg = MDSS_PCLK0_CBCR,
+	.parent = &pclk0_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_pclk0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_pclk0_clk.c),
+	},
+};
+
+static struct branch_clk mdss_pclk1_clk = {
+	.cbcr_reg = MDSS_PCLK1_CBCR,
+	.parent = &pclk1_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_pclk1_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_pclk1_clk.c),
+	},
+};
+
+static struct branch_clk mdss_vsync_clk = {
+	.cbcr_reg = MDSS_VSYNC_CBCR,
+	.parent = &vsync_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = MDSS_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_vsync_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_vsync_clk.c),
+	},
+};
+
+static struct branch_clk mmss_misc_ahb_clk = {
+	.cbcr_reg = MMSS_MISC_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MMSSNOCAHB_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_misc_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_misc_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mmss_mmssnoc_ahb_clk = {
+	.cbcr_reg = MMSS_MMSSNOC_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MMSSNOCAHB_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_mmssnoc_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_mmssnoc_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mmss_mmssnoc_bto_ahb_clk = {
+	.cbcr_reg = MMSS_MMSSNOC_BTO_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MMSSNOCAHB_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_mmssnoc_bto_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_mmssnoc_bto_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mmss_mmssnoc_axi_clk = {
+	.cbcr_reg = MMSS_MMSSNOC_AXI_CBCR,
+	.parent = &axi_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MMSSNOCAXI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_mmssnoc_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_mmssnoc_axi_clk.c),
+	},
+};
+
+static struct branch_clk mmss_s0_axi_clk = {
+	.cbcr_reg = MMSS_S0_AXI_CBCR,
+	.parent = &axi_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = MMSSNOCAXI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_s0_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_s0_axi_clk.c),
+	},
+};
+
+static struct branch_clk venus0_ahb_clk = {
+	.cbcr_reg = VENUS0_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = VENUS0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "venus0_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(venus0_ahb_clk.c),
+	},
+};
+
+static struct branch_clk venus0_axi_clk = {
+	.cbcr_reg = VENUS0_AXI_CBCR,
+	.parent = &axi_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = VENUS0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "venus0_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(venus0_axi_clk.c),
+	},
+};
+
+static struct branch_clk venus0_ocmemnoc_clk = {
+	.cbcr_reg = VENUS0_OCMEMNOC_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = VENUS0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "venus0_ocmemnoc_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(venus0_ocmemnoc_clk.c),
+	},
+};
+
+static struct branch_clk venus0_vcodec0_clk = {
+	.cbcr_reg = VENUS0_VCODEC0_CBCR,
+	.parent = &vcodec0_clk_src.c,
+	.has_sibling = 0,
+	.bcr_reg = VENUS0_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "venus0_vcodec0_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(venus0_vcodec0_clk.c),
+	},
+};
+
+static struct branch_clk oxili_gfx3d_clk = {
+	.cbcr_reg = OXILI_GFX3D_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = OXILI_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "oxili_gfx3d_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(oxili_gfx3d_clk.c),
+	},
+};
+
+static struct branch_clk oxilicx_ahb_clk = {
+	.cbcr_reg = OXILICX_AHB_CBCR,
+	.parent = &ahb_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = OXILICX_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "oxilicx_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(oxilicx_ahb_clk.c),
+	},
+};
+
+static struct branch_clk oxilicx_axi_clk = {
+	.cbcr_reg = OXILICX_AXI_CBCR,
+	.parent = &axi_clk_src.c,
+	.has_sibling = 1,
+	.bcr_reg = OXILICX_BCR,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "oxilicx_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(oxilicx_axi_clk.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clock[] = {
+	F_LPASS(28800000, lpapll0, 1, 15, 256),
+	F_END
+};
+
+static struct rcg_clk audio_core_slimbus_core_clk_src = {
+	.cmd_rcgr_reg = SLIMBUS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_slimbus_core_clock,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_slimbus_core_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 70000000, NOMINAL, 140000000),
+		CLK_INIT(audio_core_slimbus_core_clk_src.c),
+	},
+};
+
+static struct branch_clk audio_core_slimbus_core_clk = {
+	.cbcr_reg = AUDIO_CORE_SLIMBUS_CORE_CBCR,
+	.parent = &audio_core_slimbus_core_clk_src.c,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_slimbus_core_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_slimbus_core_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_slimbus_lfabif_clk = {
+	.cbcr_reg = AUDIO_CORE_SLIMBUS_LFABIF_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_slimbus_lfabif_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_slimbus_lfabif_clk.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_audio_core_lpaif_clock[] = {
+	F_LPASS(  512000, lpapll0, 16, 1, 60),
+	F_LPASS(  768000, lpapll0, 16, 1, 40),
+	F_LPASS( 1024000, lpapll0, 16, 1, 30),
+	F_LPASS( 1536000, lpapll0, 16, 1, 10),
+	F_LPASS( 2048000, lpapll0, 16, 1, 15),
+	F_LPASS( 3072000, lpapll0, 16, 1, 10),
+	F_LPASS( 4096000, lpapll0, 15, 1,  8),
+	F_LPASS( 6144000, lpapll0, 10, 1,  8),
+	F_LPASS( 8192000, lpapll0, 15, 1,  4),
+	F_LPASS(12288000, lpapll0, 10, 1,  4),
+	F_END
+};
+
+static struct rcg_clk audio_core_lpaif_codec_spkr_clk_src = {
+	.cmd_rcgr_reg = LPAIF_SPKR_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_clock,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
+		CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+	},
+};
+
+static struct rcg_clk audio_core_lpaif_pri_clk_src = {
+	.cmd_rcgr_reg = LPAIF_PRI_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_clock,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pri_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
+		CLK_INIT(audio_core_lpaif_pri_clk_src.c),
+	},
+};
+
+static struct rcg_clk audio_core_lpaif_sec_clk_src = {
+	.cmd_rcgr_reg = LPAIF_SEC_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_clock,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_sec_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
+		CLK_INIT(audio_core_lpaif_sec_clk_src.c),
+	},
+};
+
+static struct rcg_clk audio_core_lpaif_ter_clk_src = {
+	.cmd_rcgr_reg = LPAIF_TER_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_clock,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_ter_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
+		CLK_INIT(audio_core_lpaif_ter_clk_src.c),
+	},
+};
+
+static struct rcg_clk audio_core_lpaif_quad_clk_src = {
+	.cmd_rcgr_reg = LPAIF_QUAD_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_clock,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_quad_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
+		CLK_INIT(audio_core_lpaif_quad_clk_src.c),
+	},
+};
+
+static struct rcg_clk audio_core_lpaif_pcm0_clk_src = {
+	.cmd_rcgr_reg = LPAIF_PCM0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_clock,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
+		CLK_INIT(audio_core_lpaif_pcm0_clk_src.c),
+	},
+};
+
+static struct rcg_clk audio_core_lpaif_pcm1_clk_src = {
+	.cmd_rcgr_reg = LPAIF_PCM1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_clock,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
+		CLK_INIT(audio_core_lpaif_pcm1_clk_src.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR,
+	.parent = &audio_core_lpaif_codec_spkr_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR,
+	.parent = &audio_core_lpaif_codec_spkr_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR,
+	.parent = &audio_core_lpaif_codec_spkr_clk_src.c,
+	.has_sibling = 1,
+	.max_div = 16,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pri_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_OSR_CBCR,
+	.parent = &audio_core_lpaif_pri_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pri_osr_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pri_osr_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pri_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_EBIT_CBCR,
+	.parent = &audio_core_lpaif_pri_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pri_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pri_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pri_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_IBIT_CBCR,
+	.parent = &audio_core_lpaif_pri_clk_src.c,
+	.has_sibling = 1,
+	.max_div = 16,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pri_ibit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pri_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_sec_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_OSR_CBCR,
+	.parent = &audio_core_lpaif_sec_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_sec_osr_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_sec_osr_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_sec_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_EBIT_CBCR,
+	.parent = &audio_core_lpaif_sec_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_sec_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_sec_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_sec_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_IBIT_CBCR,
+	.parent = &audio_core_lpaif_sec_clk_src.c,
+	.has_sibling = 1,
+	.max_div = 16,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_sec_ibit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_sec_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_ter_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_TER_OSR_CBCR,
+	.parent = &audio_core_lpaif_ter_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_ter_osr_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_ter_osr_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_ter_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_TER_EBIT_CBCR,
+	.parent = &audio_core_lpaif_ter_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_ter_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_ter_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_ter_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_TER_IBIT_CBCR,
+	.parent = &audio_core_lpaif_ter_clk_src.c,
+	.has_sibling = 1,
+	.max_div = 16,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_ter_ibit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_ter_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_quad_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_QUAD_OSR_CBCR,
+	.parent = &audio_core_lpaif_quad_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_quad_osr_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_quad_osr_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_quad_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR,
+	.parent = &audio_core_lpaif_quad_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_quad_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_quad_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_quad_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR,
+	.parent = &audio_core_lpaif_quad_clk_src.c,
+	.has_sibling = 1,
+	.max_div = 16,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_quad_ibit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_quad_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcm0_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR,
+	.parent = &audio_core_lpaif_pcm0_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm0_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcm0_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcm0_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR,
+	.parent = &audio_core_lpaif_pcm0_clk_src.c,
+	.has_sibling = 1,
+	.max_div = 16,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm0_ibit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcm0_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcm1_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR,
+	.parent = &audio_core_lpaif_pcm1_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm1_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcm1_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcm1_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR,
+	.parent = &audio_core_lpaif_pcm1_clk_src.c,
+	.has_sibling = 1,
+	.max_div = 16,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm1_ibit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcm1_ibit_clk.c),
+	},
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+struct measure_mux_entry {
+	struct clk *c;
+	int base;
+	u32 debug_mux;
+};
+
+struct measure_mux_entry measure_mux[] = {
+	{&gcc_bam_dma_ahb_clk.c,		GCC_BASE, 0x00e8},
+	{&gcc_blsp1_ahb_clk.c,			GCC_BASE, 0x0090},
+	{&gcc_blsp1_qup1_i2c_apps_clk.c,	GCC_BASE, 0x0093},
+	{&gcc_blsp1_qup1_spi_apps_clk.c,	GCC_BASE, 0x0092},
+	{&gcc_blsp1_qup2_i2c_apps_clk.c,	GCC_BASE, 0x0098},
+	{&gcc_blsp1_qup2_spi_apps_clk.c,	GCC_BASE, 0x0096},
+	{&gcc_blsp1_qup3_i2c_apps_clk.c,	GCC_BASE, 0x009c},
+	{&gcc_blsp1_qup3_spi_apps_clk.c,	GCC_BASE, 0x009b},
+	{&gcc_blsp1_qup4_i2c_apps_clk.c,	GCC_BASE, 0x00a1},
+	{&gcc_blsp1_qup4_spi_apps_clk.c,	GCC_BASE, 0x00a0},
+	{&gcc_blsp1_qup5_i2c_apps_clk.c,	GCC_BASE, 0x00a5},
+	{&gcc_blsp1_qup5_spi_apps_clk.c,	GCC_BASE, 0x00a4},
+	{&gcc_blsp1_qup6_i2c_apps_clk.c,	GCC_BASE, 0x00aa},
+	{&gcc_blsp1_qup6_spi_apps_clk.c,	GCC_BASE, 0x00a9},
+	{&gcc_blsp1_uart1_apps_clk.c,		GCC_BASE, 0x0094},
+	{&gcc_blsp1_uart2_apps_clk.c,		GCC_BASE, 0x0099},
+	{&gcc_blsp1_uart3_apps_clk.c,		GCC_BASE, 0x009d},
+	{&gcc_blsp1_uart4_apps_clk.c,		GCC_BASE, 0x00a2},
+	{&gcc_blsp1_uart5_apps_clk.c,		GCC_BASE, 0x00a6},
+	{&gcc_blsp1_uart6_apps_clk.c,		GCC_BASE, 0x00ab},
+	{&gcc_blsp2_ahb_clk.c,			GCC_BASE, 0x00b0},
+	{&gcc_blsp2_qup1_i2c_apps_clk.c,	GCC_BASE, 0x00b3},
+	{&gcc_blsp2_qup1_spi_apps_clk.c,	GCC_BASE, 0x00b2},
+	{&gcc_blsp2_qup2_i2c_apps_clk.c,	GCC_BASE, 0x00b8},
+	{&gcc_blsp2_qup2_spi_apps_clk.c,	GCC_BASE, 0x00b6},
+	{&gcc_blsp2_qup3_i2c_apps_clk.c,	GCC_BASE, 0x00bc},
+	{&gcc_blsp2_qup3_spi_apps_clk.c,	GCC_BASE, 0x00bb},
+	{&gcc_blsp2_qup4_i2c_apps_clk.c,	GCC_BASE, 0x00c1},
+	{&gcc_blsp2_qup4_spi_apps_clk.c,	GCC_BASE, 0x00c0},
+	{&gcc_blsp2_qup5_i2c_apps_clk.c,	GCC_BASE, 0x00c5},
+	{&gcc_blsp2_qup5_spi_apps_clk.c,	GCC_BASE, 0x00c4},
+	{&gcc_blsp2_qup6_i2c_apps_clk.c,	GCC_BASE, 0x00ca},
+	{&gcc_blsp2_qup6_spi_apps_clk.c,	GCC_BASE, 0x00c9},
+	{&gcc_blsp2_uart1_apps_clk.c,		GCC_BASE, 0x00b4},
+	{&gcc_blsp2_uart2_apps_clk.c,		GCC_BASE, 0x00b9},
+	{&gcc_blsp2_uart3_apps_clk.c,		GCC_BASE, 0x00bd},
+	{&gcc_blsp2_uart4_apps_clk.c,		GCC_BASE, 0x00c2},
+	{&gcc_blsp2_uart5_apps_clk.c,		GCC_BASE, 0x00c6},
+	{&gcc_blsp2_uart6_apps_clk.c,		GCC_BASE, 0x00cb},
+	{&gcc_ce1_clk.c,			GCC_BASE, 0x0140},
+	{&gcc_ce2_clk.c,			GCC_BASE, 0x0148},
+	{&gcc_pdm2_clk.c,			GCC_BASE, 0x00da},
+	{&gcc_pdm_ahb_clk.c,			GCC_BASE, 0x00d8},
+	{&gcc_prng_ahb_clk.c,			GCC_BASE, 0x00e0},
+	{&gcc_sdcc1_ahb_clk.c,			GCC_BASE, 0x0071},
+	{&gcc_sdcc1_apps_clk.c,			GCC_BASE, 0x0070},
+	{&gcc_sdcc2_ahb_clk.c,			GCC_BASE, 0x0079},
+	{&gcc_sdcc2_apps_clk.c,			GCC_BASE, 0x0078},
+	{&gcc_sdcc3_ahb_clk.c,			GCC_BASE, 0x0081},
+	{&gcc_sdcc3_apps_clk.c,			GCC_BASE, 0x0080},
+	{&gcc_sdcc4_ahb_clk.c,			GCC_BASE, 0x0089},
+	{&gcc_sdcc4_apps_clk.c,			GCC_BASE, 0x0088},
+	{&gcc_tsif_ahb_clk.c,			GCC_BASE, 0x00f0},
+	{&gcc_tsif_ref_clk.c,			GCC_BASE, 0x00f1},
+	{&gcc_usb30_master_clk.c,		GCC_BASE, 0x0050},
+	{&gcc_usb30_mock_utmi_clk.c,		GCC_BASE, 0x0052},
+	{&gcc_usb_hs_ahb_clk.c,			GCC_BASE, 0x0069},
+	{&gcc_usb_hs_system_clk.c,		GCC_BASE, 0x0068},
+	{&gcc_usb_hsic_ahb_clk.c,		GCC_BASE, 0x0060},
+	{&gcc_usb_hsic_clk.c,			GCC_BASE, 0x0062},
+	{&gcc_usb_hsic_io_cal_clk.c,		GCC_BASE, 0x0063},
+	{&gcc_usb_hsic_system_clk.c,		GCC_BASE, 0x0061},
+	{&mmss_mmssnoc_ahb_clk.c,		MMSS_BASE, 0x0001},
+	{&mmss_mmssnoc_axi_clk.c,		MMSS_BASE, 0x0004},
+	{&camss_cci_cci_ahb_clk.c,		MMSS_BASE, 0x002e},
+	{&camss_cci_cci_clk.c,			MMSS_BASE, 0x002d},
+	{&camss_csi0_ahb_clk.c,			MMSS_BASE, 0x0042},
+	{&camss_csi0_clk.c,			MMSS_BASE, 0x0041},
+	{&camss_csi0phy_clk.c,			MMSS_BASE, 0x0043},
+	{&camss_csi0pix_clk.c,			MMSS_BASE, 0x0045},
+	{&camss_csi0rdi_clk.c,			MMSS_BASE, 0x0044},
+	{&camss_csi1_ahb_clk.c,			MMSS_BASE, 0x0047},
+	{&camss_csi1_clk.c,			MMSS_BASE, 0x0046},
+	{&camss_csi1phy_clk.c,			MMSS_BASE, 0x0048},
+	{&camss_csi1pix_clk.c,			MMSS_BASE, 0x004a},
+	{&camss_csi1rdi_clk.c,			MMSS_BASE, 0x0049},
+	{&camss_csi2_ahb_clk.c,			MMSS_BASE, 0x004c},
+	{&camss_csi2_clk.c,			MMSS_BASE, 0x004b},
+	{&camss_csi2phy_clk.c,			MMSS_BASE, 0x004d},
+	{&camss_csi2pix_clk.c,			MMSS_BASE, 0x004f},
+	{&camss_csi2rdi_clk.c,			MMSS_BASE, 0x004e},
+	{&camss_csi3_ahb_clk.c,			MMSS_BASE, 0x0051},
+	{&camss_csi3_clk.c,			MMSS_BASE, 0x0050},
+	{&camss_csi3phy_clk.c,			MMSS_BASE, 0x0052},
+	{&camss_csi3pix_clk.c,			MMSS_BASE, 0x0054},
+	{&camss_csi3rdi_clk.c,			MMSS_BASE, 0x0053},
+	{&camss_csi_vfe0_clk.c,			MMSS_BASE, 0x003f},
+	{&camss_csi_vfe1_clk.c,			MMSS_BASE, 0x0040},
+	{&camss_gp0_clk.c,			MMSS_BASE, 0x0027},
+	{&camss_gp1_clk.c,			MMSS_BASE, 0x0028},
+	{&camss_ispif_ahb_clk.c,		MMSS_BASE, 0x0055},
+	{&camss_jpeg_jpeg0_clk.c,		MMSS_BASE, 0x0032},
+	{&camss_jpeg_jpeg1_clk.c,		MMSS_BASE, 0x0033},
+	{&camss_jpeg_jpeg2_clk.c,		MMSS_BASE, 0x0034},
+	{&camss_jpeg_jpeg_ahb_clk.c,		MMSS_BASE, 0x0035},
+	{&camss_jpeg_jpeg_axi_clk.c,		MMSS_BASE, 0x0036},
+	{&camss_jpeg_jpeg_ocmemnoc_clk.c,	MMSS_BASE, 0x0037},
+	{&camss_mclk0_clk.c,			MMSS_BASE, 0x0029},
+	{&camss_mclk1_clk.c,			MMSS_BASE, 0x002a},
+	{&camss_mclk2_clk.c,			MMSS_BASE, 0x002b},
+	{&camss_mclk3_clk.c,			MMSS_BASE, 0x002c},
+	{&camss_micro_ahb_clk.c,		MMSS_BASE, 0x0026},
+	{&camss_phy0_csi0phytimer_clk.c,	MMSS_BASE, 0x002f},
+	{&camss_phy1_csi1phytimer_clk.c,	MMSS_BASE, 0x0030},
+	{&camss_phy2_csi2phytimer_clk.c,	MMSS_BASE, 0x0031},
+	{&camss_top_ahb_clk.c,			MMSS_BASE, 0x0025},
+	{&camss_vfe_cpp_ahb_clk.c,		MMSS_BASE, 0x003b},
+	{&camss_vfe_cpp_clk.c,			MMSS_BASE, 0x003a},
+	{&camss_vfe_vfe0_clk.c,			MMSS_BASE, 0x0038},
+	{&camss_vfe_vfe1_clk.c,			MMSS_BASE, 0x0039},
+	{&camss_vfe_vfe_ahb_clk.c,		MMSS_BASE, 0x003c},
+	{&camss_vfe_vfe_axi_clk.c,		MMSS_BASE, 0x003d},
+	{&camss_vfe_vfe_ocmemnoc_clk.c,		MMSS_BASE, 0x003e},
+	{&mdss_ahb_clk.c,			MMSS_BASE, 0x0022},
+	{&mdss_hdmi_clk.c,			MMSS_BASE, 0x001d},
+	{&mdss_mdp_clk.c,			MMSS_BASE, 0x0014},
+	{&mdss_mdp_lut_clk.c,			MMSS_BASE, 0x0015},
+	{&mdss_axi_clk.c,			MMSS_BASE, 0x0024},
+	{&mdss_vsync_clk.c,			MMSS_BASE, 0x001c},
+	{&mdss_esc0_clk.c,			MMSS_BASE, 0x0020},
+	{&mdss_esc1_clk.c,			MMSS_BASE, 0x0021},
+	{&mdss_edpaux_clk.c,			MMSS_BASE, 0x001b},
+	{&mdss_byte0_clk.c,			MMSS_BASE, 0x001e},
+	{&mdss_byte1_clk.c,			MMSS_BASE, 0x001f},
+	{&mdss_edplink_clk.c,			MMSS_BASE, 0x001a},
+	{&mdss_edppixel_clk.c,			MMSS_BASE, 0x0019},
+	{&mdss_extpclk_clk.c,			MMSS_BASE, 0x0018},
+	{&mdss_hdmi_ahb_clk.c,			MMSS_BASE, 0x0023},
+	{&mdss_pclk0_clk.c,			MMSS_BASE, 0x0016},
+	{&mdss_pclk1_clk.c,			MMSS_BASE, 0x0017},
+	{&audio_core_lpaif_pri_clk_src.c,	LPASS_BASE, 0x0017},
+	{&audio_core_lpaif_sec_clk_src.c,	LPASS_BASE, 0x0016},
+	{&audio_core_lpaif_ter_clk_src.c,	LPASS_BASE, 0x0015},
+	{&audio_core_lpaif_quad_clk_src.c,	LPASS_BASE, 0x0014},
+	{&audio_core_lpaif_pcm0_clk_src.c,	LPASS_BASE, 0x0013},
+	{&audio_core_lpaif_pcm1_clk_src.c,	LPASS_BASE, 0x0012},
+	{&audio_core_slimbus_core_clk.c,	LPASS_BASE, 0x003d},
+	{&audio_core_slimbus_lfabif_clk.c,	LPASS_BASE, 0x003e},
+	{&dummy_clk,				N_BASES,   0x0000},
+};
+
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
+{
+	struct measure_clk *clk = to_measure_clk(c);
+	unsigned long flags;
+	u32 regval, clk_sel, i;
+
+	if (!parent)
+		return -EINVAL;
+
+	for (i = 0; i < (ARRAY_SIZE(measure_mux) - 1); i++)
+		if (measure_mux[i].c == parent)
+			break;
+
+	if (measure_mux[i].c == &dummy_clk)
+		return -EINVAL;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	/*
+	 * Program the test vector, measurement period (sample_ticks)
+	 * and scaling multiplier.
+	 */
+	clk->sample_ticks = 0x10000;
+	clk->multiplier = 1;
+
+	writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
+	writel_relaxed(0, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
+	writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
+
+	switch (measure_mux[i].base) {
+
+	case GCC_BASE:
+		clk_sel = measure_mux[i].debug_mux;
+		break;
+
+	case MMSS_BASE:
+		clk_sel = 0x02C;
+		regval = BVAL(11, 0, measure_mux[i].debug_mux);
+		writel_relaxed(regval, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
+
+		/* Activate debug clock output */
+		regval |= BIT(16);
+		writel_relaxed(regval, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
+		break;
+
+	case LPASS_BASE:
+		clk_sel = 0x169;
+		regval = BVAL(11, 0, measure_mux[i].debug_mux);
+		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
+
+		/* Activate debug clock output */
+		regval |= BIT(16);
+		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* Set debug mux clock index */
+	regval = BVAL(8, 0, clk_sel);
+	writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
+
+	/* Activate debug clock output */
+	regval |= BIT(16);
+	writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
+
+	/* Make sure test vector is set before starting measurements. */
+	mb();
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	return 0;
+}
+
+/* Sample clock for 'ticks' reference clock ticks. */
+static u32 run_measurement(unsigned ticks)
+{
+	/* Stop counters and set the XO4 counter start value. */
+	writel_relaxed(ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL_REG));
+
+	/* Wait for timer to become ready. */
+	while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
+			BIT(25)) != 0)
+		cpu_relax();
+
+	/* Run measurement and wait for completion. */
+	writel_relaxed(BIT(20)|ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL_REG));
+	while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
+			BIT(25)) == 0)
+		cpu_relax();
+
+	/* Return measured ticks. */
+	return readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
+				BM(24, 0);
+}
+
+/*
+ * Perform a hardware rate measurement for a given clock.
+ * FOR DEBUG USE ONLY: Measurements take ~15 ms!
+ */
+static unsigned long measure_clk_get_rate(struct clk *c)
+{
+	unsigned long flags;
+	u32 gcc_xo4_reg_backup;
+	u64 raw_count_short, raw_count_full;
+	struct measure_clk *clk = to_measure_clk(c);
+	unsigned ret;
+
+	ret = clk_prepare_enable(&cxo_clk_src.c);
+	if (ret) {
+		pr_warning("CXO clock failed to enable. Can't measure\n");
+		return 0;
+	}
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+	/* Enable CXO/4 and RINGOSC branch. */
+	gcc_xo4_reg_backup = readl_relaxed(GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
+	writel_relaxed(0x1, GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
+
+	/*
+	 * The ring oscillator counter will not reset if the measured clock
+	 * is not running.  To detect this, run a short measurement before
+	 * the full measurement.  If the raw results of the two are the same
+	 * then the clock must be off.
+	 */
+
+	/* Run a short measurement. (~1 ms) */
+	raw_count_short = run_measurement(0x1000);
+	/* Run a full measurement. (~14 ms) */
+	raw_count_full = run_measurement(clk->sample_ticks);
+
+	writel_relaxed(gcc_xo4_reg_backup, GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
+
+	/* Return 0 if the clock is off. */
+	if (raw_count_full == raw_count_short) {
+		ret = 0;
+	} else {
+		/* Compute rate in Hz. */
+		raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
+		do_div(raw_count_full, ((clk->sample_ticks * 10) + 35));
+		ret = (raw_count_full * clk->multiplier);
+	}
+
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	clk_disable_unprepare(&cxo_clk_src.c);
+
+	return ret;
+}
+#else /* !CONFIG_DEBUG_FS */
+static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	return -EINVAL;
+}
+
+static unsigned long measure_clk_get_rate(struct clk *clk)
+{
+	return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static struct clk_ops measure_clk_ops = {
+	.set_parent = measure_clk_set_parent,
+	.get_rate = measure_clk_get_rate,
+};
+
+static struct measure_clk measure_clk = {
+	.c = {
+		.dbg_name = "measure_clk",
+		.ops = &measure_clk_ops,
+		CLK_INIT(measure_clk.c),
+	},
+	.multiplier = 1,
+};
+
+static struct clk_lookup msm_clocks_copper[] = {
+	CLK_LOOKUP("xo",	cxo_clk_src.c,	"msm_otg"),
+	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-lpass"),
+	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
+
+	CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
+	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "msm_serial_hsl.0"),
+	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "spi_qsd.1"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup2_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, "spi_qsd.1"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup3_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup3_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup4_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup4_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup5_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup5_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup6_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup6_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart1_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart2_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, "msm_serial_hsl.0"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart4_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart5_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
+
+	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9966000.i2c"),
+	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f995e000.serial"),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup1_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup1_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup2_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup2_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup3_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup3_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup4_i2c_apps_clk.c, "f9966000.i2c"),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup4_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup5_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup5_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup6_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup6_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_uart1_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_uart2_apps_clk.c, "f995e000.serial"),
+	CLK_LOOKUP("core_clk", gcc_blsp2_uart3_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_uart4_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_uart5_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_uart6_apps_clk.c, ""),
+
+	CLK_LOOKUP("core_clk", gcc_ce1_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_ce2_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_ce2_ahb_clk.c, ""),
+	CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, ""),
+	CLK_LOOKUP("bus_clk", gcc_ce2_axi_clk.c, ""),
+
+	CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
+
+	CLK_LOOKUP("core_clk", gcc_pdm2_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_pdm_ahb_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, ""),
+
+	CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "msm_sdcc.1"),
+	CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "msm_sdcc.1"),
+	CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "msm_sdcc.2"),
+	CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "msm_sdcc.2"),
+	CLK_LOOKUP("iface_clk", gcc_sdcc3_ahb_clk.c, "msm_sdcc.3"),
+	CLK_LOOKUP("core_clk", gcc_sdcc3_apps_clk.c, "msm_sdcc.3"),
+	CLK_LOOKUP("iface_clk", gcc_sdcc4_ahb_clk.c, "msm_sdcc.4"),
+	CLK_LOOKUP("core_clk", gcc_sdcc4_apps_clk.c, "msm_sdcc.4"),
+
+	CLK_LOOKUP("iface_clk", gcc_tsif_ahb_clk.c, ""),
+	CLK_LOOKUP("ref_clk", gcc_tsif_ref_clk.c, ""),
+
+	CLK_LOOKUP("core_clk", gcc_usb30_master_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_usb30_mock_utmi_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "msm_otg"),
+	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_usb_hsic_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_usb_hsic_io_cal_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, ""),
+
+	/* Multimedia clocks */
+	CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
+	CLK_LOOKUP("bus_clk_src", ahb_clk_src.c, ""),
+	CLK_LOOKUP("bus_clk", mmss_mmssnoc_ahb_clk.c, ""),
+	CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, ""),
+	CLK_LOOKUP("core_clk", mdss_edpaux_clk.c, ""),
+	CLK_LOOKUP("core_clk", mdss_edppixel_clk.c, ""),
+	CLK_LOOKUP("core_clk", mdss_esc0_clk.c, ""),
+	CLK_LOOKUP("core_clk", mdss_esc1_clk.c, ""),
+	CLK_LOOKUP("iface_clk", mdss_hdmi_ahb_clk.c, ""),
+	CLK_LOOKUP("core_clk", mdss_hdmi_clk.c, ""),
+	CLK_LOOKUP("core_clk", mdss_mdp_clk.c, ""),
+	CLK_LOOKUP("core_clk", mdss_mdp_lut_clk.c, ""),
+	CLK_LOOKUP("core_clk", mdp_clk_src.c, ""),
+	CLK_LOOKUP("core_clk", mdss_vsync_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_cci_cci_ahb_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_cci_cci_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_csi0_ahb_clk.c, ""),
+	CLK_LOOKUP("camss_csi0_clk", camss_csi0_clk.c, ""),
+	CLK_LOOKUP("camss_csi0phy_clk", camss_csi0phy_clk.c, ""),
+	CLK_LOOKUP("camss_csi0pix_clk", camss_csi0pix_clk.c, ""),
+	CLK_LOOKUP("camss_csi0rdi_clk", camss_csi0rdi_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_csi1_ahb_clk.c, ""),
+	CLK_LOOKUP("camss_csi1_clk", camss_csi1_clk.c, ""),
+	CLK_LOOKUP("camss_csi1phy_clk", camss_csi1phy_clk.c, ""),
+	CLK_LOOKUP("camss_csi1pix_clk", camss_csi1pix_clk.c, ""),
+	CLK_LOOKUP("camss_csi1rdi_clk", camss_csi1rdi_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_csi2_ahb_clk.c, ""),
+	CLK_LOOKUP("camss_csi2_clk", camss_csi2_clk.c, ""),
+	CLK_LOOKUP("camss_csi2phy_clk", camss_csi2phy_clk.c, ""),
+	CLK_LOOKUP("camss_csi2pix_clk", camss_csi2pix_clk.c, ""),
+	CLK_LOOKUP("camss_csi2rdi_clk", camss_csi2rdi_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_csi3_ahb_clk.c, ""),
+	CLK_LOOKUP("camss_csi3_clk", camss_csi3_clk.c, ""),
+	CLK_LOOKUP("camss_csi3phy_clk", camss_csi3phy_clk.c, ""),
+	CLK_LOOKUP("camss_csi3pix_clk", camss_csi3pix_clk.c, ""),
+	CLK_LOOKUP("camss_csi3rdi_clk", camss_csi3rdi_clk.c, ""),
+	CLK_LOOKUP("camss_csi0_clk_src", csi0_clk_src.c, ""),
+	CLK_LOOKUP("camss_csi1_clk_src", csi1_clk_src.c, ""),
+	CLK_LOOKUP("camss_csi2_clk_src", csi2_clk_src.c, ""),
+	CLK_LOOKUP("camss_csi3_clk_src", csi3_clk_src.c, ""),
+	CLK_LOOKUP("camss_csi_vfe0_clk", camss_csi_vfe0_clk.c, ""),
+	CLK_LOOKUP("camss_csi_vfe1_clk", camss_csi_vfe1_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_gp0_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_gp1_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_ispif_ahb_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_jpeg_jpeg0_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_jpeg_jpeg1_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_jpeg_jpeg2_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_jpeg_jpeg_ahb_clk.c, ""),
+	CLK_LOOKUP("bus_clk", camss_jpeg_jpeg_axi_clk.c, ""),
+	CLK_LOOKUP("bus_clk", camss_jpeg_jpeg_ocmemnoc_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_mclk0_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_mclk1_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_mclk2_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_mclk3_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_phy0_csi0phytimer_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_phy1_csi1phytimer_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_phy2_csi2phytimer_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_top_ahb_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_vfe_cpp_ahb_clk.c, ""),
+	CLK_LOOKUP("core_clk", camss_vfe_cpp_clk.c, ""),
+	CLK_LOOKUP("camss_vfe_vfe0_clk", camss_vfe_vfe0_clk.c, ""),
+	CLK_LOOKUP("camss_vfe_vfe1_clk", camss_vfe_vfe1_clk.c, ""),
+	CLK_LOOKUP("vfe0_clk_src", vfe0_clk_src.c, ""),
+	CLK_LOOKUP("vfe1_clk_src", vfe1_clk_src.c, ""),
+	CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c, ""),
+	CLK_LOOKUP("bus_clk", camss_vfe_vfe_axi_clk.c, ""),
+	CLK_LOOKUP("bus_clk", camss_vfe_vfe_ocmemnoc_clk.c, ""),
+	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, ""),
+	CLK_LOOKUP("bus_clk", mdss_axi_clk.c, ""),
+	CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, ""),
+	CLK_LOOKUP("iface_clk", oxilicx_ahb_clk.c, ""),
+	CLK_LOOKUP("bus_clk", oxilicx_axi_clk.c, ""),
+
+	/* LPASS clocks */
+	CLK_LOOKUP("core_clk", audio_core_slimbus_core_clk.c, "fe12f000.slim"),
+	CLK_LOOKUP("iface_clk", audio_core_slimbus_lfabif_clk.c,
+			"fe12f000.slim"),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_codec_spkr_clk_src.c, ""),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_codec_spkr_osr_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_codec_spkr_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_codec_spkr_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_pri_clk_src.c, ""),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_pri_osr_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pri_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pri_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_sec_clk_src.c, ""),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_sec_osr_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_sec_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_sec_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_ter_clk_src.c, ""),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_ter_osr_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_ter_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_ter_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_quad_clk_src.c, ""),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_quad_osr_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_quad_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_quad_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_clk_src.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
+
+	/* TODO: Remove dummy clocks as soon as they become unnecessary */
+	CLK_DUMMY("phy_clk",       NULL,    "msm_otg", OFF),
+	CLK_DUMMY("core_clk",      NULL,    "msm_otg", OFF),
+	CLK_DUMMY("dfab_clk",  DFAB_CLK,    "msm_sps", OFF),
+	CLK_DUMMY("mem_clk",       NULL,    "msm_sps", OFF),
+	CLK_DUMMY("bus_clk",       NULL,        "scm", OFF),
+};
+
+static struct pll_config_regs gpll0_regs __initdata = {
+	.l_reg = (void __iomem *)GPLL0_L_REG,
+	.m_reg = (void __iomem *)GPLL0_M_REG,
+	.n_reg = (void __iomem *)GPLL0_N_REG,
+	.config_reg = (void __iomem *)GPLL0_USER_CTL_REG,
+	.mode_reg = (void __iomem *)GPLL0_MODE_REG,
+	.base = &virt_bases[GCC_BASE],
+};
+
+/* GPLL0 at 600 MHz, main output enabled. */
+static struct pll_config gpll0_config __initdata = {
+	.l = 0x1f,
+	.m = 0x1,
+	.n = 0x4,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs gpll1_regs __initdata = {
+	.l_reg = (void __iomem *)GPLL1_L_REG,
+	.m_reg = (void __iomem *)GPLL1_M_REG,
+	.n_reg = (void __iomem *)GPLL1_N_REG,
+	.config_reg = (void __iomem *)GPLL1_USER_CTL_REG,
+	.mode_reg = (void __iomem *)GPLL1_MODE_REG,
+	.base = &virt_bases[GCC_BASE],
+};
+
+/* GPLL1 at 480 MHz, main output enabled. */
+static struct pll_config gpll1_config __initdata = {
+	.l = 0x19,
+	.m = 0x0,
+	.n = 0x1,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs mmpll0_regs __initdata = {
+	.l_reg = (void __iomem *)MMPLL0_L_REG,
+	.m_reg = (void __iomem *)MMPLL0_M_REG,
+	.n_reg = (void __iomem *)MMPLL0_N_REG,
+	.config_reg = (void __iomem *)MMPLL0_USER_CTL_REG,
+	.mode_reg = (void __iomem *)MMPLL0_MODE_REG,
+	.base = &virt_bases[MMSS_BASE],
+};
+
+/* MMPLL0 at 800 MHz, main output enabled. */
+static struct pll_config mmpll0_config __initdata = {
+	.l = 0x29,
+	.m = 0x2,
+	.n = 0x3,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs mmpll1_regs __initdata = {
+	.l_reg = (void __iomem *)MMPLL1_L_REG,
+	.m_reg = (void __iomem *)MMPLL1_M_REG,
+	.n_reg = (void __iomem *)MMPLL1_N_REG,
+	.config_reg = (void __iomem *)MMPLL1_USER_CTL_REG,
+	.mode_reg = (void __iomem *)MMPLL1_MODE_REG,
+	.base = &virt_bases[MMSS_BASE],
+};
+
+/* MMPLL1 at 1000 MHz, main output enabled. */
+static struct pll_config mmpll1_config __initdata = {
+	.l = 0x34,
+	.m = 0x1,
+	.n = 0xC,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs mmpll3_regs __initdata = {
+	.l_reg = (void __iomem *)MMPLL3_L_REG,
+	.m_reg = (void __iomem *)MMPLL3_M_REG,
+	.n_reg = (void __iomem *)MMPLL3_N_REG,
+	.config_reg = (void __iomem *)MMPLL3_USER_CTL_REG,
+	.mode_reg = (void __iomem *)MMPLL3_MODE_REG,
+	.base = &virt_bases[MMSS_BASE],
+};
+
+/* MMPLL3 at 820 MHz, main output enabled. */
+static struct pll_config mmpll3_config __initdata = {
+	.l = 0x2A,
+	.m = 0x11,
+	.n = 0x18,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs lpapll0_regs __initdata = {
+	.l_reg = (void __iomem *)LPAPLL_L_REG,
+	.m_reg = (void __iomem *)LPAPLL_M_REG,
+	.n_reg = (void __iomem *)LPAPLL_N_REG,
+	.config_reg = (void __iomem *)LPAPLL_USER_CTL_REG,
+	.mode_reg = (void __iomem *)LPAPLL_MODE_REG,
+	.base = &virt_bases[LPASS_BASE],
+};
+
+/* LPAPLL0 at 491.52 MHz, main output enabled. */
+static struct pll_config lpapll0_config __initdata = {
+	.l = 0x33,
+	.m = 0x1,
+	.n = 0x5,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = BVAL(14, 12, 0x1),
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+#define PLL_AUX_OUTPUT BIT(1)
+
+static void __init reg_init(void)
+{
+	u32 regval;
+
+	if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
+			& gpll0_clk_src.status_mask))
+		configure_pll(&gpll0_config, &gpll0_regs, 1);
+
+	if (!(readl_relaxed(GCC_REG_BASE(GPLL1_STATUS_REG))
+			& gpll1_clk_src.status_mask))
+		configure_pll(&gpll1_config, &gpll1_regs, 1);
+
+	configure_pll(&mmpll0_config, &mmpll0_regs, 1);
+	configure_pll(&mmpll1_config, &mmpll1_regs, 1);
+	configure_pll(&mmpll3_config, &mmpll3_regs, 0);
+	configure_pll(&lpapll0_config, &lpapll0_regs, 1);
+
+	/* Active GPLL0's aux output. This is needed by acpuclock. */
+	regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL_REG));
+	regval |= BIT(PLL_AUX_OUTPUT);
+	writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL_REG));
+
+	/* Vote for GPLL0 to turn on. Needed by acpuclock. */
+	regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
+	regval |= BIT(0);
+	writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
+
+	/*
+	 * TODO: Confirm that no clocks need to be voted on in this sleep vote
+	 * register.
+	 */
+	writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
+}
+
+static void __init msmcopper_clock_post_init(void)
+{
+	clk_set_rate(&ahb_clk_src.c, 80000000);
+	clk_set_rate(&axi_clk_src.c, 333330000);
+
+	/* Set rates for single-rate clocks. */
+	clk_set_rate(&usb30_master_clk_src.c,
+			usb30_master_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&tsif_ref_clk_src.c,
+			tsif_ref_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&usb_hs_system_clk_src.c,
+			usb_hs_system_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&usb_hsic_clk_src.c,
+			usb_hsic_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&usb_hsic_io_cal_clk_src.c,
+			usb_hsic_io_cal_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&usb_hsic_system_clk_src.c,
+			usb_hsic_system_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&usb30_mock_utmi_clk_src.c,
+			usb30_mock_utmi_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&pdm2_clk_src.c, pdm2_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&cci_clk_src.c, cci_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&mclk0_clk_src.c, mclk0_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&mclk1_clk_src.c, mclk1_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&mclk2_clk_src.c, mclk2_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&edpaux_clk_src.c, edpaux_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&esc0_clk_src.c, esc0_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&esc1_clk_src.c, esc1_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&hdmi_clk_src.c, hdmi_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&vsync_clk_src.c, vsync_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&audio_core_slimbus_core_clk_src.c,
+			audio_core_slimbus_core_clk_src.freq_tbl[0].freq_hz);
+}
+
+#define GCC_CC_PHYS	0xFC400000
+#define GCC_CC_SIZE	SZ_16K
+
+#define MMSS_CC_PHYS	0xFD8C0000
+#define MMSS_CC_SIZE	SZ_256K
+
+#define LPASS_CC_PHYS	0xFE000000
+#define LPASS_CC_SIZE	SZ_256K
+
+static void __init msmcopper_clock_pre_init(void)
+{
+	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
+	if (!virt_bases[GCC_BASE])
+		panic("clock-copper: Unable to ioremap GCC memory!");
+
+	virt_bases[MMSS_BASE] = ioremap(MMSS_CC_PHYS, MMSS_CC_SIZE);
+	if (!virt_bases[MMSS_BASE])
+		panic("clock-copper: Unable to ioremap MMSS_CC memory!");
+
+	virt_bases[LPASS_BASE] = ioremap(LPASS_CC_PHYS, LPASS_CC_SIZE);
+	if (!virt_bases[LPASS_BASE])
+		panic("clock-copper: Unable to ioremap LPASS_CC memory!");
+
+	clk_ops_local_pll.enable = copper_pll_clk_enable;
+
+	reg_init();
+}
+
+struct clock_init_data msmcopper_clock_init_data __initdata = {
+	.table = msm_clocks_copper,
+	.size = ARRAY_SIZE(msm_clocks_copper),
+	.pre_init = msmcopper_clock_pre_init,
+	.post_init = msmcopper_clock_post_init,
+};
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 55282b6..e8e88d7 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -316,7 +316,7 @@
 				  void __iomem *cbcr_reg,
 				  enum branch_state br_status)
 {
-	char *status_str = (br_status == BRANCH_ON) ? "on" : "off";
+	char *status_str = (br_status == BRANCH_ON) ? "off" : "on";
 
 	/*
 	 * Use a memory barrier since some halt status registers are
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index 5022811..a4750bc 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -42,6 +42,14 @@
 				((x)->status_reg))
 #define PLL_MODE_REG(x) ((x)->base ? (*(x)->base + (u32)((x)->mode_reg)) : \
 				((x)->mode_reg))
+#define PLL_L_REG(x) ((x)->base ? (*(x)->base + (u32)((x)->l_reg)) : \
+				((x)->l_reg))
+#define PLL_M_REG(x) ((x)->base ? (*(x)->base + (u32)((x)->m_reg)) : \
+				((x)->m_reg))
+#define PLL_N_REG(x) ((x)->base ? (*(x)->base + (u32)((x)->n_reg)) : \
+				((x)->n_reg))
+#define PLL_CONFIG_REG(x) ((x)->base ? (*(x)->base + (u32)((x)->config_reg)) : \
+				((x)->config_reg))
 
 static DEFINE_SPINLOCK(pll_reg_lock);
 
@@ -67,7 +75,7 @@
 
 	/* Wait for pll to enable. */
 	for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) {
-		if (readl_relaxed(pll->status_reg) & pll->status_mask)
+		if (readl_relaxed(PLL_STATUS_REG(pll)) & pll->status_mask)
 			return 0;
 		udelay(1);
 	}
@@ -218,6 +226,57 @@
 	return 0;
 }
 
+#define PLL_LOCKED_BIT BIT(16)
+
+int copper_pll_clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	struct pll_clk *pll = to_pll_clk(clk);
+	u32 count, mode;
+	int ret = 0;
+
+	spin_lock_irqsave(&pll_reg_lock, flags);
+	mode = readl_relaxed(PLL_MODE_REG(pll));
+	/* Disable PLL bypass mode. */
+	mode |= BIT(1);
+	writel_relaxed(mode, PLL_MODE_REG(pll));
+
+	/*
+	 * H/W requires a 5us delay between disabling the bypass and
+	 * de-asserting the reset. Delay 10us just to be safe.
+	 */
+	mb();
+	udelay(10);
+
+	/* De-assert active-low PLL reset. */
+	mode |= BIT(2);
+	writel_relaxed(mode, PLL_MODE_REG(pll));
+
+	/* Wait for pll to enable. */
+	for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) {
+		if (readl_relaxed(PLL_STATUS_REG(pll)) & PLL_LOCKED_BIT)
+			break;
+		udelay(1);
+	}
+
+	if (!(readl_relaxed(PLL_STATUS_REG(pll)) & PLL_LOCKED_BIT)) {
+		WARN("PLL %s didn't lock after enabling it!\n", clk->dbg_name);
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+
+	/* Enable PLL output. */
+	mode |= BIT(0);
+	writel_relaxed(mode, PLL_MODE_REG(pll));
+
+	/* Ensure the write above goes through before returning. */
+	mb();
+
+out:
+	spin_unlock_irqrestore(&pll_reg_lock, flags);
+	return ret;
+}
+
 struct clk_ops clk_ops_local_pll = {
 	.enable = local_pll_clk_enable,
 	.disable = local_pll_clk_disable,
@@ -374,3 +433,65 @@
 	.handoff = pll_clk_handoff,
 	.is_enabled = pll_clk_is_enabled,
 };
+
+static void __init __set_fsm_mode(void __iomem *mode_reg)
+{
+	u32 regval = readl_relaxed(mode_reg);
+
+	/* De-assert reset to FSM */
+	regval &= ~BIT(21);
+	writel_relaxed(regval, mode_reg);
+
+	/* Program bias count */
+	regval &= ~BM(19, 14);
+	regval |= BVAL(19, 14, 0x1);
+	writel_relaxed(regval, mode_reg);
+
+	/* Program lock count */
+	regval &= ~BM(13, 8);
+	regval |= BVAL(13, 8, 0x8);
+	writel_relaxed(regval, mode_reg);
+
+	/* Enable PLL FSM voting */
+	regval |= BIT(20);
+	writel_relaxed(regval, mode_reg);
+}
+
+void __init configure_pll(struct pll_config *config,
+		struct pll_config_regs *regs, u32 ena_fsm_mode)
+{
+	u32 regval;
+
+	writel_relaxed(config->l, PLL_L_REG(regs));
+	writel_relaxed(config->m, PLL_M_REG(regs));
+	writel_relaxed(config->n, PLL_N_REG(regs));
+
+	regval = readl_relaxed(PLL_CONFIG_REG(regs));
+
+	/* Enable the MN accumulator  */
+	if (config->mn_ena_mask) {
+		regval &= ~config->mn_ena_mask;
+		regval |= config->mn_ena_val;
+	}
+
+	/* Enable the main output */
+	if (config->main_output_mask) {
+		regval &= ~config->main_output_mask;
+		regval |= config->main_output_val;
+	}
+
+	/* Set pre-divider and post-divider values */
+	regval &= ~config->pre_div_mask;
+	regval |= config->pre_div_val;
+	regval &= ~config->post_div_mask;
+	regval |= config->post_div_val;
+
+	/* Select VCO setting */
+	regval &= ~config->vco_mask;
+	regval |= config->vco_val;
+	writel_relaxed(regval, PLL_CONFIG_REG(regs));
+
+	/* Configure in FSM mode if necessary */
+	if (ena_fsm_mode)
+		__set_fsm_mode(PLL_MODE_REG(regs));
+}
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
index 26bfc68..231668f 100644
--- a/arch/arm/mach-msm/clock-pll.h
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -89,11 +89,14 @@
 /**
  * struct pll_clk - phase locked loop
  * @mode_reg: enable register
+ * @status_reg: status register, contains the lock detection bit
  * @parent: clock source
  * @c: clk
+ * @base: pointer to base address of ioremapped registers.
  */
 struct pll_clk {
 	void __iomem *const mode_reg;
+	void __iomem *const status_reg;
 
 	struct clk *parent;
 	struct clk c;
@@ -108,6 +111,7 @@
 }
 
 int sr_pll_clk_enable(struct clk *clk);
+int copper_pll_clk_enable(struct clk *clk);
 
 /*
  * PLL vote clock APIs
@@ -117,4 +121,31 @@
 struct clk *pll_vote_clk_get_parent(struct clk *clk);
 int pll_vote_clk_is_enabled(struct clk *clk);
 
+struct pll_config {
+	u32 l;
+	u32 m;
+	u32 n;
+	u32 vco_val;
+	u32 vco_mask;
+	u32 pre_div_val;
+	u32 pre_div_mask;
+	u32 post_div_val;
+	u32 post_div_mask;
+	u32 mn_ena_val;
+	u32 mn_ena_mask;
+	u32 main_output_val;
+	u32 main_output_mask;
+};
+
+struct pll_config_regs {
+	void __iomem *l_reg;
+	void __iomem *m_reg;
+	void __iomem *n_reg;
+	void __iomem *config_reg;
+	void __iomem *mode_reg;
+	void *const __iomem *base;
+};
+
+void __init configure_pll(struct pll_config *, struct pll_config_regs *, u32);
+
 #endif
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 7ea464f..1be05ad 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -172,6 +172,7 @@
 extern struct clock_init_data qds8x50_clock_init_data;
 extern struct clock_init_data msm8625_dummy_clock_init_data;
 extern struct clock_init_data msm8930_clock_init_data;
+extern struct clock_init_data msmcopper_clock_init_data;
 
 void msm_clock_init(struct clock_init_data *data);
 int vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index aaa5bfb..b51fb83 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -31,6 +31,7 @@
 #include <mach/mdm2.h>
 #include <mach/msm_smd.h>
 #include <mach/msm_dcvs.h>
+#include <mach/msm_rtb.h>
 #include <mach/qdss.h>
 #include <linux/ion.h>
 #include "clock.h"
@@ -1065,6 +1066,7 @@
 #endif
 	.disable_dmx = 0,
 	.disable_fullhd = 0,
+	.cont_mode_dpb_count = 18,
 };
 
 struct platform_device apq8064_msm_device_vidc = {
@@ -2406,5 +2408,27 @@
 	.id = -1,
 	.dev = {
 		.platform_data = &apq8064_iommu_domain_pdata,
+	}
+};
+
+struct msm_rtb_platform_data apq8064_rtb_pdata = {
+	.size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+	int s;
+
+	s = memparse(p, NULL);
+	apq8064_rtb_pdata.size = ALIGN(s, SZ_4K);
+	return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+struct platform_device apq8064_rtb_device = {
+	.name           = "msm_rtb",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &apq8064_rtb_pdata,
 	},
 };
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index b7048db..ae97189 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -23,6 +23,7 @@
 #include <mach/board.h>
 #include <mach/socinfo.h>
 #include <mach/iommu_domains.h>
+#include <mach/msm_rtb.h>
 
 #include "devices.h"
 #include "rpm_log.h"
@@ -785,5 +786,28 @@
 	.id = -1,
 	.dev = {
 		.platform_data = &msm8930_iommu_domain_pdata,
+	}
+};
+
+struct msm_rtb_platform_data msm8930_rtb_pdata = {
+	.size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+	int s;
+
+	s = memparse(p, NULL);
+	msm8930_rtb_pdata.size = ALIGN(s, SZ_4K);
+	return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+
+struct platform_device msm8930_rtb_device = {
+	.name           = "msm_rtb",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &msm8930_rtb_pdata,
 	},
 };
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 8df1d7a..7fb4b01 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -32,6 +32,7 @@
 #include <mach/msm_memtypes.h>
 #include <mach/msm_smd.h>
 #include <mach/msm_dcvs.h>
+#include <mach/msm_rtb.h>
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
 #include <mach/msm_tsif.h>
@@ -654,12 +655,14 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	.memtype = ION_CP_MM_HEAP_ID,
 	.enable_ion = 1,
+	.cp_enabled = 1,
 #else
 	.memtype = MEMTYPE_EBI1,
 	.enable_ion = 0,
 #endif
 	.disable_dmx = 0,
 	.disable_fullhd = 0,
+	.cont_mode_dpb_count = 18,
 };
 
 struct platform_device msm_device_vidc = {
@@ -2614,15 +2617,15 @@
 	},
 };
 
-static const char *kgsl_3d0_iommu_ctx_names[] = {
-	"gfx3d_user",
-	/* priv_ctx goes here */
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu_ctxs[] = {
+	{ "gfx3d_user", 0 },
+	{ "gfx3d_priv", 1 },
 };
 
 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),
+		.iommu_ctxs = kgsl_3d0_iommu_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu_ctxs),
 		.physstart = 0x07C00000,
 		.physend = 0x07C00000 + SZ_1M - 1,
 	},
@@ -2694,14 +2697,14 @@
 	},
 };
 
-static const char *kgsl_2d0_iommu_ctx_names[] = {
-	"gfx2d0_2d0",
+static const struct kgsl_iommu_ctx kgsl_2d0_iommu_ctxs[] = {
+	{ "gfx2d0_2d0", 0 },
 };
 
 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),
+		.iommu_ctxs = kgsl_2d0_iommu_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_2d0_iommu_ctxs),
 		.physstart = 0x07D00000,
 		.physend = 0x07D00000 + SZ_1M - 1,
 	},
@@ -2746,14 +2749,14 @@
 	},
 };
 
-static const char *kgsl_2d1_iommu_ctx_names[] = {
-	"gfx2d1_2d1",
+static const struct kgsl_iommu_ctx kgsl_2d1_iommu_ctxs[] = {
+	{ "gfx2d1_2d1", 0 },
 };
 
 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),
+		.iommu_ctxs = kgsl_2d1_iommu_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_2d1_iommu_ctxs),
 		.physstart = 0x07E00000,
 		.physend = 0x07E00000 + SZ_1M - 1,
 	},
@@ -3500,5 +3503,28 @@
 	.id = -1,
 	.dev = {
 		.platform_data = &msm8960_iommu_domain_pdata,
+	}
+};
+
+struct msm_rtb_platform_data msm8960_rtb_pdata = {
+	.size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+	int s;
+
+	s = memparse(p, NULL);
+	msm8960_rtb_pdata.size = ALIGN(s, SZ_4K);
+	return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+
+struct platform_device msm8960_rtb_device = {
+	.name           = "msm_rtb",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &msm8960_rtb_pdata,
 	},
 };
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 34298c5..c084d29 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -19,6 +19,7 @@
 #include <linux/dma-mapping.h>
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
+#include <linux/usb/android.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/flash.h>
 #include <mach/board.h>
@@ -1247,11 +1248,36 @@
 	},
 };
 
+uint32_t __init msm9615_rpm_get_swfi_latency(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
+		if (msm_rpmrs_levels[i].sleep_mode ==
+			MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
+				return msm_rpmrs_levels[i].latency_us;
+	}
+	return 0;
+}
+
+struct android_usb_platform_data msm_android_usb_pdata;
+
+struct platform_device msm_android_usb_device = {
+	.name	= "android_usb",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &msm_android_usb_pdata,
+	},
+};
+
 void __init msm9615_device_init(void)
 {
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
 	BUG_ON(msm_rpm_init(&msm9615_rpm_data));
 	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
+	msm_android_usb_pdata.swfi_latency =
+		msm_rpmrs_levels[0].latency_us;
+
 }
 
 #define MSM_SHARED_RAM_PHYS 0x40000000
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index bd0376e..a9d68a6 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -17,6 +17,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/notifier.h>
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
 #include <mach/board.h>
@@ -26,6 +27,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/mmc.h>
+#include <asm/cacheflush.h>
 #include <mach/rpc_hsusb.h>
 #include <mach/socinfo.h>
 
@@ -1704,3 +1706,23 @@
 	return 0;
 }
 postcore_initcall(msm7627a_init_gpio);
+
+static int msm7627a_panic_handler(struct notifier_block *this,
+		unsigned long event, void *ptr)
+{
+	flush_cache_all();
+	outer_flush_all();
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_handler = {
+	.notifier_call = msm7627a_panic_handler,
+};
+
+static int __init panic_register(void)
+{
+	atomic_notifier_chain_register(&panic_notifier_list,
+			&panic_handler);
+	return 0;
+}
+module_init(panic_register);
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 5f08d77..234af04 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -955,7 +955,8 @@
 struct msm_vidc_platform_data vidc_platform_data = {
 	.memtype = MEMTYPE_EBI0,
 	.enable_ion = 0,
-	.disable_dmx = 0
+	.disable_dmx = 0,
+	.cont_mode_dpb_count = 8
 };
 
 struct platform_device msm_device_vidc_720p = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 614f6ff..e19beb8 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -2260,12 +2260,14 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	.memtype = ION_CP_MM_HEAP_ID,
 	.enable_ion = 1,
+	.cp_enabled = 0,
 #else
 	.memtype = MEMTYPE_SMI_KERNEL,
 	.enable_ion = 0,
 #endif
 	.disable_dmx = 0,
-	.disable_fullhd = 0
+	.disable_fullhd = 0,
+	.cont_mode_dpb_count = 8
 };
 
 struct platform_device msm_device_vidc = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 5718fe0..f7f0611 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -109,6 +109,7 @@
 extern struct platform_device msm_device_hsic_host;
 
 extern struct platform_device msm_device_otg;
+extern struct platform_device msm_android_usb_device;
 extern struct platform_device msm_device_hsic_peripheral;
 extern struct platform_device msm8960_device_otg;
 extern struct platform_device msm8960_device_gadget_peripheral;
@@ -378,3 +379,7 @@
 extern struct platform_device msm8960_iommu_domain_device;
 extern struct platform_device msm8930_iommu_domain_device;
 extern struct platform_device apq8064_iommu_domain_device;
+
+extern struct platform_device msm8960_rtb_device;
+extern struct platform_device msm8930_rtb_device;
+extern struct platform_device apq8064_rtb_device;
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index 087227c..4f34443 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -400,7 +400,7 @@
 {
 	errdata->flush[0] = readl_relaxed(DMOV_REG(DMOV_FLUSH0(ch), adm));
 	errdata->flush[1] = readl_relaxed(DMOV_REG(DMOV_FLUSH1(ch), adm));
-	errdata->flush[2] = readl_relaxed(DMOV_REG(DMOV_FLUSH2(ch), adm));
+	errdata->flush[2] = 0;
 	errdata->flush[3] = readl_relaxed(DMOV_REG(DMOV_FLUSH3(ch), adm));
 	errdata->flush[4] = readl_relaxed(DMOV_REG(DMOV_FLUSH4(ch), adm));
 	errdata->flush[5] = readl_relaxed(DMOV_REG(DMOV_FLUSH5(ch), adm));
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index c46c493..d6476f7 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -505,9 +505,11 @@
 	u32 enable_ion;
 	int disable_dmx;
 	int disable_fullhd;
+	u32 cp_enabled;
 #ifdef CONFIG_MSM_BUS_SCALING
 	struct msm_bus_scale_pdata *vidc_bus_client_pdata;
 #endif
+	int cont_mode_dpb_count;
 };
 
 struct vcap_platform_data {
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 994150f..a6f27d7 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.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
@@ -73,7 +73,6 @@
  */
 struct msm_iommu_drvdata {
 	void __iomem *base;
-	int irq;
 	int ncb;
 	int ttbr_split;
 	struct clk *clk;
@@ -95,6 +94,8 @@
 	int num;
 	struct platform_device *pdev;
 	struct list_head attached_elm;
+	struct iommu_domain *attached_domain;
+	const char *name;
 };
 
 /*
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index aee562e..ae0ea0c 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -38,10 +38,13 @@
 	of_machine_is_compatible("qcom,msmcopper")
 #define machine_is_copper_sim()		\
 	of_machine_is_compatible("qcom,msmcopper-sim")
+#define machine_is_copper_rumi()	\
+	of_machine_is_compatible("qcom,msmcopper-rumi")
 #else
 #define early_machine_is_copper()	0
 #define machine_is_copper()		0
 #define machine_is_copper_sim()	0
+#define machine_is_copper_rumi()	0
 #endif
 
 #define PLATFORM_SUBTYPE_SGLTE	6
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index 19e1684..0652f3b 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -374,6 +374,7 @@
 	__disable_clocks(iommu_drvdata);
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 
+	ctx_drvdata->attached_domain = domain;
 fail:
 	mutex_unlock(&msm_iommu_lock);
 	return ret;
@@ -411,7 +412,7 @@
 	__reset_context(iommu_drvdata->base, ctx_dev->num);
 	__disable_clocks(iommu_drvdata);
 	list_del_init(&ctx_drvdata->attached_elm);
-
+	ctx_drvdata->attached_domain = NULL;
 fail:
 	mutex_unlock(&msm_iommu_lock);
 }
@@ -974,41 +975,55 @@
 
 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 {
-	struct msm_iommu_drvdata *drvdata = dev_id;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata = dev_id;
+	struct msm_iommu_drvdata *drvdata;
 	void __iomem *base;
-	unsigned int fsr;
-	int i, ret;
+	unsigned int fsr, num;
+	int ret;
 
 	mutex_lock(&msm_iommu_lock);
+	BUG_ON(!ctx_drvdata);
 
-	if (!drvdata) {
-		pr_err("Invalid device ID in context interrupt handler\n");
-		goto fail;
-	}
+	drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+	BUG_ON(!drvdata);
 
 	base = drvdata->base;
-
-	pr_err("Unexpected IOMMU page fault!\n");
-	pr_err("base = %08x\n", (unsigned int) base);
-	pr_err("name = %s\n", drvdata->name);
+	num = ctx_drvdata->num;
 
 	ret = __enable_clocks(drvdata);
 	if (ret)
 		goto fail;
 
-	for (i = 0; i < drvdata->ncb; i++) {
-		fsr = GET_FSR(base, i);
-		if (fsr) {
-			pr_err("Fault occurred in context %d.\n", i);
+	fsr = GET_FSR(base, num);
+
+	if (fsr) {
+		if (!ctx_drvdata->attached_domain) {
+			pr_err("Bad domain in interrupt handler\n");
+			ret = -ENOSYS;
+		} else
+			ret = report_iommu_fault(ctx_drvdata->attached_domain,
+						&ctx_drvdata->pdev->dev,
+						GET_FAR(base, num), 0);
+
+		if (ret == -ENOSYS) {
+			pr_err("Unexpected IOMMU page fault!\n");
+			pr_err("name    = %s\n", drvdata->name);
+			pr_err("context = %s (%d)\n", ctx_drvdata->name, num);
 			pr_err("Interesting registers:\n");
-			print_ctx_regs(base, i);
-			SET_FSR(base, i, 0x4000000F);
+			print_ctx_regs(base, num);
 		}
-	}
+
+		SET_FSR(base, num, fsr);
+		SET_RESUME(base, num, 1);
+
+		ret = IRQ_HANDLED;
+	} else
+		ret = IRQ_NONE;
+
 	__disable_clocks(drvdata);
 fail:
 	mutex_unlock(&msm_iommu_lock);
-	return 0;
+	return ret;
 }
 
 static phys_addr_t msm_iommu_get_pt_base_addr(struct iommu_domain *domain)
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index 6633cae..b8b5aa3 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -131,7 +131,7 @@
 	struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
 	void __iomem *regs_base;
 	resource_size_t	len;
-	int ret, irq, par;
+	int ret, par;
 
 	if (pdev->id == -1) {
 		msm_iommu_root_dev = pdev;
@@ -202,12 +202,6 @@
 		goto fail_mem;
 	}
 
-	irq = platform_get_irq_byname(pdev, "nonsecure_irq");
-	if (irq < 0) {
-		ret = -ENODEV;
-		goto fail_io;
-	}
-
 	msm_iommu_reset(regs_base, iommu_dev->ncb);
 
 	SET_M(regs_base, 0, 1);
@@ -226,24 +220,15 @@
 		goto fail_io;
 	}
 
-	ret = request_threaded_irq(irq, NULL, msm_iommu_fault_handler,
-			IRQF_ONESHOT, "msm_iommu_secure_irpt_handler", drvdata);
-	if (ret) {
-		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-		goto fail_io;
-	}
-
-
 	drvdata->pclk = iommu_pclk;
 	drvdata->clk = iommu_clk;
 	drvdata->base = regs_base;
-	drvdata->irq = irq;
 	drvdata->ncb = iommu_dev->ncb;
 	drvdata->ttbr_split = iommu_dev->ttbr_split;
 	drvdata->name = iommu_dev->name;
 
-	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
-		iommu_dev->name, regs_base, irq, iommu_dev->ncb);
+	pr_info("device %s mapped at %p, with %d ctx banks\n",
+		iommu_dev->name, regs_base, iommu_dev->ncb);
 
 	platform_set_drvdata(pdev, drvdata);
 
@@ -292,7 +277,7 @@
 	struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
-	int i, ret;
+	int i, ret, irq;
 	if (!c || !pdev->dev.parent) {
 		ret = -EINVAL;
 		goto fail;
@@ -312,6 +297,23 @@
 	}
 	ctx_drvdata->num = c->num;
 	ctx_drvdata->pdev = pdev;
+	ctx_drvdata->name = c->name;
+
+	irq = platform_get_irq_byname(to_platform_device(pdev->dev.parent),
+				      "nonsecure_irq");
+	if (irq < 0) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = request_threaded_irq(irq, NULL, msm_iommu_fault_handler,
+				   IRQF_ONESHOT | IRQF_SHARED,
+				   "msm_iommu_nonsecure_irq", ctx_drvdata);
+
+	if (ret) {
+		pr_err("request_threaded_irq %d failed: %d\n", irq, ret);
+		goto fail;
+	}
 
 	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
 	platform_set_drvdata(pdev, ctx_drvdata);
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
new file mode 100644
index 0000000..58d5176
--- /dev/null
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -0,0 +1,349 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/elf.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include "peripheral-loader.h"
+#include "scm-pas.h"
+
+#define PRONTO_PMU_COMMON_GDSCR				0x24
+#define PRONTO_PMU_COMMON_GDSCR_SW_COLLAPSE		BIT(0)
+#define CLK_DIS_WAIT					12
+#define EN_FEW_WAIT					16
+#define EN_REST_WAIT					20
+
+#define PRONTO_PMU_COMMON_CPU_CBCR			0x30
+#define PRONTO_PMU_COMMON_CPU_CBCR_CLK_EN		BIT(0)
+#define PRONTO_PMU_COMMON_CPU_CLK_OFF			BIT(31)
+
+#define PRONTO_PMU_COMMON_AHB_CBCR			0x34
+#define PRONTO_PMU_COMMON_AHB_CBCR_CLK_EN		BIT(0)
+#define PRONTO_PMU_COMMON_AHB_CLK_OFF			BIT(31)
+
+#define PRONTO_PMU_COMMON_CSR				0x1040
+#define PRONTO_PMU_COMMON_CSR_A2XB_CFG_EN		BIT(0)
+
+#define PRONTO_PMU_SOFT_RESET				0x104C
+#define PRONTO_PMU_SOFT_RESET_CRCM_CCPU_SOFT_RESET	BIT(10)
+
+#define PRONTO_PMU_CCPU_CTL				0x2000
+#define PRONTO_PMU_CCPU_CTL_REMAP_EN			BIT(2)
+#define PRONTO_PMU_CCPU_CTL_HIGH_IVT			BIT(0)
+
+#define PRONTO_PMU_CCPU_BOOT_REMAP_ADDR			0x2004
+
+#define CLK_CTL_WCNSS_RESTART_BIT			BIT(0)
+
+#define AXI_HALTREQ					0x0
+#define AXI_HALTACK					0x4
+#define AXI_IDLE					0x8
+
+#define HALT_ACK_TIMEOUT_US				500000
+#define CLK_UPDATE_TIMEOUT_US				500000
+
+struct pronto_data {
+	void __iomem *base;
+	void __iomem *reset_base;
+	void __iomem *axi_halt_base;
+	unsigned long start_addr;
+	struct pil_device *pil;
+	struct clk *cxo;
+	struct regulator *vreg;
+};
+
+static int pil_pronto_make_proxy_vote(struct pil_desc *pil)
+{
+	struct pronto_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+
+	ret = regulator_enable(drv->vreg);
+	if (ret) {
+		dev_err(pil->dev, "failed to enable pll supply\n");
+		goto err;
+	}
+	ret = clk_prepare_enable(drv->cxo);
+	if (ret) {
+		dev_err(pil->dev, "failed to enable cxo\n");
+		goto err_clk;
+	}
+	return 0;
+err_clk:
+	regulator_disable(drv->vreg);
+err:
+	return ret;
+}
+
+static void pil_pronto_remove_proxy_vote(struct pil_desc *pil)
+{
+	struct pronto_data *drv = dev_get_drvdata(pil->dev);
+	regulator_disable(drv->vreg);
+	clk_disable_unprepare(drv->cxo);
+}
+
+static int pil_pronto_init_image(struct pil_desc *pil, const u8 *metadata,
+		size_t size)
+{
+	const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
+	struct pronto_data *drv = dev_get_drvdata(pil->dev);
+	drv->start_addr = ehdr->e_entry;
+	return 0;
+}
+
+static int pil_pronto_reset(struct pil_desc *pil)
+{
+	u32 reg;
+	int rc;
+	struct pronto_data *drv = dev_get_drvdata(pil->dev);
+	void __iomem *base = drv->base;
+	unsigned long start_addr = drv->start_addr;
+
+	/* Deassert reset to Pronto */
+	reg = readl_relaxed(drv->reset_base);
+	reg &= ~CLK_CTL_WCNSS_RESTART_BIT;
+	writel_relaxed(reg, drv->reset_base);
+	mb();
+
+	/* Configure boot address */
+	writel_relaxed(start_addr >> 16, base +
+			PRONTO_PMU_CCPU_BOOT_REMAP_ADDR);
+
+	/* Use the high vector table */
+	reg = readl_relaxed(base + PRONTO_PMU_CCPU_CTL);
+	reg |= PRONTO_PMU_CCPU_CTL_REMAP_EN | PRONTO_PMU_CCPU_CTL_HIGH_IVT;
+	writel_relaxed(reg, base + PRONTO_PMU_CCPU_CTL);
+
+	/* Turn on AHB clock of common_ss */
+	reg = readl_relaxed(base + PRONTO_PMU_COMMON_AHB_CBCR);
+	reg |= PRONTO_PMU_COMMON_AHB_CBCR_CLK_EN;
+	writel_relaxed(reg, base + PRONTO_PMU_COMMON_AHB_CBCR);
+
+	/* Turn on CPU clock of common_ss */
+	reg = readl_relaxed(base + PRONTO_PMU_COMMON_CPU_CBCR);
+	reg |= PRONTO_PMU_COMMON_CPU_CBCR_CLK_EN;
+	writel_relaxed(reg, base + PRONTO_PMU_COMMON_CPU_CBCR);
+
+	/* Enable A2XB bridge */
+	reg = readl_relaxed(base + PRONTO_PMU_COMMON_CSR);
+	reg |= PRONTO_PMU_COMMON_CSR_A2XB_CFG_EN;
+	writel_relaxed(reg, base + PRONTO_PMU_COMMON_CSR);
+
+	/* Enable common_ss power */
+	reg = readl_relaxed(base + PRONTO_PMU_COMMON_GDSCR);
+	reg &= ~PRONTO_PMU_COMMON_GDSCR_SW_COLLAPSE;
+	writel_relaxed(reg, base + PRONTO_PMU_COMMON_GDSCR);
+
+	/* Wait for AHB clock to be on */
+	rc = readl_tight_poll_timeout(base + PRONTO_PMU_COMMON_AHB_CBCR,
+				      reg,
+				      !(reg & PRONTO_PMU_COMMON_AHB_CLK_OFF),
+				      CLK_UPDATE_TIMEOUT_US);
+	if (rc) {
+		dev_err(pil->dev, "pronto common ahb clk enable timeout\n");
+		return rc;
+	}
+
+	/* Wait for CPU clock to be on */
+	rc = readl_tight_poll_timeout(base + PRONTO_PMU_COMMON_CPU_CBCR,
+				      reg,
+				      !(reg & PRONTO_PMU_COMMON_CPU_CLK_OFF),
+				      CLK_UPDATE_TIMEOUT_US);
+	if (rc) {
+		dev_err(pil->dev, "pronto common cpu clk enable timeout\n");
+		return rc;
+	}
+
+	/* Deassert ARM9 software reset */
+	reg = readl_relaxed(base + PRONTO_PMU_SOFT_RESET);
+	reg &= ~PRONTO_PMU_SOFT_RESET_CRCM_CCPU_SOFT_RESET;
+	writel_relaxed(reg, base + PRONTO_PMU_SOFT_RESET);
+
+	return 0;
+}
+
+static int pil_pronto_shutdown(struct pil_desc *pil)
+{
+	struct pronto_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+	u32 reg, status;
+
+	/* Halt A2XB */
+	writel_relaxed(1, drv->axi_halt_base + AXI_HALTREQ);
+	ret = readl_poll_timeout(drv->axi_halt_base + AXI_HALTACK,
+				status, status, 50, HALT_ACK_TIMEOUT_US);
+	if (ret)
+		dev_err(pil->dev, "Port halt timeout\n");
+	else if (!readl_relaxed(drv->axi_halt_base + AXI_IDLE))
+		dev_err(pil->dev, "Port halt failed\n");
+
+	writel_relaxed(0, drv->axi_halt_base + AXI_HALTREQ);
+
+	/* Assert reset to Pronto */
+	reg = readl_relaxed(drv->reset_base);
+	reg |= CLK_CTL_WCNSS_RESTART_BIT;
+	writel_relaxed(reg, drv->reset_base);
+
+	/* Wait for reset to complete */
+	mb();
+	usleep_range(1000, 2000);
+
+	/* Deassert reset to Pronto */
+	reg = readl_relaxed(drv->reset_base);
+	reg &= ~CLK_CTL_WCNSS_RESTART_BIT;
+	writel_relaxed(reg, drv->reset_base);
+	mb();
+
+	return 0;
+}
+
+static struct pil_reset_ops pil_pronto_ops = {
+	.init_image = pil_pronto_init_image,
+	.auth_and_reset = pil_pronto_reset,
+	.shutdown = pil_pronto_shutdown,
+	.proxy_vote = pil_pronto_make_proxy_vote,
+	.proxy_unvote = pil_pronto_remove_proxy_vote,
+};
+
+static int __devinit pil_pronto_probe(struct platform_device *pdev)
+{
+	struct pronto_data *drv;
+	struct resource *res;
+	struct pil_desc *desc;
+	int ret;
+	uint32_t regval;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, drv);
+
+	drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!drv->base)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+
+	drv->reset_base = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!res)
+		return -EINVAL;
+
+	drv->axi_halt_base = devm_ioremap(&pdev->dev, res->start,
+					  resource_size(res));
+
+	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
+				      &desc->name);
+	if (ret)
+		return ret;
+
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	desc->proxy_timeout = 10000;
+
+	/* TODO: need to add secure boot when the support is available */
+	desc->ops = &pil_pronto_ops;
+	dev_info(&pdev->dev, "using non-secure boot\n");
+
+	drv->vreg = devm_regulator_get(&pdev->dev, "vdd_pronto_pll");
+	if (IS_ERR(drv->vreg)) {
+		dev_err(&pdev->dev, "failed to get pronto pll supply");
+		return PTR_ERR(drv->vreg);
+	}
+
+	ret = regulator_set_voltage(drv->vreg, 1800000, 1800000);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to set pll supply voltage\n");
+		return ret;
+	}
+
+	ret = regulator_set_optimum_mode(drv->vreg, 18000);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to set pll supply mode\n");
+		return ret;
+	}
+
+	drv->cxo = devm_clk_get(&pdev->dev, "xo");
+	if (IS_ERR(drv->cxo))
+		return PTR_ERR(drv->cxo);
+
+	drv->pil = msm_pil_register(desc);
+	if (IS_ERR(drv->pil))
+		return PTR_ERR(drv->pil);
+
+	/* Initialize common_ss GDSCR to wait 4 cycles between states */
+	regval = readl_relaxed(drv->base + PRONTO_PMU_COMMON_GDSCR)
+		& PRONTO_PMU_COMMON_GDSCR_SW_COLLAPSE;
+	regval |= (2 << EN_REST_WAIT) | (2 << EN_FEW_WAIT)
+		  | (2 << CLK_DIS_WAIT);
+	writel_relaxed(regval, drv->base + PRONTO_PMU_COMMON_GDSCR);
+
+	return 0;
+}
+
+static int __devexit pil_pronto_remove(struct platform_device *pdev)
+{
+	struct pronto_data *drv = platform_get_drvdata(pdev);
+	msm_pil_unregister(drv->pil);
+	return 0;
+}
+
+static struct of_device_id msm_pil_pronto_match[] = {
+	{.compatible = "qcom,pil-pronto"},
+	{}
+};
+
+static struct platform_driver pil_pronto_driver = {
+	.probe = pil_pronto_probe,
+	.remove = __devexit_p(pil_pronto_remove),
+	.driver = {
+		.name = "pil_pronto",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_pil_pronto_match,
+	},
+};
+
+static int __init pil_pronto_init(void)
+{
+	return platform_driver_register(&pil_pronto_driver);
+}
+module_init(pil_pronto_init);
+
+static void __exit pil_pronto_exit(void)
+{
+	platform_driver_unregister(&pil_pronto_driver);
+}
+module_exit(pil_pronto_exit);
+
+MODULE_DESCRIPTION("Support for booting PRONTO (WCNSS) processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index 8760e443..dab53dc 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -73,7 +73,7 @@
 
 /* Size must be power of 2 */
 #define MAX_BUF 2
-#define BUFSZ (1024000)
+#define BUFSZ (524288)
 
 #define AUDDEC_DEC_PCM 0
 
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
index 1182a4d..25e10a6 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
@@ -21,7 +21,7 @@
 #include "q6usm.h"
 
 /* The driver version*/
-#define DRV_VERSION "1.1"
+#define DRV_VERSION "1.2"
 
 #define SESSION_MAX 0x02 /* aDSP:USM limit */
 
@@ -38,7 +38,7 @@
 #define WRITEDONE_IDX_STATUS    0
 
 /* Standard timeout in the asynchronous ops */
-#define Q6USM_TIMEOUT_JIFFIES	(3*HZ) /* 3 sec */
+#define Q6USM_TIMEOUT_JIFFIES	(1*HZ) /* 1 sec */
 
 static DEFINE_MUTEX(session_lock);
 
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
index b4a0a7f..614339b 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -27,10 +27,10 @@
 #include "usfcdev.h"
 
 /* The driver version*/
-#define DRV_VERSION "1.3"
+#define DRV_VERSION "1.3.1"
 
 /* Standard timeout in the asynchronous ops */
-#define USF_TIMEOUT_JIFFIES (3*HZ) /* 3 sec */
+#define USF_TIMEOUT_JIFFIES (1*HZ) /* 1 sec */
 
 /* Undefined USF device */
 #define USF_UNDEF_DEV_ID 0xffff
@@ -735,24 +735,27 @@
 
 	/* Get US detection result */
 	if (detect_info.detect_timeout == USF_INFINITIVE_TIMEOUT) {
-		wait_event(usf_xx->wait,
-				(usf_xx->us_detect_type !=
-				 USF_US_DETECT_UNDEF));
+		rc = wait_event_interruptible(usf_xx->wait,
+						(usf_xx->us_detect_type !=
+						USF_US_DETECT_UNDEF));
 	} else {
 		if (detect_info.detect_timeout == USF_DEFAULT_TIMEOUT)
 			timeout = USF_TIMEOUT_JIFFIES;
 		else
 			timeout = detect_info.detect_timeout * HZ;
-
-		rc = wait_event_timeout(usf_xx->wait,
+	}
+	rc = wait_event_interruptible_timeout(usf_xx->wait,
 					(usf_xx->us_detect_type !=
 					 USF_US_DETECT_UNDEF),
 					timeout);
-		/* In the case of timeout, "no US" is assumed */
+	/* In the case of timeout, "no US" is assumed */
+	if (rc < 0) {
+		pr_err("%s: Getting US detection failed rc[%d]\n",
+		       __func__, rc);
+		return rc;
 	}
 
 	usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type;
-
 	detect_info.is_us = (usf_xx->us_detect_type == USF_US_DETECT_YES);
 	rc = copy_to_user((void __user *)arg,
 			  &detect_info,
@@ -913,7 +916,7 @@
 
 	/* Get data ready regions */
 	if (upd_tx_info.timeout == USF_INFINITIVE_TIMEOUT) {
-		wait_event(usf_xx->wait,
+		rc = wait_event_interruptible(usf_xx->wait,
 			   (usf_xx->prev_region !=
 			    usf_xx->new_region) ||
 			   (usf_xx->usf_state !=
@@ -922,18 +925,26 @@
 		if (upd_tx_info.timeout == USF_NO_WAIT_TIMEOUT)
 			rc = (usf_xx->prev_region != usf_xx->new_region);
 		else {
-			if (upd_tx_info.timeout == USF_DEFAULT_TIMEOUT)
-				timeout = USF_TIMEOUT_JIFFIES;
-			else
-				timeout = upd_tx_info.timeout * HZ;
-
 			prev_jiffies = jiffies;
-			rc = wait_event_timeout(usf_xx->wait,
+			if (upd_tx_info.timeout == USF_DEFAULT_TIMEOUT) {
+				timeout = USF_TIMEOUT_JIFFIES;
+				rc = wait_event_timeout(
+						usf_xx->wait,
 						(usf_xx->prev_region !=
 						 usf_xx->new_region) ||
 						(usf_xx->usf_state !=
 						 USF_WORK_STATE),
 						timeout);
+			} else {
+				timeout = upd_tx_info.timeout * HZ;
+				rc = wait_event_interruptible_timeout(
+						usf_xx->wait,
+						(usf_xx->prev_region !=
+						 usf_xx->new_region) ||
+						(usf_xx->usf_state !=
+						 USF_WORK_STATE),
+						timeout);
+			}
 		}
 		if (!rc) {
 			pr_debug("%s: timeout. prev_j=%lu; j=%lu\n",
@@ -952,9 +963,11 @@
 		}
 	}
 
-	if (usf_xx->usf_state != USF_WORK_STATE) {
-		pr_err("%s: TX device is in not work state[%d]\n",
-		       __func__, usf_xx->usf_state);
+	if ((usf_xx->usf_state != USF_WORK_STATE) ||
+	    (rc == -ERESTARTSYS)) {
+		pr_err("%s: Getting ready region failed "
+			"work state[%d]; rc[%d]\n",
+		       __func__, usf_xx->usf_state, rc);
 		return -EINTR;
 	}
 
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 2a6294f..051d4de 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -21,6 +21,14 @@
 
 #include "spm_driver.h"
 
+#define MSM_SPM_PMIC_STATE_IDLE  0
+
+#define SAW2_V1_VER_REG 0x04
+#define SAW2_V2_VER_REG 0xfd0
+
+#define SAW2_MAJOR_2 2
+
+
 enum {
 	MSM_SPM_DEBUG_SHADOW = 1U << 0,
 	MSM_SPM_DEBUG_VCTL = 1U << 1,
@@ -31,35 +39,95 @@
 	debug_mask, msm_spm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP
 );
 
-#define MSM_SPM_PMIC_STATE_IDLE  0
 
+static uint32_t msm_spm_reg_offsets_v1[MSM_SPM_REG_NR] = {
+	[MSM_SPM_REG_SAW2_SECURE]		= 0x00,
+	[MSM_SPM_REG_SAW2_ID]			= 0x04,
+	[MSM_SPM_REG_SAW2_CFG]			= 0x08,
+	[MSM_SPM_REG_SAW2_STS0]			= 0x0C,
+	[MSM_SPM_REG_SAW2_STS1]			= 0x10,
+	[MSM_SPM_REG_SAW2_VCTL]			= 0x14,
+	[MSM_SPM_REG_SAW2_AVS_CTL]		= 0x18,
+	[MSM_SPM_REG_SAW2_AVS_HYSTERESIS]	= 0x1C,
+	[MSM_SPM_REG_SAW2_SPM_CTL]		= 0x20,
+	[MSM_SPM_REG_SAW2_PMIC_DLY]		= 0x24,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_0]		= 0x28,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_1]		= 0x2C,
+	[MSM_SPM_REG_SAW2_RST]			= 0x30,
+	[MSM_SPM_REG_SAW2_SEQ_ENTRY]		= 0x80,
+};
 
-static uint32_t msm_spm_reg_offsets[MSM_SPM_REG_NR] = {
-	[MSM_SPM_REG_SAW2_SECURE] = 0x00,
-
-	[MSM_SPM_REG_SAW2_ID] = 0x04,
-	[MSM_SPM_REG_SAW2_CFG] = 0x08,
-	[MSM_SPM_REG_SAW2_STS0] = 0x0C,
-	[MSM_SPM_REG_SAW2_STS1] = 0x10,
-
-	[MSM_SPM_REG_SAW2_VCTL] = 0x14,
-
-	[MSM_SPM_REG_SAW2_AVS_CTL] = 0x18,
-	[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x1C,
-
-	[MSM_SPM_REG_SAW2_SPM_CTL] = 0x20,
-	[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x24,
-	[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x28,
-	[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x2C,
-	[MSM_SPM_REG_SAW2_RST] = 0x30,
-
-	[MSM_SPM_REG_SAW2_SEQ_ENTRY] = 0x80,
+static uint32_t msm_spm_reg_offsets_v2[MSM_SPM_REG_NR] = {
+	[MSM_SPM_REG_SAW2_SECURE]		= 0x00,
+	[MSM_SPM_REG_SAW2_ID]			= 0x04,
+	[MSM_SPM_REG_SAW2_CFG]			= 0x08,
+	[MSM_SPM_REG_SAW2_SPM_STS]		= 0x0C,
+	[MSM_SPM_REG_SAW2_AVS_STS]		= 0x10,
+	[MSM_SPM_REG_SAW2_PMIC_STS]		= 0x14,
+	[MSM_SPM_REG_SAW2_RST]			= 0x18,
+	[MSM_SPM_REG_SAW2_VCTL]			= 0x1C,
+	[MSM_SPM_REG_SAW2_AVS_CTL]		= 0x20,
+	[MSM_SPM_REG_SAW2_AVS_LIMIT]		= 0x24,
+	[MSM_SPM_REG_SAW2_AVS_DLY]		= 0x28,
+	[MSM_SPM_REG_SAW2_AVS_HYSTERESIS]	= 0x2C,
+	[MSM_SPM_REG_SAW2_SPM_CTL]		= 0x30,
+	[MSM_SPM_REG_SAW2_SPM_DLY]		= 0x34,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_0]		= 0x40,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_1]		= 0x44,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_2]		= 0x48,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_3]		= 0x4C,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_4]		= 0x50,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_5]		= 0x54,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_6]		= 0x58,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_7]		= 0x5C,
+	[MSM_SPM_REG_SAW2_SEQ_ENTRY]		= 0x80,
+	[MSM_SPM_REG_SAW2_VERSION]		= 0xFD0,
 };
 
 /******************************************************************************
  * Internal helper functions
  *****************************************************************************/
 
+static inline uint32_t msm_spm_drv_get_num_spm_entry(
+		struct msm_spm_driver_data *dev)
+{
+	return 32;
+}
+
+static void msm_spm_drv_flush_shadow(struct msm_spm_driver_data *dev,
+		unsigned int reg_index)
+{
+	__raw_writel(dev->reg_shadow[reg_index],
+		dev->reg_base_addr + dev->reg_offsets[reg_index]);
+}
+
+static void msm_spm_drv_load_shadow(struct msm_spm_driver_data *dev,
+		unsigned int reg_index)
+{
+	dev->reg_shadow[reg_index] =
+		__raw_readl(dev->reg_base_addr +
+				dev->reg_offsets[reg_index]);
+}
+
+static inline void msm_spm_drv_set_start_addr(
+		struct msm_spm_driver_data *dev, uint32_t addr)
+{
+	addr &= 0x7F;
+	addr <<= 4;
+	dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFFF80F;
+	dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= addr;
+}
+
+static inline bool msm_spm_pmic_arb_present(struct msm_spm_driver_data *dev)
+{
+	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_ID);
+
+	if (dev->major == SAW2_MAJOR_2)
+		return (dev->reg_shadow[MSM_SPM_REG_SAW2_ID] >> 2) & 0x1;
+	else
+		return (dev->reg_shadow[MSM_SPM_REG_SAW2_ID] >> 18) & 0x1;
+}
+
 static inline void msm_spm_drv_set_vctl(struct msm_spm_driver_data *dev,
 		uint32_t vlevel)
 {
@@ -73,58 +141,81 @@
 	dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_DATA_1] |= (vlevel & 0x3F);
 }
 
-static void msm_spm_drv_flush_shadow(struct msm_spm_driver_data *dev,
-		unsigned int reg_index)
+static inline void msm_spm_drv_set_vctl2(struct msm_spm_driver_data *dev,
+		uint32_t vlevel)
 {
-	__raw_writel(dev->reg_shadow[reg_index],
-		dev->reg_base_addr + msm_spm_reg_offsets[reg_index]);
+	unsigned int pmic_data = 0;
+
+	pmic_data |= vlevel;
+	pmic_data |= (dev->vctl_port & 0x7) << 16;
+
+	dev->reg_shadow[MSM_SPM_REG_SAW2_VCTL] &= ~0x700FF;
+	dev->reg_shadow[MSM_SPM_REG_SAW2_VCTL] |= pmic_data;
+
+	dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_DATA_0] &= ~0x700FF;
+	dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_DATA_0] |= pmic_data;
 }
 
-static void msm_spm_drv_load_shadow(struct msm_spm_driver_data *dev,
-		unsigned int reg_index)
+static inline void msm_spm_drv_apcs_set_vctl(struct msm_spm_driver_data *dev,
+		unsigned int vlevel)
 {
-	dev->reg_shadow[reg_index] =
-		__raw_readl(dev->reg_base_addr +
-				msm_spm_reg_offsets[reg_index]);
-}
-
-static inline uint32_t msm_spm_drv_get_awake_vlevel(
-		struct msm_spm_driver_data *dev)
-{
-	return dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_DATA_0] & 0xFF;
+	if (dev->major == SAW2_MAJOR_2)
+		return msm_spm_drv_set_vctl2(dev, vlevel);
+	else
+		return msm_spm_drv_set_vctl(dev, vlevel);
 }
 
 static inline uint32_t msm_spm_drv_get_sts_pmic_state(
 		struct msm_spm_driver_data *dev)
 {
-	return (dev->reg_shadow[MSM_SPM_REG_SAW2_STS0] >> 10) & 0x03;
+	if (dev->major == SAW2_MAJOR_2) {
+		msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_PMIC_STS);
+		return (dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_STS] >> 16) &
+				0x03;
+	} else {
+		msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS0);
+		return (dev->reg_shadow[MSM_SPM_REG_SAW2_STS0] >> 10) & 0x03;
+	}
 }
 
 static inline uint32_t msm_spm_drv_get_sts_curr_pmic_data(
 		struct msm_spm_driver_data *dev)
 {
-	return dev->reg_shadow[MSM_SPM_REG_SAW2_STS1] & 0xFF;
+	if (dev->major == SAW2_MAJOR_2) {
+		msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_PMIC_STS);
+		return dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_STS] & 0xFF;
+	} else {
+		msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS1);
+		return dev->reg_shadow[MSM_SPM_REG_SAW2_STS1] & 0xFF;
+	}
 }
 
-static inline uint32_t msm_spm_drv_get_num_spm_entry(
-		struct msm_spm_driver_data *dev)
+static inline uint32_t msm_spm_drv_get_saw2_ver(struct msm_spm_driver_data *dev,
+		uint32_t *major, uint32_t *minor)
 {
-	return 32;
-}
+	int ret = -ENODEV;
+	uint32_t val = 0;
 
-static inline void msm_spm_drv_set_start_addr(
-		struct msm_spm_driver_data *dev, uint32_t addr)
-{
-	addr &= 0x7F;
-	addr <<= 4;
-	dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFFF80F;
-	dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= addr;
-}
+	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_VERSION);
+	val = dev->reg_shadow[MSM_SPM_REG_SAW2_VERSION];
 
+	if (dev->ver_reg == SAW2_V2_VER_REG) {
+		*major = (val >> 28) & 0xF;
+		*minor = (val >> 16) & 0xFFF;
+		ret = 0;
+	} else if (dev->ver_reg == SAW2_V1_VER_REG) {
+		*major = (val >> 4) & 0xF;
+		*minor = val & 0xF;
+		ret = 0;
+	}
+
+	return ret;
+}
 
 /******************************************************************************
  * Public functions
  *****************************************************************************/
+
 inline int msm_spm_drv_set_spm_enable(
 		struct msm_spm_driver_data *dev, bool enable)
 {
@@ -156,48 +247,42 @@
 	for (i = 0; i < num_spm_entry; i++) {
 		__raw_writel(dev->reg_seq_entry_shadow[i],
 			dev->reg_base_addr
-			+ msm_spm_reg_offsets[MSM_SPM_REG_SAW2_SEQ_ENTRY]
+			+ dev->reg_offsets[MSM_SPM_REG_SAW2_SEQ_ENTRY]
 			+ 4 * i);
 	}
 	mb();
 }
 
 int msm_spm_drv_write_seq_data(struct msm_spm_driver_data *dev,
-		uint8_t *cmd, uint32_t offset)
+		uint8_t *cmd, uint32_t *offset)
 {
-	uint32_t offset_w = offset / 4;
-	int ret = 0;
+	uint32_t cmd_w;
+	uint32_t offset_w = *offset / 4;
+	uint8_t last_cmd;
 
-	if (!cmd || !dev) {
-		__WARN();
-		goto failed_write_seq_data;
-	};
+	if (!cmd)
+		return -EINVAL;
 
 	while (1) {
 		int i;
-		uint32_t cmd_w = 0;
-		uint8_t last_cmd = 0;
+		cmd_w = 0;
+		last_cmd = 0;
+		cmd_w = dev->reg_seq_entry_shadow[offset_w];
 
-		for (i = 0; i < 4; i++) {
-			last_cmd = (last_cmd == 0x0f) ? 0x0f : *(cmd + i);
-			cmd_w |= last_cmd << (i * 8);
-			ret++;
+		for (i = (*offset % 4) ; i < 4; i++) {
+			last_cmd = *(cmd++);
+			cmd_w |=  last_cmd << (i * 8);
+			(*offset)++;
+			if (last_cmd == 0x0f)
+				break;
 		}
 
-		if (offset_w >=  msm_spm_drv_get_num_spm_entry(dev)) {
-			__WARN();
-			goto failed_write_seq_data;
-		}
-
-		cmd += i;
 		dev->reg_seq_entry_shadow[offset_w++] = cmd_w;
 		if (last_cmd == 0x0f)
 			break;
 	}
-	return ret;
 
-failed_write_seq_data:
-	 return -EINVAL;
+	return 0;
 }
 
 int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev,
@@ -218,7 +303,7 @@
 		int i;
 		for (i = 0; i < MSM_SPM_REG_NR; i++)
 			pr_info("%s: reg %02x = 0x%08x\n", __func__,
-				msm_spm_reg_offsets[i], dev->reg_shadow[i]);
+				dev->reg_offsets[i], dev->reg_shadow[i]);
 	}
 
 	return 0;
@@ -231,11 +316,14 @@
 	if (!dev)
 		return -EINVAL;
 
+	if (!msm_spm_pmic_arb_present(dev))
+		return -ENOSYS;
+
 	if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
 		pr_info("%s: requesting vlevel 0x%x\n",
 			__func__, vlevel);
 
-	msm_spm_drv_set_vctl(dev, vlevel);
+	msm_spm_drv_apcs_set_vctl(dev, vlevel);
 	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_VCTL);
 	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_PMIC_DATA_0);
 	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_PMIC_DATA_1);
@@ -243,7 +331,6 @@
 
 	/* Wait for PMIC state to return to idle or until timeout */
 	timeout_us = dev->vctl_timeout_us;
-	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS0);
 	while (msm_spm_drv_get_sts_pmic_state(dev) != MSM_SPM_PMIC_STATE_IDLE) {
 		if (!timeout_us)
 			goto set_vdd_bail;
@@ -255,11 +342,8 @@
 			udelay(timeout_us);
 			timeout_us = 0;
 		}
-		msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS0);
 	}
 
-	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS1);
-
 	if (msm_spm_drv_get_sts_curr_pmic_data(dev) != vlevel)
 		goto set_vdd_bail;
 
@@ -275,6 +359,54 @@
 	return -EIO;
 }
 
+int msm_spm_drv_set_phase(struct msm_spm_driver_data *dev,
+		unsigned int phase_cnt)
+{
+	unsigned int pmic_data = 0;
+	unsigned int timeout_us = 0;
+
+	if (dev->major != SAW2_MAJOR_2)
+		return -ENODEV;
+
+	pmic_data |= phase_cnt & 0xFF;
+	pmic_data |= (dev->phase_port & 0x7) << 16;
+
+	dev->reg_shadow[MSM_SPM_REG_SAW2_VCTL] &= ~0x700FF;
+	dev->reg_shadow[MSM_SPM_REG_SAW2_VCTL] |= pmic_data;
+	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_VCTL);
+	mb();
+
+	/* Wait for PMIC state to return to idle or until timeout */
+	timeout_us = dev->vctl_timeout_us;
+	while (msm_spm_drv_get_sts_pmic_state(dev) != MSM_SPM_PMIC_STATE_IDLE) {
+		if (!timeout_us)
+			goto set_phase_bail;
+
+		if (timeout_us > 10) {
+			udelay(10);
+			timeout_us -= 10;
+		} else {
+			udelay(timeout_us);
+			timeout_us = 0;
+		}
+	}
+
+	if (msm_spm_drv_get_sts_curr_pmic_data(dev) != phase_cnt)
+		goto set_phase_bail;
+
+	if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
+		pr_info("%s: done, remaining timeout %uus\n",
+			__func__, timeout_us);
+
+	return 0;
+
+set_phase_bail:
+	pr_err("%s: failed, remaining timeout %uus, phase count %d\n",
+	       __func__, timeout_us, msm_spm_drv_get_sts_curr_pmic_data(dev));
+	return -EIO;
+
+}
+
 void msm_spm_drv_reinit(struct msm_spm_driver_data *dev)
 {
 	int i;
@@ -289,12 +421,18 @@
 int __init msm_spm_drv_init(struct msm_spm_driver_data *dev,
 		struct msm_spm_platform_data *data)
 {
-
 	int i;
 	int num_spm_entry;
 
 	BUG_ON(!dev || !data);
 
+	if (dev->ver_reg == SAW2_V2_VER_REG)
+		dev->reg_offsets = msm_spm_reg_offsets_v2;
+	else
+		dev->reg_offsets = msm_spm_reg_offsets_v1;
+
+	dev->vctl_port = data->vctl_port;
+	dev->phase_port = data->phase_port;
 	dev->reg_base_addr = data->reg_base_addr;
 	memcpy(dev->reg_shadow, data->reg_init_values,
 			sizeof(data->reg_init_values));
@@ -314,18 +452,16 @@
 	/* barrier to ensure read completes before we proceed further*/
 	mb();
 
+	msm_spm_drv_get_saw2_ver(dev, &dev->major, &dev->minor);
+
 	num_spm_entry = msm_spm_drv_get_num_spm_entry(dev);
 
 	dev->reg_seq_entry_shadow =
-		kmalloc(sizeof(*dev->reg_seq_entry_shadow) * num_spm_entry,
+		kzalloc(sizeof(*dev->reg_seq_entry_shadow) * num_spm_entry,
 				GFP_KERNEL);
 
 	if (!dev->reg_seq_entry_shadow)
 		return -ENOMEM;
 
-
-	memset(dev->reg_seq_entry_shadow, 0x0f,
-			num_spm_entry * sizeof(*dev->reg_seq_entry_shadow));
-
 	return 0;
 }
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index 21c7dca..154303b 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -70,19 +70,33 @@
 	MSM_SPM_REG_SAW2_AVS_HYSTERESIS,
 	MSM_SPM_REG_SAW2_SPM_CTL,
 	MSM_SPM_REG_SAW2_PMIC_DLY,
+	MSM_SPM_REG_SAW2_AVS_LIMIT,
+	MSM_SPM_REG_SAW2_AVS_DLY,
+	MSM_SPM_REG_SAW2_SPM_DLY,
 	MSM_SPM_REG_SAW2_PMIC_DATA_0,
 	MSM_SPM_REG_SAW2_PMIC_DATA_1,
+	MSM_SPM_REG_SAW2_PMIC_DATA_2,
+	MSM_SPM_REG_SAW2_PMIC_DATA_3,
+	MSM_SPM_REG_SAW2_PMIC_DATA_4,
+	MSM_SPM_REG_SAW2_PMIC_DATA_5,
+	MSM_SPM_REG_SAW2_PMIC_DATA_6,
+	MSM_SPM_REG_SAW2_PMIC_DATA_7,
 	MSM_SPM_REG_SAW2_RST,
 
 	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_SAW2_SEQ_ENTRY,
+	MSM_SPM_REG_SAW2_SPM_STS,
+	MSM_SPM_REG_SAW2_AVS_STS,
+	MSM_SPM_REG_SAW2_PMIC_STS,
+	MSM_SPM_REG_SAW2_VERSION,
 
-	MSM_SPM_REG_NR
+	MSM_SPM_REG_NR,
 };
 
 struct msm_spm_seq_entry {
@@ -95,8 +109,13 @@
 	void __iomem *reg_base_addr;
 	uint32_t reg_init_values[MSM_SPM_REG_NR_INITIALIZE];
 
+	uint32_t ver_reg;
+	uint32_t vctl_port;
+	uint32_t phase_port;
+
 	uint8_t awake_vlevel;
 	uint32_t vctl_timeout_us;
+	uint32_t avs_timeout_us;
 
 	uint32_t num_modes;
 	struct msm_spm_seq_entry *modes;
@@ -105,18 +124,93 @@
 
 #if defined(CONFIG_MSM_SPM_V1) || defined(CONFIG_MSM_SPM_V2)
 
+/* Public functions */
+
+/**
+ * msm_spm_set_low_power_mode() - Configure SPM start address for low power mode
+ * @mode: SPM LPM mode to enter
+ * @notify_rpm: Notify RPM in this mode
+ */
 int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm);
+
+/**
+ * msm_spm_set_vdd(): Set core voltage
+ * @cpu: core id
+ * @vlevel: Encoded PMIC data.
+ */
 int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel);
-void msm_spm_reinit(void);
-void msm_spm_allow_x_cpu_set_vdd(bool allowed);
-int msm_spm_init(struct msm_spm_platform_data *data, int nr_devs);
+
+/**
+ * msm_spm_turn_on_cpu_rail(): Power on cpu rail before turning on core
+ * @cpu: core id
+ */
 int msm_spm_turn_on_cpu_rail(unsigned int cpu);
 
+
+/* Internal low power management specific functions */
+
+/**
+ * msm_spm_allow_x_cpu_set_vdd(): Turn on/off cross calling to set voltage
+ * @allowed: boolean to indicate on/off.
+ */
+void msm_spm_allow_x_cpu_set_vdd(bool allowed);
+
+/**
+ * msm_spm_reinit(): Reinitialize SPM registers
+ */
+void msm_spm_reinit(void);
+
+/**
+ * msm_spm_init(): Board initalization function
+ * @data: platform specific SPM register configuration data
+ * @nr_devs: Number of SPM devices being initialized
+ */
+int msm_spm_init(struct msm_spm_platform_data *data, int nr_devs);
+
+/**
+ * msm_spm_device_init(): Device tree initialization function
+ */
+int msm_spm_device_init(void);
+
 #if defined(CONFIG_MSM_L2_SPM)
+
+/* Public functions */
+
+/**
+ * msm_spm_l2_set_low_power_mode(): Configure L2 SPM start address
+ *                                  for low power mode
+ * @mode: SPM LPM mode to enter
+ * @notify_rpm: Notify RPM in this mode
+ */
 int msm_spm_l2_set_low_power_mode(unsigned int mode, bool notify_rpm);
+
+/**
+ * msm_spm_apcs_set_vdd(): Set Apps processor core sub-system voltage
+ * @vlevel: Encoded PMIC data.
+ */
+int msm_spm_apcs_set_vdd(unsigned int vlevel);
+
+/**
+ * msm_spm_apcs_set_phase(): Set number of SMPS phases.
+ * phase_cnt: Number of phases to be set active
+ */
+int msm_spm_apcs_set_phase(unsigned int phase_cnt);
+
+/* Internal low power management specific functions */
+
+/**
+ * msm_spm_l2_init(): Board initialization function
+ * @data: SPM target specific register configuration
+ */
 int msm_spm_l2_init(struct msm_spm_platform_data *data);
+
+/**
+ * msm_spm_l2_reinit(): Reinitialize L2 SPM registers
+ */
 void msm_spm_l2_reinit(void);
+
 #else
+
 static inline int msm_spm_l2_set_low_power_mode(unsigned int mode,
 		bool notify_rpm)
 {
@@ -130,10 +224,18 @@
 {
 	/* empty */
 }
+
+static inline int msm_spm_apcs_set_vdd(unsigned int vlevel)
+{
+	return -ENOSYS;
+}
+
+static inline int msm_spm_apcs_set_phase(unsigned int phase_cnt)
+{
+	return -ENOSYS;
+}
 #endif /* defined(CONFIG_MSM_L2_SPM) */
-
 #else /* defined(CONFIG_MSM_SPM_V1) || defined(CONFIG_MSM_SPM_V2) */
-
 static inline int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
 {
 	return -ENOSYS;
@@ -158,6 +260,11 @@
 {
 	return -ENOSYS;
 }
-#endif  /*defined(CONFIG_MSM_SPM_V1) || defined (CONFIG_MSM_SPM_V2) */
 
+static inline int msm_spm_device_init(void)
+{
+	return -ENOSYS;
+}
+
+#endif  /*defined(CONFIG_MSM_SPM_V1) || defined (CONFIG_MSM_SPM_V2) */
 #endif  /* __ARCH_ARM_MACH_MSM_SPM_H */
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 2b17fa3..838ec55 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -17,6 +17,9 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
 #include "spm.h"
@@ -35,6 +38,7 @@
 	uint32_t num_modes;
 };
 
+static struct msm_spm_device msm_spm_l2_device;
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_spm_device, msm_cpu_spm_device);
 static atomic_t msm_spm_set_vdd_x_cpu_allowed = ATOMIC_INIT(1);
 
@@ -42,6 +46,7 @@
 {
 	atomic_set(&msm_spm_set_vdd_x_cpu_allowed, allowed ? 1 : 0);
 }
+EXPORT_SYMBOL(msm_spm_allow_x_cpu_set_vdd);
 
 int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel)
 {
@@ -62,6 +67,7 @@
 	local_irq_restore(flags);
 	return ret;
 }
+EXPORT_SYMBOL(msm_spm_set_vdd);
 
 static int msm_spm_dev_set_low_power_mode(struct msm_spm_device *dev,
 		unsigned int mode, bool notify_rpm)
@@ -100,6 +106,7 @@
 	if (!dev->modes)
 		goto spm_failed_malloc;
 
+	dev->reg_data.ver_reg = data->ver_reg;
 	ret = msm_spm_drv_init(&dev->reg_data, data);
 
 	if (ret)
@@ -107,15 +114,17 @@
 
 	for (i = 0; i < dev->num_modes; i++) {
 
+		/* Default offset is 0 and gets updated as we write more
+		 * sequences into SPM
+		 */
+		dev->modes[i].start_addr = offset;
 		ret = msm_spm_drv_write_seq_data(&dev->reg_data,
-						data->modes[i].cmd, offset);
+						data->modes[i].cmd, &offset);
 		if (ret < 0)
 			goto spm_failed_init;
 
 		dev->modes[i].mode = data->modes[i].mode;
 		dev->modes[i].notify_rpm = data->modes[i].notify_rpm;
-		dev->modes[i].start_addr = offset;
-		offset += ret;
 	}
 	msm_spm_drv_flush_seq_entry(&dev->reg_data);
 	return 0;
@@ -126,39 +135,6 @@
 	return ret;
 }
 
-void msm_spm_reinit(void)
-{
-	unsigned int cpu;
-	for_each_possible_cpu(cpu)
-		msm_spm_drv_reinit(&per_cpu(msm_cpu_spm_device.reg_data, cpu));
-}
-
-int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
-{
-	struct msm_spm_device *dev = &__get_cpu_var(msm_cpu_spm_device);
-	return msm_spm_dev_set_low_power_mode(dev, mode, notify_rpm);
-}
-
-int __init msm_spm_init(struct msm_spm_platform_data *data, int nr_devs)
-{
-	unsigned int cpu;
-	int ret = 0;
-
-	BUG_ON((nr_devs < num_possible_cpus()) || !data);
-
-	for_each_possible_cpu(cpu) {
-		struct msm_spm_device *dev = &per_cpu(msm_cpu_spm_device, cpu);
-		ret = msm_spm_dev_init(dev, &data[cpu]);
-		if (ret < 0) {
-			pr_warn("%s():failed CPU:%u ret:%d\n", __func__,
-					cpu, ret);
-			break;
-		}
-	}
-
-	return ret;
-}
-
 int msm_spm_turn_on_cpu_rail(unsigned int cpu)
 {
 	uint32_t val = 0;
@@ -192,22 +168,227 @@
 }
 EXPORT_SYMBOL(msm_spm_turn_on_cpu_rail);
 
-#if defined(CONFIG_MSM_L2_SPM)
-static struct msm_spm_device msm_spm_l2_device;
+void msm_spm_reinit(void)
+{
+	unsigned int cpu;
+	for_each_possible_cpu(cpu)
+		msm_spm_drv_reinit(&per_cpu(msm_cpu_spm_device.reg_data, cpu));
+}
+EXPORT_SYMBOL(msm_spm_reinit);
+
+int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
+{
+	struct msm_spm_device *dev = &__get_cpu_var(msm_cpu_spm_device);
+	return msm_spm_dev_set_low_power_mode(dev, mode, notify_rpm);
+}
+EXPORT_SYMBOL(msm_spm_set_low_power_mode);
+
+/* Board file init function */
+int __init msm_spm_init(struct msm_spm_platform_data *data, int nr_devs)
+{
+	unsigned int cpu;
+	int ret = 0;
+
+	BUG_ON((nr_devs < num_possible_cpus()) || !data);
+
+	for_each_possible_cpu(cpu) {
+		struct msm_spm_device *dev = &per_cpu(msm_cpu_spm_device, cpu);
+		ret = msm_spm_dev_init(dev, &data[cpu]);
+		if (ret < 0) {
+			pr_warn("%s():failed CPU:%u ret:%d\n", __func__,
+					cpu, ret);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_MSM_L2_SPM
 
 int msm_spm_l2_set_low_power_mode(unsigned int mode, bool notify_rpm)
 {
 	return msm_spm_dev_set_low_power_mode(
 			&msm_spm_l2_device, mode, notify_rpm);
 }
-
-int __init msm_spm_l2_init(struct msm_spm_platform_data *data)
-{
-	return msm_spm_dev_init(&msm_spm_l2_device, data);
-}
+EXPORT_SYMBOL(msm_spm_l2_set_low_power_mode);
 
 void msm_spm_l2_reinit(void)
 {
 	msm_spm_drv_reinit(&msm_spm_l2_device.reg_data);
 }
+EXPORT_SYMBOL(msm_spm_l2_reinit);
+
+int msm_spm_apcs_set_vdd(unsigned int vlevel)
+{
+	return msm_spm_drv_set_vdd(&msm_spm_l2_device.reg_data, vlevel);
+}
+EXPORT_SYMBOL(msm_spm_apcs_set_vdd);
+
+int msm_spm_apcs_set_phase(unsigned int phase_cnt)
+{
+	return msm_spm_drv_set_phase(&msm_spm_l2_device.reg_data, phase_cnt);
+}
+EXPORT_SYMBOL(msm_spm_apcs_set_phase);
+
+/* Board file init function */
+int __init msm_spm_l2_init(struct msm_spm_platform_data *data)
+{
+	return msm_spm_dev_init(&msm_spm_l2_device, data);
+}
 #endif
+
+static int __devinit msm_spm_dev_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	int cpu = 0;
+	int i = 0;
+	struct device_node *node = pdev->dev.of_node;
+	struct msm_spm_platform_data spm_data;
+	char *key = NULL;
+	uint32_t val = 0;
+	struct msm_spm_seq_entry modes[MSM_SPM_MODE_NR];
+	size_t len = 0;
+	struct msm_spm_device *dev = NULL;
+	struct resource *res = NULL;
+	uint32_t mode_count = 0;
+
+	struct spm_of {
+		char *key;
+		uint32_t id;
+	};
+
+	struct spm_of spm_of_data[] = {
+		{"qcom,saw2-cfg", MSM_SPM_REG_SAW2_CFG},
+		{"qcom,saw2-avs-ctl", MSM_SPM_REG_SAW2_AVS_CTL},
+		{"qcom,saw2-avs-hysteresis", MSM_SPM_REG_SAW2_AVS_HYSTERESIS},
+		{"qcom,saw2-spm-ctl", MSM_SPM_REG_SAW2_SPM_CTL},
+		{"qcom,saw2-pmic-dly", MSM_SPM_REG_SAW2_PMIC_DLY},
+		{"qcom,saw2-avs-limit", MSM_SPM_REG_SAW2_AVS_LIMIT},
+		{"qcom,saw2-spm-dly", MSM_SPM_REG_SAW2_SPM_DLY},
+		{"qcom,saw2-pmic-data0", MSM_SPM_REG_SAW2_PMIC_DATA_0},
+		{"qcom,saw2-pmic-data1", MSM_SPM_REG_SAW2_PMIC_DATA_1},
+		{"qcom,saw2-pmic-data2", MSM_SPM_REG_SAW2_PMIC_DATA_2},
+		{"qcom,saw2-pmic-data3", MSM_SPM_REG_SAW2_PMIC_DATA_3},
+		{"qcom,saw2-pmic-data4", MSM_SPM_REG_SAW2_PMIC_DATA_4},
+		{"qcom,saw2-pmic-data5", MSM_SPM_REG_SAW2_PMIC_DATA_5},
+		{"qcom,saw2-pmic-data6", MSM_SPM_REG_SAW2_PMIC_DATA_6},
+		{"qcom,saw2-pmic-data7", MSM_SPM_REG_SAW2_PMIC_DATA_7},
+	};
+
+	struct mode_of {
+		char *key;
+		uint32_t id;
+		uint32_t notify_rpm;
+	};
+
+	struct mode_of mode_of_data[] = {
+		{"qcom,spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING, 0},
+		{"qcom,spm-cmd-ret", MSM_SPM_MODE_POWER_RETENTION, 0},
+		{"qcom,spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE, 0},
+		{"qcom,spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE, 1},
+	};
+
+	BUG_ON(ARRAY_SIZE(mode_of_data) > MSM_SPM_MODE_NR);
+	memset(&spm_data, 0, sizeof(struct msm_spm_platform_data));
+	memset(&modes, 0,
+		(MSM_SPM_MODE_NR - 2) * sizeof(struct msm_spm_seq_entry));
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto fail;
+
+	spm_data.reg_base_addr = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+	if (!spm_data.reg_base_addr)
+		return -ENOMEM;
+
+	key = "qcom,core-id";
+	ret = of_property_read_u32(node, key, &val);
+	if (ret)
+		goto fail;
+	cpu = val;
+
+	key = "qcom,saw2-ver-reg";
+	ret = of_property_read_u32(node, key, &val);
+	if (ret)
+		goto fail;
+	spm_data.ver_reg = val;
+
+	key = "qcom,vctl-timeout-us";
+	ret = of_property_read_u32(node, key, &val);
+	if (!ret)
+		spm_data.vctl_timeout_us = val;
+
+	/* optional */
+	key = "qcom,vctl-port";
+	ret = of_property_read_u32(node, key, &val);
+	if (!ret)
+		spm_data.vctl_port = val;
+
+	/* optional */
+	key = "qcom,phase-port";
+	ret = of_property_read_u32(node, key, &val);
+	if (!ret)
+		spm_data.phase_port = val;
+
+	for (i = 0; i < ARRAY_SIZE(spm_of_data); i++) {
+		ret = of_property_read_u32(node, spm_of_data[i].key, &val);
+		if (ret)
+			continue;
+		spm_data.reg_init_values[spm_of_data[i].id] = val;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mode_of_data); i++) {
+		key = mode_of_data[i].key;
+		modes[mode_count].cmd =
+			(uint8_t *)of_get_property(node, key, &len);
+		if (!modes[mode_count].cmd)
+			continue;
+		modes[mode_count].mode = mode_of_data[i].id;
+		modes[mode_count].notify_rpm = mode_of_data[i].notify_rpm;
+		mode_count++;
+	}
+
+	spm_data.modes = modes;
+	spm_data.num_modes = mode_count;
+
+	/*
+	 * Device with id 0..NR_CPUS are SPM for apps cores
+	 * Device with id 0xFFFF is for L2 SPM.
+	 */
+	if (cpu >= 0 && cpu < num_possible_cpus())
+		dev = &per_cpu(msm_cpu_spm_device, cpu);
+	else
+		dev = &msm_spm_l2_device;
+
+	ret = msm_spm_dev_init(dev, &spm_data);
+	if (ret < 0)
+		pr_warn("%s():failed core-id:%u ret:%d\n", __func__, cpu, ret);
+
+	return ret;
+
+fail:
+	pr_err("%s: Failed reading node=%s, key=%s\n",
+			__func__, node->full_name, key);
+	return -EFAULT;
+}
+
+static struct of_device_id msm_spm_match_table[] = {
+	{.compatible = "qcom,spm-v2"},
+	{},
+};
+
+static struct platform_driver msm_spm_device_driver = {
+	.probe = msm_spm_dev_probe,
+	.driver = {
+		.name = "spm-v2",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_spm_match_table,
+	},
+};
+
+int __init msm_spm_device_init(void)
+{
+	return platform_driver_register(&msm_spm_device_driver);
+}
diff --git a/arch/arm/mach-msm/spm_driver.h b/arch/arm/mach-msm/spm_driver.h
index 712f051..f272adb0 100644
--- a/arch/arm/mach-msm/spm_driver.h
+++ b/arch/arm/mach-msm/spm_driver.h
@@ -15,10 +15,17 @@
 #include "spm.h"
 
 struct msm_spm_driver_data {
+	uint32_t major;
+	uint32_t minor;
+	uint32_t ver_reg;
+	uint32_t vctl_port;
+	uint32_t phase_port;
 	void __iomem *reg_base_addr;
 	uint32_t vctl_timeout_us;
+	uint32_t avs_timeout_us;
 	uint32_t reg_shadow[MSM_SPM_REG_NR];
 	uint32_t *reg_seq_entry_shadow;
+	uint32_t *reg_offsets;
 };
 
 int msm_spm_drv_init(struct msm_spm_driver_data *dev,
@@ -29,9 +36,10 @@
 int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev,
 		unsigned int vlevel);
 int msm_spm_drv_write_seq_data(struct msm_spm_driver_data *dev,
-		uint8_t *cmd, uint32_t offset);
+		uint8_t *cmd, uint32_t *offset);
 void msm_spm_drv_flush_seq_entry(struct msm_spm_driver_data *dev);
 int msm_spm_drv_set_spm_enable(struct msm_spm_driver_data *dev,
 		bool enable);
-
+int msm_spm_drv_set_phase(struct msm_spm_driver_data *dev,
+		unsigned int phase_cnt);
 #endif
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 0ff30c3..0aa88ff 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1143,3 +1143,4 @@
 msm8625_surf		MACH_MSM8625_SURF	MSM8625_SURF		4037
 msm8625_evb		MACH_MSM8625_EVB	MSM8625_EVB		4042
 msm8625_qrd7		MACH_MSM8625_QRD7	MSM8625_QRD7		4095
+msm8625_ffa		MACH_MSM8625_FFA	MSM8625_FFA		4166
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c
index ea2a1df6..b8333b0 100644
--- a/drivers/base/iommu.c
+++ b/drivers/base/iommu.c
@@ -40,6 +40,26 @@
 }
 EXPORT_SYMBOL_GPL(iommu_found);
 
+/**
+ * iommu_set_fault_handler() - set a fault handler for an iommu domain
+ * @domain: iommu domain
+ * @handler: fault handler
+ *
+ * This function should be used by IOMMU users which want to be notified
+ * whenever an IOMMU fault happens.
+ *
+ * The fault handler itself should return 0 on success, and an appropriate
+ * error code otherwise.
+ */
+void iommu_set_fault_handler(struct iommu_domain *domain,
+					iommu_fault_handler_t handler)
+{
+	BUG_ON(!domain);
+
+	domain->handler = handler;
+}
+EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
+
 struct iommu_domain *iommu_domain_alloc(int flags)
 {
 	struct iommu_domain *domain;
@@ -48,7 +68,7 @@
 	if (!iommu_found())
 		return NULL;
 
-	domain = kmalloc(sizeof(*domain), GFP_KERNEL);
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
 	if (!domain)
 		return NULL;
 
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index a63e344..4726da1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -23,6 +23,7 @@
 #include <linux/reboot.h>
 #include <linux/of.h>
 #include <linux/spinlock.h>
+#include <linux/kmemleak.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <mach/usbdiag.h>
 #endif
@@ -1798,48 +1799,57 @@
 			struct diag_ctrl_event_mask), GFP_KERNEL);
 		if (driver->event_mask == NULL)
 			goto err;
+		kmemleak_not_leak(driver->event_mask);
 	}
 	if (driver->msg_mask == NULL) {
 		driver->msg_mask = kzalloc(sizeof(
 			struct diag_ctrl_msg_mask), GFP_KERNEL);
 		if (driver->msg_mask == NULL)
 			goto err;
+		kmemleak_not_leak(driver->msg_mask);
 	}
 	if (driver->log_mask == NULL) {
 		driver->log_mask = kzalloc(sizeof(
 			struct diag_ctrl_log_mask), GFP_KERNEL);
 		if (driver->log_mask == NULL)
 			goto err;
+		kmemleak_not_leak(driver->log_mask);
 	}
 	if (driver->buf_in_1 == NULL) {
 		driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_1 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_1);
 	}
 	if (driver->buf_in_2 == NULL) {
 		driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_2 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_2);
 	}
 	if (driver->buf_in_qdsp_1 == NULL) {
 		driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_qdsp_1 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_qdsp_1);
 	}
 	if (driver->buf_in_qdsp_2 == NULL) {
 		driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_qdsp_2 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_qdsp_2);
 	}
 	if (driver->buf_in_wcnss_1 == NULL) {
 		driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_wcnss_1 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_wcnss_1);
 	}
 	if (driver->buf_in_wcnss_2 == NULL) {
 		driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_wcnss_2 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_wcnss_2);
 	}
 
 	if (driver->buf_msg_mask_update == NULL) {
@@ -1847,98 +1857,117 @@
 								 GFP_KERNEL);
 		if (driver->buf_msg_mask_update == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_msg_mask_update);
 	}
 	if (driver->buf_log_mask_update == NULL) {
 		driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
 								 GFP_KERNEL);
 		if (driver->buf_log_mask_update == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_log_mask_update);
 	}
 	if (driver->buf_event_mask_update == NULL) {
 		driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
 								 GFP_KERNEL);
 		if (driver->buf_event_mask_update == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_event_mask_update);
 	}
 	if (driver->usb_buf_out  == NULL &&
 	     (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
 					 GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->usb_buf_out);
 	if (driver->hdlc_buf == NULL
 	    && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->hdlc_buf);
 	if (driver->user_space_data == NULL)
 		driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
 		if (driver->user_space_data == NULL)
 			goto err;
+	kmemleak_not_leak(driver->user_space_data);
 	if (driver->msg_masks == NULL
 	    && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
 					     GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->msg_masks);
 	diag_create_msg_mask_table();
 	diag_event_num_bytes = 0;
 	if (driver->log_masks == NULL &&
 	    (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->log_masks);
 	driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
 	if (driver->event_masks == NULL &&
 	    (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
 					    GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->event_masks);
 	if (driver->client_map == NULL &&
 	    (driver->client_map = kzalloc
 	     ((driver->num_clients) * sizeof(struct diag_client_map),
 		   GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->client_map);
 	if (driver->buf_tbl == NULL)
 			driver->buf_tbl = kzalloc(buf_tbl_size *
 			  sizeof(struct diag_write_device), GFP_KERNEL);
 	if (driver->buf_tbl == NULL)
 		goto err;
+	kmemleak_not_leak(driver->buf_tbl);
 	if (driver->data_ready == NULL &&
 	     (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
 							, GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->data_ready);
 	if (driver->table == NULL &&
 	     (driver->table = kzalloc(diag_max_reg*
 		      sizeof(struct diag_master_table),
 		       GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->table);
 	if (driver->write_ptr_1 == NULL) {
 		driver->write_ptr_1 = kzalloc(
 			sizeof(struct diag_request), GFP_KERNEL);
 		if (driver->write_ptr_1 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->write_ptr_1);
 	}
 	if (driver->write_ptr_2 == NULL) {
 		driver->write_ptr_2 = kzalloc(
 			sizeof(struct diag_request), GFP_KERNEL);
 		if (driver->write_ptr_2 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->write_ptr_2);
 	}
 	if (driver->write_ptr_qdsp_1 == NULL) {
 		driver->write_ptr_qdsp_1 = kzalloc(
 			sizeof(struct diag_request), GFP_KERNEL);
 		if (driver->write_ptr_qdsp_1 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->write_ptr_qdsp_1);
 	}
 	if (driver->write_ptr_qdsp_2 == NULL) {
 		driver->write_ptr_qdsp_2 = kzalloc(
 			sizeof(struct diag_request), GFP_KERNEL);
 		if (driver->write_ptr_qdsp_2 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->write_ptr_qdsp_2);
 	}
 	if (driver->write_ptr_wcnss_1 == NULL) {
 		driver->write_ptr_wcnss_1 = kzalloc(
 			sizeof(struct diag_request), GFP_KERNEL);
 		if (driver->write_ptr_wcnss_1 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->write_ptr_wcnss_1);
 	}
 	if (driver->write_ptr_wcnss_2 == NULL) {
 		driver->write_ptr_wcnss_2 = kzalloc(
 			sizeof(struct diag_request), GFP_KERNEL);
 		if (driver->write_ptr_wcnss_2 == NULL)
 			goto err;
+		kmemleak_not_leak(driver->write_ptr_wcnss_2);
 	}
 
 	if (driver->usb_read_ptr == NULL) {
@@ -1946,15 +1975,18 @@
 			sizeof(struct diag_request), GFP_KERNEL);
 		if (driver->usb_read_ptr == NULL)
 			goto err;
+		kmemleak_not_leak(driver->usb_read_ptr);
 	}
 	if (driver->pkt_buf == NULL &&
 	     (driver->pkt_buf = kzalloc(PKT_SIZE,
 			 GFP_KERNEL)) == NULL)
 		goto err;
+	kmemleak_not_leak(driver->pkt_buf);
 	if (driver->apps_rsp_buf == NULL) {
 		driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
 		if (driver->apps_rsp_buf == NULL)
 			goto err;
+		kmemleak_not_leak(driver->apps_rsp_buf);
 	}
 	driver->diag_wq = create_singlethread_workqueue("diag_wq");
 #ifdef CONFIG_DIAG_OVER_USB
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 8efe10b..de1a5b5 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/diagchar.h>
 #include <linux/platform_device.h>
+#include <linux/kmemleak.h>
 #include "diagchar.h"
 #include "diagfwd.h"
 #include "diagfwd_cntl.h"
@@ -280,16 +281,19 @@
 		driver->buf_in_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_cntl == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_cntl);
 	}
 	if (driver->buf_in_qdsp_cntl == NULL) {
 		driver->buf_in_qdsp_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_qdsp_cntl == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_qdsp_cntl);
 	}
 	if (driver->buf_in_wcnss_cntl == NULL) {
 		driver->buf_in_wcnss_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_wcnss_cntl == NULL)
 			goto err;
+		kmemleak_not_leak(driver->buf_in_wcnss_cntl);
 	}
 	platform_driver_register(&msm_smd_ch1_cntl_driver);
 	platform_driver_register(&diag_smd_lite_cntl_driver);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 8328ee2..cf024cf 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -485,4 +485,12 @@
 	help
 	  Say 'y' here to include support for the Qualcomm QPNP gpio
 	  support. QPNP is a SPMI based PMIC implementation.
+
+config GPIO_QPNP_DEBUG
+	depends on GPIO_QPNP
+	depends on DEBUG_FS
+	bool "Qualcomm QPNP GPIO debug support"
+	help
+	  Say 'y' here to include debug support for the Qualcomm
+	  QPNP gpio support
 endif
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
index 594b974..bc0904ec 100644
--- a/drivers/gpio/qpnp-gpio.c
+++ b/drivers/gpio/qpnp-gpio.c
@@ -16,6 +16,7 @@
 #include <linux/types.h>
 #include <linux/spmi.h>
 #include <linux/platform_device.h>
+#include <linux/debugfs.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -84,6 +85,20 @@
 #define Q_REG_MASTER_EN_SHIFT		7
 #define Q_REG_MASTER_EN_MASK		0x80
 
+enum qpnp_gpio_param_type {
+	Q_GPIO_CFG_DIRECTION,
+	Q_GPIO_CFG_OUTPUT_TYPE,
+	Q_GPIO_CFG_INVERT,
+	Q_GPIO_CFG_PULL,
+	Q_GPIO_CFG_VIN_SEL,
+	Q_GPIO_CFG_OUT_STRENGTH,
+	Q_GPIO_CFG_SRC_SELECT,
+	Q_GPIO_CFG_MASTER_EN,
+	Q_GPIO_CFG_INVALID,
+};
+
+#define Q_NUM_PARAMS			Q_GPIO_CFG_INVALID
+
 /* param error checking */
 #define QPNP_GPIO_DIR_INVALID		3
 #define QPNP_GPIO_INVERT_INVALID	2
@@ -104,6 +119,8 @@
 	u8 type;			/* peripheral type */
 	u8 subtype;			/* peripheral subtype */
 	struct device_node *node;
+	enum qpnp_gpio_param_type params[Q_NUM_PARAMS];
+	struct qpnp_gpio_chip *q_chip;
 };
 
 struct qpnp_gpio_chip {
@@ -115,6 +132,7 @@
 	uint32_t		pmic_gpio_highest;
 	struct device_node	*int_ctrl;
 	struct list_head	chip_list;
+	struct dentry		*dfs_dir;
 };
 
 static LIST_HEAD(qpnp_gpio_chips);
@@ -583,15 +601,254 @@
 	return rc;
 }
 
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+struct qpnp_gpio_reg {
+	uint32_t addr;
+	uint32_t idx;
+	uint32_t shift;
+	uint32_t mask;
+};
+
+static struct dentry *driver_dfs_dir;
+
+static int qpnp_gpio_reg_attr(enum qpnp_gpio_param_type type,
+			     struct qpnp_gpio_reg *cfg)
+{
+	switch (type) {
+	case Q_GPIO_CFG_DIRECTION:
+		cfg->addr = Q_REG_MODE_CTL;
+		cfg->idx = Q_REG_I_MODE_CTL;
+		cfg->shift = Q_REG_MODE_SEL_SHIFT;
+		cfg->mask = Q_REG_MODE_SEL_MASK;
+		break;
+	case Q_GPIO_CFG_OUTPUT_TYPE:
+		cfg->addr = Q_REG_DIG_OUT_CTL;
+		cfg->idx = Q_REG_I_DIG_OUT_CTL;
+		cfg->shift = Q_REG_OUT_TYPE_SHIFT;
+		cfg->mask = Q_REG_OUT_TYPE_MASK;
+		break;
+	case Q_GPIO_CFG_INVERT:
+		cfg->addr = Q_REG_MODE_CTL;
+		cfg->idx = Q_REG_I_MODE_CTL;
+		cfg->shift = Q_REG_OUT_INVERT_SHIFT;
+		cfg->mask = Q_REG_OUT_INVERT_MASK;
+		break;
+	case Q_GPIO_CFG_PULL:
+		cfg->addr = Q_REG_DIG_PULL_CTL;
+		cfg->idx = Q_REG_I_DIG_PULL_CTL;
+		cfg->shift = Q_REG_PULL_SHIFT;
+		cfg->mask = Q_REG_PULL_MASK;
+		break;
+	case Q_GPIO_CFG_VIN_SEL:
+		cfg->addr = Q_REG_DIG_VIN_CTL;
+		cfg->idx = Q_REG_I_DIG_VIN_CTL;
+		cfg->shift = Q_REG_VIN_SHIFT;
+		cfg->mask = Q_REG_VIN_MASK;
+		break;
+	case Q_GPIO_CFG_OUT_STRENGTH:
+		cfg->addr = Q_REG_DIG_OUT_CTL;
+		cfg->idx = Q_REG_I_DIG_OUT_CTL;
+		cfg->shift = Q_REG_OUT_STRENGTH_SHIFT;
+		cfg->mask = Q_REG_OUT_STRENGTH_MASK;
+		break;
+	case Q_GPIO_CFG_SRC_SELECT:
+		cfg->addr = Q_REG_MODE_CTL;
+		cfg->idx = Q_REG_I_MODE_CTL;
+		cfg->shift = Q_REG_SRC_SEL_SHIFT;
+		cfg->mask = Q_REG_SRC_SEL_MASK;
+		break;
+	case Q_GPIO_CFG_MASTER_EN:
+		cfg->addr = Q_REG_EN_CTL;
+		cfg->idx = Q_REG_I_EN_CTL;
+		cfg->shift = Q_REG_MASTER_EN_SHIFT;
+		cfg->mask = Q_REG_MASTER_EN_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int qpnp_gpio_debugfs_get(void *data, u64 *val)
+{
+	enum qpnp_gpio_param_type *idx = data;
+	struct qpnp_gpio_spec *q_spec;
+	struct qpnp_gpio_reg cfg = {};
+	int rc;
+
+	rc = qpnp_gpio_reg_attr(*idx, &cfg);
+	if (rc)
+		return rc;
+	q_spec = container_of(idx, struct qpnp_gpio_spec, params[*idx]);
+	*val = q_reg_get(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask);
+	return 0;
+}
+
+static int qpnp_gpio_check_reg_val(enum qpnp_gpio_param_type idx,
+				   struct qpnp_gpio_spec *q_spec,
+				   uint32_t val)
+{
+	switch (idx) {
+	case Q_GPIO_CFG_DIRECTION:
+		if (val >= QPNP_GPIO_DIR_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_OUTPUT_TYPE:
+		if ((val >= QPNP_GPIO_OUT_BUF_INVALID) ||
+		   ((val == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS ||
+		   val == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS) &&
+		   (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
+		   (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_8CH))))
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_INVERT:
+		if (val >= QPNP_GPIO_INVERT_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_PULL:
+		if (val >= QPNP_GPIO_PULL_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_VIN_SEL:
+		if (val >= QPNP_GPIO_VIN_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_OUT_STRENGTH:
+		if (val >= QPNP_GPIO_OUT_STRENGTH_INVALID ||
+		    val == 0)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_SRC_SELECT:
+		if (val >= QPNP_GPIO_SRC_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_MASTER_EN:
+		if (val >= QPNP_GPIO_MASTER_INVALID)
+			return -EINVAL;
+		break;
+	default:
+		pr_err("invalid param type %u specified\n", idx);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int qpnp_gpio_debugfs_set(void *data, u64 val)
+{
+	enum qpnp_gpio_param_type *idx = data;
+	struct qpnp_gpio_spec *q_spec;
+	struct qpnp_gpio_chip *q_chip;
+	struct qpnp_gpio_reg cfg = {};
+	int rc;
+
+	q_spec = container_of(idx, struct qpnp_gpio_spec, params[*idx]);
+	q_chip = q_spec->q_chip;
+
+	rc = qpnp_gpio_check_reg_val(*idx, q_spec, val);
+	if (rc)
+		return rc;
+
+	rc = qpnp_gpio_reg_attr(*idx, &cfg);
+	if (rc)
+		return rc;
+	q_reg_clr_set(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask, val);
+	rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
+				      Q_REG_ADDR(q_spec, cfg.addr),
+				      &q_spec->regs[cfg.idx], 1);
+
+	return rc;
+}
+DEFINE_SIMPLE_ATTRIBUTE(qpnp_gpio_fops, qpnp_gpio_debugfs_get,
+			qpnp_gpio_debugfs_set, "%llu\n");
+
+#define DEBUGFS_BUF_SIZE 11 /* supports 2^32 in decimal */
+
+struct qpnp_gpio_debugfs_args {
+	enum qpnp_gpio_param_type type;
+	const char *filename;
+};
+
+static struct qpnp_gpio_debugfs_args dfs_args[] = {
+	{ Q_GPIO_CFG_DIRECTION, "direction" },
+	{ Q_GPIO_CFG_OUTPUT_TYPE, "output_type" },
+	{ Q_GPIO_CFG_INVERT, "invert" },
+	{ Q_GPIO_CFG_PULL, "pull" },
+	{ Q_GPIO_CFG_VIN_SEL, "vin_sel" },
+	{ Q_GPIO_CFG_OUT_STRENGTH, "out_strength" },
+	{ Q_GPIO_CFG_SRC_SELECT, "src_select" },
+	{ Q_GPIO_CFG_MASTER_EN, "master_en" }
+};
+
+static int qpnp_gpio_debugfs_create(struct qpnp_gpio_chip *q_chip)
+{
+	struct spmi_device *spmi = q_chip->spmi;
+	struct device *dev = &spmi->dev;
+	struct qpnp_gpio_spec *q_spec;
+	enum qpnp_gpio_param_type *params;
+	enum qpnp_gpio_param_type type;
+	char pmic_gpio[DEBUGFS_BUF_SIZE];
+	const char *filename;
+	struct dentry *dfs, *dfs_io_dir;
+	int i, j;
+
+	BUG_ON(Q_NUM_PARAMS != ARRAY_SIZE(dfs_args));
+
+	q_chip->dfs_dir = debugfs_create_dir(dev->of_node->name,
+							driver_dfs_dir);
+	if (q_chip->dfs_dir == NULL) {
+		dev_err(dev, "%s: cannot register chip debugfs directory %s\n",
+						__func__, dev->of_node->name);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < spmi->num_dev_node; i++) {
+		q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
+		params = q_spec->params;
+		snprintf(pmic_gpio, DEBUGFS_BUF_SIZE, "%u", q_spec->pmic_gpio);
+		dfs_io_dir = debugfs_create_dir(pmic_gpio,
+							q_chip->dfs_dir);
+		if (dfs_io_dir == NULL)
+			goto dfs_err;
+
+		for (j = 0; j < Q_NUM_PARAMS; j++) {
+			type = dfs_args[j].type;
+			filename = dfs_args[j].filename;
+
+			params[type] = type;
+			dfs = debugfs_create_file(
+					filename,
+					S_IRUGO | S_IWUSR,
+					dfs_io_dir,
+					&q_spec->params[type],
+					&qpnp_gpio_fops);
+			if (dfs == NULL)
+				goto dfs_err;
+		}
+	}
+	return 0;
+dfs_err:
+	dev_err(dev, "%s: cannot register debugfs for pmic gpio %u on"
+				     " chip %s\n", __func__,
+				     q_spec->pmic_gpio, dev->of_node->name);
+	debugfs_remove_recursive(q_chip->dfs_dir);
+	return -ENFILE;
+}
+#else
+static int qpnp_gpio_debugfs_create(struct qpnp_gpio_chip *q_chip)
+{
+	return 0;
+}
+#endif
+
 static int qpnp_gpio_probe(struct spmi_device *spmi)
 {
 	struct qpnp_gpio_chip *q_chip;
 	struct resource *res;
 	struct qpnp_gpio_spec *q_spec;
-	const __be32 *prop;
-	int i, rc, ret, gpio, len;
-	int lowest_gpio = INT_MAX, highest_gpio = INT_MIN;
-	u32 intspec[3];
+	int i, rc;
+	int lowest_gpio = UINT_MAX, highest_gpio = 0;
+	u32 intspec[3], gpio;
 	char buf[2];
 
 	q_chip = kzalloc(sizeof(*q_chip), GFP_KERNEL);
@@ -609,21 +866,14 @@
 
 	/* first scan through nodes to find the range required for allocation */
 	for (i = 0; i < spmi->num_dev_node; i++) {
-		prop = of_get_property(spmi->dev_node[i].of_node,
-						"qcom,gpio-num", &len);
-		if (!prop) {
+		rc = of_property_read_u32(spmi->dev_node[i].of_node,
+							"qcom,gpio-num", &gpio);
+		if (rc) {
 			dev_err(&spmi->dev, "%s: unable to get"
 				" qcom,gpio-num property\n", __func__);
-			ret = -EINVAL;
-			goto err_probe;
-		} else if (len != sizeof(__be32)) {
-			dev_err(&spmi->dev, "%s: invalid qcom,gpio-num"
-				" property\n", __func__);
-			ret = -EINVAL;
 			goto err_probe;
 		}
 
-		gpio = be32_to_cpup(prop);
 		if (gpio < lowest_gpio)
 			lowest_gpio = gpio;
 		if (gpio > highest_gpio)
@@ -633,12 +883,12 @@
 	if (highest_gpio < lowest_gpio) {
 		dev_err(&spmi->dev, "%s: no device nodes specified in"
 					" topology\n", __func__);
-		ret = -EINVAL;
+		rc = -EINVAL;
 		goto err_probe;
 	} else if (lowest_gpio == 0) {
 		dev_err(&spmi->dev, "%s: 0 is not a valid PMIC GPIO\n",
 								__func__);
-		ret = -EINVAL;
+		rc = -EINVAL;
 		goto err_probe;
 	}
 
@@ -654,7 +904,7 @@
 	if (!q_chip->pmic_gpios || !q_chip->chip_gpios) {
 		dev_err(&spmi->dev, "%s: unable to allocate memory\n",
 								__func__);
-		ret = -ENOMEM;
+		rc = -ENOMEM;
 		goto err_probe;
 	}
 
@@ -663,7 +913,7 @@
 	if (!q_chip->int_ctrl) {
 		dev_err(&spmi->dev, "%s: Can't find interrupt parent\n",
 								__func__);
-		ret = -EINVAL;
+		rc = -EINVAL;
 		goto err_probe;
 	}
 
@@ -676,20 +926,13 @@
 				__func__, spmi->dev_node[i].of_node->full_name);
 		}
 
-		prop = of_get_property(spmi->dev_node[i].of_node,
-				"qcom,gpio-num", &len);
-		if (!prop) {
+		rc = of_property_read_u32(spmi->dev_node[i].of_node,
+							"qcom,gpio-num", &gpio);
+		if (rc) {
 			dev_err(&spmi->dev, "%s: unable to get"
 				" qcom,gpio-num property\n", __func__);
-			ret = -EINVAL;
-			goto err_probe;
-		} else if (len != sizeof(__be32)) {
-			dev_err(&spmi->dev, "%s: invalid qcom,qpnp-gpio-num"
-				" property\n", __func__);
-			ret = -EINVAL;
 			goto err_probe;
 		}
-		gpio = be32_to_cpup(prop);
 
 		q_spec = kzalloc(sizeof(struct qpnp_gpio_spec),
 							GFP_KERNEL);
@@ -697,7 +940,7 @@
 			dev_err(&spmi->dev, "%s: unable to allocate"
 						" memory\n",
 					__func__);
-			ret = -ENOMEM;
+			rc = -ENOMEM;
 			goto err_probe;
 		}
 
@@ -706,13 +949,13 @@
 		q_spec->gpio_chip_idx = i;
 		q_spec->pmic_gpio = gpio;
 		q_spec->node = spmi->dev_node[i].of_node;
+		q_spec->q_chip = q_chip;
 
 		rc = spmi_ext_register_readl(spmi->ctrl, q_spec->slave,
 				Q_REG_ADDR(q_spec, Q_REG_TYPE), &buf[0], 2);
 		if (rc) {
 			dev_err(&spmi->dev, "%s: unable to read type regs\n",
 						__func__);
-			ret = rc;
 			goto err_probe;
 		}
 		q_spec->type	= buf[0];
@@ -727,10 +970,10 @@
 		if (!q_spec->irq) {
 			dev_err(&spmi->dev, "%s: invalid irq for gpio"
 					" %u\n", __func__, gpio);
-			ret = -EINVAL;
+			rc = -EINVAL;
 			goto err_probe;
 		}
-		/* initialize lookup table entries */
+		/* initialize lookup table params */
 		qpnp_pmic_gpio_set_spec(q_chip, gpio, q_spec);
 		qpnp_chip_gpio_set_spec(q_chip, i, q_spec);
 	}
@@ -752,43 +995,49 @@
 	if (rc) {
 		dev_err(&spmi->dev, "%s: Can't add gpio chip, rc = %d\n",
 								__func__, rc);
-		ret = rc;
 		goto err_probe;
 	}
 
 	/* now configure gpio config defaults if they exist */
 	for (i = 0; i < spmi->num_dev_node; i++) {
 		q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
-		if (WARN_ON(!q_spec))
-			return -ENODEV;
+		if (WARN_ON(!q_spec)) {
+			rc = -ENODEV;
+			goto err_probe;
+		}
 
 		rc = qpnp_gpio_cache_regs(q_chip, q_spec);
-		if (rc) {
-			ret = rc;
+		if (rc)
 			goto err_probe;
-		}
 
 		rc = qpnp_gpio_apply_config(q_chip, q_spec);
-		if (rc) {
-			ret = rc;
+		if (rc)
 			goto err_probe;
-		}
 	}
 
 	dev_dbg(&spmi->dev, "%s: gpio_chip registered between %d-%u\n",
 			__func__, q_chip->gpio_chip.base,
 			(q_chip->gpio_chip.base + q_chip->gpio_chip.ngpio) - 1);
+
+	rc = qpnp_gpio_debugfs_create(q_chip);
+	if (rc) {
+		dev_err(&spmi->dev, "%s: debugfs creation failed\n", __func__);
+		goto err_probe;
+	}
+
 	return 0;
 
 err_probe:
 	qpnp_gpio_free_chip(q_chip);
-	return ret;
+	return rc;
 }
 
 static int qpnp_gpio_remove(struct spmi_device *spmi)
 {
 	struct qpnp_gpio_chip *q_chip = dev_get_drvdata(&spmi->dev);
 
+	debugfs_remove_recursive(q_chip->dfs_dir);
+
 	return qpnp_gpio_free_chip(q_chip);
 }
 
@@ -816,11 +1065,21 @@
 
 static int __init qpnp_gpio_init(void)
 {
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+	driver_dfs_dir = debugfs_create_dir("qpnp_gpio", NULL);
+	if (driver_dfs_dir == NULL)
+		pr_err("Cannot register top level debugfs directory\n");
+#endif
+
 	return spmi_driver_register(&qpnp_gpio_driver);
 }
 
 static void __exit qpnp_gpio_exit(void)
 {
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+	debugfs_remove_recursive(driver_dfs_dir);
+#endif
+	spmi_driver_unregister(&qpnp_gpio_driver);
 }
 
 MODULE_DESCRIPTION("QPNP PMIC gpio driver");
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 00dba96..7c152721 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -263,7 +263,7 @@
 	 */
 
 	if (adreno_is_a3xx(adreno_dev)) {
-		kgsl_mmu_device_setstate(device, flags);
+		kgsl_mmu_device_setstate(&device->mmu, flags);
 		return;
 	}
 
@@ -349,7 +349,7 @@
 		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
 					&link[0], sizedwords);
 	} else {
-		kgsl_mmu_device_setstate(device, flags);
+		kgsl_mmu_device_setstate(&device->mmu, flags);
 	}
 }
 
@@ -575,7 +575,7 @@
 	}
 
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
-	kgsl_mmu_stop(device);
+	kgsl_mmu_stop(&device->mmu);
 error_clk_off:
 	kgsl_pwrctrl_disable(device);
 
@@ -590,7 +590,7 @@
 
 	adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
 
-	kgsl_mmu_stop(device);
+	kgsl_mmu_stop(&device->mmu);
 
 	device->ftbl->irqctrl(device, 0);
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 050fd83..e10edea 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1510,7 +1510,7 @@
 
 	if (context == NULL) {
 		/* No context - set the default apgetable and thats it */
-		kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
+		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable);
 		return;
 	}
 
@@ -1523,7 +1523,7 @@
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
 	cmds[4] = context->id;
 	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
-	kgsl_mmu_setstate(device, context->pagetable);
+	kgsl_mmu_setstate(&device->mmu, context->pagetable);
 
 #ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
 	kgsl_cffdump_syncmem(NULL, &context->gpustate,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 6b58545..8c5d76a 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2257,7 +2257,7 @@
 
 	if (context == NULL) {
 		/* No context - set the default pagetable and thats it */
-		kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
+		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable);
 		return;
 	}
 
@@ -2270,7 +2270,7 @@
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
 	cmds[4] = context->id;
 	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
-	kgsl_mmu_setstate(device, context->pagetable);
+	kgsl_mmu_setstate(&device->mmu, context->pagetable);
 
 	/*
 	 * Restore GMEM.  (note: changes shader.
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 6bdf284..9d68c60 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -661,7 +661,7 @@
 
 	kgsl_regread(device, MH_MMU_MPU_END, &r1);
 	kgsl_regread(device, MH_MMU_VA_RANGE, &r2);
-	r3 = kgsl_mmu_get_current_ptbase(device);
+	r3 = kgsl_mmu_get_current_ptbase(&device->mmu);
 	KGSL_LOG_DUMP(device,
 		"        MPU_END    = %08X | VA_RANGE = %08X | PT_BASE  ="
 		" %08X\n", r1, r2, r3);
@@ -706,7 +706,7 @@
 	else if (adreno_is_a3xx(adreno_dev))
 		adreno_dump_a3xx(device);
 
-	pt_base = kgsl_mmu_get_current_ptbase(device);
+	pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
 	cur_pt_base = pt_base;
 
 	kgsl_regread(device, REG_CP_RB_BASE, &cp_rb_base);
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 2dc6f6c..a0907d7 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -531,7 +531,7 @@
 	int skip_pktsize = 1;
 
 	/* Get the physical address of the MMU pagetable */
-	ptbase = kgsl_mmu_get_current_ptbase(device);
+	ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
 
 	/* Get the current read pointers for the RB */
 	kgsl_regread(device, REG_CP_RB_RPTR, &rptr);
@@ -792,7 +792,7 @@
 	memset(vbo, 0, sizeof(vbo));
 
 	/* Get the physical address of the MMU pagetable */
-	ptbase = kgsl_mmu_get_current_ptbase(device);
+	ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
 
 	/* Dump the ringbuffer */
 	snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_RB,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 321c59e..072edad 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -537,6 +537,10 @@
 			INIT_COMPLETION(device->hwaccess_gate);
 			device->ftbl->suspend_context(device);
 			device->ftbl->stop(device);
+			if (device->idle_wakelock.name)
+				wake_unlock(&device->idle_wakelock);
+			pm_qos_update_request(&device->pm_qos_req_dma,
+						PM_QOS_DEFAULT_VALUE);
 			kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND);
 			break;
 		case KGSL_STATE_SLUMBER:
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 1d80a30..5a10654 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -686,12 +686,10 @@
 	return 0;
 }
 
-static int kgsl_gpummu_stop(struct kgsl_mmu *mmu)
+static void kgsl_gpummu_stop(struct kgsl_mmu *mmu)
 {
 	kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
 	mmu->flags &= ~KGSL_FLAGS_STARTED;
-
-	return 0;
 }
 
 static int kgsl_gpummu_close(struct kgsl_mmu *mmu)
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index bf2a4ee..e2a945f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.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
@@ -16,32 +16,13 @@
 #include <linux/genalloc.h>
 #include <linux/slab.h>
 #include <linux/iommu.h>
-#include <mach/iommu.h>
 #include <linux/msm_kgsl.h>
 
 #include "kgsl.h"
 #include "kgsl_device.h"
 #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 kgsl_iommu_device dev[KGSL_IOMMU_MAX_DEV];
-	int dev_count;
-};
+#include "kgsl_iommu.h"
 
 static int kgsl_iommu_pt_equal(struct kgsl_pagetable *pt,
 					unsigned int pt_base)
@@ -66,103 +47,181 @@
 	return domain;
 }
 
+/*
+ * kgsl_detach_pagetable_iommu_domain - Detach the IOMMU unit from a
+ * pagetable
+ * @mmu - Pointer to the device mmu structure
+ * @priv - Flag indicating whether the private or user context is to be
+ * detached
+ *
+ * Detach the IOMMU unit with the domain that is contained in the
+ * hwpagetable of the given mmu. After detaching the IOMMU unit is not
+ * in use because the PTBR will not be set after a detach
+ * Return - void
+ */
 static void kgsl_detach_pagetable_iommu_domain(struct kgsl_mmu *mmu)
 {
 	struct iommu_domain *domain;
 	struct kgsl_iommu *iommu = mmu->priv;
-	int i;
+	int i, j;
 
 	BUG_ON(mmu->hwpagetable == NULL);
 	BUG_ON(mmu->hwpagetable->priv == NULL);
 
 	domain = mmu->hwpagetable->priv;
 
-	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);
+	for (i = 0; i < iommu->unit_count; i++) {
+		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
+		for (j = 0; j < iommu_unit->dev_count; j++) {
+			if (iommu_unit->dev[j].attached) {
+				iommu_detach_device(domain,
+						iommu_unit->dev[j].dev);
+				iommu_unit->dev[j].attached = false;
+				KGSL_MEM_INFO(mmu->device, "iommu %p detached "
+					"from user dev of MMU: %p\n",
+					domain, mmu);
+			}
+		}
 	}
 }
 
+/*
+ * kgsl_attach_pagetable_iommu_domain - Attach the IOMMU unit to a
+ * pagetable, i.e set the IOMMU's PTBR to the pagetable address and
+ * setup other IOMMU registers for the device so that it becomes
+ * active
+ * @mmu - Pointer to the device mmu structure
+ * @priv - Flag indicating whether the private or user context is to be
+ * attached
+ *
+ * Attach the IOMMU unit with the domain that is contained in the
+ * hwpagetable of the given mmu.
+ * Return - 0 on success else error code
+ */
 static int kgsl_attach_pagetable_iommu_domain(struct kgsl_mmu *mmu)
 {
 	struct iommu_domain *domain;
 	struct kgsl_iommu *iommu = mmu->priv;
-	int i, ret = 0;
+	int i, j, ret = 0;
 
 	BUG_ON(mmu->hwpagetable == NULL);
 	BUG_ON(mmu->hwpagetable->priv == NULL);
 
 	domain = mmu->hwpagetable->priv;
 
-	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",
+	/*
+	 * Loop through all the iommu devcies under all iommu units and
+	 * attach the domain
+	 */
+	for (i = 0; i < iommu->unit_count; i++) {
+		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
+		for (j = 0; j < iommu_unit->dev_count; j++) {
+			if (!iommu_unit->dev[j].attached) {
+				ret = iommu_attach_device(domain,
+							iommu_unit->dev[j].dev);
+				if (ret) {
+					KGSL_MEM_ERR(mmu->device,
+						"Failed to attach device, err %d\n",
 						ret);
-				goto done;
+					goto done;
+				}
+				iommu_unit->dev[j].attached = true;
+				KGSL_MEM_INFO(mmu->device,
+				"iommu pt %p attached to dev %p, ctx_id %d\n",
+					domain, iommu_unit->dev[j].dev,
+					iommu_unit->dev[j].ctx_id);
 			}
-
-			iommu->dev[i].attached = 1;
-			KGSL_MEM_INFO(mmu->device,
-				"iommu %p detached from user 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)
+/*
+ * _get_iommu_ctxs - Get device pointer to IOMMU contexts
+ * @mmu - Pointer to mmu device
+ * data - Pointer to the platform data containing information about
+ * iommu devices for one iommu unit
+ * unit_id - The IOMMU unit number. This is not a specific ID but just
+ * a serial number. The serial numbers are treated as ID's of the
+ * IOMMU units
+ *
+ * Return - 0 on success else error code
+ */
+static int _get_iommu_ctxs(struct kgsl_mmu *mmu,
+	struct kgsl_device_iommu_data *data, unsigned int unit_id)
 {
+	struct kgsl_iommu *iommu = mmu->priv;
+	struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[unit_id];
 	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_count > KGSL_IOMMU_MAX_DEVS_PER_UNIT) {
+		KGSL_CORE_ERR("Too many iommu devices defined for an "
+				"IOMMU unit\n");
+		return -EINVAL;
+	}
 
-		if (!data->iommu_ctx_names[i])
+	for (i = 0; i < data->iommu_ctx_count; i++) {
+		if (!data->iommu_ctxs[i].iommu_ctx_name)
 			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]);
+		iommu_unit->dev[iommu_unit->dev_count].dev =
+			msm_iommu_get_ctx(data->iommu_ctxs[i].iommu_ctx_name);
+		if (iommu_unit->dev[iommu_unit->dev_count].dev == NULL) {
+			KGSL_CORE_ERR("Failed to get iommu dev handle for "
+			"device %s\n", data->iommu_ctxs[i].iommu_ctx_name);
 			return -EINVAL;
 		}
+		if (KGSL_IOMMU_CONTEXT_USER != data->iommu_ctxs[i].ctx_id &&
+			KGSL_IOMMU_CONTEXT_PRIV != data->iommu_ctxs[i].ctx_id) {
+			KGSL_CORE_ERR("Invalid context ID defined: %d\n",
+					data->iommu_ctxs[i].ctx_id);
+			return -EINVAL;
+		}
+		iommu_unit->dev[iommu_unit->dev_count].ctx_id =
+						data->iommu_ctxs[i].ctx_id;
+		KGSL_DRV_INFO(mmu->device,
+				"Obtained dev handle %p for iommu context %s\n",
+				iommu_unit->dev[iommu_unit->dev_count].dev,
+				data->iommu_ctxs[i].iommu_ctx_name);
 
-		iommu->dev_count++;
+		iommu_unit->dev_count++;
 	}
 
 	return 0;
 }
 
-static int kgsl_get_iommu_ctxt(struct kgsl_iommu *iommu,
-				struct kgsl_device *device)
+/*
+ * kgsl_get_iommu_ctxt - Get device pointer to IOMMU contexts
+ * @mmu - Pointer to mmu device
+ *
+ * Get the device pointers for the IOMMU user and priv contexts of the
+ * kgsl device
+ * Return - 0 on success else error code
+ */
+static int kgsl_get_iommu_ctxt(struct kgsl_mmu *mmu)
 {
-	struct kgsl_device_platform_data *pdata =
-		kgsl_device_get_drvdata(device);
+	struct platform_device *pdev =
+		container_of(mmu->device->parentdev, struct platform_device,
+				dev);
+	struct kgsl_device_platform_data *pdata_dev = pdev->dev.platform_data;
+	struct kgsl_iommu *iommu = mmu->device->mmu.priv;
 	int i, ret = 0;
 
-	/* Go through the IOMMU data and attach all the domains */
+	/* Go through the IOMMU data and get all the context devices */
+	if (KGSL_IOMMU_MAX_UNITS < pdata_dev->iommu_count) {
+		KGSL_CORE_ERR("Too many IOMMU units defined\n");
+		ret = -EINVAL;
+		goto  done;
+	}
 
-	for (i = 0; i < pdata->iommu_count; i++) {
-		ret = _get_iommu_ctxs(iommu, device,
-			&pdata->iommu_data[i]);
+	for (i = 0; i < pdata_dev->iommu_count; i++) {
+		ret = _get_iommu_ctxs(mmu, &pdata_dev->iommu_data[i], i);
 		if (ret)
 			break;
 	}
-
+	iommu->unit_count = pdata_dev->iommu_count;
+done:
 	return ret;
 }
 
@@ -200,15 +259,18 @@
 		return -ENOMEM;
 	}
 
-	status = kgsl_get_iommu_ctxt(iommu, mmu->device);
-	if (status) {
-		kfree(iommu);
-		iommu = NULL;
-	}
 	mmu->priv = iommu;
+	status = kgsl_get_iommu_ctxt(mmu);
+	if (status)
+		goto done;
 
 	dev_info(mmu->device->dev, "|%s| MMU type set for device is IOMMU\n",
 			__func__);
+done:
+	if (status) {
+		kfree(iommu);
+		mmu->priv = NULL;
+	}
 	return status;
 }
 
@@ -229,8 +291,12 @@
 	mmu->hwpagetable = mmu->defaultpagetable;
 
 	status = kgsl_attach_pagetable_iommu_domain(mmu);
-	if (!status)
+	if (!status) {
 		mmu->flags |= KGSL_FLAGS_STARTED;
+	} else {
+		kgsl_detach_pagetable_iommu_domain(mmu);
+		mmu->hwpagetable = NULL;
+	}
 
 	return status;
 }
@@ -298,7 +364,7 @@
 	return ret;
 }
 
-static int kgsl_iommu_stop(struct kgsl_mmu *mmu)
+static void kgsl_iommu_stop(struct kgsl_mmu *mmu)
 {
 	/*
 	 *  stop device mmu
@@ -309,11 +375,10 @@
 	if (mmu->flags & KGSL_FLAGS_STARTED) {
 		/* detach iommu attachment */
 		kgsl_detach_pagetable_iommu_domain(mmu);
+		mmu->hwpagetable = NULL;
 
 		mmu->flags &= ~KGSL_FLAGS_STARTED;
 	}
-
-	return 0;
 }
 
 static int kgsl_iommu_close(struct kgsl_mmu *mmu)
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
new file mode 100644
index 0000000..e2033c5
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __KGSL_IOMMU_H
+#define __KGSL_IOMMU_H
+
+#include <mach/iommu.h>
+
+/*
+ * Max number of iommu units that the gpu core can have
+ * On APQ8064, KGSL can control a maximum of 2 IOMMU units.
+ */
+#define KGSL_IOMMU_MAX_UNITS 2
+
+/* Max number of iommu contexts per IOMMU unit */
+#define KGSL_IOMMU_MAX_DEVS_PER_UNIT 2
+
+/*
+ * struct kgsl_iommu_device - Structure holding data about iommu contexts
+ * @dev: Device pointer to iommu context
+ * @attached: Indicates whether this iommu context is presently attached to
+ * a pagetable/domain or not
+ * @pt_lsb: The LSB of IOMMU_TTBR0 register which is the pagetable
+ * register
+ * @ctx_id: This iommu units context id. It can be either 0 or 1
+ * @clk_enabled: If set indicates that iommu clocks of this iommu context
+ * are on, else the clocks are off
+ */
+struct kgsl_iommu_device {
+	struct device *dev;
+	bool attached;
+	unsigned int pt_lsb;
+	enum kgsl_iommu_context_id ctx_id;
+	bool clk_enabled;
+};
+
+/*
+ * struct kgsl_iommu_unit - Structure holding data about iommu units. An IOMMU
+ * units is basically a separte IOMMU h/w block with it's own IOMMU contexts
+ * @dev: Pointer to array of struct kgsl_iommu_device which has information
+ * about the IOMMU contexts under this IOMMU unit
+ * @dev_count: Number of IOMMU contexts that are valid in the previous feild
+ * @reg_map: Memory descriptor which holds the mapped address of this IOMMU
+ * units register range
+ */
+struct kgsl_iommu_unit {
+	struct kgsl_iommu_device dev[KGSL_IOMMU_MAX_DEVS_PER_UNIT];
+	unsigned int dev_count;
+	struct kgsl_memdesc reg_map;
+};
+
+/*
+ * struct kgsl_iommu - Structure holding iommu data for kgsl driver
+ * @dev: Array of kgsl_iommu_device which contain information about
+ * iommu contexts owned by graphics cores
+ * @unit_count: Number of IOMMU units that are available for this
+ * instance of the IOMMU driver
+ * @iommu_last_cmd_ts: The timestamp of last command submitted that
+ * aceeses iommu registers
+ * @device: Pointer to kgsl device
+ * @asids: A bit structure indicating which id's are presently used
+ * @asid: Contains the initial value of IOMMU_CONTEXTIDR when a domain
+ * is first attached
+ */
+struct kgsl_iommu {
+	struct kgsl_iommu_unit iommu_units[KGSL_IOMMU_MAX_UNITS];
+	unsigned int unit_count;
+	unsigned int iommu_last_cmd_ts;
+	struct kgsl_device *device;
+	unsigned long *asids;
+	unsigned int asid;
+	unsigned int active_ctx;
+};
+
+#endif
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 2b359ec..e11b119 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -322,16 +322,6 @@
 		return 0;
 }
 
-unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_device *device)
-{
-	struct kgsl_mmu *mmu = &device->mmu;
-	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
-		return 0;
-	else
-		return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
-}
-EXPORT_SYMBOL(kgsl_mmu_get_current_ptbase);
-
 int
 kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base)
 {
@@ -351,19 +341,6 @@
 }
 EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase);
 
-void kgsl_mmu_setstate(struct kgsl_device *device,
-			struct kgsl_pagetable *pagetable)
-{
-	struct kgsl_mmu *mmu = &device->mmu;
-
-	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
-		return;
-	else
-		mmu->mmu_ops->mmu_setstate(mmu,
-					pagetable);
-}
-EXPORT_SYMBOL(kgsl_mmu_setstate);
-
 int kgsl_mmu_init(struct kgsl_device *device)
 {
 	struct kgsl_mmu *mmu = &device->mmu;
@@ -555,16 +532,6 @@
 }
 EXPORT_SYMBOL(kgsl_setstate);
 
-void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags)
-{
-	struct kgsl_mmu *mmu = &device->mmu;
-	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
-		return;
-	else if (mmu->mmu_ops->mmu_device_setstate)
-		mmu->mmu_ops->mmu_device_setstate(mmu, flags);
-}
-EXPORT_SYMBOL(kgsl_mmu_device_setstate);
-
 void kgsl_mh_start(struct kgsl_device *device)
 {
 	struct kgsl_mh *mh = &device->mh;
@@ -746,17 +713,6 @@
 }
 EXPORT_SYMBOL(kgsl_mmu_map_global);
 
-int kgsl_mmu_stop(struct kgsl_device *device)
-{
-	struct kgsl_mmu *mmu = &device->mmu;
-
-	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
-		return 0;
-	else
-		return mmu->mmu_ops->mmu_stop(mmu);
-}
-EXPORT_SYMBOL(kgsl_mmu_stop);
-
 int kgsl_mmu_close(struct kgsl_device *device)
 {
 	struct kgsl_mmu *mmu = &device->mmu;
@@ -814,16 +770,6 @@
 }
 EXPORT_SYMBOL(kgsl_mmu_enabled);
 
-int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
-			unsigned int pt_base)
-{
-	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
-		return true;
-	else
-		return pt->pt_ops->mmu_pt_equal(pt, pt_base);
-}
-EXPORT_SYMBOL(kgsl_mmu_pt_equal);
-
 enum kgsl_mmutype kgsl_mmu_get_mmutype(void)
 {
 	return kgsl_mmu_type;
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index e35f368..b476add 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -122,7 +122,7 @@
 	int (*mmu_init) (struct kgsl_mmu *mmu);
 	int (*mmu_close) (struct kgsl_mmu *mmu);
 	int (*mmu_start) (struct kgsl_mmu *mmu);
-	int (*mmu_stop) (struct kgsl_mmu *mmu);
+	void (*mmu_stop) (struct kgsl_mmu *mmu);
 	void (*mmu_setstate) (struct kgsl_mmu *mmu,
 		struct kgsl_pagetable *pagetable);
 	void (*mmu_device_setstate) (struct kgsl_mmu *mmu,
@@ -169,7 +169,6 @@
 void kgsl_mh_intrcallback(struct kgsl_device *device);
 int kgsl_mmu_init(struct kgsl_device *device);
 int kgsl_mmu_start(struct kgsl_device *device);
-int kgsl_mmu_stop(struct kgsl_device *device);
 int kgsl_mmu_close(struct kgsl_device *device);
 int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
 		 struct kgsl_memdesc *memdesc,
@@ -180,19 +179,57 @@
 		    struct kgsl_memdesc *memdesc);
 unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
 void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags);
-void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags);
-void kgsl_mmu_setstate(struct kgsl_device *device,
-			struct kgsl_pagetable *pt);
 int kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base);
 int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
 			enum kgsl_deviceid id);
 void kgsl_mmu_ptpool_destroy(void *ptpool);
 void *kgsl_mmu_ptpool_init(int entries);
 int kgsl_mmu_enabled(void);
-int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
-			unsigned int pt_base);
 void kgsl_mmu_set_mmutype(char *mmutype);
-unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_device *device);
 enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
 unsigned int kgsl_mmu_get_ptsize(void);
+
+/*
+ * Static inline functions of MMU that simply call the SMMU specific
+ * function using a function pointer. These functions can be thought
+ * of as wrappers around the actual function
+ */
+
+static inline unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_current_ptbase)
+		return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
+	else
+		return 0;
+}
+
+static inline void kgsl_mmu_setstate(struct kgsl_mmu *mmu,
+			struct kgsl_pagetable *pagetable)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_setstate)
+		mmu->mmu_ops->mmu_setstate(mmu, pagetable);
+}
+
+static inline void kgsl_mmu_device_setstate(struct kgsl_mmu *mmu,
+						uint32_t flags)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_device_setstate)
+		mmu->mmu_ops->mmu_device_setstate(mmu, flags);
+}
+
+static inline void kgsl_mmu_stop(struct kgsl_mmu *mmu)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_stop)
+		mmu->mmu_ops->mmu_stop(mmu);
+}
+
+static inline int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
+			unsigned int pt_base)
+{
+	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_get_mmutype())
+		return 1;
+	else
+		return pt->pt_ops->mmu_pt_equal(pt, pt_base);
+}
+
 #endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 24ea571..f61c74f 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -122,7 +122,7 @@
 	header->current_context = -1;
 
 	/* Get the current PT base */
-	header->ptbase = kgsl_mmu_get_current_ptbase(device);
+	header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
 	/* And the PID for the task leader */
 	pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(header->ptbase);
 
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 3ca9e18..df2ca78 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -158,13 +158,6 @@
 		.active_cnt = 0,
 		.iomemname = KGSL_2D0_REG_MEMORY,
 		.ftbl = &z180_functable,
-#ifdef CONFIG_HAS_EARLYSUSPEND
-		.display_off = {
-			.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
-			.suspend = kgsl_early_suspend_driver,
-			.resume = kgsl_late_resume_driver,
-		},
-#endif
 	},
 };
 
@@ -196,13 +189,6 @@
 		.active_cnt = 0,
 		.iomemname = KGSL_2D1_REG_MEMORY,
 		.ftbl = &z180_functable,
-		.display_off = {
-#ifdef CONFIG_HAS_EARLYSUSPEND
-			.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
-			.suspend = kgsl_early_suspend_driver,
-			.resume = kgsl_late_resume_driver,
-#endif
-		},
 	},
 };
 
@@ -464,7 +450,7 @@
 	    (ctrl & KGSL_CONTEXT_CTX_SWITCH)) {
 		KGSL_CMD_INFO(device, "context switch %d -> %d\n",
 			context->id, z180_dev->ringbuffer.prevctx);
-		kgsl_mmu_setstate(device, pagetable);
+		kgsl_mmu_setstate(&device->mmu, pagetable);
 		cnt = PACKETSIZE_STATESTREAM;
 		ofs = 0;
 	}
@@ -613,7 +599,7 @@
 
 	del_timer_sync(&device->idle_timer);
 
-	kgsl_mmu_stop(device);
+	kgsl_mmu_stop(&device->mmu);
 
 	/* Disable the clocks before the power rail. */
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index c7aa2ce..dc1feaa 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -2,6 +2,7 @@
  *  GPIO driven matrix keyboard driver
  *
  *  Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
+ *  Copyright (c) 2012, Code Aurora Forum. All rights reserved.
  *
  *  Based on corgikbd.c
  *
@@ -34,7 +35,7 @@
 
 	uint32_t last_key_state[MATRIX_MAX_COLS];
 	struct delayed_work work;
-	spinlock_t lock;
+	struct mutex lock;
 	bool scan_pending;
 	bool stopped;
 	bool gpio_all_disabled;
@@ -162,19 +163,17 @@
 
 	activate_all_cols(pdata, true);
 
-	/* Enable IRQs again */
-	spin_lock_irq(&keypad->lock);
+	mutex_lock(&keypad->lock);
 	keypad->scan_pending = false;
 	enable_row_irqs(keypad);
-	spin_unlock_irq(&keypad->lock);
+	mutex_unlock(&keypad->lock);
 }
 
 static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
 {
 	struct matrix_keypad *keypad = id;
-	unsigned long flags;
 
-	spin_lock_irqsave(&keypad->lock, flags);
+	mutex_lock(&keypad->lock);
 
 	/*
 	 * See if another IRQ beaten us to it and scheduled the
@@ -190,7 +189,7 @@
 		msecs_to_jiffies(keypad->pdata->debounce_ms));
 
 out:
-	spin_unlock_irqrestore(&keypad->lock, flags);
+	mutex_unlock(&keypad->lock);
 	return IRQ_HANDLED;
 }
 
@@ -341,10 +340,11 @@
 		}
 	} else {
 		for (i = 0; i < pdata->num_row_gpios; i++) {
-			err = request_any_context_irq(
+			err = request_threaded_irq(
 					gpio_to_irq(pdata->row_gpios[i]),
+					NULL,
 					matrix_keypad_interrupt,
-					IRQF_DISABLED |
+					IRQF_DISABLED | IRQF_ONESHOT |
 					IRQF_TRIGGER_RISING |
 					IRQF_TRIGGER_FALLING,
 					"matrix-keypad", keypad);
@@ -417,7 +417,7 @@
 	keypad->row_shift = row_shift;
 	keypad->stopped = true;
 	INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
-	spin_lock_init(&keypad->lock);
+	mutex_init(&keypad->lock);
 
 	input_dev->name		= pdev->name;
 	input_dev->id.bustype	= BUS_HOST;
@@ -479,6 +479,7 @@
 	for (i = 0; i < pdata->num_col_gpios; i++)
 		gpio_free(pdata->col_gpios[i]);
 
+	mutex_destroy(&keypad->lock);
 	input_unregister_device(keypad->input_dev);
 	platform_set_drvdata(pdev, NULL);
 	kfree(keypad->keycodes);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index a276e84..fd72638 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -963,7 +963,8 @@
 
 	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
 		HCI_OCF_FM_DEFAULT_DATA_WRITE);
-	return radio_hci_send_cmd(hdev, opcode, sizeof((*def_data_wr)),
+
+	return radio_hci_send_cmd(hdev, opcode, (def_data_wr->length+2),
 	def_data_wr);
 }
 
@@ -2470,7 +2471,7 @@
 			radio->fm_hdev);
 	if (retval < 0)
 		FMDERR("Disable Failed after calibration %d", retval);
-		return retval;
+	return retval;
 }
 static int iris_vidioc_g_ctrl(struct file *file, void *priv,
 		struct v4l2_control *ctrl)
@@ -2726,10 +2727,44 @@
 	case V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT:
 		data = (ctrl->controls[0]).string;
 		memset(&default_data, 0, sizeof(default_data));
-		if (copy_from_user(&default_data, data, sizeof(default_data)))
+		/*
+		 * Check if length of the 'FM Default Data' to be sent
+		 * is within the maximum  'FM Default Data' packet limit.
+		 * Max. 'FM Default Data' packet length is 251 bytes:
+		 *	1 byte    - XFR Mode
+		 *	1 byte    - length of the default data
+		 *	249 bytes - actual data to be configured
+		 */
+		if (ctrl->controls[0].size > (DEFAULT_DATA_SIZE + 2)) {
+			pr_err("%s: Default data buffer overflow!\n", __func__);
+			return -EINVAL;
+		}
+
+		/* copy only 'size' bytes of data as requested by user */
+		retval = copy_from_user(&default_data, data,
+			ctrl->controls[0].size);
+		if (retval > 0) {
+			pr_err("%s: Failed to copy %d bytes of default data"
+				" passed by user\n", __func__, retval);
 			return -EFAULT;
+		}
+		FMDBG("%s: XFR Mode\t: 0x%x\n", __func__, default_data.mode);
+		FMDBG("%s: XFR Data Length\t: %d\n", __func__,
+			default_data.length);
+		/*
+		 * Check if the 'length' of the actual XFR data to be configured
+		 * is valid or not. Length of actual XFR data should be always
+		 * 2 bytes less than the total length of the 'FM Default Data'.
+		 * Length of 'FM Default Data' DEF_DATA_LEN: (1+1+XFR Data Size)
+		 * Length of 'Actual XFR Data' XFR_DATA_LEN: (DEF_DATA_LEN - 2)
+		 */
+		if (default_data.length != (ctrl->controls[0].size - 2)) {
+			pr_err("%s: Invalid 'length' parameter passed for "
+				"actual xfr data\n", __func__);
+			return -EINVAL;
+		}
 		retval = hci_def_data_write(&default_data, radio->fm_hdev);
-			break;
+		break;
 	case V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION:
 		data = (ctrl->controls[0]).string;
 		bytes_to_copy = (ctrl->controls[0]).size;
@@ -3377,7 +3412,12 @@
 					struct v4l2_hw_freq_seek *seek)
 {
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
-	return iris_search(radio, CTRL_ON, seek->seek_upward);
+	int dir;
+	if (seek->seek_upward)
+		dir = SRCH_DIR_UP;
+	else
+		dir = SRCH_DIR_DOWN;
+	return iris_search(radio, CTRL_ON, dir);
 }
 
 static int iris_vidioc_querycap(struct file *file, void *priv,
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index acf551e..c15609f 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -3561,14 +3561,21 @@
 {
 
 	struct tavarua_device  *radio = video_get_drvdata(video_devdata(file));
-	enum tavarua_buf_t buf_type = buffer->index;
-	struct kfifo *data_fifo;
-	unsigned char *buf = (unsigned char *)buffer->m.userptr;
-	unsigned int len = buffer->length;
+	enum tavarua_buf_t buf_type = -1;
+	unsigned char buf_fifo[STD_BUF_SIZE] = {0};
+	struct kfifo *data_fifo = NULL;
+	unsigned char *buf = NULL;
+	unsigned int len = 0, retval = -1;
+
+	if ((radio == NULL) || (buffer == NULL)) {
+		FMDERR("radio/buffer is NULL\n");
+		return -ENXIO;
+	}
+	buf_type = buffer->index;
+	buf = (unsigned char *)buffer->m.userptr;
+	len = buffer->length;
 	FMDBG("%s: requesting buffer %d\n", __func__, buf_type);
-	/* check if we can access the user buffer */
-	if (!access_ok(VERIFY_WRITE, buf, len))
-		return -EFAULT;
+
 	if ((buf_type < TAVARUA_BUF_MAX) && (buf_type >= 0)) {
 		data_fifo = &radio->data_buf[buf_type];
 		if (buf_type == TAVARUA_BUF_EVENTS) {
@@ -3581,10 +3588,20 @@
 		FMDERR("invalid buffer type\n");
 		return -EINVAL;
 	}
-	buffer->bytesused = kfifo_out_locked(data_fifo, buf, len,
-					&radio->buf_lock[buf_type]);
+	if (len <= STD_BUF_SIZE) {
+		buffer->bytesused = kfifo_out_locked(data_fifo, &buf_fifo[0],
+					len, &radio->buf_lock[buf_type]);
+	} else {
+		FMDERR("kfifo_out_locked can not use len more than 128\n");
+		return -EINVAL;
+	}
+	retval = copy_to_user(buf, &buf_fifo[0], buffer->bytesused);
+	if (retval > 0) {
+		FMDERR("Failed to copy %d bytes of data\n", retval);
+		return -EAGAIN;
+	}
 
-	return 0;
+	return retval;
 }
 
 /*=============================================================================
@@ -3633,8 +3650,13 @@
 					struct v4l2_hw_freq_seek *seek)
 {
 	struct tavarua_device  *radio = video_get_drvdata(video_devdata(file));
+	int dir;
+	if (seek->seek_upward)
+		dir = SRCH_DIR_UP;
+	else
+		dir = SRCH_DIR_DOWN;
 	FMDBG("starting search\n");
-	return tavarua_search(radio, CTRL_ON, seek->seek_upward);
+	return tavarua_search(radio, CTRL_ON, dir);
 }
 
 /*
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 6d8cc5c..eee351b 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -115,7 +115,7 @@
 	if (rc < 0)
 		goto err_request_irq;
 
-	device_init_wakeup(pdata->can_wakeup);
+	device_init_wakeup(&pdev->dev, pdata->can_wakeup);
 
 	return 0;
 
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.c b/drivers/media/video/msm/gemini/msm_gemini_platform.c
index fb5b035..39b135d 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_platform.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_platform.c
@@ -82,17 +82,17 @@
 }
 
 static struct msm_cam_clk_info gemini_8x_clk_info[] = {
-	{"ijpeg_clk", 228571000},
-	{"ijpeg_pclk", -1},
+	{"core_clk", 228571000},
+	{"iface_clk", -1},
 };
 
 static struct msm_cam_clk_info gemini_7x_clk_info[] = {
-	{"jpeg_clk", 153600000},
-	{"jpeg_pclk", -1},
+	{"core_clk", 153600000},
+	{"iface_clk", -1},
 };
 
 static struct msm_cam_clk_info gemini_imem_clk_info[] = {
-	{"imem_clk", -1},
+	{"mem_clk", -1},
 };
 
 int msm_gemini_platform_init(struct platform_device *pdev,
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index eff64be..668fd8e 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -25,6 +25,7 @@
 #include "msm_ispif.h"
 #include "msm_sensor.h"
 #include "msm_actuator.h"
+#include "msm_vfe32.h"
 
 #define MSM_MAX_CAMERA_SENSORS 5
 
@@ -1525,6 +1526,7 @@
 	/*for single VFE msms (8660, 8960v1), just populate the session
 	with our VFE devices that registered*/
 	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	pmctl->axi_sdev = ps->axi_device[0];
 	pmctl->isp_sdev = ps->isp_subdev[0];
 	return rc;
 }
@@ -2548,16 +2550,37 @@
 				g_server_dev.vfe_device[0], notification, arg);
 		}
 		break;
-	case NOTIFY_VPE_MSG_EVT:
-		if (g_server_dev.isp_subdev[0] &&
-			g_server_dev.isp_subdev[0]->isp_notify) {
-			rc = g_server_dev.isp_subdev[0]->isp_notify(
-				g_server_dev.vpe_device[0], notification, arg);
-		}
+	case NOTIFY_VPE_MSG_EVT: {
+		struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)
+		v4l2_get_subdev_hostdata(sd);
+		struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
+		msm_mctl_pp_notify(pmctl,
+		(struct msm_mctl_pp_frame_info *)
+		vdata->extdata);
+		break;
+	}
+	case NOTIFY_VFE_IRQ:{
+		struct msm_vfe_cfg_cmd cfg_cmd;
+		struct msm_camvfe_params vfe_params;
+		cfg_cmd.cmd_type = CMD_VFE_PROCESS_IRQ;
+		vfe_params.vfe_cfg = &cfg_cmd;
+		vfe_params.data = arg;
+		rc = v4l2_subdev_call(g_server_dev.vfe_device[0],
+			core, ioctl, 0, &vfe_params);
+	}
+		break;
+	case NOTIFY_AXI_IRQ:
+		rc = v4l2_subdev_call(g_server_dev.axi_device[0],
+			core, ioctl, VIDIOC_MSM_AXI_IRQ, arg);
 		break;
 	case NOTIFY_PCLK_CHANGE:
-		rc = v4l2_subdev_call(g_server_dev.vfe_device[0], video,
-			s_crystal_freq, *(uint32_t *)arg, 0);
+		if (g_server_dev.axi_device[0])
+			rc = v4l2_subdev_call(g_server_dev.axi_device[0], video,
+				s_crystal_freq, *(uint32_t *)arg, 0);
+		else
+			rc = v4l2_subdev_call(g_server_dev.vfe_device[0], video,
+				s_crystal_freq, *(uint32_t *)arg, 0);
 		break;
 	case NOTIFY_CSIPHY_CFG:
 		rc = v4l2_subdev_call(g_server_dev.csiphy_device[csid_core],
@@ -2606,6 +2629,10 @@
 		if (index >= MAX_NUM_VPE_DEV)
 			return -EINVAL;
 		g_server_dev.vpe_device[index] = sd;
+	} else if (sdev_type == AXI_DEV) {
+		if (index >= MAX_NUM_AXI_DEV)
+			return -EINVAL;
+		g_server_dev.axi_device[index] = sd;
 	}
 
 	err = v4l2_device_register_subdev(&g_server_dev.v4l2_dev, sd);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 77b654d..fa97e22 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -55,6 +55,7 @@
 #define MAX_NUM_CSIC_DEV 3
 #define MAX_NUM_ISPIF_DEV 1
 #define MAX_NUM_VFE_DEV 2
+#define MAX_NUM_AXI_DEV 2
 #define MAX_NUM_VPE_DEV 1
 
 enum msm_cam_subdev_type {
@@ -63,6 +64,7 @@
 	CSIC_DEV,
 	ISPIF_DEV,
 	VFE_DEV,
+	AXI_DEV,
 	VPE_DEV,
 	SENSOR_DEV,
 	ACTUATOR_DEV,
@@ -145,6 +147,8 @@
 	NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
 	NOTIFY_CSIC_CFG, /* arg = msm_camera_csic_params */
 	NOTIFY_VFE_BUF_FREE_EVT, /* arg = msm_camera_csic_params */
+	NOTIFY_VFE_IRQ,
+	NOTIFY_AXI_IRQ,
 	NOTIFY_INVALID
 };
 
@@ -238,6 +242,8 @@
 	struct v4l2_subdev *csic_sdev; /*csid sub device*/
 	struct v4l2_subdev *ispif_sdev; /* ispif sub device */
 	struct v4l2_subdev *gemini_sdev; /* gemini sub device */
+	struct v4l2_subdev *vpe_sdev; /* vpe sub device */
+	struct v4l2_subdev *axi_sdev; /* vpe sub device */
 
 	struct msm_isp_ops *isp_sdev;    /* isp sub device : camif/VFE */
 	struct msm_cam_config_dev *config_device;
@@ -266,7 +272,7 @@
 	char *config_dev_name;
 
 	/*int (*isp_init)(struct msm_cam_v4l2_device *pcam);*/
-	int (*isp_open)(struct v4l2_subdev *sd, struct v4l2_subdev *sd_vpe,
+	int (*isp_open)(struct v4l2_subdev *sd,
 		struct msm_cam_media_controller *mctl);
 	int (*isp_config)(struct msm_cam_media_controller *pmctl,
 		 unsigned int cmd, unsigned long arg);
@@ -433,6 +439,7 @@
 	struct v4l2_subdev *csic_device[MAX_NUM_CSIC_DEV];
 	struct v4l2_subdev *ispif_device;
 	struct v4l2_subdev *vfe_device[MAX_NUM_VFE_DEV];
+	struct v4l2_subdev *axi_device[MAX_NUM_AXI_DEV];
 	struct v4l2_subdev *vpe_device[MAX_NUM_VPE_DEV];
 };
 
@@ -496,8 +503,6 @@
 int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
 void msm_vpe_subdev_release(void);
 void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
-int msm_isp_subdev_ioctl_vpe(struct v4l2_subdev *isp_subdev,
-	struct msm_mctl_pp_cmd *cmd, void *data);
 int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
 	int msg_type);
 int msm_mctl_do_pp(struct msm_cam_media_controller *p_mctl,
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 9ab4895..5b3101b 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -447,33 +447,14 @@
 	return rc;
 }
 
-static int msm_isp_notify_vpe(struct v4l2_subdev *sd, void *arg)
-{
-	struct msm_cam_media_controller *pmctl =
-		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
-	struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
-	if (pmctl == NULL) {
-		pr_err("%s: VPE subdev hostdata not set\n", __func__);
-		return -EINVAL;
-	}
-
-	msm_mctl_pp_notify(pmctl,
-		(struct msm_mctl_pp_frame_info *)vdata->extdata);
-	return 0;
-}
-
 static int msm_isp_notify(struct v4l2_subdev *sd,
 	unsigned int notification, void *arg)
 {
-	if (notification == NOTIFY_VPE_MSG_EVT)
-		return msm_isp_notify_vpe(sd, arg);
-	else
-		return msm_isp_notify_vfe(sd, notification, arg);
+	return msm_isp_notify_vfe(sd, notification, arg);
 }
 
 /* This function is called by open() function, so we need to init HW*/
 static int msm_isp_open(struct v4l2_subdev *sd,
-	struct v4l2_subdev *sd_vpe,
 	struct msm_cam_media_controller *mctl)
 {
 	/* init vfe and senor, register sync callbacks for init*/
@@ -489,12 +470,6 @@
 		pr_err("%s: vfe_init failed at %d\n",
 					__func__, rc);
 	}
-	D("%s: init vpe subdev", __func__);
-	rc = msm_vpe_subdev_init(sd_vpe, mctl);
-	if (rc < 0) {
-		pr_err("%s: vpe_init failed at %d\n",
-					__func__, rc);
-	}
 	return rc;
 }
 
@@ -503,7 +478,6 @@
 {
 	D("%s\n", __func__);
 	msm_vfe_subdev_release(sd);
-	msm_vpe_subdev_release();
 }
 
 static int msm_config_vfe(struct v4l2_subdev *sd,
@@ -631,48 +605,6 @@
 	return -EINVAL;
 }
 
-static int msm_stats_axi_cfg(struct v4l2_subdev *sd,
-	struct msm_cam_media_controller *mctl, struct msm_vfe_cfg_cmd *cfgcmd)
-{
-	int rc = -EIO;
-	struct axidata axi_data;
-	void *data = &axi_data;
-	struct msm_pmem_region region[3];
-	int pmem_type = MSM_PMEM_MAX;
-
-	memset(&axi_data, 0, sizeof(axi_data));
-
-	switch (cfgcmd->cmd_type) {
-	case CMD_STATS_AF_AXI_CFG:
-		pmem_type = MSM_PMEM_AF;
-		break;
-	case CMD_GENERAL:
-		data = NULL;
-		break;
-	default:
-		pr_err("%s: unknown command type %d\n",
-			__func__, cfgcmd->cmd_type);
-		return -EINVAL;
-	}
-
-	if (cfgcmd->cmd_type != CMD_GENERAL) {
-		axi_data.bufnum1 =
-			msm_pmem_region_lookup(
-				&mctl->stats_info.pmem_stats_list, pmem_type,
-				&region[0], NUM_STAT_OUTPUT_BUFFERS);
-		if (!axi_data.bufnum1) {
-			pr_err("%s %d: pmem region lookup error\n",
-				__func__, __LINE__);
-			return -EINVAL;
-		}
-		axi_data.region = &region[0];
-	}
-
-	/* send the AEC/AWB STATS configuration command to driver */
-	rc = msm_isp_subdev_ioctl(sd, cfgcmd, data);
-	return rc;
-}
-
 static int msm_axi_config(struct v4l2_subdev *sd,
 		struct msm_cam_media_controller *mctl, void __user *arg)
 {
@@ -684,13 +616,6 @@
 	}
 
 	switch (cfgcmd.cmd_type) {
-	case CMD_AXI_CFG_VIDEO:
-	case CMD_AXI_CFG_PREVIEW:
-	case CMD_AXI_CFG_SNAP:
-	case CMD_AXI_CFG_ZSL:
-	case CMD_AXI_CFG_VIDEO_ALL_CHNLS:
-	case CMD_AXI_CFG_ZSL_ALL_CHNLS:
-	case CMD_RAW_PICT_AXI_CFG:
 	case CMD_AXI_CFG_PRIM:
 	case CMD_AXI_CFG_SEC:
 	case CMD_AXI_CFG_PRIM_ALL_CHNLS:
@@ -703,10 +628,6 @@
 		 */
 		return msm_isp_subdev_ioctl(sd, &cfgcmd, NULL);
 
-	case CMD_STATS_AXI_CFG:
-	case CMD_STATS_AF_AXI_CFG:
-		return msm_stats_axi_cfg(sd, mctl, &cfgcmd);
-
 	default:
 		pr_err("%s: unknown command type %d\n",
 			__func__,
@@ -794,14 +715,7 @@
 		rc = msm_config_vfe(sd, pmctl, argp);
 		break;
 
-	case MSM_CAM_IOCTL_CONFIG_VPE:
-		/* Coming from config thread for update */
-		/*rc = msm_config_vpe(pmsm->sync, argp);*/
-		rc = 0;
-		break;
-
 	case MSM_CAM_IOCTL_AXI_CONFIG:
-	case MSM_CAM_IOCTL_AXI_VPE_CONFIG:
 		D("Received MSM_CAM_IOCTL_AXI_CONFIG\n");
 		rc = msm_axi_config(sd, pmctl, argp);
 		break;
@@ -870,15 +784,3 @@
 	vfe_params.data = data;
 	return v4l2_subdev_call(isp_subdev, core, ioctl, 0, &vfe_params);
 }
-
-int msm_isp_subdev_ioctl_vpe(struct v4l2_subdev *isp_subdev,
-	struct msm_mctl_pp_cmd *cmd, void *data)
-{
-	int rc = 0;
-	struct msm_mctl_pp_params parm;
-	parm.cmd = cmd;
-	parm.data = data;
-	rc = v4l2_subdev_call(isp_subdev, core, ioctl, 0, &parm);
-	return rc;
-}
-
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 1f6f32a..4a15b7a 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -34,6 +34,8 @@
 #include "msm_ispif.h"
 #include "msm_sensor.h"
 #include "msm_actuator.h"
+#include "msm_vpe.h"
+#include "msm_vfe32.h"
 
 #ifdef CONFIG_MSM_CAMERA_DEBUG
 #define D(fmt, args...) pr_debug("msm_mctl: " fmt, ##args)
@@ -361,6 +363,13 @@
 			(void __user *)arg);
 		break;
 			/* ISFIF config*/
+	case MSM_CAM_IOCTL_AXI_CONFIG:
+		if (p_mctl->axi_sdev)
+			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+				VIDIOC_MSM_AXI_CFG, (void __user *)arg);
+		else
+			rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
+		break;
 	default:
 		/* ISP config*/
 		D("%s:%d: go to default. Calling msm_isp_config\n",
@@ -480,7 +489,7 @@
 		if (!dev)
 			goto out_put_driver;
 
-		p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
+		p_mctl->vpe_sdev = dev_get_drvdata(dev);
 		put_driver(driver);
 	}
 
@@ -595,14 +604,34 @@
 		}
 
 		/* ISP first*/
-		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_open)
+		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_open) {
 			rc = p_mctl->isp_sdev->isp_open(
-				p_mctl->isp_sdev->sd,
-				p_mctl->isp_sdev->sd_vpe,
-				p_mctl);
-		if (rc < 0) {
-			pr_err("%s: isp init failed: %d\n", __func__, rc);
-			goto msm_open_done;
+				p_mctl->isp_sdev->sd, p_mctl);
+			if (rc < 0) {
+				pr_err("%s: isp init failed: %d\n",
+					__func__, rc);
+				goto msm_open_done;
+			}
+		}
+
+		if (p_mctl->axi_sdev) {
+			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+				VIDIOC_MSM_AXI_INIT, p_mctl);
+			if (rc < 0) {
+				pr_err("%s: vpe initialization failed %d\n",
+				__func__, rc);
+				goto msm_open_done;
+			}
+		}
+
+		if (camdev->is_vpe) {
+			rc = v4l2_subdev_call(p_mctl->vpe_sdev, core, ioctl,
+				VIDIOC_MSM_VPE_INIT, p_mctl);
+			if (rc < 0) {
+				pr_err("%s: vpe initialization failed %d\n",
+				__func__, rc);
+				goto msm_open_done;
+			}
 		}
 
 		if (camdev->is_ispif) {
@@ -652,6 +681,16 @@
 			VIDIOC_MSM_CSIC_RELEASE, NULL);
 	}
 
+	if (camdev->is_vpe) {
+		v4l2_subdev_call(p_mctl->vpe_sdev, core, ioctl,
+			VIDIOC_MSM_VPE_RELEASE, NULL);
+	}
+
+	if (p_mctl->axi_sdev) {
+		v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+			VIDIOC_MSM_AXI_RELEASE, NULL);
+	}
+
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
 		p_mctl->isp_sdev->isp_release(
 			p_mctl->isp_sdev->sd);
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 2e46728..e1138aa 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -28,6 +28,7 @@
 #include <linux/android_pmem.h>
 
 #include "msm.h"
+#include "msm_vpe.h"
 
 #ifdef CONFIG_MSM_CAMERA_DEBUG
 #define D(fmt, args...) pr_debug("msm_mctl: " fmt, ##args)
@@ -35,6 +36,18 @@
 #define D(fmt, args...) do {} while (0)
 #endif
 
+
+static int msm_mctl_pp_vpe_ioctl(struct v4l2_subdev *vpe_sd,
+	struct msm_mctl_pp_cmd *cmd, void *data)
+{
+	int rc = 0;
+	struct msm_mctl_pp_params parm;
+	parm.cmd = cmd;
+	parm.data = data;
+	rc = v4l2_subdev_call(vpe_sd, core, ioctl, VIDIOC_MSM_VPE_CFG, &parm);
+	return rc;
+}
+
 static int msm_mctl_pp_buf_divert(
 			struct msm_cam_media_controller *pmctl,
 			struct msm_cam_v4l2_dev_inst *pcam_inst,
@@ -381,13 +394,13 @@
 	switch (pp_cmd->id) {
 	case VPE_CMD_INIT:
 	case VPE_CMD_DEINIT:
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		break;
 	case VPE_CMD_DISABLE:
 	case VPE_CMD_RESET:
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		break;
 	case VPE_CMD_ENABLE: {
 		struct msm_vpe_clock_rate clk_rate;
@@ -406,8 +419,8 @@
 			return -EFAULT;
 		}
 		pp_cmd->value = (void *)&clk_rate;
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		pp_cmd->value = argp;
 		break;
 	}
@@ -425,8 +438,8 @@
 			&flush_buf, pp_cmd->value, sizeof(flush_buf)))
 			return -EFAULT;
 		pp_cmd->value = (void *)&flush_buf;
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		if (rc == 0) {
 			if (copy_to_user((void *)argp,
 						&flush_buf,
@@ -453,8 +466,8 @@
 			sizeof(op_mode_cfg)))
 			return -EFAULT;
 		pp_cmd->value = (void *)&op_mode_cfg;
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_INPUT_PLANE_CFG: {
@@ -471,8 +484,8 @@
 			&input_cfg, pp_cmd->value, sizeof(input_cfg)))
 			return -EFAULT;
 		pp_cmd->value = (void *)&input_cfg;
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_OUTPUT_PLANE_CFG: {
@@ -492,8 +505,8 @@
 			return -EFAULT;
 		}
 		pp_cmd->value = (void *)&output_cfg;
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_INPUT_PLANE_UPDATE: {
@@ -510,8 +523,8 @@
 			sizeof(input_update_cfg)))
 			return -EFAULT;
 		pp_cmd->value = (void *)&input_update_cfg;
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_SCALE_CFG_TYPE: {
@@ -528,8 +541,8 @@
 			sizeof(scaler_cfg)))
 			return -EFAULT;
 		pp_cmd->value = (void *)&scaler_cfg;
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_ZOOM: {
@@ -593,8 +606,8 @@
 			kfree(zoom);
 			break;
 		}
-		rc = msm_isp_subdev_ioctl_vpe(
-			p_mctl->isp_sdev->sd_vpe, pp_cmd, (void *)zoom);
+		rc = msm_mctl_pp_vpe_ioctl(
+			p_mctl->vpe_sdev, pp_cmd, (void *)zoom);
 		if (rc) {
 			kfree(zoom);
 			break;
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 0ce4983..e265b25 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -3420,9 +3420,9 @@
 	return;
 }
 
-static void vfe32_process_stats_irq(uint32_t *irqstatus)
+static void vfe32_process_stats_irq(uint32_t irqstatus)
 {
-	uint32_t status_bits = VFE_COM_STATUS & *irqstatus;
+	uint32_t status_bits = VFE_COM_STATUS & irqstatus;
 
 	if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
 		(vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
@@ -3434,47 +3434,113 @@
 	return;
 }
 
-static void vfe32_do_tasklet(unsigned long data)
+static void vfe32_process_irq(uint32_t irqstatus)
+{
+	if (irqstatus &
+		VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
+		vfe32_process_stats_irq(irqstatus);
+		return;
+	}
+
+	switch (irqstatus) {
+	case VFE_IRQ_STATUS0_CAMIF_SOF_MASK:
+		CDBG("irq	camifSofIrq\n");
+		vfe32_process_camif_sof_irq();
+		break;
+	case VFE_IRQ_STATUS0_REG_UPDATE_MASK:
+		CDBG("irq	regUpdateIrq\n");
+		vfe32_process_reg_update_irq();
+		break;
+	case VFE_IMASK_WHILE_STOPPING_1:
+		CDBG("irq	resetAckIrq\n");
+		vfe32_process_reset_irq();
+		break;
+	case VFE_IRQ_STATUS0_STATS_AEC:
+		CDBG("Stats AEC irq occured.\n");
+		vfe32_process_stats_ae_irq();
+		break;
+	case VFE_IRQ_STATUS0_STATS_AWB:
+		CDBG("Stats AWB irq occured.\n");
+		vfe32_process_stats_awb_irq();
+		break;
+	case VFE_IRQ_STATUS0_STATS_AF:
+		CDBG("Stats AF irq occured.\n");
+		vfe32_process_stats_af_irq();
+		break;
+	case VFE_IRQ_STATUS0_STATS_IHIST:
+		CDBG("Stats IHIST irq occured.\n");
+		vfe32_process_stats_ihist_irq();
+		break;
+	case VFE_IRQ_STATUS0_STATS_RS:
+		CDBG("Stats RS irq occured.\n");
+		vfe32_process_stats_rs_irq();
+		break;
+	case VFE_IRQ_STATUS0_STATS_CS:
+		CDBG("Stats CS irq occured.\n");
+		vfe32_process_stats_cs_irq();
+		break;
+	case VFE_IRQ_STATUS0_SYNC_TIMER0:
+		CDBG("SYNC_TIMER 0 irq occured.\n");
+		vfe32_send_isp_msg(vfe32_ctrl,
+			MSG_ID_SYNC_TIMER0_DONE);
+		break;
+	case VFE_IRQ_STATUS0_SYNC_TIMER1:
+		CDBG("SYNC_TIMER 1 irq occured.\n");
+		vfe32_send_isp_msg(vfe32_ctrl,
+			MSG_ID_SYNC_TIMER1_DONE);
+		break;
+	case VFE_IRQ_STATUS0_SYNC_TIMER2:
+		CDBG("SYNC_TIMER 2 irq occured.\n");
+		vfe32_send_isp_msg(vfe32_ctrl,
+			MSG_ID_SYNC_TIMER2_DONE);
+		break;
+	default:
+		pr_err("Invalid IRQ status\n");
+	}
+}
+
+static void axi32_do_tasklet(unsigned long data)
 {
 	unsigned long flags;
-
+	struct axi_ctrl_t *axi_ctrl = (struct axi_ctrl_t *)data;
 	struct vfe32_isr_queue_cmd *qcmd = NULL;
 
-	CDBG("=== vfe32_do_tasklet start ===\n");
+	CDBG("=== axi32_do_tasklet start ===\n");
 
 	while (atomic_read(&irq_cnt)) {
-		spin_lock_irqsave(&vfe32_ctrl->tasklet_lock, flags);
-		qcmd = list_first_entry(&vfe32_ctrl->tasklet_q,
+		spin_lock_irqsave(&axi_ctrl->tasklet_lock, flags);
+		qcmd = list_first_entry(&axi_ctrl->tasklet_q,
 			struct vfe32_isr_queue_cmd, list);
 		atomic_sub(1, &irq_cnt);
 
 		if (!qcmd) {
-			spin_unlock_irqrestore(&vfe32_ctrl->tasklet_lock,
+			spin_unlock_irqrestore(&axi_ctrl->tasklet_lock,
 				flags);
 			return;
 		}
 
 		list_del(&qcmd->list);
-		spin_unlock_irqrestore(&vfe32_ctrl->tasklet_lock,
+		spin_unlock_irqrestore(&axi_ctrl->tasklet_lock,
 			flags);
 
 		if (qcmd->vfeInterruptStatus0 &
-				VFE_IRQ_STATUS0_CAMIF_SOF_MASK) {
-			CDBG("irq	camifSofIrq\n");
-			vfe32_process_camif_sof_irq();
-		}
+				VFE_IRQ_STATUS0_CAMIF_SOF_MASK)
+			v4l2_subdev_notify(&axi_ctrl->subdev,
+				NOTIFY_VFE_IRQ,
+				(void *)VFE_IRQ_STATUS0_CAMIF_SOF_MASK);
+
 		/* interrupt to be processed,  *qcmd has the payload.  */
 		if (qcmd->vfeInterruptStatus0 &
-				VFE_IRQ_STATUS0_REG_UPDATE_MASK) {
-			CDBG("irq	regUpdateIrq\n");
-			vfe32_process_reg_update_irq();
-		}
+				VFE_IRQ_STATUS0_REG_UPDATE_MASK)
+			v4l2_subdev_notify(&axi_ctrl->subdev,
+				NOTIFY_VFE_IRQ,
+				(void *)VFE_IRQ_STATUS0_REG_UPDATE_MASK);
 
 		if (qcmd->vfeInterruptStatus1 &
-				VFE_IMASK_WHILE_STOPPING_1) {
-			CDBG("irq	resetAckIrq\n");
-			vfe32_process_reset_irq();
-		}
+				VFE_IMASK_WHILE_STOPPING_1)
+			v4l2_subdev_notify(&axi_ctrl->subdev,
+				NOTIFY_VFE_IRQ,
+				(void *)VFE_IMASK_WHILE_STOPPING_1);
 
 		if (atomic_read(&vfe32_ctrl->vstate)) {
 			if (qcmd->vfeInterruptStatus1 &
@@ -3484,113 +3550,88 @@
 					qcmd->vfeInterruptStatus1 &
 					VFE32_IMASK_ERROR_ONLY_1);
 			}
-			/* next, check output path related interrupts. */
-			if (qcmd->vfeInterruptStatus0 &
-				VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) {
-				CDBG("Image composite done 0 irq occured.\n");
-				vfe32_process_output_path_irq_0();
-			}
-			if (qcmd->vfeInterruptStatus0 &
-				VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK) {
-				CDBG("Image composite done 1 irq occured.\n");
-				vfe32_process_output_path_irq_1();
-			}
-			/* in snapshot mode if done then send
-			snapshot done message */
-			if (vfe32_ctrl->operation_mode ==
-					VFE_OUTPUTS_THUMB_AND_MAIN ||
-				vfe32_ctrl->operation_mode ==
-					VFE_OUTPUTS_MAIN_AND_THUMB ||
-				vfe32_ctrl->operation_mode ==
-					VFE_OUTPUTS_THUMB_AND_JPEG ||
-				vfe32_ctrl->operation_mode ==
-					VFE_OUTPUTS_JPEG_AND_THUMB ||
-				vfe32_ctrl->operation_mode ==
-					VFE_OUTPUTS_RAW) {
-				if ((vfe32_ctrl->outpath.out0.capture_cnt == 0)
-						&& (vfe32_ctrl->outpath.out1.
-						capture_cnt == 0)) {
-					msm_camera_io_w_mb(
-						CAMIF_COMMAND_STOP_IMMEDIATELY,
-						vfe32_ctrl->vfebase +
-						VFE_CAMIF_COMMAND);
-					vfe32_send_isp_msg(vfe32_ctrl,
-						MSG_ID_SNAPSHOT_DONE);
-				}
-			}
+			v4l2_subdev_notify(&axi_ctrl->subdev,
+				NOTIFY_AXI_IRQ,
+				(void *)qcmd->vfeInterruptStatus0);
+
 			/* then process stats irq. */
 			if (vfe32_ctrl->stats_comp) {
 				/* process stats comb interrupt. */
 				if (qcmd->vfeInterruptStatus0 &
 					VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
 					CDBG("Stats composite irq occured.\n");
-					vfe32_process_stats_irq(
-						&qcmd->vfeInterruptStatus0);
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)qcmd->vfeInterruptStatus0);
 				}
 			} else {
 				/* process individual stats interrupt. */
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_STATS_AEC) {
-					CDBG("Stats AEC irq occured.\n");
-					vfe32_process_stats_ae_irq();
-				}
+						VFE_IRQ_STATUS0_STATS_AEC)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_STATS_AEC);
+
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_STATS_AWB) {
-					CDBG("Stats AWB irq occured.\n");
-					vfe32_process_stats_awb_irq();
-				}
+						VFE_IRQ_STATUS0_STATS_AWB)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_STATS_AWB);
+
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_STATS_AF) {
-					CDBG("Stats AF irq occured.\n");
-					vfe32_process_stats_af_irq();
-				}
+						VFE_IRQ_STATUS0_STATS_AF)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_STATS_AF);
+
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_STATS_IHIST) {
-					CDBG("Stats IHIST irq occured.\n");
-					vfe32_process_stats_ihist_irq();
-				}
+						VFE_IRQ_STATUS0_STATS_IHIST)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_STATS_IHIST);
+
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_STATS_RS) {
-					CDBG("Stats RS irq occured.\n");
-					vfe32_process_stats_rs_irq();
-				}
+						VFE_IRQ_STATUS0_STATS_RS)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_STATS_RS);
+
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_STATS_CS) {
-					CDBG("Stats CS irq occured.\n");
-					vfe32_process_stats_cs_irq();
-				}
+						VFE_IRQ_STATUS0_STATS_CS)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_STATS_CS);
+
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_SYNC_TIMER0) {
-					CDBG("SYNC_TIMER 0 irq occured.\n");
-					vfe32_send_isp_msg(vfe32_ctrl,
-						MSG_ID_SYNC_TIMER0_DONE);
-				}
+						VFE_IRQ_STATUS0_SYNC_TIMER0)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_SYNC_TIMER0);
+
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_SYNC_TIMER1) {
-					CDBG("SYNC_TIMER 1 irq occured.\n");
-					vfe32_send_isp_msg(vfe32_ctrl,
-						MSG_ID_SYNC_TIMER1_DONE);
-				}
+						VFE_IRQ_STATUS0_SYNC_TIMER1)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_SYNC_TIMER1);
+
 				if (qcmd->vfeInterruptStatus0 &
-						VFE_IRQ_STATUS0_SYNC_TIMER2) {
-					CDBG("SYNC_TIMER 2 irq occured.\n");
-					vfe32_send_isp_msg(vfe32_ctrl,
-						MSG_ID_SYNC_TIMER2_DONE);
-				}
+						VFE_IRQ_STATUS0_SYNC_TIMER2)
+					v4l2_subdev_notify(&axi_ctrl->subdev,
+					NOTIFY_VFE_IRQ,
+					(void *)VFE_IRQ_STATUS0_SYNC_TIMER2);
 			}
 		}
 		kfree(qcmd);
 	}
-	CDBG("=== vfe32_do_tasklet end ===\n");
+	CDBG("=== axi32_do_tasklet end ===\n");
 }
 
-DECLARE_TASKLET(vfe32_tasklet, vfe32_do_tasklet, 0);
-
 static irqreturn_t vfe32_parse_irq(int irq_num, void *data)
 {
 	unsigned long flags;
 	struct vfe32_irq_status irq;
 	struct vfe32_isr_queue_cmd *qcmd;
+	struct axi_ctrl_t *axi_ctrl = data;
 
 	CDBG("vfe_parse_irq\n");
 
@@ -3621,12 +3662,12 @@
 	qcmd->vfeInterruptStatus0 = irq.vfeIrqStatus0;
 	qcmd->vfeInterruptStatus1 = irq.vfeIrqStatus1;
 
-	spin_lock_irqsave(&vfe32_ctrl->tasklet_lock, flags);
-	list_add_tail(&qcmd->list, &vfe32_ctrl->tasklet_q);
+	spin_lock_irqsave(&axi_ctrl->tasklet_lock, flags);
+	list_add_tail(&qcmd->list, &axi_ctrl->tasklet_q);
 
 	atomic_add(1, &irq_cnt);
-	spin_unlock_irqrestore(&vfe32_ctrl->tasklet_lock, flags);
-	tasklet_schedule(&vfe32_tasklet);
+	spin_unlock_irqrestore(&axi_ctrl->tasklet_lock, flags);
+	tasklet_schedule(&axi_ctrl->vfe32_tasklet);
 	return IRQ_HANDLED;
 }
 
@@ -3646,7 +3687,10 @@
 	struct vfe_cmd_stats_buf *scfg = NULL;
 	struct msm_pmem_region   *regptr = NULL;
 	struct vfe_cmd_stats_ack *sack = NULL;
-	if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+	if (cmd->cmd_type == CMD_VFE_PROCESS_IRQ) {
+		vfe32_process_irq((uint32_t) data);
+		return rc;
+	} else if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
 		cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
 		cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
 		cmd->cmd_type != CMD_STATS_AEC_BUF_RELEASE &&
@@ -3783,7 +3827,201 @@
 	case CMD_STATS_CS_BUF_RELEASE:
 		vfe32_stats_cs_ack(sack);
 		break;
+	default:
+		pr_err("%s Unsupported AXI configuration %x ", __func__,
+			cmd->cmd_type);
+		break;
+	}
+vfe32_config_done:
+	kfree(scfg);
+	kfree(sack);
+	CDBG("%s done: rc = %d\n", __func__, (int) rc);
+	return rc;
+}
 
+static struct msm_cam_clk_info vfe32_clk_info[] = {
+	{"vfe_clk", 228570000},
+	{"vfe_pclk", -1},
+	{"csi_vfe_clk", -1},
+};
+
+static int msm_axi_subdev_s_crystal_freq(struct v4l2_subdev *sd,
+						u32 freq, u32 flags)
+{
+	int rc = 0;
+	int round_rate;
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+
+	round_rate = clk_round_rate(axi_ctrl->vfe_clk[0], freq);
+	if (rc < 0) {
+		pr_err("%s: clk_round_rate failed %d\n",
+					__func__, rc);
+		return rc;
+	}
+
+	vfe_clk_rate = round_rate;
+	rc = clk_set_rate(axi_ctrl->vfe_clk[0], round_rate);
+	if (rc < 0)
+		pr_err("%s: clk_set_rate failed %d\n",
+					__func__, rc);
+
+	return rc;
+}
+
+static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
+	.ioctl = msm_vfe_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
+	.core = &msm_vfe_subdev_core_ops,
+};
+
+int msm_axi_subdev_init(struct v4l2_subdev *sd,
+			struct msm_cam_media_controller *mctl)
+{
+	int rc = 0;
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	v4l2_set_subdev_hostdata(sd, mctl);
+	spin_lock_init(&axi_ctrl->tasklet_lock);
+	INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
+
+	axi_ctrl->vfebase = ioremap(axi_ctrl->vfemem->start,
+		resource_size(axi_ctrl->vfemem));
+	if (!axi_ctrl->vfebase) {
+		rc = -ENOMEM;
+		pr_err("%s: vfe ioremap failed\n", __func__);
+		goto remap_failed;
+	}
+
+	vfe32_ctrl->vfebase = axi_ctrl->vfebase;
+
+	if (axi_ctrl->fs_vfe == NULL) {
+		axi_ctrl->fs_vfe =
+			regulator_get(&axi_ctrl->pdev->dev, "fs_vfe");
+		if (IS_ERR(axi_ctrl->fs_vfe)) {
+			pr_err("%s: Regulator FS_VFE get failed %ld\n",
+				__func__, PTR_ERR(axi_ctrl->fs_vfe));
+			axi_ctrl->fs_vfe = NULL;
+			goto fs_failed;
+		} else if (regulator_enable(axi_ctrl->fs_vfe)) {
+			pr_err("%s: Regulator FS_VFE enable failed\n",
+							__func__);
+			regulator_put(axi_ctrl->fs_vfe);
+			axi_ctrl->fs_vfe = NULL;
+			goto fs_failed;
+		}
+	}
+
+	rc = msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
+			axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 1);
+	if (rc < 0)
+		goto clk_enable_failed;
+
+	msm_camio_bus_scale_cfg(
+		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
+	msm_camio_bus_scale_cfg(
+		mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+
+	if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
+		VFE32_HW_NUMBER)
+		vfe32_ctrl->register_total = VFE32_REGISTER_TOTAL;
+	else
+		vfe32_ctrl->register_total = VFE33_REGISTER_TOTAL;
+
+	enable_irq(axi_ctrl->vfeirq->start);
+
+	return rc;
+clk_enable_failed:
+	regulator_disable(axi_ctrl->fs_vfe);
+	regulator_put(axi_ctrl->fs_vfe);
+	axi_ctrl->fs_vfe = NULL;
+fs_failed:
+	iounmap(axi_ctrl->vfebase);
+	axi_ctrl->vfebase = NULL;
+remap_failed:
+	disable_irq(axi_ctrl->vfeirq->start);
+	return rc;
+}
+
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+			struct msm_cam_media_controller *mctl)
+{
+	int rc = 0;
+	v4l2_set_subdev_hostdata(sd, mctl);
+
+	spin_lock_init(&vfe32_ctrl->stop_flag_lock);
+	spin_lock_init(&vfe32_ctrl->state_lock);
+	spin_lock_init(&vfe32_ctrl->io_lock);
+	spin_lock_init(&vfe32_ctrl->update_ack_lock);
+
+	spin_lock_init(&vfe32_ctrl->aec_ack_lock);
+	spin_lock_init(&vfe32_ctrl->awb_ack_lock);
+	spin_lock_init(&vfe32_ctrl->af_ack_lock);
+	spin_lock_init(&vfe32_ctrl->ihist_ack_lock);
+	spin_lock_init(&vfe32_ctrl->rs_ack_lock);
+	spin_lock_init(&vfe32_ctrl->cs_ack_lock);
+	spin_lock_init(&vfe32_ctrl->comp_stats_ack_lock);
+	spin_lock_init(&vfe32_ctrl->sd_notify_lock);
+
+	vfe32_ctrl->update_linear = false;
+	vfe32_ctrl->update_rolloff = false;
+	vfe32_ctrl->update_la = false;
+	vfe32_ctrl->update_gamma = false;
+	vfe32_ctrl->hfr_mode = HFR_MODE_OFF;
+
+	return rc;
+}
+
+void msm_axi_subdev_release(struct v4l2_subdev *sd)
+{
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	CDBG("%s, free_irq\n", __func__);
+	disable_irq(axi_ctrl->vfeirq->start);
+	tasklet_kill(&axi_ctrl->vfe32_tasklet);
+	msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
+			axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
+	if (axi_ctrl->fs_vfe) {
+		regulator_disable(axi_ctrl->fs_vfe);
+		regulator_put(axi_ctrl->fs_vfe);
+		axi_ctrl->fs_vfe = NULL;
+	}
+	iounmap(axi_ctrl->vfebase);
+	axi_ctrl->vfebase = NULL;
+
+	if (atomic_read(&irq_cnt))
+		pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
+
+	msm_camio_bus_scale_cfg(
+		pmctl->sdata->pdata->cam_bus_scale_table, S_EXIT);
+}
+
+void msm_vfe_subdev_release(struct v4l2_subdev *sd)
+{
+	vfe32_ctrl->vfebase = 0;
+}
+
+static int msm_axi_config(struct v4l2_subdev *sd, void __user *arg)
+{
+	struct msm_vfe_cfg_cmd cfgcmd;
+	struct msm_isp_cmd vfecmd;
+	int rc = 0;
+
+	if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
+		ERR_COPY_FROM_USER();
+		return -EFAULT;
+	}
+
+	if (copy_from_user(&vfecmd,
+			(void __user *)(cfgcmd.value),
+			sizeof(vfecmd))) {
+		pr_err("%s %d: copy_from_user failed\n", __func__,
+			__LINE__);
+		return -EFAULT;
+	}
+
+	switch (cfgcmd.cmd_type) {
 	case CMD_AXI_CFG_PRIM: {
 		uint32_t *axio = NULL;
 		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
@@ -3881,175 +4119,100 @@
 		break;
 	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC_ALL_CHNLS:
 		pr_err("%s Invalid/Unsupported AXI configuration %x",
-			__func__, cmd->cmd_type);
+			__func__, cfgcmd.cmd_type);
 		break;
 	default:
 		pr_err("%s Unsupported AXI configuration %x ", __func__,
-			cmd->cmd_type);
+			cfgcmd.cmd_type);
 		break;
 	}
-vfe32_config_done:
-	kfree(scfg);
-	kfree(sack);
-	CDBG("%s done: rc = %d\n", __func__, (int) rc);
 	return rc;
 }
 
-static struct msm_cam_clk_info vfe32_clk_info[] = {
-	{"vfe_clk", 228570000},
-	{"vfe_pclk", -1},
-	{"csi_vfe_clk", -1},
-};
-
-static int msm_vfe_subdev_s_crystal_freq(struct v4l2_subdev *sd,
-						u32 freq, u32 flags)
+static void msm_axi_process_irq(struct v4l2_subdev *sd, void *arg)
 {
-	int rc = 0;
-	int round_rate;
-
-	round_rate = clk_round_rate(vfe32_ctrl->vfe_clk[0], freq);
-	if (rc < 0) {
-		pr_err("%s: clk_round_rate failed %d\n",
-					__func__, rc);
-		return rc;
+	uint32_t irqstatus = (uint32_t) arg;
+	/* next, check output path related interrupts. */
+	if (irqstatus &
+		VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) {
+		CDBG("Image composite done 0 irq occured.\n");
+		vfe32_process_output_path_irq_0();
 	}
-
-	vfe_clk_rate = round_rate;
-	rc = clk_set_rate(vfe32_ctrl->vfe_clk[0], round_rate);
-	if (rc < 0)
-		pr_err("%s: clk_set_rate failed %d\n",
-					__func__, rc);
-
-	return rc;
-}
-
-static const struct v4l2_subdev_video_ops msm_vfe_subdev_video_ops = {
-	.s_crystal_freq = msm_vfe_subdev_s_crystal_freq,
-};
-
-static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
-	.ioctl = msm_vfe_subdev_ioctl,
-};
-
-static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
-	.core = &msm_vfe_subdev_core_ops,
-	.video = &msm_vfe_subdev_video_ops,
-};
-
-int msm_vfe_subdev_init(struct v4l2_subdev *sd,
-			struct msm_cam_media_controller *mctl)
-{
-	int rc = 0;
-	v4l2_set_subdev_hostdata(sd, mctl);
-
-	spin_lock_init(&vfe32_ctrl->stop_flag_lock);
-	spin_lock_init(&vfe32_ctrl->state_lock);
-	spin_lock_init(&vfe32_ctrl->io_lock);
-	spin_lock_init(&vfe32_ctrl->update_ack_lock);
-	spin_lock_init(&vfe32_ctrl->tasklet_lock);
-
-	spin_lock_init(&vfe32_ctrl->aec_ack_lock);
-	spin_lock_init(&vfe32_ctrl->awb_ack_lock);
-	spin_lock_init(&vfe32_ctrl->af_ack_lock);
-	spin_lock_init(&vfe32_ctrl->ihist_ack_lock);
-	spin_lock_init(&vfe32_ctrl->rs_ack_lock);
-	spin_lock_init(&vfe32_ctrl->cs_ack_lock);
-	spin_lock_init(&vfe32_ctrl->comp_stats_ack_lock);
-	spin_lock_init(&vfe32_ctrl->sd_notify_lock);
-	INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
-
-	vfe32_ctrl->update_linear = false;
-	vfe32_ctrl->update_rolloff = false;
-	vfe32_ctrl->update_la = false;
-	vfe32_ctrl->update_gamma = false;
-	vfe32_ctrl->hfr_mode = HFR_MODE_OFF;
-
-	enable_irq(vfe32_ctrl->vfeirq->start);
-
-	vfe32_ctrl->vfebase = ioremap(vfe32_ctrl->vfemem->start,
-		resource_size(vfe32_ctrl->vfemem));
-	if (!vfe32_ctrl->vfebase) {
-		rc = -ENOMEM;
-		pr_err("%s: vfe ioremap failed\n", __func__);
-		goto vfe_remap_failed;
+	if (irqstatus &
+		VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK) {
+		CDBG("Image composite done 1 irq occured.\n");
+		vfe32_process_output_path_irq_1();
 	}
-
-	if (vfe32_ctrl->fs_vfe == NULL) {
-		vfe32_ctrl->fs_vfe =
-			regulator_get(&vfe32_ctrl->pdev->dev, "fs_vfe");
-		if (IS_ERR(vfe32_ctrl->fs_vfe)) {
-			pr_err("%s: Regulator FS_VFE get failed %ld\n",
-				__func__, PTR_ERR(vfe32_ctrl->fs_vfe));
-			vfe32_ctrl->fs_vfe = NULL;
-			goto vfe_fs_failed;
-		} else if (regulator_enable(vfe32_ctrl->fs_vfe)) {
-			pr_err("%s: Regulator FS_VFE enable failed\n",
-							__func__);
-			regulator_put(vfe32_ctrl->fs_vfe);
-			vfe32_ctrl->fs_vfe = NULL;
-			goto vfe_fs_failed;
+	/* in snapshot mode if done then send
+	snapshot done message */
+	if (vfe32_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_MAIN ||
+		vfe32_ctrl->operation_mode ==
+			VFE_OUTPUTS_MAIN_AND_THUMB ||
+		vfe32_ctrl->operation_mode ==
+			VFE_OUTPUTS_THUMB_AND_JPEG ||
+		vfe32_ctrl->operation_mode ==
+			VFE_OUTPUTS_JPEG_AND_THUMB ||
+		vfe32_ctrl->operation_mode ==
+			VFE_OUTPUTS_RAW) {
+		if ((vfe32_ctrl->outpath.out0.capture_cnt == 0)
+				&& (vfe32_ctrl->outpath.out1.
+				capture_cnt == 0)) {
+			msm_camera_io_w_mb(
+				CAMIF_COMMAND_STOP_IMMEDIATELY,
+				vfe32_ctrl->vfebase +
+				VFE_CAMIF_COMMAND);
+			vfe32_send_isp_msg(vfe32_ctrl,
+				MSG_ID_SNAPSHOT_DONE);
 		}
 	}
-
-	rc = msm_cam_clk_enable(&vfe32_ctrl->pdev->dev, vfe32_clk_info,
-			vfe32_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 1);
-	if (rc < 0)
-		goto vfe_clk_enable_failed;
-
-	msm_camio_bus_scale_cfg(
-		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
-	msm_camio_bus_scale_cfg(
-		mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
-
-	if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
-		VFE32_HW_NUMBER)
-		vfe32_ctrl->register_total = VFE32_REGISTER_TOTAL;
-	else
-		vfe32_ctrl->register_total = VFE33_REGISTER_TOTAL;
-
-	return rc;
-
-vfe_clk_enable_failed:
-	regulator_disable(vfe32_ctrl->fs_vfe);
-	regulator_put(vfe32_ctrl->fs_vfe);
-	vfe32_ctrl->fs_vfe = NULL;
-vfe_fs_failed:
-	iounmap(vfe32_ctrl->vfebase);
-	vfe32_ctrl->vfebase = NULL;
-vfe_remap_failed:
-	disable_irq(vfe32_ctrl->vfeirq->start);
-	return rc;
-}
-
-void msm_vfe_subdev_release(struct v4l2_subdev *sd)
-{
-	struct msm_cam_media_controller *pmctl =
-		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
-	CDBG("%s, free_irq\n", __func__);
-	disable_irq(vfe32_ctrl->vfeirq->start);
-	tasklet_kill(&vfe32_tasklet);
-	msm_cam_clk_enable(&vfe32_ctrl->pdev->dev, vfe32_clk_info,
-			vfe32_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
-	if (vfe32_ctrl->fs_vfe) {
-		regulator_disable(vfe32_ctrl->fs_vfe);
-		regulator_put(vfe32_ctrl->fs_vfe);
-		vfe32_ctrl->fs_vfe = NULL;
-	}
-	iounmap(vfe32_ctrl->vfebase);
-	vfe32_ctrl->vfebase = NULL;
-
-	if (atomic_read(&irq_cnt))
-		pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
-
-	msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_EXIT);
 }
 
 static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
 
+static long msm_axi_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	int rc = -ENOIOCTLCMD;
+	switch (cmd) {
+	case VIDIOC_MSM_AXI_INIT:
+		rc = msm_axi_subdev_init(sd,
+				(struct msm_cam_media_controller *)arg);
+		break;
+	case VIDIOC_MSM_AXI_CFG:
+		rc = msm_axi_config(sd, arg);
+		break;
+	case VIDIOC_MSM_AXI_IRQ:
+		msm_axi_process_irq(sd, arg);
+		break;
+	case VIDIOC_MSM_AXI_RELEASE:
+		msm_axi_subdev_release(sd);
+		break;
+	default:
+		pr_err("%s: command not found\n", __func__);
+	}
+	return rc;
+}
+
+static const struct v4l2_subdev_core_ops msm_axi_subdev_core_ops = {
+	.ioctl = msm_axi_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_video_ops msm_axi_subdev_video_ops = {
+	.s_crystal_freq = msm_axi_subdev_s_crystal_freq,
+};
+
+static const struct v4l2_subdev_ops msm_axi_subdev_ops = {
+	.core = &msm_axi_subdev_core_ops,
+	.video = &msm_axi_subdev_video_ops,
+};
+
+static const struct v4l2_subdev_internal_ops msm_axi_internal_ops;
+
 static int __devinit vfe32_probe(struct platform_device *pdev)
 {
 	int rc = 0;
+	struct axi_ctrl_t *axi_ctrl;
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
 	vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
 	if (!vfe32_ctrl) {
@@ -4057,6 +4220,16 @@
 		return -ENOMEM;
 	}
 
+	axi_ctrl = kzalloc(sizeof(struct axi_ctrl_t), GFP_KERNEL);
+	v4l2_subdev_init(&axi_ctrl->subdev, &msm_axi_subdev_ops);
+	axi_ctrl->subdev.internal_ops = &msm_axi_internal_ops;
+	axi_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(axi_ctrl->subdev.name,
+			 sizeof(axi_ctrl->subdev.name), "axi");
+	v4l2_set_subdevdata(&axi_ctrl->subdev, axi_ctrl);
+	axi_ctrl->pdev = pdev;
+	msm_cam_register_subdev_node(&axi_ctrl->subdev, AXI_DEV, 0);
+
 	v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
 	vfe32_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
 	vfe32_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -4065,40 +4238,43 @@
 	v4l2_set_subdevdata(&vfe32_ctrl->subdev, vfe32_ctrl);
 	platform_set_drvdata(pdev, &vfe32_ctrl->subdev);
 
-	vfe32_ctrl->vfemem = platform_get_resource_byname(pdev,
+	axi_ctrl->vfemem = platform_get_resource_byname(pdev,
 					IORESOURCE_MEM, "vfe32");
-	if (!vfe32_ctrl->vfemem) {
+	if (!axi_ctrl->vfemem) {
 		pr_err("%s: no mem resource?\n", __func__);
 		rc = -ENODEV;
 		goto vfe32_no_resource;
 	}
-	vfe32_ctrl->vfeirq = platform_get_resource_byname(pdev,
+	axi_ctrl->vfeirq = platform_get_resource_byname(pdev,
 					IORESOURCE_IRQ, "vfe32");
-	if (!vfe32_ctrl->vfeirq) {
+	if (!axi_ctrl->vfeirq) {
 		pr_err("%s: no irq resource?\n", __func__);
 		rc = -ENODEV;
 		goto vfe32_no_resource;
 	}
 
-	vfe32_ctrl->vfeio = request_mem_region(vfe32_ctrl->vfemem->start,
-		resource_size(vfe32_ctrl->vfemem), pdev->name);
-	if (!vfe32_ctrl->vfeio) {
+	axi_ctrl->vfeio = request_mem_region(axi_ctrl->vfemem->start,
+		resource_size(axi_ctrl->vfemem), pdev->name);
+	if (!axi_ctrl->vfeio) {
 		pr_err("%s: no valid mem region\n", __func__);
 		rc = -EBUSY;
 		goto vfe32_no_resource;
 	}
 
-	rc = request_irq(vfe32_ctrl->vfeirq->start, vfe32_parse_irq,
-		IRQF_TRIGGER_RISING, "vfe", 0);
+	rc = request_irq(axi_ctrl->vfeirq->start, vfe32_parse_irq,
+		IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
 	if (rc < 0) {
-		release_mem_region(vfe32_ctrl->vfemem->start,
-			resource_size(vfe32_ctrl->vfemem));
+		release_mem_region(axi_ctrl->vfemem->start,
+			resource_size(axi_ctrl->vfemem));
 		pr_err("%s: irq request fail\n", __func__);
 		rc = -EBUSY;
 		goto vfe32_no_resource;
 	}
 
-	disable_irq(vfe32_ctrl->vfeirq->start);
+	disable_irq(axi_ctrl->vfeirq->start);
+
+	tasklet_init(&axi_ctrl->vfe32_tasklet,
+		axi32_do_tasklet, (unsigned long)axi_ctrl);
 
 	vfe32_ctrl->pdev = pdev;
 	msm_cam_register_subdev_node(&vfe32_ctrl->subdev, VFE_DEV, 0);
@@ -4106,6 +4282,7 @@
 
 vfe32_no_resource:
 	kfree(vfe32_ctrl);
+	kfree(axi_ctrl);
 	return 0;
 }
 
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 0d8be58..d1faded 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -901,6 +901,23 @@
 	uint32_t bufToRender;
 };
 
+struct axi_ctrl_t {
+	struct v4l2_subdev subdev;
+	struct platform_device *pdev;
+	struct resource *vfeirq;
+	spinlock_t  tasklet_lock;
+	struct list_head tasklet_q;
+
+	void __iomem *vfebase;
+	void *syncdata;
+
+	struct resource	*vfemem;
+	struct resource *vfeio;
+	struct regulator *fs_vfe;
+	struct clk *vfe_clk[3];
+	struct tasklet_struct vfe32_tasklet;
+};
+
 struct vfe32_ctrl_type {
 	uint16_t operation_mode;     /* streaming or snapshot */
 	struct vfe32_output_path outpath;
@@ -934,17 +951,9 @@
 	int8_t update_gamma;
 	enum vfe_output_state liveshot_state;
 
-	spinlock_t  tasklet_lock;
-	struct list_head tasklet_q;
 	void __iomem *vfebase;
-	void *syncdata;
 	uint32_t register_total;
 
-	struct resource	*vfemem;
-	struct resource *vfeio;
-	struct resource *vfeirq;
-	struct regulator *fs_vfe;
-
 	uint32_t stats_comp;
 	atomic_t vstate;
 	uint32_t vfe_capture_count;
@@ -969,7 +978,6 @@
 	/* v4l2 subdev */
 	struct v4l2_subdev subdev;
 	struct platform_device *pdev;
-	struct clk *vfe_clk[3];
 	spinlock_t  sd_notify_lock;
 	uint32_t hfr_mode;
 	uint32_t frame_skip_cnt;
@@ -994,4 +1002,17 @@
 struct vfe_cmd_stats_buf {
 	uint32_t statsBuf[VFE_STATS_BUFFER_COUNT];
 };
+
+#define VIDIOC_MSM_AXI_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 18, struct msm_cam_media_controller *)
+
+#define VIDIOC_MSM_AXI_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 19, struct msm_cam_media_controller *)
+
+#define VIDIOC_MSM_AXI_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 20, void *)
+
+#define VIDIOC_MSM_AXI_IRQ \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 21, void *)
+
 #endif /* __MSM_VFE32_H__ */
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 0ab6531..b7376dc 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -582,64 +582,6 @@
 	return rc;
 }
 
-static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
-			unsigned int subdev_cmd, void *arg)
-{
-	struct msm_mctl_pp_params *vpe_params =
-		(struct msm_mctl_pp_params *)arg;
-	struct msm_mctl_pp_cmd *cmd = vpe_params->cmd;
-	int rc = 0;
-	switch (cmd->id) {
-	case VPE_CMD_INIT:
-	case VPE_CMD_DEINIT:
-		break;
-	case VPE_CMD_RESET:
-		rc = vpe_reset();
-		break;
-	case VPE_CMD_OPERATION_MODE_CFG:
-		rc = vpe_operation_config(cmd->value);
-		break;
-	case VPE_CMD_INPUT_PLANE_CFG:
-		vpe_input_plane_config(cmd->value);
-		break;
-	case VPE_CMD_OUTPUT_PLANE_CFG:
-		vpe_output_plane_config(cmd->value);
-		break;
-	case VPE_CMD_SCALE_CFG_TYPE:
-		vpe_update_scale_coef(cmd->value);
-		break;
-	case VPE_CMD_ZOOM: {
-		rc = msm_vpe_do_pp(cmd,
-			(struct msm_mctl_pp_frame_info *)vpe_params->data);
-		break;
-	}
-	case VPE_CMD_ENABLE: {
-		struct msm_vpe_clock_rate *clk_rate = cmd->value;
-		int turbo_mode = (int)clk_rate->rate;
-		rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
-			vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
-		break;
-	}
-	case VPE_CMD_DISABLE:
-		rc = vpe_disable();
-		break;
-	case VPE_CMD_INPUT_PLANE_UPDATE:
-	case VPE_CMD_FLUSH:
-	default:
-		break;
-	}
-	CDBG("%s: end, id = %d, rc = %d", __func__, cmd->id, rc);
-	return rc;
-}
-
-static const struct v4l2_subdev_core_ops msm_vpe_subdev_core_ops = {
-	.ioctl = msm_vpe_subdev_ioctl,
-};
-
-static const struct v4l2_subdev_ops msm_vpe_subdev_ops = {
-	.core = &msm_vpe_subdev_core_ops,
-};
-
 static int msm_vpe_resource_init(void);
 
 int msm_vpe_subdev_init(struct v4l2_subdev *sd,
@@ -702,6 +644,75 @@
 }
 EXPORT_SYMBOL(msm_vpe_subdev_release);
 
+static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int subdev_cmd, void *arg)
+{
+	struct msm_mctl_pp_params *vpe_params;
+	struct msm_mctl_pp_cmd *cmd;
+	int rc = 0;
+
+	if (subdev_cmd == VIDIOC_MSM_VPE_INIT) {
+		struct msm_cam_media_controller *mctl =
+			(struct msm_cam_media_controller *)arg;
+		msm_vpe_subdev_init(sd, mctl);
+	} else if (subdev_cmd == VIDIOC_MSM_VPE_RELEASE) {
+		msm_vpe_subdev_release();
+	} else if (subdev_cmd == VIDIOC_MSM_VPE_CFG) {
+		vpe_params = (struct msm_mctl_pp_params *)arg;
+		cmd = vpe_params->cmd;
+		switch (cmd->id) {
+		case VPE_CMD_INIT:
+		case VPE_CMD_DEINIT:
+			break;
+		case VPE_CMD_RESET:
+			rc = vpe_reset();
+			break;
+		case VPE_CMD_OPERATION_MODE_CFG:
+			rc = vpe_operation_config(cmd->value);
+			break;
+		case VPE_CMD_INPUT_PLANE_CFG:
+			vpe_input_plane_config(cmd->value);
+			break;
+		case VPE_CMD_OUTPUT_PLANE_CFG:
+			vpe_output_plane_config(cmd->value);
+			break;
+		case VPE_CMD_SCALE_CFG_TYPE:
+			vpe_update_scale_coef(cmd->value);
+			break;
+		case VPE_CMD_ZOOM: {
+			rc = msm_vpe_do_pp(cmd,
+			(struct msm_mctl_pp_frame_info *)vpe_params->data);
+			break;
+		}
+		case VPE_CMD_ENABLE: {
+			struct msm_vpe_clock_rate *clk_rate = cmd->value;
+			int turbo_mode = (int)clk_rate->rate;
+			rc = turbo_mode ?
+				vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
+				vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
+			break;
+		}
+		case VPE_CMD_DISABLE:
+			rc = vpe_disable();
+			break;
+		case VPE_CMD_INPUT_PLANE_UPDATE:
+		case VPE_CMD_FLUSH:
+		default:
+			break;
+		}
+		CDBG("%s: end, id = %d, rc = %d", __func__, cmd->id, rc);
+	}
+	return rc;
+}
+
+static const struct v4l2_subdev_core_ops msm_vpe_subdev_core_ops = {
+	.ioctl = msm_vpe_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_vpe_subdev_ops = {
+	.core = &msm_vpe_subdev_core_ops,
+};
+
 static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops;
 
 static int __devinit vpe_probe(struct platform_device *pdev)
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 46c9d2f..553ee4f 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -177,6 +177,14 @@
 	int32_t phase_step_y;
 };
 
+#define VIDIOC_MSM_VPE_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct msm_cam_media_controller *)
+
+#define VIDIOC_MSM_VPE_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 16, struct msm_cam_media_controller *)
+
+#define VIDIOC_MSM_VPE_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 17, struct msm_mctl_pp_params *)
 
 #endif /*_MSM_VPE_H_*/
 
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index e9c710a..b7ae0f4 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -244,9 +244,11 @@
 		WFD_MSG_DBG("EVENT: not expected = %d\n", event);
 		venc_stop_done(client_ctx, status);
 		break;
-	case VCD_EVT_RESP_PAUSE:
 	case VCD_EVT_RESP_FLUSH_INPUT_DONE:
 	case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+		venc_notify_client(client_ctx);
+		break;
+	case VCD_EVT_RESP_PAUSE:
 	case VCD_EVT_IND_OUTPUT_RECONFIG:
 		WFD_MSG_DBG("EVENT: not expected = %d\n", event);
 		break;
@@ -1935,6 +1937,46 @@
 					 (u8 *)kernel_vaddr);
 }
 
+static long venc_flush_buffers(struct v4l2_subdev *sd, void *arg)
+{
+	int rc = 0;
+	struct venc_inst *inst = sd->dev_priv;
+	struct video_client_ctx *client_ctx = &inst->venc_client;
+	if (!client_ctx) {
+		WFD_MSG_ERR("Invalid input\n");
+		return -EINVAL;
+	}
+	rc = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_INPUT);
+	if (rc) {
+		WFD_MSG_ERR("Failed to flush input buffers\n");
+		rc = -EIO;
+		goto flush_failed;
+	}
+	wait_for_completion(&client_ctx->event);
+	if (client_ctx->event_status) {
+		WFD_MSG_ERR("callback for vcd_flush input returned error: %u",
+				client_ctx->event_status);
+		rc = -EIO;
+		goto flush_failed;
+	}
+	rc = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_OUTPUT);
+	if (rc) {
+		WFD_MSG_ERR("Failed to flush output buffers\n");
+		rc = -EIO;
+		goto flush_failed;
+	}
+	wait_for_completion(&client_ctx->event);
+	if (client_ctx->event_status) {
+		WFD_MSG_ERR("callback for vcd_flush output returned error: %u",
+				client_ctx->event_status);
+		rc = -EIO;
+		goto flush_failed;
+	}
+
+flush_failed:
+	return rc;
+}
+
 static long venc_free_input_buffer(struct v4l2_subdev *sd, void *arg)
 {
 	int del_rc = 0, free_rc = 0;
@@ -2203,6 +2245,9 @@
 	case FREE_RECON_BUFFERS:
 		rc = venc_free_recon_buffers(sd, arg);
 		break;
+	case ENCODE_FLUSH:
+		rc = venc_flush_buffers(sd, arg);
+		break;
 	default:
 		rc = -1;
 		break;
diff --git a/drivers/media/video/msm/wfd/enc-subdev.h b/drivers/media/video/msm/wfd/enc-subdev.h
index cafc9d5..5873e62 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.h
+++ b/drivers/media/video/msm/wfd/enc-subdev.h
@@ -74,6 +74,7 @@
 #define FREE_OUTPUT_BUFFER _IOWR('V', 21, struct mem_region *)
 #define FREE_INPUT_BUFFER _IOWR('V', 22, struct mem_region *)
 #define FREE_RECON_BUFFERS _IO('V', 23)
+#define ENCODE_FLUSH _IO('V', 24)
 
 extern int venc_init(struct v4l2_subdev *sd, u32 val);
 extern int venc_load_fw(struct v4l2_subdev *sd);
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 7ab5d17..0a2b1c1 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -614,6 +614,10 @@
 		WFD_MSG_ERR("Failed to stop VSG\n");
 
 	kthread_stop(inst->mdp_task);
+	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+			ENCODE_FLUSH, (void *)inst->venc_inst);
+	if (rc)
+		WFD_MSG_ERR("Failed to flush encoder\n");
 	WFD_MSG_DBG("enc stop\n");
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
 			ENCODE_STOP, (void *)inst->venc_inst);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 54e1b9a..3b6a56a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -869,6 +869,13 @@
 	  This driver implements several miscellaneous APIs that may be needed
 	  in order to control the PM8XXX PMIC chip.
 
+config MFD_PM8XXX_SPK
+	tristate "Support for Qualcomm PM8xxx speaker APIs"
+	depends on MFD_PM8XXX
+	help
+	  This driver implements several external speaker amplifier APIs that
+	  may be needed in order to control the PM8XXX PMIC chip.
+
 config MFD_PM8XXX_BATT_ALARM
 	tristate "Support for Qualcomm PM8xxx battery voltage alarm"
 	depends on MFD_PM8XXX
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index fd887ea..3c10f63 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -123,4 +123,5 @@
 obj-$(CONFIG_MFD_PM8XXX_DEBUG) 	+= pm8xxx-debug.o
 obj-$(CONFIG_MFD_PM8XXX_PWM) 	+= pm8xxx-pwm.o
 obj-$(CONFIG_MFD_PM8XXX_MISC) 	+= pm8xxx-misc.o
+obj-$(CONFIG_MFD_PM8XXX_SPK) 	+= pm8xxx-spk.o
 obj-$(CONFIG_MFD_PM8XXX_BATT_ALARM) 	+= pm8xxx-batt-alarm.o
diff --git a/drivers/mfd/marimba-core.c b/drivers/mfd/marimba-core.c
index 8b41518..12746dd 100644
--- a/drivers/mfd/marimba-core.c
+++ b/drivers/mfd/marimba-core.c
@@ -169,6 +169,11 @@
 	u8 mask_value[num_bytes];
 
 	marimba = &marimba_modules[marimba->mod_id];
+	if (marimba == NULL) {
+		pr_err("%s: Unable to access Marimba core\n", __func__);
+		return -ENODEV;
+	}
+
 
 	mutex_lock(&marimba->xfer_lock);
 
@@ -177,6 +182,12 @@
 					& ~mask) | (value[i] & mask);
 
 	msg = &marimba->xfer_msg[0];
+	if (marimba->client == NULL) {
+		pr_err("%s: Unable to access the Marimba slave device.\n",
+								__func__);
+		return -ENODEV;
+	}
+
 	msg->addr = marimba->client->addr;
 	msg->flags = 0;
 	msg->len = num_bytes + 1;
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index b03b7ac..f48c302 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -32,6 +32,9 @@
 #define REG_RTC_BASE		0x11D
 #define REG_IRQ_BASE            0x1BB
 
+#define REG_SPK_BASE		0x253
+#define REG_SPK_REGISTERS	3
+
 #define PM8038_VERSION_MASK	0xFFF0
 #define PM8038_VERSION_VALUE	0x09F0
 #define PM8038_REVISION_MASK	0x000F
@@ -273,6 +276,22 @@
 	.id		= -1,
 };
 
+static const struct resource resources_spk[] __devinitconst = {
+	[0] = {
+		.name   = PM8XXX_SPK_DEV_NAME,
+		.start  = REG_SPK_BASE,
+		.end    = REG_SPK_BASE + REG_SPK_REGISTERS,
+		.flags  = IORESOURCE_IO,
+	},
+};
+
+static struct mfd_cell spk_cell __devinitdata = {
+	.name           = PM8XXX_SPK_DEV_NAME,
+	.id             = -1,
+	.num_resources	= ARRAY_SIZE(resources_spk),
+	.resources	= resources_spk,
+};
+
 static struct mfd_cell debugfs_cell __devinitdata = {
 	.name		= "pm8xxx-debug",
 	.id		= 0,
@@ -516,6 +535,16 @@
 		}
 	}
 
+	if (pdata->spk_pdata) {
+		spk_cell.platform_data = pdata->spk_pdata;
+		spk_cell.pdata_size = sizeof(struct pm8xxx_spk_platform_data);
+		ret = mfd_add_devices(pmic->dev, 0, &spk_cell, 1, NULL, 0);
+		if (ret) {
+			pr_err("Failed to add spk subdevice ret=%d\n", ret);
+			goto bail;
+		}
+	}
+
 	if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
 		ret = pm8038_add_regulators(pdata, pmic, irq_base);
 		if (ret) {
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index 64c0bd1..a311029 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -502,6 +502,8 @@
 		case PM8XXX_VERSION_8901:
 			rc = __pm8901_reset_pwr_off(chip, reset);
 			break;
+		case PM8XXX_VERSION_8038:
+		case PM8XXX_VERSION_8917:
 		case PM8XXX_VERSION_8921:
 			rc = __pm8921_reset_pwr_off(chip, reset);
 			break;
diff --git a/drivers/mfd/pm8xxx-spk.c b/drivers/mfd/pm8xxx-spk.c
new file mode 100644
index 0000000..297ddfa
--- /dev/null
+++ b/drivers/mfd/pm8xxx-spk.c
@@ -0,0 +1,279 @@
+/* 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/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/debugfs.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/spk.h>
+
+#define PM8XXX_SPK_CTL1_REG_OFF		0
+#define PM8XXX_SPK_TEST_REG_1_OFF	1
+#define PM8XXX_SPK_TEST_REG_2_OFF	2
+
+#define PM8XXX_SPK_BANK_SEL		4
+#define PM8XXX_SPK_BANK_WRITE		0x80
+#define PM8XXX_SPK_BANK_VAL_MASK	0xF
+
+#define BOOST_6DB_GAIN_EN_MASK		0x8
+#define VSEL_LD0_1P1			0x0
+#define VSEL_LD0_1P2			0x2
+#define VSEL_LD0_1P0			0x4
+
+#define PWM_EN_MASK			0xF
+#define PM8XXX_SPK_TEST_REG_1_BANKS	8
+#define PM8XXX_SPK_TEST_REG_2_BANKS	2
+
+#define PM8XXX_SPK_GAIN			0x5
+#define PM8XXX_ADD_EN			0x1
+
+struct pm8xxx_spk_chip {
+	struct list_head                        link;
+	struct pm8xxx_spk_platform_data		pdata;
+	struct device                           *dev;
+	enum pm8xxx_version                     version;
+	struct mutex				spk_mutex;
+	u16					base;
+	u16					end;
+};
+
+static struct pm8xxx_spk_chip *the_spk_chip;
+
+static inline bool spk_defined(void)
+{
+	if (the_spk_chip == NULL || IS_ERR(the_spk_chip))
+		return false;
+	return true;
+}
+
+static int pm8xxx_spk_bank_write(u16 reg, u16 bank, u8 val)
+{
+	int rc = 0;
+	u8 bank_val = PM8XXX_SPK_BANK_WRITE | (bank << PM8XXX_SPK_BANK_SEL);
+
+	bank_val |= (val & PM8XXX_SPK_BANK_VAL_MASK);
+	mutex_lock(&the_spk_chip->spk_mutex);
+	rc = pm8xxx_writeb(the_spk_chip->dev->parent, reg, bank_val);
+	if (rc)
+		pr_err("pm8xxx_writeb(): rc=%d\n", rc);
+	mutex_unlock(&the_spk_chip->spk_mutex);
+	return rc;
+}
+
+
+static int pm8xxx_spk_read(u16 addr)
+{
+	int rc = 0;
+	u8 val = 0;
+
+	mutex_lock(&the_spk_chip->spk_mutex);
+	rc = pm8xxx_readb(the_spk_chip->dev->parent,
+			the_spk_chip->base + addr, &val);
+	if (rc) {
+		pr_err("pm8xxx_spk_readb() failed: rc=%d\n", rc);
+		val = rc;
+	}
+	mutex_unlock(&the_spk_chip->spk_mutex);
+
+	return val;
+}
+
+static int pm8xxx_spk_write(u16 addr, u8 val)
+{
+	int rc = 0;
+
+	mutex_lock(&the_spk_chip->spk_mutex);
+	rc = pm8xxx_writeb(the_spk_chip->dev->parent,
+			the_spk_chip->base + addr, val);
+	if (rc)
+		pr_err("pm8xxx_writeb() failed: rc=%d\n", rc);
+	mutex_unlock(&the_spk_chip->spk_mutex);
+	return rc;
+}
+
+int pm8xxx_spk_mute(bool mute)
+{
+	u8 val = 0;
+	int ret = 0;
+	if (spk_defined() == false) {
+		pr_err("Invalid spk handle or no spk_chip\n");
+		return -ENODEV;
+	}
+
+	val = pm8xxx_spk_read(PM8XXX_SPK_CTL1_REG_OFF);
+	if (val < 0)
+		return val;
+	val |= mute << 2;
+	ret = pm8xxx_spk_write(PM8XXX_SPK_CTL1_REG_OFF, val);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_spk_mute);
+
+int pm8xxx_spk_gain(u8 gain)
+{
+	u8 val;
+	int ret = 0;
+
+	if (spk_defined() == false) {
+		pr_err("Invalid spk handle or no spk_chip\n");
+		return -ENODEV;
+	}
+
+	val = pm8xxx_spk_read(PM8XXX_SPK_CTL1_REG_OFF);
+	if (val < 0)
+		return val;
+	val |= (gain << 4);
+	ret = pm8xxx_spk_write(PM8XXX_SPK_CTL1_REG_OFF, val);
+	if (!ret) {
+		pm8xxx_spk_bank_write(the_spk_chip->base
+			+ PM8XXX_SPK_TEST_REG_1_OFF,
+			0, BOOST_6DB_GAIN_EN_MASK | VSEL_LD0_1P2);
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_spk_gain);
+
+int pm8xxx_spk_enable(int enable)
+{
+	int val = 0;
+	u16 addr;
+	int ret = 0;
+
+	if (spk_defined() == false) {
+		pr_err("Invalid spk handle or no spk_chip\n");
+		return -ENODEV;
+	}
+
+	addr = the_spk_chip->base + PM8XXX_SPK_TEST_REG_1_OFF;
+	val = pm8xxx_spk_read(PM8XXX_SPK_CTL1_REG_OFF);
+	if (val < 0)
+		return val;
+	val |= (enable << 3);
+	ret = pm8xxx_spk_write(PM8XXX_SPK_CTL1_REG_OFF, val);
+	if (!ret)
+		ret = pm8xxx_spk_bank_write(addr, 6, PWM_EN_MASK);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_spk_enable);
+
+static int pm8xxx_spk_config(void)
+{
+	u16 addr;
+	int ret = 0;
+
+	if (spk_defined() == false) {
+		pr_err("Invalid spk handle or no spk_chip\n");
+		return -ENODEV;
+	}
+
+	addr = the_spk_chip->base + PM8XXX_SPK_TEST_REG_1_OFF;
+	ret = pm8xxx_spk_bank_write(addr, 6, PWM_EN_MASK & 0);
+	if (!ret)
+		ret = pm8xxx_spk_gain(PM8XXX_SPK_GAIN);
+	return ret;
+}
+
+static int __devinit pm8xxx_spk_probe(struct platform_device *pdev)
+{
+	const struct pm8xxx_spk_platform_data *pdata = pdev->dev.platform_data;
+	int ret = 0;
+
+	if (!pdata) {
+		pr_err("missing platform data\n");
+		return -EINVAL;
+	}
+
+	the_spk_chip = kzalloc(sizeof(struct pm8xxx_spk_chip), GFP_KERNEL);
+	if (the_spk_chip == NULL) {
+		pr_err("kzalloc() failed.\n");
+		return -ENOMEM;
+	}
+
+	mutex_init(&the_spk_chip->spk_mutex);
+
+	the_spk_chip->dev = &pdev->dev;
+	the_spk_chip->version = pm8xxx_get_version(the_spk_chip->dev->parent);
+	switch (pm8xxx_get_version(the_spk_chip->dev->parent)) {
+	case PM8XXX_VERSION_8038:
+		break;
+	default:
+		ret = -ENODEV;
+		goto err_handle;
+	}
+
+	memcpy(&(the_spk_chip->pdata), pdata,
+			sizeof(struct pm8xxx_spk_platform_data));
+
+	the_spk_chip->base = pdev->resource[0].start;
+	the_spk_chip->end = pdev->resource[0].end;
+
+	if (the_spk_chip->pdata.spk_add_enable) {
+		int val;
+		val = pm8xxx_spk_read(PM8XXX_SPK_CTL1_REG_OFF);
+		if (val < 0) {
+			ret = val;
+			goto err_handle;
+		}
+		val |= (the_spk_chip->pdata.spk_add_enable & PM8XXX_ADD_EN);
+		ret = pm8xxx_spk_write(PM8XXX_SPK_CTL1_REG_OFF, val);
+		if (ret < 0)
+			goto err_handle;
+	}
+	return pm8xxx_spk_config();
+err_handle:
+	pr_err("pm8xxx_spk_probe failed."
+			"Audio unavailable on speaker.\n");
+	mutex_destroy(&the_spk_chip->spk_mutex);
+	kfree(the_spk_chip);
+	return ret;
+}
+
+static int __devexit pm8xxx_spk_remove(struct platform_device *pdev)
+{
+	if (spk_defined() == false) {
+		pr_err("Invalid spk handle or no spk_chip\n");
+		return -ENODEV;
+	}
+	mutex_destroy(&the_spk_chip->spk_mutex);
+	kfree(the_spk_chip);
+	return 0;
+}
+
+static struct platform_driver pm8xxx_spk_driver = {
+	.probe		= pm8xxx_spk_probe,
+	.remove		= __devexit_p(pm8xxx_spk_remove),
+	.driver		= {
+		.name = PM8XXX_SPK_DEV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pm8xxx_spk_init(void)
+{
+	return platform_driver_register(&pm8xxx_spk_driver);
+}
+subsys_initcall(pm8xxx_spk_init);
+
+static void __exit pm8xxx_spk_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_spk_driver);
+}
+module_exit(pm8xxx_spk_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PM8XXX SPK driver");
+MODULE_ALIAS("platform:" PM8XXX_SPK_DEV_NAME);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 5040fc8..e458429 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1557,10 +1557,17 @@
 	struct mmc_command *cmd = host->curr.cmd;
 
 	host->curr.cmd = NULL;
-	cmd->resp[0] = readl_relaxed(host->base + MMCIRESPONSE0);
-	cmd->resp[1] = readl_relaxed(host->base + MMCIRESPONSE1);
-	cmd->resp[2] = readl_relaxed(host->base + MMCIRESPONSE2);
-	cmd->resp[3] = readl_relaxed(host->base + MMCIRESPONSE3);
+	if (mmc_resp_type(cmd))
+		cmd->resp[0] = readl_relaxed(host->base + MMCIRESPONSE0);
+	/*
+	 * Read rest of the response registers only if
+	 * long response is expected for this command
+	 */
+	if (mmc_resp_type(cmd) & MMC_RSP_136) {
+		cmd->resp[1] = readl_relaxed(host->base + MMCIRESPONSE1);
+		cmd->resp[2] = readl_relaxed(host->base + MMCIRESPONSE2);
+		cmd->resp[3] = readl_relaxed(host->base + MMCIRESPONSE3);
+	}
 
 	if (status & (MCI_CMDTIMEOUT | MCI_AUTOCMD19TIMEOUT)) {
 		pr_debug("%s: CMD%d: Command timeout\n",
@@ -1862,10 +1869,6 @@
 	}
 
 	spin_lock_irqsave(&host->lock, flags);
-	WARN(host->curr.mrq, "Request in progress\n");
-	WARN(!host->pwr, "SDCC power is turned off\n");
-	WARN(!host->clks_on, "SDCC clocks are turned off\n");
-	WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
 
 	if (host->eject) {
 		if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) {
@@ -1881,6 +1884,29 @@
 	}
 
 	/*
+	 * Don't start the request if SDCC is not in proper state to handle it
+	 */
+	if (!host->pwr || !host->clks_on || host->sdcc_irq_disabled) {
+		WARN(1, "%s: %s: SDCC is in bad state. don't process"
+		     " new request (CMD%d)\n", mmc_hostname(host->mmc),
+		     __func__, mrq->cmd->opcode);
+		msmsdcc_dump_sdcc_state(host);
+		mrq->cmd->error = -EIO;
+		if (mrq->data) {
+			mrq->data->error = -EIO;
+			mrq->data->bytes_xfered = 0;
+		}
+		spin_unlock_irqrestore(&host->lock, flags);
+		mmc_request_done(mmc, mrq);
+		return;
+	}
+
+	WARN(host->curr.mrq, "%s: %s: New request (CMD%d) received while"
+	     " other request (CMD%d) is in progress\n",
+	     mmc_hostname(host->mmc), __func__,
+	     mrq->cmd->opcode, host->curr.mrq->cmd->opcode);
+
+	/*
 	 * Kick the software command timeout timer here.
 	 * Timer expires in 10 secs.
 	 */
@@ -2830,6 +2856,20 @@
 }
 
 #ifdef CONFIG_PM_RUNTIME
+static void msmsdcc_print_rpm_info(struct msmsdcc_host *host)
+{
+	struct device *dev = mmc_dev(host->mmc);
+
+	pr_info("%s: RPM: runtime_status=%d, usage_count=%d,"
+		" is_suspended=%d, disable_depth=%d, runtime_error=%d,"
+		" request_pending=%d, request=%d\n",
+		mmc_hostname(host->mmc), dev->power.runtime_status,
+		atomic_read(&dev->power.usage_count),
+		dev->power.is_suspended, dev->power.disable_depth,
+		dev->power.runtime_error, dev->power.request_pending,
+		dev->power.request);
+}
+
 static int msmsdcc_enable(struct mmc_host *mmc)
 {
 	int rc = 0;
@@ -2862,6 +2902,7 @@
 	if (rc < 0) {
 		pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
 				__func__, rc);
+		msmsdcc_print_rpm_info(host);
 		return rc;
 	}
 
@@ -2892,18 +2933,21 @@
 	if (rc < 0 && (rc != -EAGAIN)) {
 		pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
 				__func__, rc);
+		msmsdcc_print_rpm_info(host);
 		return rc;
 	}
 
 	return 0;
 }
 #else
+static void msmsdcc_print_rpm_info(struct msmsdcc_host *host) {}
+
 static int msmsdcc_enable(struct mmc_host *mmc)
 {
 	struct device *dev = mmc->parent;
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	unsigned long flags;
-	int rc;
+	int rc = 0;
 
 	msmsdcc_pm_qos_update_latency(host, 1);
 
@@ -4153,7 +4197,7 @@
 				mmc_hostname(host->mmc), host->dma.busy,
 				host->dma.channel, host->dma.crci);
 		else if (host->is_sps_mode) {
-			if (host->sps.busy)
+			if (host->sps.busy && host->clks_on)
 				msmsdcc_print_regs("SDCC-DML", host->dml_base,
 						   host->dml_memres->start,
 						   16);
@@ -4171,6 +4215,7 @@
 		mmc_hostname(host->mmc), host->curr.got_dataend,
 		host->prog_enable, host->curr.wait_for_auto_prog_done,
 		host->curr.got_auto_prog_done);
+	msmsdcc_print_rpm_info(host);
 }
 
 static void msmsdcc_req_tout_timer_hdlr(unsigned long data)
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index 71df297..fbb377e 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -24,6 +24,7 @@
 #include <linux/msm_tsens.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/pm.h>
 
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
@@ -134,6 +135,9 @@
 #define TSENS_8064_S5_STATUS_ADDR		(MSM_CLK_CTL_BASE + 0x00003664)
 #define TSENS_8064_SEQ_SENSORS				5
 #define TSENS_8064_S4_S5_OFFSET				40
+#define TSENS_CNTL_RESUME_MASK				0xfffffff9
+#define TSENS_8960_SENSOR_MASK				0xf8
+#define TSENS_8064_SENSOR_MASK				0x3ff8
 
 static int tsens_status_cntl_start;
 
@@ -153,6 +157,8 @@
 	int				tsens_factor;
 	uint32_t			tsens_num_sensor;
 	enum platform_type		hw_type;
+	int				pm_tsens_thr_data;
+	int				pm_tsens_cntl;
 	struct tsens_tm_device_sensor	sensor[0];
 };
 
@@ -265,9 +271,6 @@
 		return -EINVAL;
 
 	if (mode != tm_sensor->mode) {
-		pr_info("%s: mode: %d --> %d\n", __func__, tm_sensor->mode,
-									 mode);
-
 		reg = readl_relaxed(TSENS_CNTL_ADDR);
 
 		mask = 1 << (tm_sensor->sensor_num + TSENS_SENSOR0_SHIFT);
@@ -686,6 +689,83 @@
 	}
 }
 
+#ifdef CONFIG_PM
+static int tsens_suspend(struct device *dev)
+{
+	int i = 0;
+
+	tmdev->pm_tsens_thr_data = readl_relaxed(TSENS_THRESHOLD_ADDR);
+	tmdev->pm_tsens_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	writel_relaxed(tmdev->pm_tsens_cntl &
+		~(TSENS_8960_SLP_CLK_ENA | TSENS_EN), TSENS_CNTL_ADDR);
+	tmdev->prev_reading_avail = 0;
+	for (i = 0; i < tmdev->tsens_num_sensor; i++)
+		tmdev->sensor[i].mode = THERMAL_DEVICE_DISABLED;
+	disable_irq_nosync(TSENS_UPPER_LOWER_INT);
+	mb();
+	return 0;
+}
+
+static int tsens_resume(struct device *dev)
+{
+	unsigned int reg_cntl = 0, reg_cfg = 0, reg_sensor_mask = 0;
+	unsigned int reg_status_cntl = 0, reg_thr_data = 0, i = 0;
+
+	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	writel_relaxed(reg_cntl | TSENS_SW_RST, TSENS_CNTL_ADDR);
+
+	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MDM_9615) {
+		reg_cntl |= TSENS_8960_SLP_CLK_ENA |
+			(TSENS_MEASURE_PERIOD << 18) |
+			TSENS_MIN_STATUS_MASK | TSENS_MAX_STATUS_MASK |
+			SENSORS_EN;
+		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) |
+			TSENS_8064_SENSORS_EN;
+		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+		reg_status_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+		reg_status_cntl |= TSENS_MIN_STATUS_MASK |
+			TSENS_MAX_STATUS_MASK;
+		writel_relaxed(reg_status_cntl, TSENS_8064_STATUS_CNTL);
+	}
+
+	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);
+
+	writel_relaxed((tmdev->pm_tsens_cntl & TSENS_CNTL_RESUME_MASK),
+						TSENS_CNTL_ADDR);
+	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	writel_relaxed(tmdev->pm_tsens_thr_data, TSENS_THRESHOLD_ADDR);
+	reg_thr_data = readl_relaxed(TSENS_THRESHOLD_ADDR);
+	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MDM_9615)
+		reg_sensor_mask = ((reg_cntl & TSENS_8960_SENSOR_MASK)
+				>> TSENS_SENSOR0_SHIFT);
+	else {
+		reg_sensor_mask = ((reg_cntl & TSENS_8064_SENSOR_MASK)
+				>> TSENS_SENSOR0_SHIFT);
+	}
+
+	for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+		if (reg_sensor_mask & TSENS_MASK1)
+			tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
+		reg_sensor_mask >>= 1;
+	}
+
+	enable_irq(TSENS_UPPER_LOWER_INT);
+	mb();
+	return 0;
+}
+
+static const struct dev_pm_ops tsens_pm_ops = {
+	.suspend	= tsens_suspend,
+	.resume		= tsens_resume,
+};
+#endif
+
 static void tsens_disable_mode(void)
 {
 	unsigned int reg_cntl = 0;
@@ -717,8 +797,7 @@
 			(TSENS_MEASURE_PERIOD << 18) |
 			TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR |
 			TSENS_MIN_STATUS_MASK | TSENS_MAX_STATUS_MASK |
-			(((1 << tmdev->tsens_num_sensor) - 1) <<
-			TSENS_SENSOR0_SHIFT);
+			SENSORS_EN;
 		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
 		reg_cntl |= TSENS_EN;
 		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
@@ -744,8 +823,7 @@
 	} 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);
+			TSENS_8064_SENSORS_EN;
 		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
 		reg_status_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
 		reg_status_cntl |= TSENS_LOWER_STATUS_CLR |
@@ -910,7 +988,7 @@
 	return rc;
 }
 
-static int __init tsens_tm_init(void)
+static int __devinit tsens_tm_probe(struct platform_device *pdev)
 {
 	int rc, i;
 
@@ -958,7 +1036,7 @@
 	return rc;
 }
 
-static void __exit tsens_tm_remove(void)
+static int __devexit tsens_tm_remove(struct platform_device *pdev)
 {
 	int i;
 
@@ -969,10 +1047,32 @@
 		thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
 	kfree(tmdev);
 	tmdev = NULL;
+	return 0;
 }
 
-module_init(tsens_tm_init);
-module_exit(tsens_tm_remove);
+static struct platform_driver tsens_tm_driver = {
+	.probe = tsens_tm_probe,
+	.remove = tsens_tm_remove,
+	.driver = {
+		.name = "tsens8960-tm",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &tsens_pm_ops,
+#endif
+	},
+};
+
+static int __init _tsens_tm_init(void)
+{
+	return platform_driver_register(&tsens_tm_driver);
+}
+module_init(_tsens_tm_init);
+
+static void __exit _tsens_tm_remove(void)
+{
+	platform_driver_unregister(&tsens_tm_driver);
+}
+module_exit(_tsens_tm_remove);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("MSM8960 Temperature Sensor driver");
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index fd119c6..c017859 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/utsname.h>
 #include <linux/platform_device.h>
+#include <linux/pm_qos_params.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/composite.h>
@@ -121,6 +122,8 @@
 	struct mutex mutex;
 	bool connected;
 	bool sw_connected;
+	char pm_qos[5];
+	struct pm_qos_request_list pm_qos_req_dma;
 	struct work_struct work;
 };
 
@@ -191,6 +194,25 @@
 	USB_CONFIGURED,
 };
 
+static void android_pm_qos_update_latency(struct android_dev *dev, int vote)
+{
+	struct android_usb_platform_data *pdata = dev->pdata;
+	u32 swfi_latency = 0;
+	static int last_vote = -1;
+
+	if (!pdata || vote == last_vote)
+		return;
+
+	swfi_latency = pdata->swfi_latency + 1;
+	if (vote)
+		pm_qos_update_request(&dev->pm_qos_req_dma,
+				swfi_latency);
+	else
+		pm_qos_update_request(&dev->pm_qos_req_dma,
+				PM_QOS_DEFAULT_VALUE);
+	last_vote = vote;
+}
+
 static void android_work(struct work_struct *data)
 {
 	struct android_dev *dev = container_of(data, struct android_dev, work);
@@ -209,6 +231,10 @@
 	} else if (dev->connected != dev->sw_connected) {
 		uevent_envp = dev->connected ? connected : disconnected;
 		next_state = dev->connected ? USB_CONNECTED : USB_DISCONNECTED;
+		if (dev->connected && strncmp(dev->pm_qos, "low", 3))
+			android_pm_qos_update_latency(dev, 1);
+		else if (!dev->connected || !strncmp(dev->pm_qos, "low", 3))
+			android_pm_qos_update_latency(dev, 0);
 	}
 	dev->sw_connected = dev->connected;
 	spin_unlock_irqrestore(&cdev->lock, flags);
@@ -1313,6 +1339,25 @@
 	return size;
 }
 
+static ssize_t pm_qos_show(struct device *pdev,
+			   struct device_attribute *attr, char *buf)
+{
+	struct android_dev *dev = dev_get_drvdata(pdev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", dev->pm_qos);
+}
+
+static ssize_t pm_qos_store(struct device *pdev,
+			   struct device_attribute *attr,
+			   const char *buff, size_t size)
+{
+	struct android_dev *dev = dev_get_drvdata(pdev);
+
+	strlcpy(dev->pm_qos, buff, sizeof(dev->pm_qos));
+
+	return size;
+}
+
 static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
 			   char *buf)
 {
@@ -1387,6 +1432,8 @@
 
 static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show, functions_store);
 static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
+static DEVICE_ATTR(pm_qos, S_IRUGO | S_IWUSR,
+		pm_qos_show, pm_qos_store);
 static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
 static DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR,
 		remote_wakeup_show, remote_wakeup_store);
@@ -1403,6 +1450,7 @@
 	&dev_attr_iSerial,
 	&dev_attr_functions,
 	&dev_attr_enable,
+	&dev_attr_pm_qos,
 	&dev_attr_state,
 	&dev_attr_remote_wakeup,
 	NULL
@@ -1630,6 +1678,12 @@
 		goto err_probe;
 	}
 
+	/* pm qos request to prevent apps idle power collapse */
+	if (pdata->swfi_latency)
+		pm_qos_add_request(&dev->pm_qos_req_dma,
+			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
+	strlcpy(dev->pm_qos, "high", sizeof(dev->pm_qos));
+
 	return ret;
 err_probe:
 	android_destroy_device(dev);
@@ -1641,10 +1695,14 @@
 static int android_remove(struct platform_device *pdev)
 {
 	struct android_dev *dev = _android_dev;
+	struct android_usb_platform_data *pdata = pdev->dev.platform_data;
 
 	android_destroy_device(dev);
 	class_destroy(android_class);
 	usb_composite_unregister(&android_usb_driver);
+	if (pdata->swfi_latency)
+		pm_qos_remove_request(&dev->pm_qos_req_dma);
+
 	return 0;
 }
 
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
index 17fa7b1..4657283 100644
--- a/drivers/usb/host/ehci-msm2.c
+++ b/drivers/usb/host/ehci-msm2.c
@@ -33,10 +33,13 @@
 #include <linux/usb/msm_hsusb_hw.h>
 #include <linux/usb/msm_hsusb.h>
 #include <mach/clk.h>
+#include <mach/msm_xo.h>
 #include <mach/msm_iomap.h>
 
 #define MSM_USB_BASE (hcd->regs)
 
+#define PDEV_NAME_LEN 20
+
 struct msm_hcd {
 	struct ehci_hcd				ehci;
 	struct device				*dev;
@@ -47,6 +50,7 @@
 	struct regulator			*hsusb_3p3;
 	struct regulator			*hsusb_1p8;
 	struct regulator			*vbus;
+	struct msm_xo_voter			*xo_handle;
 	bool					async_int;
 	bool					vbus_on;
 	atomic_t				in_lpm;
@@ -539,6 +543,7 @@
 {
 	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
 	unsigned long timeout;
+	int ret;
 	u32 portsc;
 
 	if (atomic_read(&mhcd->in_lpm)) {
@@ -588,6 +593,12 @@
 	clk_disable_unprepare(mhcd->iface_clk);
 	clk_disable_unprepare(mhcd->core_clk);
 
+	/* usb phy does not require TCXO clock, hence vote for TCXO disable */
+	ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_OFF);
+	if (ret)
+		dev_err(mhcd->dev, "%s failed to devote for "
+			"TCXO D0 buffer%d\n", __func__, ret);
+
 	msm_ehci_config_vddcx(mhcd, 0);
 
 	atomic_set(&mhcd->in_lpm, 1);
@@ -604,6 +615,7 @@
 	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
 	unsigned long timeout;
 	unsigned temp;
+	int ret;
 
 	if (!atomic_read(&mhcd->in_lpm)) {
 		dev_dbg(mhcd->dev, "%s called in !in_lpm\n", __func__);
@@ -612,6 +624,12 @@
 
 	wake_lock(&mhcd->wlock);
 
+	/* Vote for TCXO when waking up the phy */
+	ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_ON);
+	if (ret)
+		dev_err(mhcd->dev, "%s failed to vote for "
+			"TCXO D0 buffer%d\n", __func__, ret);
+
 	clk_prepare_enable(mhcd->core_clk);
 	clk_prepare_enable(mhcd->iface_clk);
 
@@ -816,6 +834,7 @@
 	struct resource *res;
 	struct msm_hcd *mhcd;
 	const struct msm_usb_host_platform_data *pdata;
+	char pdev_name[PDEV_NAME_LEN];
 	int ret;
 
 	dev_dbg(&pdev->dev, "ehci_msm2 probe\n");
@@ -853,11 +872,27 @@
 	mhcd = hcd_to_mhcd(hcd);
 	mhcd->dev = &pdev->dev;
 
+	snprintf(pdev_name, PDEV_NAME_LEN, "%s.%d", pdev->name, pdev->id);
+	mhcd->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, pdev_name);
+	if (IS_ERR(mhcd->xo_handle)) {
+		dev_err(&pdev->dev, "%s not able to get the handle "
+			"to vote for TCXO D0 buffer\n", __func__);
+		ret = PTR_ERR(mhcd->xo_handle);
+		goto unmap;
+	}
+
+	ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_ON);
+	if (ret) {
+		dev_err(&pdev->dev, "%s failed to vote for TCXO "
+			"D0 buffer%d\n", __func__, ret);
+		goto free_xo_handle;
+	}
+
 	ret = msm_ehci_init_clocks(mhcd, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to initialize clocks\n");
 		ret = -ENODEV;
-		goto unmap;
+		goto devote_xo_handle;
 	}
 
 	ret = msm_ehci_init_vddcx(mhcd, 1);
@@ -931,6 +966,10 @@
 	msm_ehci_init_vddcx(mhcd, 0);
 deinit_clocks:
 	msm_ehci_init_clocks(mhcd, 0);
+devote_xo_handle:
+	msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_OFF);
+free_xo_handle:
+	msm_xo_put(mhcd->xo_handle);
 unmap:
 	iounmap(hcd->regs);
 put_hcd:
@@ -950,6 +989,7 @@
 
 	usb_remove_hcd(hcd);
 
+	msm_xo_put(mhcd->xo_handle);
 	msm_ehci_vbus_power(mhcd, 0);
 	msm_ehci_init_vbus(mhcd, 0);
 	msm_ehci_ldo_enable(mhcd, 0);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index f319eb5..4dd6aff 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -39,7 +39,6 @@
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/misc.h>
-#include <linux/pm_qos_params.h>
 #include <linux/power_supply.h>
 
 #include <mach/clk.h>
@@ -71,25 +70,6 @@
 static bool debug_aca_enabled;
 static bool debug_bus_voting_enabled;
 
-/* Prevent idle power collapse(pc) while operating in peripheral mode */
-static void otg_pm_qos_update_latency(struct msm_otg *dev, int vote)
-{
-	struct msm_otg_platform_data *pdata = dev->pdata;
-	u32 swfi_latency = 0;
-
-	if (!pdata || !pdata->swfi_latency)
-		return;
-
-	swfi_latency = pdata->swfi_latency + 1;
-
-	if (vote)
-		pm_qos_update_request(&dev->pm_qos_req_dma,
-				swfi_latency);
-	else
-		pm_qos_update_request(&dev->pm_qos_req_dma,
-				PM_QOS_DEFAULT_VALUE);
-}
-
 static struct regulator *hsusb_3p3;
 static struct regulator *hsusb_1p8;
 static struct regulator *hsusb_vddcx;
@@ -1308,11 +1288,7 @@
 		 */
 		if (pdata->setup_gpio)
 			pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
-		/*
-		 * vote for minimum dma_latency to prevent idle
-		 * power collapse(pc) while running in peripheral mode.
-		 */
-		otg_pm_qos_update_latency(motg, 1);
+
 		/* Configure BUS performance parameters for MAX bandwidth */
 		if (motg->bus_perf_client && debug_bus_voting_enabled) {
 			ret = msm_bus_scale_client_update_request(
@@ -1325,7 +1301,6 @@
 	} else {
 		dev_dbg(otg->dev, "gadget off\n");
 		usb_gadget_vbus_disconnect(otg->gadget);
-		otg_pm_qos_update_latency(motg, 0);
 		/* Configure BUS performance parameters to default */
 		if (motg->bus_perf_client) {
 			ret = msm_bus_scale_client_update_request(
@@ -3213,11 +3188,6 @@
 	else
 		clk_set_rate(motg->clk, 60000000);
 
-	/* pm qos request to prevent apps idle power collapse */
-	if (motg->pdata->swfi_latency)
-		pm_qos_add_request(&motg->pm_qos_req_dma,
-			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
-
 	/*
 	 * USB Core is running its protocol engine based on CORE CLK,
 	 * CORE CLK  must be running at >55Mhz for correct HSUSB
@@ -3452,8 +3422,6 @@
 	if (!IS_ERR(motg->phy_reset_clk))
 		clk_put(motg->phy_reset_clk);
 free_motg:
-	if (motg->pdata->swfi_latency)
-		pm_qos_remove_request(&motg->pm_qos_req_dma);
 	kfree(motg);
 	return ret;
 }
@@ -3523,9 +3491,6 @@
 		clk_put(motg->clk);
 	clk_put(motg->core_clk);
 
-	if (motg->pdata->swfi_latency)
-		pm_qos_remove_request(&motg->pm_qos_req_dma);
-
 	if (motg->bus_perf_client)
 		msm_bus_scale_unregister_client(motg->bus_perf_client);
 
diff --git a/drivers/video/msm/mdp4_dtv.c b/drivers/video/msm/mdp4_dtv.c
index f7e74e6..f0353bd 100644
--- a/drivers/video/msm/mdp4_dtv.c
+++ b/drivers/video/msm/mdp4_dtv.c
@@ -149,7 +149,7 @@
 	}
 	pr_info("%s: tv_src_clk=%dkHz, pm_qos_rate=%ldkHz, [%d]\n", __func__,
 		mfd->fbi->var.pixclock/1000, pm_qos_rate, ret);
-
+	mfd->panel_info.clk_rate = mfd->fbi->var.pixclock;
 	clk_prepare_enable(hdmi_clk);
 	clk_reset(hdmi_clk, CLK_RESET_ASSERT);
 	udelay(20);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 7cc73de..42edecc 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1470,6 +1470,33 @@
 	return cnt;
 }
 
+static void mdp4_overlay_bg_solidfill_clear(uint32 mixer_num)
+{
+	struct mdp4_overlay_pipe *bg_pipe;
+	unsigned char *rgb_base;
+	uint32 rgb_src_format;
+	int pnum;
+
+	bg_pipe = mdp4_overlay_stage_pipe(mixer_num,
+		MDP4_MIXER_STAGE_BASE);
+	if (bg_pipe && bg_pipe->pipe_type == OVERLAY_TYPE_BF) {
+		bg_pipe = mdp4_overlay_stage_pipe(mixer_num,
+				MDP4_MIXER_STAGE0);
+	}
+
+	if (bg_pipe && bg_pipe->pipe_type == OVERLAY_TYPE_RGB) {
+		rgb_src_format = mdp4_overlay_format(bg_pipe);
+		if (!(rgb_src_format & MDP4_FORMAT_SOLID_FILL)) {
+			pnum = bg_pipe->pipe_num - OVERLAY_PIPE_RGB1;
+			rgb_base = MDP_BASE + MDP4_RGB_BASE;
+			rgb_base += MDP4_RGB_OFF * pnum;
+			outpdw(rgb_base + 0x50, rgb_src_format);
+			outpdw(rgb_base + 0x0058, bg_pipe->op_mode);
+			mdp4_overlay_reg_flush(bg_pipe, 0);
+		}
+	}
+}
+
 static void mdp4_mixer_stage_commit(int mixer)
 {
 	struct mdp4_overlay_pipe *pipe;
@@ -2573,6 +2600,12 @@
 		hdmi_prim_display)) {
 			ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
 	} else {
+		if (pipe->is_fg &&
+			!mdp4_overlay_is_rgb_type(pipe->src_format)) {
+			mdp4_overlay_bg_solidfill_clear(pipe->mixer_num);
+			pipe->is_fg = 0;
+		}
+
 		mdp4_mixer_stage_down(pipe);
 
 		if (pipe->mixer_num == MDP4_MIXER0) {
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index f92fb43..2fba83d 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -203,7 +203,7 @@
 	if (mfd->dma->busy == TRUE) {
 		if (busy_wait_cnt == 0)
 			INIT_COMPLETION(mfd->dma->comp);
-		busy_wait_cnt++;
+		busy_wait_cnt = 1;
 		need_wait++;
 	}
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
@@ -220,22 +220,21 @@
 {
 	spin_lock(&mdp_spin_lock);
 	dma->busy = FALSE;
-	spin_unlock(&mdp_spin_lock);
-	complete(&dma->comp);
 	if (busy_wait_cnt)
-		busy_wait_cnt--;
-
+		busy_wait_cnt = 0;
 	mdp_disable_irq_nosync(MDP_OVERLAY2_TERM);
+	spin_unlock(&mdp_spin_lock);
+	complete_all(&dma->comp);
 	pr_debug("%s ovdone interrupt\n", __func__);
 
 }
 void mdp4_writeback_overlay_kickoff(struct msm_fb_data_type *mfd,
-		struct mdp4_overlay_pipe *pipe)
+				    struct mdp4_overlay_pipe *pipe)
 {
 	unsigned long flag;
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	mdp_enable_irq(MDP_OVERLAY2_TERM);
-	INIT_COMPLETION(writeback_pipe->comp);
+
 	mfd->dma->busy = TRUE;
 	outp32(MDP_INTR_CLEAR, INTR_OVERLAY2_DONE);
 	mdp_intr_mask |= INTR_OVERLAY2_DONE;
@@ -247,7 +246,6 @@
 	mdp_pipe_kickoff(MDP_OVERLAY2_TERM, mfd);
 	wmb();
 	pr_debug("%s: before ov done interrupt\n", __func__);
-	wait_for_completion_killable(&mfd->dma->comp);
 }
 void mdp4_writeback_dma_stop(struct msm_fb_data_type *mfd)
 {
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 6ebc955..8da0995 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -252,13 +252,11 @@
 	void *ptr;
 	u32 status = VCD_S_SUCCESS;
 	DDL_MSG_HIGH("ddl_encode_start");
-	if (vidc_msg_timing) {
-		if (first_time < 2) {
-			ddl_reset_core_time_variables(ENC_OP_TIME);
-			first_time++;
-		 }
-		ddl_set_core_start_time(__func__, ENC_OP_TIME);
-	}
+	if (first_time < 2) {
+		ddl_reset_core_time_variables(ENC_OP_TIME);
+		first_time++;
+	 }
+	ddl_set_core_start_time(__func__, ENC_OP_TIME);
 	ddl_context = ddl_get_context();
 	if (!DDL_IS_INITIALIZED(ddl_context)) {
 		DDL_MSG_ERROR("ddl_enc_start:Not_inited");
@@ -300,6 +298,27 @@
 				encoder->seq_header.virtual_base_addr,
 				encoder->seq_header.buffer_size,
 				ION_IOC_CLEAN_INV_CACHES);
+	if (encoder->slice_delivery_info.enable) {
+		DDL_MSG_LOW("%s: slice mode allocate memory for struct\n",
+					__func__);
+		ptr = ddl_pmem_alloc(&encoder->batch_frame.slice_batch_in,
+				DDL_ENC_SLICE_BATCH_INPSTRUCT_SIZE,
+				DDL_LINEAR_BUFFER_ALIGN_BYTES);
+		if (ptr) {
+			ptr = ddl_pmem_alloc(
+				&encoder->batch_frame.slice_batch_out,
+				DDL_ENC_SLICE_BATCH_OUTSTRUCT_SIZE,
+				DDL_LINEAR_BUFFER_ALIGN_BYTES);
+		}
+		if (!ptr) {
+			ddl_pmem_free(&encoder->batch_frame.slice_batch_in);
+			ddl_pmem_free(&encoder->batch_frame.slice_batch_out);
+			ddl_free_enc_hw_buffers(ddl);
+			ddl_pmem_free(&encoder->seq_header);
+			DDL_MSG_ERROR("ddlEncStart:SeqHdrAllocFailed");
+			return VCD_ERR_ALLOC_FAIL;
+		}
+	}
 	if (!ddl_take_command_channel(ddl_context, ddl, client_data))
 		return VCD_ERR_BUSY;
 	ddl_vidc_channel_set(ddl);
@@ -316,10 +335,8 @@
 	u32 status = VCD_S_SUCCESS;
 
 	DDL_MSG_HIGH("ddl_decode_start");
-	if (vidc_msg_timing) {
-		ddl_reset_core_time_variables(DEC_OP_TIME);
-		ddl_reset_core_time_variables(DEC_IP_TIME);
-	}
+	ddl_reset_core_time_variables(DEC_OP_TIME);
+	ddl_reset_core_time_variables(DEC_IP_TIME);
 	ddl_context = ddl_get_context();
 	if (!DDL_IS_INITIALIZED(ddl_context)) {
 		DDL_MSG_ERROR("ddl_dec_start:Not_inited");
@@ -451,11 +468,20 @@
 	struct ddl_client_context *ddl =
 		(struct ddl_client_context *) ddl_handle;
 	struct ddl_context *ddl_context;
+	struct ddl_encoder_data *encoder =
+		&ddl->codec_data.encoder;
 	u32 vcd_status = VCD_S_SUCCESS;
+	if (encoder->slice_delivery_info.enable) {
+		return ddl_encode_frame_batch(ddl_handle,
+					input_frame,
+					output_bit,
+					1,
+					encoder->slice_delivery_info.num_slices,
+					client_data);
+	}
 
 	DDL_MSG_HIGH("ddl_encode_frame");
-	if (vidc_msg_timing)
-		ddl_set_core_start_time(__func__, ENC_OP_TIME);
+	ddl_set_core_start_time(__func__, ENC_OP_TIME);
 	ddl_context = ddl_get_context();
 	if (!DDL_IS_INITIALIZED(ddl_context)) {
 		DDL_MSG_ERROR("ddl_enc_frame:Not_inited");
@@ -519,6 +545,76 @@
 	return vcd_status;
 }
 
+u32 ddl_encode_frame_batch(u32 *ddl_handle,
+	struct ddl_frame_data_tag *input_frame,
+	struct ddl_frame_data_tag *output_bit,
+	u32 num_in_frames, u32 num_out_frames,
+	void *client_data)
+{
+	struct ddl_client_context *ddl =
+		(struct ddl_client_context *) ddl_handle;
+	struct ddl_context *ddl_context;
+	u32 vcd_status = VCD_S_SUCCESS;
+	struct ddl_encoder_data *encoder;
+
+	DDL_MSG_LOW("ddl_encode_frame_batch");
+	ddl_context = ddl_get_context();
+	if (!DDL_IS_INITIALIZED(ddl_context)) {
+		DDL_MSG_ERROR("ddl_enc_frame:Not_inited");
+		return VCD_ERR_ILLEGAL_OP;
+	}
+	if (DDL_IS_BUSY(ddl_context)) {
+		DDL_MSG_ERROR("ddl_enc_frame:Ddl_busy");
+		return VCD_ERR_BUSY;
+	}
+	if (!ddl || ddl->decoding) {
+		DDL_MSG_ERROR("ddl_enc_frame:Bad_handle");
+	return VCD_ERR_BAD_HANDLE;
+	}
+	if (!input_frame || !input_frame->vcd_frm.physical	||
+		!input_frame->vcd_frm.data_len) {
+		DDL_MSG_ERROR("ddl_enc_frame:Bad_input_params");
+		return VCD_ERR_ILLEGAL_PARM;
+	}
+	if ((((u32) input_frame->vcd_frm.physical +
+		input_frame->vcd_frm.offset) &
+		(DDL_STREAMBUF_ALIGN_GUARD_BYTES))) {
+		DDL_MSG_ERROR("ddl_enc_frame:Un_aligned_yuv_start_address");
+		return VCD_ERR_ILLEGAL_PARM;
+	}
+	if (!output_bit || !output_bit->vcd_frm.physical ||
+		!output_bit->vcd_frm.alloc_len) {
+		DDL_MSG_ERROR("ddl_enc_frame:Bad_output_params");
+		return VCD_ERR_ILLEGAL_PARM;
+	}
+	if ((ddl->codec_data.encoder.output_buf_req.sz +
+		output_bit->vcd_frm.offset) >
+		output_bit->vcd_frm.alloc_len)
+		DDL_MSG_ERROR("ddl_enc_frame:offset_large,"
+			"Exceeds_min_buf_size");
+	if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME)) {
+		DDL_MSG_ERROR("ddl_enc_frame:Wrong_state");
+		return VCD_ERR_ILLEGAL_OP;
+	}
+	if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+		return VCD_ERR_BUSY;
+	encoder = &ddl->codec_data.encoder;
+	if (encoder->slice_delivery_info.enable) {
+		DDL_MEMCPY((void *)&(encoder->batch_frame.output_frame[0]),
+			(void *)output_bit,
+			sizeof(struct ddl_frame_data_tag) * num_out_frames);
+		encoder->batch_frame.num_output_frames = num_out_frames;
+		ddl->input_frame = *input_frame;
+		vcd_status = ddl_insert_input_frame_to_pool(ddl, input_frame);
+		if (!vcd_status)
+			ddl_vidc_encode_slice_batch_run(ddl);
+		else
+			DDL_MSG_ERROR("insert to frame pool failed %u",
+					vcd_status);
+	}
+	return vcd_status;
+}
+
 u32 ddl_decode_end(u32 *ddl_handle, void *client_data)
 {
 	struct ddl_client_context *ddl =
@@ -526,10 +622,8 @@
 	struct ddl_context *ddl_context;
 
 	DDL_MSG_HIGH("ddl_decode_end");
-	if (vidc_msg_timing) {
-		ddl_reset_core_time_variables(DEC_OP_TIME);
-		ddl_reset_core_time_variables(DEC_IP_TIME);
-	}
+	ddl_reset_core_time_variables(DEC_OP_TIME);
+	ddl_reset_core_time_variables(DEC_IP_TIME);
 	ddl_context = ddl_get_context();
 	if (!DDL_IS_INITIALIZED(ddl_context)) {
 		DDL_MSG_ERROR("ddl_dec_end:Not_inited");
@@ -563,8 +657,7 @@
 	struct ddl_context *ddl_context;
 
 	DDL_MSG_HIGH("ddl_encode_end");
-	if (vidc_msg_timing)
-		ddl_reset_core_time_variables(ENC_OP_TIME);
+	ddl_reset_core_time_variables(ENC_OP_TIME);
 	ddl_context = ddl_get_context();
 	if (!DDL_IS_INITIALIZED(ddl_context)) {
 		DDL_MSG_ERROR("ddl_enc_end:Not_inited");
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index c3874fa..4a952c9 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -100,6 +100,7 @@
 	struct ion_handle *alloc_handle;
 	u32 buffer_size;
 	enum ddl_mem_area mem_type;
+	void *pil_cookie;
 };
 enum ddl_cmd_state{
 	DDL_CMD_INVALID         = 0x0,
@@ -113,6 +114,7 @@
 	DDL_CMD_ENCODE_FRAME    = 0x8,
 	DDL_CMD_EOS             = 0x9,
 	DDL_CMD_CHANNEL_END     = 0xA,
+	DDL_CMD_ENCODE_CONTINUE = 0xB,
 	DDL_CMD_32BIT           = 0x7FFFFFFF
 };
 enum ddl_client_state{
@@ -129,6 +131,7 @@
 	DDL_CLIENT_WAIT_FOR_CHEND          = 0xA,
 	DDL_CLIENT_FATAL_ERROR             = 0xB,
 	DDL_CLIENT_FAVIDC_ERROR            = 0xC,
+	DDL_CLIENT_WAIT_FOR_CONTINUE       = 0xD,
 	DDL_CLIENT_32BIT                   = 0x7FFFFFFF
 };
 struct ddl_hw_interface{
@@ -215,6 +218,15 @@
 struct ddl_codec_data_hdr{
 	u32  decoding;
 };
+struct ddl_batch_frame_data {
+	struct ddl_buf_addr slice_batch_in;
+	struct ddl_buf_addr slice_batch_out;
+	struct ddl_frame_data_tag input_frame;
+	struct ddl_frame_data_tag output_frame
+			[DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH];
+	u32 num_output_frames;
+	u32 out_frm_next_frmindex;
+};
 struct ddl_encoder_data{
 	struct ddl_codec_data_hdr   hdr;
 	struct vcd_property_codec   codec;
@@ -262,6 +274,8 @@
 	u32  ext_enc_control_val;
 	u32  num_references_for_p_frame;
 	u32  closed_gop;
+	struct vcd_property_slice_delivery_info slice_delivery_info;
+	struct ddl_batch_frame_data batch_frame;
 };
 struct ddl_decoder_data {
 	struct ddl_codec_data_hdr  hdr;
@@ -303,6 +317,8 @@
 	u32  cont_mode;
 	u32  reconfig_detected;
 	u32  dmx_disable;
+	int avg_dec_time;
+	int dec_time_sum;
 };
 union ddl_codec_data{
 	struct ddl_codec_data_hdr  hdr;
@@ -344,6 +360,8 @@
 		(struct vidc_1080p_enc_seq_start_param *param);
 	void(*vidc_encode_frame_start[2])
 		(struct vidc_1080p_enc_frame_start_param *param);
+	void(*vidc_encode_slice_batch_start[2])
+		(struct vidc_1080p_enc_frame_start_param *param);
 	u32 frame_channel_depth;
 };
 struct ddl_client_context{
@@ -375,9 +393,12 @@
 void ddl_vidc_channel_end(struct ddl_client_context *);
 void ddl_vidc_encode_init_codec(struct ddl_client_context *);
 void ddl_vidc_decode_init_codec(struct ddl_client_context *);
+void ddl_vidc_encode_frame_continue(struct ddl_client_context *);
 void ddl_vidc_encode_frame_run(struct ddl_client_context *);
+void ddl_vidc_encode_slice_batch_run(struct ddl_client_context *);
 void ddl_vidc_decode_frame_run(struct ddl_client_context *);
 void ddl_vidc_decode_eos_run(struct ddl_client_context *ddl);
+void ddl_vidc_encode_eos_run(struct ddl_client_context *ddl);
 void ddl_release_context_buffers(struct ddl_context *);
 void ddl_release_client_internal_buffers(struct ddl_client_context *ddl);
 u32  ddl_vidc_decode_set_buffers(struct ddl_client_context *);
@@ -438,9 +459,10 @@
 
 u32 ddl_get_input_frame_from_pool(struct ddl_client_context *ddl,
 	u8 *input_buffer_address);
+u32 ddl_get_stream_buf_from_batch_pool(struct ddl_client_context *ddl,
+	struct ddl_frame_data_tag *stream_buffer);
 u32 ddl_insert_input_frame_to_pool(struct ddl_client_context *ddl,
 	struct ddl_frame_data_tag *ddl_input_frame);
-
 void ddl_decoder_chroma_dpb_change(struct ddl_client_context *ddl);
 u32  ddl_check_reconfig(struct ddl_client_context *ddl);
 void ddl_handle_reconfig(u32 res_change, struct ddl_client_context *ddl);
@@ -458,5 +480,9 @@
 u32 ddl_fw_init(struct ddl_buf_addr *dram_base);
 void ddl_get_fw_info(const unsigned char **fw_array_addr,
 	unsigned int *fw_size);
-void ddl_fw_release(void);
+void ddl_fw_release(struct ddl_buf_addr *);
+int ddl_vidc_decode_get_avg_time(struct ddl_client_context *ddl);
+void ddl_vidc_decode_reset_avg_time(struct ddl_client_context *ddl);
+void ddl_calc_core_proc_time(const char *func_name, u32 index,
+		struct ddl_client_context *ddl);
 #endif
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 433dad4..5c1ee21 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
@@ -62,6 +62,11 @@
 	u32 disable_static_region_as_flag;
 	u32 disable_activity_region_flag;
 };
+struct vcd_property_slice_delivery_info {
+	u32  enable;
+	u32  num_slices;
+	u32  num_slices_enc;
+};
 struct ddl_property_dec_pic_buffers{
 	struct ddl_frame_data_tag *dec_pic_buffers;
 	u32 no_of_dec_pic_buf;
@@ -94,6 +99,11 @@
 u32 ddl_encode_frame(u32 *ddl_handle,
 	struct ddl_frame_data_tag *input_frame,
 	struct ddl_frame_data_tag *output_bit, void *client_data);
+u32 ddl_encode_frame_batch(u32 *ddl_handle,
+	struct ddl_frame_data_tag *input_frame,
+	struct ddl_frame_data_tag *output_bit,
+	u32 num_in_frames, u32 num_out_frames,
+	void *client_data);
 u32 ddl_encode_end(u32 *ddl_handle, void *client_data);
 u32 ddl_decode_start(u32 *ddl_handle, struct vcd_sequence_hdr *header,
 	void *client_data);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index a8ccebf..41604b0 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -64,13 +64,20 @@
 #define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE  (DDL_KILO_BYTE(800))
 #define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE      (DDL_KILO_BYTE(800))
 #define DDL_FW_H264ENC_CONTEXT_SPACE_SIZE      (DDL_KILO_BYTE(20))
-#define DDL_FW_OTHER_CONTEXT_SPACE_SIZE        (DDL_KILO_BYTE(10))
+#define DDL_FW_OTHER_CONTEXT_SPACE_SIZE        (DDL_KILO_BYTE(20))
 
 #define VCD_DEC_CPB_SIZE         (DDL_KILO_BYTE(512))
 #define DDL_DBG_CORE_DUMP_SIZE   (DDL_KILO_BYTE(10))
+#define DDL_VIDC_1080P_BASE_OFFSET_SHIFT        11
 
 #define DDL_BUFEND_PAD                    256
 #define DDL_ENC_SEQHEADER_SIZE            (512+DDL_BUFEND_PAD)
+#define DDL_ENC_SLICE_BATCH_FACTOR         5
+#define DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH   8
+#define DDL_ENC_SLICE_BATCH_INPSTRUCT_SIZE (128 + \
+				32 * DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH)
+#define DDL_ENC_SLICE_BATCH_OUTSTRUCT_SIZE (64 + \
+				64 * DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH)
 #define DDL_MAX_BUFFER_COUNT              32
 #define DDL_MIN_BUFFER_COUNT              1
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index 62f0976..2862b00 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -353,7 +353,7 @@
 void ddl_release_context_buffers(struct ddl_context *ddl_context)
 {
 	ddl_pmem_free(&ddl_context->metadata_shared_input);
-	ddl_fw_release();
+	ddl_fw_release(&ddl_context->dram_base_a);
 }
 
 void ddl_release_client_internal_buffers(struct ddl_client_context *ddl)
@@ -375,10 +375,14 @@
 		struct ddl_encoder_data *encoder =
 			&(ddl->codec_data.encoder);
 		ddl_pmem_free(&encoder->seq_header);
+		ddl_pmem_free(&encoder->batch_frame.slice_batch_in);
+		ddl_pmem_free(&encoder->batch_frame.slice_batch_out);
 		ddl_vidc_encode_dynamic_property(ddl, false);
 		encoder->dynamic_prop_change = 0;
 		ddl_free_enc_hw_buffers(ddl);
 	}
+	ddl_pmem_free(&ddl->shared_mem[0]);
+	ddl_pmem_free(&ddl->shared_mem[1]);
 }
 
 u32 ddl_codec_type_transact(struct ddl_client_context *ddl,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index 830c777c3..5b9aea8 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -29,7 +29,11 @@
 	enum vidc_1080p_encode_frame frame_type);
 static void ddl_get_dec_profile_level(struct ddl_decoder_data *decoder,
 	u32 profile, u32 level);
-static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl);
+static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl,
+	u32 eos_present);
+static void ddl_handle_slice_done_slice_batch(struct ddl_client_context *ddl);
+static void ddl_handle_enc_frame_done_slice_mode(
+		struct ddl_client_context *ddl, u32 eos_present);
 
 static void ddl_fw_status_done_callback(struct ddl_context *ddl_context)
 {
@@ -113,9 +117,8 @@
 			ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODEC;
 			ddl->instance_id = instance_id;
 			if (ddl->decoding) {
-				if (vidc_msg_timing)
-					ddl_calc_core_proc_time(__func__,
-						DEC_OP_TIME);
+				ddl_calc_core_proc_time(__func__,
+						DEC_OP_TIME, ddl);
 				if (ddl->codec_data.decoder.header_in_start)
 					ddl_vidc_decode_init_codec(ddl);
 				else {
@@ -141,14 +144,13 @@
 {
 	struct ddl_encoder_data *encoder;
 
-	DDL_MSG_MED("ddl_encoder_seq_done_callback");
+	DDL_MSG_HIGH("ddl_encoder_seq_done_callback");
 	if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) {
 		DDL_MSG_ERROR("STATE-CRITICAL-INITCODEC");
 		ddl_client_fatal_cb(ddl);
 		return true;
 	}
-	if (vidc_msg_timing)
-		ddl_calc_core_proc_time(__func__, ENC_OP_TIME);
+	ddl_calc_core_proc_time(__func__, ENC_OP_TIME, ddl);
 	ddl->cmd_state = DDL_CMD_INVALID;
 	DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_FRAME",
 	ddl_get_state_string(ddl->client_state));
@@ -245,8 +247,7 @@
 		DDL_MSG_ERROR("STATE-CRITICAL-HDDONE");
 		ddl_client_fatal_cb(ddl);
 	} else {
-		if (vidc_msg_timing)
-			ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+		ddl_calc_core_proc_time(__func__, DEC_OP_TIME, ddl);
 		ddl->cmd_state = DDL_CMD_INVALID;
 		DDL_MSG_LOW("ddl_state_transition: %s ~~>"
 			"DDL_CLIENT_WAIT_FOR_DPB",
@@ -466,10 +467,8 @@
 			DDL_MSG_LOW("ddl_state_transition: %s ~~>"
 				"DDL_CLIENT_WAIT_FOR_FRAME",
 				ddl_get_state_string(ddl->client_state));
-			if (vidc_msg_timing) {
-				ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
-				ddl_reset_core_time_variables(DEC_OP_TIME);
-			}
+			ddl_calc_core_proc_time(__func__, DEC_OP_TIME, ddl);
+			ddl_reset_core_time_variables(DEC_OP_TIME);
 			ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
 			ddl_vidc_decode_frame_run(ddl);
 			ret_status = false;
@@ -486,60 +485,40 @@
 		&(ddl->codec_data.encoder);
 	struct vcd_frame_data *output_frame =
 		&(ddl->output_frame.vcd_frm);
-	u32 bottom_frame_tag;
+	u32 eos_present = false;
 
-	DDL_MSG_MED("ddl_encoder_frame_run_callback");
+	DDL_MSG_MED("ddl_encoder_frame_run_callback\n");
 	if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE) &&
 		!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
 		DDL_MSG_ERROR("STATE-CRITICAL-ENCFRMRUN");
 		ddl_client_fatal_cb(ddl);
 	} else {
-		if (vidc_msg_timing)
-			ddl_calc_core_proc_time(__func__, ENC_OP_TIME);
+		ddl_calc_core_proc_time(__func__, ENC_OP_TIME, ddl);
 		DDL_MSG_LOW("ENC_FRM_RUN_DONE");
 		ddl->cmd_state = DDL_CMD_INVALID;
 		vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
-		vidc_sm_get_frame_tags(&ddl->shared_mem
-			[ddl->command_channel],
-			&output_frame->ip_frm_tag, &bottom_frame_tag);
 
 		if (encoder->meta_data_enable_flag)
 			vidc_sm_get_metadata_status(&ddl->shared_mem
 				[ddl->command_channel],
 				&encoder->enc_frame_info.meta_data_exists);
 
+		if (VCD_FRAME_FLAG_EOS & ddl->input_frame.vcd_frm.flags) {
+				DDL_MSG_LOW("%s EOS detected\n", __func__);
+				eos_present = true;
+		}
+
 		if (encoder->enc_frame_info.enc_frame_size ||
 			(encoder->enc_frame_info.enc_frame ==
 			VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED) ||
 			DDLCLIENT_STATE_IS(ddl,
 			DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
-			u8 *input_buffer_address = NULL;
-			output_frame->data_len =
-				encoder->enc_frame_info.enc_frame_size;
-			output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
-			ddl_get_encoded_frame(output_frame,
-				encoder->codec.codec,
-				encoder->enc_frame_info.enc_frame);
-			ddl_process_encoder_metadata(ddl);
-			ddl_vidc_encode_dynamic_property(ddl, false);
-			ddl->input_frame.frm_trans_end = false;
-			input_buffer_address = ddl_context->dram_base_a.\
-				align_physical_addr +
-				encoder->enc_frame_info.enc_luma_address;
-			ddl_get_input_frame_from_pool(ddl,
-				input_buffer_address);
-			ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
-				VCD_S_SUCCESS, &(ddl->input_frame),
-				sizeof(struct ddl_frame_data_tag),
-				(u32 *)ddl, ddl->client_data);
-			ddl->output_frame.frm_trans_end =
-				DDLCLIENT_STATE_IS(ddl,
-				DDL_CLIENT_WAIT_FOR_EOS_DONE) ? false : true;
-			ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
-				VCD_S_SUCCESS, &(ddl->output_frame),
-				sizeof(struct ddl_frame_data_tag),
-				(u32 *)ddl, ddl->client_data);
-
+			if (encoder->slice_delivery_info.enable) {
+				ddl_handle_enc_frame_done_slice_mode(ddl,
+								eos_present);
+			} else {
+				ddl_handle_enc_frame_done(ddl, eos_present);
+			}
 			if (DDLCLIENT_STATE_IS(ddl,
 				DDL_CLIENT_WAIT_FOR_EOS_DONE) &&
 				encoder->i_period.b_frames) {
@@ -547,7 +526,7 @@
 					(ddl->extra_output_buf_count >
 					encoder->i_period.b_frames)) {
 					DDL_MSG_ERROR("Invalid B frame output"
-								"buffer index");
+								  "buffer index");
 				} else {
 					struct vidc_1080p_enc_frame_start_param
 						enc_param;
@@ -581,7 +560,11 @@
 					ddl_context->vidc_encode_frame_start
 						[ddl->command_channel]
 						(&enc_param);
-				} } else {
+					}
+				} else if (eos_present &&
+					encoder->slice_delivery_info.enable) {
+					ddl_vidc_encode_eos_run(ddl);
+				} else {
 				DDL_MSG_LOW("ddl_state_transition: %s ~~>"
 					"DDL_CLIENT_WAIT_FOR_FRAME",
 					ddl_get_state_string(
@@ -885,6 +868,7 @@
 	vidc_1080p_clear_returned_channel_inst_id();
 	ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
 			ddl_context->response_cmd_ch_id);
+	DDL_MSG_LOW("ddl_encoder_eos_done\n");
 	if (ddl == NULL) {
 		DDL_MSG_ERROR("NO_DDL_CONTEXT");
 	} else {
@@ -896,9 +880,11 @@
 				&(ddl->codec_data.encoder);
 			vidc_1080p_get_encode_frame_info(
 				&encoder->enc_frame_info);
-			ddl_handle_enc_frame_done(ddl);
+			if (!encoder->slice_delivery_info.enable) {
+				ddl_handle_enc_frame_done(ddl, true);
+				ddl->cmd_state = DDL_CMD_INVALID;
+			}
 			DDL_MSG_LOW("encoder_eos_done");
-			ddl->cmd_state = DDL_CMD_INVALID;
 			DDL_MSG_LOW("ddl_state_transition: %s ~~>"
 				"DDL_CLIENT_WAIT_FOR_FRAME",
 				ddl_get_state_string(ddl->client_state));
@@ -913,6 +899,35 @@
 	}
 }
 
+static u32 ddl_slice_done_callback(struct ddl_context *ddl_context)
+{
+	struct ddl_client_context *ddl;
+	u32 channel_inst_id;
+	u32 return_status = true;
+	DDL_MSG_LOW("ddl_sliceDoneCallback");
+	vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+	vidc_1080p_clear_returned_channel_inst_id();
+	ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+			ddl_context->response_cmd_ch_id);
+	if (ddl == NULL) {
+		DDL_MSG_ERROR("NO_DDL_CONTEXT");
+		return_status = false;
+	} else if (ddl->cmd_state == DDL_CMD_ENCODE_FRAME) {
+			ddl->cmd_state = DDL_CMD_INVALID;
+			if (DDLCLIENT_STATE_IS(ddl,
+				DDL_CLIENT_WAIT_FOR_FRAME_DONE)) {
+				ddl_handle_slice_done_slice_batch(ddl);
+			} else {
+				DDL_MSG_ERROR("STATE-CRITICAL-ENCFRMRUN : %s\n",
+					 __func__);
+				ddl_client_fatal_cb(ddl);
+			}
+	} else {
+		DDL_MSG_ERROR("UNKNOWN_SLICEDONE : %s\n", __func__);
+	}
+	return return_status;
+}
+
 static u32 ddl_process_intr_status(struct ddl_context *ddl_context,
 	u32 intr_status)
 {
@@ -931,6 +946,9 @@
 	case VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET:
 		return_status = ddl_frame_run_callback(ddl_context);
 	break;
+	case VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET:
+		 ddl_slice_done_callback(ddl_context);
+	break;
 	case VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET:
 		ddl_sys_init_done_callback(ddl_context,
 			ddl_context->response_cmd_ch_id);
@@ -963,6 +981,8 @@
 {
 	struct ddl_context *ddl_context;
 	struct ddl_hw_interface  *ddl_hw_response;
+	struct ddl_client_context *ddl;
+	struct ddl_encoder_data *encoder;
 
 	ddl_context = ddl_get_context();
 	if (!ddl_context->core_virtual_base_addr) {
@@ -971,12 +991,37 @@
 		ddl_hw_response = &ddl_context->ddl_hw_response;
 		vidc_1080p_get_risc2host_cmd(&ddl_hw_response->cmd,
 			&ddl_hw_response->arg1, &ddl_hw_response->arg2,
-			&ddl_hw_response->arg3, &ddl_hw_response->arg4);
+			&ddl_hw_response->arg3,
+			&ddl_hw_response->arg4);
+		DDL_MSG_LOW("%s vidc_1080p_get_risc2host_cmd cmd = %u"
+			"arg1 = %u arg2 = %u arg3 = %u"
+			"arg4 = %u\n",
+			__func__, ddl_hw_response->cmd,
+			ddl_hw_response->arg1, ddl_hw_response->arg2,
+			ddl_hw_response->arg3,
+			ddl_hw_response->arg4);
+		ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+			ddl_context->response_cmd_ch_id);
+		if (ddl) {
+			encoder = &(ddl->codec_data.encoder);
+			if (encoder && encoder->slice_delivery_info.enable
+			&&
+			((ddl_hw_response->cmd ==
+				VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET)
+			|| (ddl_hw_response->cmd ==
+				VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET))) {
+				vidc_sm_set_encoder_slice_batch_int_ctrl(
+				&ddl->shared_mem[ddl->command_channel],
+				1);
+			}
+		}
 		vidc_1080p_clear_risc2host_cmd();
 		vidc_1080p_clear_interrupt();
 		vidc_1080p_get_risc2host_cmd_status(ddl_hw_response->arg2,
 			&ddl_context->cmd_err_status,
 			&ddl_context->disp_pic_err_status);
+		DDL_MSG_LOW("%s cmd_err_status = %d\n", __func__,
+				ddl_context->cmd_err_status);
 		ddl_context->response_cmd_ch_id = ddl_hw_response->arg1;
 	}
 }
@@ -1028,8 +1073,7 @@
 	input_vcd_frm->offset += dec_disp_info->input_bytes_consumed;
 	input_vcd_frm->data_len -= dec_disp_info->input_bytes_consumed;
 	ddl->input_frame.frm_trans_end = frame_transact_end;
-	if (vidc_msg_timing)
-		ddl_calc_core_proc_time(__func__, DEC_IP_TIME);
+	ddl_calc_core_proc_time(__func__, DEC_IP_TIME, ddl);
 	ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE, VCD_S_SUCCESS,
 		&ddl->input_frame, sizeof(struct ddl_frame_data_tag),
 		(u32 *)ddl, ddl->client_data);
@@ -1233,8 +1277,7 @@
 		}
 		output_vcd_frm->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
 		output_frame->frm_trans_end = frame_transact_end;
-		if (vidc_msg_timing)
-			ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+		ddl_calc_core_proc_time(__func__, DEC_OP_TIME, ddl);
 		ddl_process_decoder_metadata(ddl);
 		vidc_sm_get_aspect_ratio_info(
 			&ddl->shared_mem[ddl->command_channel],
@@ -1638,39 +1681,214 @@
 	decoder->level.level = level;
 }
 
-static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl)
+static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl,
+					u32 eos_present)
 {
 	struct ddl_context       *ddl_context = ddl->ddl_context;
 	struct ddl_encoder_data  *encoder = &(ddl->codec_data.encoder);
 	struct vcd_frame_data    *output_frame = &(ddl->output_frame.vcd_frm);
 	u32 bottom_frame_tag;
-	u8  *input_buffer_address = NULL;
+	u8 *input_buffer_address = NULL;
 
 	vidc_sm_get_frame_tags(&ddl->shared_mem[ddl->command_channel],
 		&output_frame->ip_frm_tag, &bottom_frame_tag);
 	output_frame->data_len = encoder->enc_frame_info.enc_frame_size;
 	output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
 	(void)ddl_get_encoded_frame(output_frame,
-		encoder->codec.codec, encoder->enc_frame_info.enc_frame);
+		encoder->codec.codec, encoder->enc_frame_info.enc_frame
+								);
 	ddl_process_encoder_metadata(ddl);
 	ddl_vidc_encode_dynamic_property(ddl, false);
 	ddl->input_frame.frm_trans_end = false;
 	input_buffer_address = ddl_context->dram_base_a.align_physical_addr +
 			encoder->enc_frame_info.enc_luma_address;
 	ddl_get_input_frame_from_pool(ddl, input_buffer_address);
-
 	ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
-		VCD_S_SUCCESS, &(ddl->input_frame),
-		sizeof(struct ddl_frame_data_tag),
-		(u32 *) ddl, ddl->client_data);
-
-	ddl->output_frame.frm_trans_end =
-		DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)
-			? false : true;
-
+					VCD_S_SUCCESS, &(ddl->input_frame),
+					sizeof(struct ddl_frame_data_tag),
+					(u32 *) ddl, ddl->client_data);
+	ddl->output_frame.frm_trans_end = eos_present ?
+		false : true;
 	ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
-		VCD_S_SUCCESS, &(ddl->output_frame),
-		sizeof(struct ddl_frame_data_tag),
-		(u32 *) ddl, ddl->client_data);
+				VCD_S_SUCCESS, &(ddl->output_frame),
+				sizeof(struct ddl_frame_data_tag),
+				(u32 *) ddl, ddl->client_data);
+}
 
+static void ddl_handle_slice_done_slice_batch(struct ddl_client_context *ddl)
+{
+	struct ddl_context       *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data  *encoder = &(ddl->codec_data.encoder);
+	struct vcd_frame_data    *output_frame = NULL;
+	u32 bottom_frame_tag;
+	struct vidc_1080p_enc_slice_batch_out_param *slice_output = NULL;
+	u32 num_slices_comp = 0;
+	u32 index = 0;
+	u32 start_bfr_idx = 0;
+	u32 actual_idx = 0;
+
+	DDL_MSG_LOW("%s\n", __func__);
+	vidc_sm_get_num_slices_comp(
+			&ddl->shared_mem[ddl->command_channel],
+			&num_slices_comp);
+	slice_output = (struct vidc_1080p_enc_slice_batch_out_param *)
+		(encoder->batch_frame.slice_batch_out.align_virtual_addr);
+	DDL_MSG_LOW(" after get no of slices = %d\n", num_slices_comp);
+	if (slice_output == NULL)
+		DDL_MSG_ERROR(" slice_output is NULL\n");
+	encoder->slice_delivery_info.num_slices_enc += num_slices_comp;
+	if (vidc_msg_timing) {
+		ddl_calc_core_proc_time_cnt(__func__, ENC_SLICE_OP_TIME,
+					num_slices_comp);
+		ddl_set_core_start_time(__func__, ENC_SLICE_OP_TIME);
+	}
+	DDL_MSG_LOW("%s : Slices Completed %d Total slices %d OutBfrInfo:"
+			"Cmd %d Size %d\n",
+			__func__,
+			num_slices_comp,
+			encoder->slice_delivery_info.num_slices_enc,
+			slice_output->cmd_type,
+			slice_output->output_size);
+	start_bfr_idx = encoder->batch_frame.out_frm_next_frmindex;
+	for (index = 0; index < num_slices_comp; index++) {
+		actual_idx =
+		slice_output->slice_info[start_bfr_idx+index].stream_buffer_idx;
+		DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d\n",
+			actual_idx,
+			slice_output->slice_info[start_bfr_idx+index].
+			stream_buffer_size);
+		output_frame = &(
+			encoder->batch_frame.output_frame[actual_idx].vcd_frm);
+		DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+			"frmbfr(physical) 0x%x\n",
+			&output_frame,
+			output_frame.virtual_base_addr,
+			output_frame.physical_base_addr);
+		vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
+		vidc_sm_get_frame_tags(&ddl->shared_mem
+			[ddl->command_channel],
+			&output_frame->ip_frm_tag, &bottom_frame_tag);
+		ddl_get_encoded_frame(output_frame,
+				encoder->codec.codec,
+				encoder->enc_frame_info.enc_frame);
+		output_frame->data_len =
+			slice_output->slice_info[actual_idx].stream_buffer_size;
+		ddl->output_frame =
+			encoder->batch_frame.output_frame[actual_idx];
+		ddl->output_frame.frm_trans_end = false;
+		ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+				VCD_S_SUCCESS, &(ddl->output_frame),
+				sizeof(struct ddl_frame_data_tag),
+				(u32 *) ddl, ddl->client_data);
+		ddl->input_frame.frm_trans_end = false;
+		DDL_MSG_LOW("%s Set i/p o/p transactions to false\n", __func__);
+	}
+	encoder->batch_frame.out_frm_next_frmindex = start_bfr_idx + index;
+	ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+	vidc_sm_set_encoder_slice_batch_int_ctrl(
+			&ddl->shared_mem[ddl->command_channel],
+			0);
+}
+
+static void ddl_handle_enc_frame_done_slice_mode(
+		struct ddl_client_context *ddl, u32 eos_present)
+{
+	struct ddl_context       *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data  *encoder = &(ddl->codec_data.encoder);
+	struct vcd_frame_data    *output_frame = NULL;
+	u32 bottom_frame_tag;
+	u8 *input_buffer_address = NULL;
+	struct vidc_1080p_enc_slice_batch_out_param *slice_output = NULL;
+	u32 num_slices_comp = 0;
+	u32 index = 0;
+	u32 start_bfr_idx = 0;
+	u32 actual_idx = 0;
+	struct vcd_transc *transc;
+
+	DDL_MSG_LOW("%s\n", __func__);
+	vidc_sm_get_num_slices_comp(
+				&ddl->shared_mem[ddl->command_channel],
+				&num_slices_comp);
+	slice_output = (struct vidc_1080p_enc_slice_batch_out_param *)
+		encoder->batch_frame.slice_batch_out.align_virtual_addr;
+	encoder->slice_delivery_info.num_slices_enc += num_slices_comp;
+	if (vidc_msg_timing) {
+		ddl_calc_core_proc_time_cnt(__func__, ENC_OP_TIME,
+					num_slices_comp);
+	}
+	DDL_MSG_LOW("%s Slices Completed %d Total slices done = %d"
+		" OutBfrInfo: Cmd %d Size %d",
+		__func__,
+		num_slices_comp,
+		encoder->slice_delivery_info.num_slices_enc,
+		slice_output->cmd_type,
+		slice_output->output_size);
+	start_bfr_idx = encoder->batch_frame.out_frm_next_frmindex;
+	if ((encoder->slice_delivery_info.num_slices_enc %
+		encoder->batch_frame.num_output_frames) != 0) {
+		DDL_MSG_ERROR("ERROR : %d %d\n",
+		encoder->slice_delivery_info.num_slices_enc,
+		encoder->batch_frame.num_output_frames);
+	}
+	for (index = 0; index < num_slices_comp; index++) {
+		actual_idx =
+			slice_output->slice_info[start_bfr_idx+index]. \
+			stream_buffer_idx;
+		DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d",
+			actual_idx,
+			slice_output->slice_info[start_bfr_idx+index]. \
+			stream_buffer_size, 0);
+		output_frame =
+		&(encoder->batch_frame.output_frame[actual_idx].vcd_frm);
+		DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+				"frmbfr(physical) 0x%x",
+				&output_frame,
+				output_frame.virtual_base_addr,
+				output_frame.physical_base_addr);
+		vidc_1080p_get_encode_frame_info(
+			&encoder->enc_frame_info);
+		vidc_sm_get_frame_tags(&ddl->shared_mem
+			[ddl->command_channel],
+			&output_frame->ip_frm_tag, &bottom_frame_tag);
+		ddl_get_encoded_frame(output_frame,
+				encoder->codec.codec,
+				encoder->enc_frame_info.enc_frame);
+		output_frame->data_len =
+			slice_output->slice_info[actual_idx].stream_buffer_size;
+		ddl->output_frame =
+			encoder->batch_frame.output_frame[actual_idx];
+		DDL_MSG_LOW(" %s actual_idx = %d"
+		"encoder->batch_frame.num_output_frames = %d\n", __func__,
+		actual_idx, encoder->batch_frame.num_output_frames);
+		if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
+			output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+			ddl_vidc_encode_dynamic_property(ddl, false);
+			ddl->input_frame.frm_trans_end = true;
+			DDL_MSG_LOW("%s End of frame detected\n", __func__);
+			input_buffer_address =
+				ddl_context->dram_base_a.align_physical_addr +
+				encoder->enc_frame_info.enc_luma_address;
+			ddl_get_input_frame_from_pool(ddl,
+				input_buffer_address);
+			transc = (struct vcd_transc *)(ddl->client_data);
+			if (eos_present)
+				ddl->output_frame.frm_trans_end = false;
+			else
+				ddl->output_frame.frm_trans_end = true;
+		}
+		DDL_MSG_LOW("%s Before output done cb\n", __func__);
+		transc = (struct vcd_transc *)(ddl->client_data);
+		ddl->output_frame.vcd_frm = *output_frame;
+		ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+				VCD_S_SUCCESS, &(ddl->output_frame),
+				sizeof(struct ddl_frame_data_tag),
+				(u32 *) ddl, ddl->client_data);
+	}
+	if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
+		DDL_MSG_LOW("%s sending input done\n", __func__);
+		ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
+				VCD_S_SUCCESS, &(ddl->input_frame),
+				sizeof(struct ddl_frame_data_tag),
+				(u32 *) ddl, ddl->client_data);
+	}
 }
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 7b284e9..a5192b0 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -287,6 +287,9 @@
 				ddl_set_default_decoder_buffer_req(decoder,
 					true);
 			}
+			DDL_MSG_LOW("set  VCD_I_FRAME_SIZE width = %d"
+				" height = %d\n",
+				frame_size->width, frame_size->height);
 			vcd_status = VCD_S_SUCCESS;
 		}
 	}
@@ -608,7 +611,15 @@
 		struct vcd_property_multi_slice *multi_slice =
 			(struct vcd_property_multi_slice *)
 				property_value;
-
+		DDL_MSG_HIGH("VCD_I_MULTI_SLICE eMSliceSel %d  nMSliceSize %d"
+				"Tot#of MB %d encoder->frame_size.width = %d"
+				"encoder->frame_size.height = %d",
+				(int)multi_slice->m_slice_sel,
+				multi_slice->m_slice_size,
+				DDL_NO_OF_MB(encoder->frame_size.width,
+					encoder->frame_size.height),
+				encoder->frame_size.width,
+				encoder->frame_size.height);
 		switch (multi_slice->m_slice_sel) {
 		case VCD_MSLICE_OFF:
 			vcd_status = VCD_S_SUCCESS;
@@ -618,11 +629,14 @@
 				vcd_status = VCD_S_SUCCESS;
 		break;
 		case VCD_MSLICE_BY_MB_COUNT:
-			if (multi_slice->m_slice_size >= 1 &&
+		{
+			if ((multi_slice->m_slice_size >= 1) &&
 				(multi_slice->m_slice_size <=
 				DDL_NO_OF_MB(encoder->frame_size.width,
-				encoder->frame_size.height)))
+					encoder->frame_size.height))) {
 				vcd_status = VCD_S_SUCCESS;
+			}
+		}
 		break;
 		case VCD_MSLICE_BY_BYTE_COUNT:
 			if (multi_slice->m_slice_size > 0)
@@ -850,6 +864,9 @@
 			encoder->client_output_buf_req.sz =
 				DDL_ALIGN(buffer_req->sz,
 				DDL_KILO_BYTE(4));
+			DDL_MSG_LOW("%s encoder->client_output_buf_req.sz"
+				"  = %d\n", __func__,
+				encoder->client_output_buf_req.sz);
 			vcd_status = VCD_S_SUCCESS;
 		}
 	}
@@ -920,8 +937,14 @@
 	case VCD_I_METADATA_HEADER:
 		DDL_MSG_LOW("Meta Data Interface is Requested");
 		if (!res_trk_check_for_sec_session()) {
-			vcd_status = ddl_set_metadata_params(ddl,
-				property_hdr, property_value);
+			if (!encoder->slice_delivery_info.enable) {
+				vcd_status = ddl_set_metadata_params(ddl,
+						property_hdr, property_value);
+			} else {
+				DDL_MSG_ERROR("Ignoring meta data settting in "
+					"slice mode: %s\n", __func__);
+				vcd_status = VCD_S_SUCCESS;
+			}
 		} else {
 			DDL_MSG_ERROR("Meta Data Interface is not "
 				"supported in secure session");
@@ -946,6 +969,70 @@
 		}
 		break;
 	}
+	case VCD_I_SLICE_DELIVERY_MODE:
+	{
+		size_t output_buf_size;
+		u32 num_mb, num_slices;
+		struct vcd_property_hdr slice_property_hdr;
+		struct vcd_property_meta_data_enable slice_meta_data;
+		DDL_MSG_HIGH("Set property VCD_I_SLICE_DELIVERY_MODE\n");
+		if (sizeof(u32) == property_hdr->sz &&
+			encoder->codec.codec == VCD_CODEC_H264 &&
+			encoder->multi_slice.m_slice_sel
+				 == VCD_MSLICE_BY_MB_COUNT &&
+			DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+			encoder->slice_delivery_info.enable
+				= *(u32 *)property_value;
+			DDL_MSG_HIGH("set encoder->slice_delivery_mode"
+				"  = %u\n",
+				encoder->slice_delivery_info.enable);
+			output_buf_size =
+				encoder->client_output_buf_req.sz;
+			num_mb = DDL_NO_OF_MB(encoder->frame_size.width,
+					encoder->frame_size.height);
+			num_slices = num_mb/
+				encoder->multi_slice.m_slice_size;
+			num_slices = ((num_mb - num_slices *
+				encoder->multi_slice.m_slice_size) > 0)
+				? (num_slices + 1) : num_slices;
+			encoder->slice_delivery_info.num_slices =
+				num_slices;
+			if (num_slices <= DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH) {
+				encoder->client_output_buf_req.min_count
+				= ((DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2)
+				> DDL_MAX_BUFFER_COUNT)
+				? DDL_MAX_BUFFER_COUNT :
+				(DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2);
+				output_buf_size =
+				encoder->client_output_buf_req.sz/num_slices;
+				encoder->client_output_buf_req.sz =
+				DDL_ALIGN(output_buf_size, DDL_KILO_BYTE(4));
+				encoder->output_buf_req =
+				encoder->client_output_buf_req;
+				DDL_MSG_HIGH("%s num_mb = %u num_slices = %u "
+				"output_buf_count = %u "
+				"output_buf_size = %u aligned size = %u\n",
+				__func__, num_mb, num_slices,
+				encoder->client_output_buf_req.min_count,
+				output_buf_size,
+				encoder->client_output_buf_req.sz);
+				slice_property_hdr.prop_id =
+					VCD_I_METADATA_ENABLE;
+				slice_property_hdr.sz =
+				sizeof(struct vcd_property_meta_data_enable);
+				ddl_get_metadata_params(ddl,
+						&slice_property_hdr,
+						&slice_meta_data);
+				slice_meta_data.meta_data_enable_flag
+					&= ~VCD_METADATA_ENC_SLICE;
+				ddl_set_metadata_params(ddl,
+						&slice_property_hdr,
+						&slice_meta_data);
+				vcd_status = VCD_S_SUCCESS;
+			}
+		}
+		break;
+	}
 	case VCD_REQ_PERF_LEVEL:
 		vcd_status = VCD_S_SUCCESS;
 		break;
@@ -1354,7 +1441,10 @@
 			property_hdr->sz) {
 				*(struct vcd_buffer_requirement *)
 			property_value = encoder->client_output_buf_req;
-				vcd_status = VCD_S_SUCCESS;
+			DDL_MSG_LOW("%s encoder->client_output_buf_req = %d\n",
+				 __func__,
+				encoder->client_output_buf_req.sz);
+			vcd_status = VCD_S_SUCCESS;
 		}
 	break;
 	case VCD_I_BUFFER_FORMAT:
@@ -1421,6 +1511,14 @@
 			vcd_status = VCD_S_SUCCESS;
 		}
 	break;
+	case VCD_I_SLICE_DELIVERY_MODE:
+		if (sizeof(struct vcd_property_slice_delivery_info) ==
+			property_hdr->sz) {
+			*(struct vcd_property_slice_delivery_info *)
+				property_value = encoder->slice_delivery_info;
+			vcd_status = VCD_S_SUCCESS;
+		}
+		break;
 	default:
 		vcd_status = VCD_ERR_ILLEGAL_OP;
 		break;
@@ -1579,6 +1677,9 @@
 		encoder->closed_gop = true;
 	ddl_set_default_metadata_flag(ddl);
 	ddl_set_default_encoder_buffer_req(encoder);
+	encoder->slice_delivery_info.enable = 0;
+	encoder->slice_delivery_info.num_slices = 0;
+	encoder->slice_delivery_info.num_slices_enc = 0;
 }
 
 static void ddl_set_default_enc_profile(struct ddl_encoder_data *encoder)
@@ -1725,8 +1826,7 @@
 	encoder->client_input_buf_req = encoder->input_buf_req;
 	memset(&encoder->output_buf_req , 0 ,
 		sizeof(struct vcd_buffer_requirement));
-	encoder->output_buf_req.min_count    =
-		encoder->i_period.b_frames + 2;
+	encoder->output_buf_req.min_count = encoder->i_period.b_frames + 2;
 	encoder->output_buf_req.actual_count =
 		encoder->output_buf_req.min_count + 3;
 	encoder->output_buf_req.max_count    = DDL_MAX_BUFFER_COUNT;
@@ -1737,6 +1837,8 @@
 		DDL_ALIGN(y_cb_cr_size, DDL_KILO_BYTE(4));
 	ddl_set_default_encoder_metadata_buffer_size(encoder);
 	encoder->client_output_buf_req = encoder->output_buf_req;
+	DDL_MSG_LOW("%s encoder->client_output_buf_req.sz = %d\n",
+		__func__, encoder->client_output_buf_req.sz);
 }
 
 u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder,
@@ -1753,7 +1855,7 @@
 		if (!decoder->cont_mode)
 			min_dpb = ddl_decoder_min_num_dpb(decoder);
 		else
-			min_dpb = 5;
+			min_dpb = res_trk_get_min_dpb_count();
 		frame_size = &decoder->client_frame_size;
 		output_buf_req = &decoder->client_output_buf_req;
 		input_buf_req = &decoder->client_input_buf_req;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index cce779e..ac81916 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -156,6 +156,24 @@
 #define VIDC_SM_NEW_I_PERIOD_VALUE_BMASK       0xffffffff
 #define VIDC_SM_NEW_I_PERIOD_VALUE_SHFT        0
 
+#define VIDC_SM_BATCH_INPUT_ADDR                                  0x00a4
+#define VIDC_SM_BATCH_INPUT_ADDR_VALUE_BMSK                       0xffffffff
+#define VIDC_SM_BATCH_INPUT_ADDRL_VALUE_SHFT                      0
+#define VIDC_SM_BATCH_OUTPUT_ADDR                                 0x00a8
+#define VIDC_SM_BATCH_OUTPUT_ADDR_VALUE_BMSK                      0xffffffff
+#define VIDC_SM_BATCH_OUTPUT_ADDR_VALUE_SHFT                      0
+#define VIDC_SM_BATCH_OUTPUT_SIZE_ADDR                            0x00ac
+#define VIDC_SM_BATCH_OUTPUT_SIZE_VALUE_BMSK                      0xffffffff
+#define VIDC_SM_BATCH_OUTPUT_SIZE_VALUE_SHFT                      0
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_ADDR                     0x01c8
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_VALUE_BMSK               0x1
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_VALUE_SHFT               0
+#define VIDC_SM_ENC_NUM_OF_SLICE_ADDR                             0x01cc
+#define VIDC_SM_ENC_NUM_OF_SLICE_VALUE_BMSK                       0xffffffff
+#define VIDC_SM_ENC_NUM_OF_SLICE_VALUE_SHFT                       0
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_ADDR                        0x01d0
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_VALUE_BMSK                  0xffffffff
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_VALUE_SHFT                  0
 
 #define VIDC_SM_ALLOCATED_LUMA_DPB_SIZE_ADDR               0x0064
 #define VIDC_SM_ALLOCATED_CHROMA_DPB_SIZE_ADDR             0x0068
@@ -799,3 +817,48 @@
 			VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
 	}
 }
+
+void vidc_sm_set_encoder_slice_batch_int_ctrl(struct ddl_buf_addr *shared_mem,
+	u32 slice_batch_int_enable)
+{
+	u32 slice_batch_int_ctrl = VIDC_SETFIELD((slice_batch_int_enable) ?
+				1 : 0,
+				VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_SHFT,
+				VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_BMSK);
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_ADDR,
+			slice_batch_int_ctrl);
+}
+
+void vidc_sm_get_num_slices_comp(struct ddl_buf_addr *shared_mem,
+	u32 *num_slices_comp)
+{
+	*num_slices_comp = DDL_MEM_READ_32(shared_mem,
+				VIDC_SM_ENC_NUM_OF_SLICE_COMP_ADDR);
+}
+
+void vidc_sm_set_encoder_batch_config(struct ddl_buf_addr *shared_mem,
+				u32 num_slices,
+				u32 input_addr, u32 output_addr,
+				u32 output_buffer_size)
+{
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_ENC_NUM_OF_SLICE_ADDR,
+			num_slices);
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_BATCH_INPUT_ADDR,
+			input_addr);
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_BATCH_OUTPUT_ADDR,
+			output_addr);
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_BATCH_OUTPUT_SIZE_ADDR,
+			output_buffer_size);
+}
+
+void vidc_sm_get_encoder_batch_output_size(struct ddl_buf_addr *shared_mem,
+	u32 *output_buffer_size)
+{
+	*output_buffer_size = DDL_MEM_READ_32(shared_mem,
+			VIDC_SM_BATCH_OUTPUT_SIZE_ADDR);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
index b0e6758..7d9896f 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -181,4 +181,14 @@
 	enum vidc_sm_num_stuff_bytes_consume_info consume_info);
 void vidc_sm_get_aspect_ratio_info(struct ddl_buf_addr *shared_mem,
 	struct vcd_aspect_ratio *aspect_ratio_info);
+void vidc_sm_set_encoder_slice_batch_int_ctrl(struct ddl_buf_addr *shared_mem,
+	u32 slice_batch_int_enable);
+void vidc_sm_get_num_slices_comp(struct ddl_buf_addr *shared_mem,
+	u32 *num_slices_comp);
+void vidc_sm_set_encoder_batch_config(struct ddl_buf_addr *shared_mem,
+				u32 num_slices,
+				u32 input_addr, u32 output_addr,
+				u32 output_buffer_size);
+void vidc_sm_get_encoder_batch_output_size(struct ddl_buf_addr *shared_mem,
+	u32 *output_buffer_size);
 #endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 126698c..b63bd81 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -11,7 +11,9 @@
  *
  */
 #include <linux/memory_alloc.h>
+#include <linux/delay.h>
 #include <mach/msm_subsystem_map.h>
+#include <mach/peripheral-loader.h>
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl.h"
 #include "vcd_res_tracker_api.h"
@@ -103,7 +105,7 @@
 		addr->alloced_phys_addr = (phys_addr_t) iova;
 		if (!addr->alloced_phys_addr) {
 			DDL_MSG_ERROR("%s():DDL ION client physical failed\n",
-						 __func__);
+						__func__);
 			goto unmap_ion_alloc;
 		}
 		addr->mapped_buffer = NULL;
@@ -332,23 +334,67 @@
 
 u32 ddl_fw_init(struct ddl_buf_addr *dram_base)
 {
-
 	u8 *dest_addr;
-
 	dest_addr = DDL_GET_ALIGNED_VITUAL(*dram_base);
-	if (vidc_video_codec_fw_size > dram_base->buffer_size ||
-		!vidc_video_codec_fw)
-		return false;
 	DDL_MSG_LOW("FW Addr / FW Size : %x/%d", (u32)vidc_video_codec_fw,
 		vidc_video_codec_fw_size);
-	memcpy(dest_addr, vidc_video_codec_fw,
-		vidc_video_codec_fw_size);
+	if (res_trk_check_for_sec_session() && res_trk_is_cp_enabled()) {
+		if (res_trk_enable_footswitch()) {
+			pr_err("Failed to enable footswitch");
+			return false;
+		}
+		if (res_trk_enable_iommu_clocks()) {
+			res_trk_disable_footswitch();
+			pr_err("Failed to enable iommu clocks\n");
+			return false;
+		}
+		dram_base->pil_cookie = pil_get("vidc");
+		if (res_trk_disable_iommu_clocks())
+			pr_err("Failed to disable iommu clocks\n");
+		if (IS_ERR_OR_NULL(dram_base->pil_cookie)) {
+			res_trk_disable_footswitch();
+			pr_err("pil_get failed\n");
+			return false;
+		}
+	} else {
+		if (vidc_video_codec_fw_size > dram_base->buffer_size ||
+				!vidc_video_codec_fw)
+			return false;
+		memcpy(dest_addr, vidc_video_codec_fw,
+				vidc_video_codec_fw_size);
+	}
 	return true;
 }
 
-void ddl_fw_release(void)
+void ddl_fw_release(struct ddl_buf_addr *dram_base)
 {
-	res_trk_close_secure_session();
+	void *cookie = dram_base->pil_cookie;
+	if (res_trk_is_cp_enabled() &&
+		res_trk_check_for_sec_session()) {
+		res_trk_close_secure_session();
+		if (IS_ERR_OR_NULL(cookie)) {
+			pr_err("Invalid params");
+		return;
+	}
+	if (res_trk_enable_footswitch()) {
+		pr_err("Failed to enable footswitch");
+		return;
+	}
+	if (res_trk_enable_iommu_clocks()) {
+		res_trk_disable_footswitch();
+		pr_err("Failed to enable iommu clocks\n");
+		return;
+	}
+	pil_put(cookie);
+	if (res_trk_disable_iommu_clocks())
+		pr_err("Failed to disable iommu clocks\n");
+	if (res_trk_disable_footswitch())
+		pr_err("Failed to disable footswitch\n");
+	} else {
+	if (res_trk_check_for_sec_session())
+		res_trk_close_secure_session();
+		res_trk_release_fw_addr();
+	}
 }
 
 void ddl_set_core_start_time(const char *func_name, u32 index)
@@ -361,13 +407,45 @@
 	if (!time_data->ddl_t1) {
 		time_data->ddl_t1 = act_time;
 		DDL_MSG_LOW("\n%s(): Start Time (%u)", func_name, act_time);
-	} else {
+	} else if (vidc_msg_timing) {
 		DDL_MSG_TIME("\n%s(): Timer already started! St(%u) Act(%u)",
 			func_name, time_data->ddl_t1, act_time);
 	}
 }
 
-void ddl_calc_core_proc_time(const char *func_name, u32 index)
+void ddl_calc_core_proc_time(const char *func_name, u32 index,
+			struct ddl_client_context *ddl)
+{
+	struct time_data *time_data = &proc_time[index];
+	struct ddl_decoder_data *decoder = NULL;
+	if (time_data->ddl_t1) {
+		int ddl_t2;
+		struct timeval ddl_tv;
+		do_gettimeofday(&ddl_tv);
+		ddl_t2 = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+		time_data->ddl_ttotal += (ddl_t2 - time_data->ddl_t1);
+		time_data->ddl_count++;
+		if (vidc_msg_timing) {
+			DDL_MSG_TIME("\n%s(): cnt(%u) End Time (%u)"
+				"Diff(%u) Avg(%u)",
+				func_name, time_data->ddl_count, ddl_t2,
+				ddl_t2 - time_data->ddl_t1,
+				time_data->ddl_ttotal/time_data->ddl_count);
+		}
+		if ((index == DEC_OP_TIME) && (time_data->ddl_count > 2) &&
+					(time_data->ddl_count < 6)) {
+			decoder = &(ddl->codec_data.decoder);
+			decoder->dec_time_sum = decoder->dec_time_sum +
+				ddl_t2 - time_data->ddl_t1;
+			if (time_data->ddl_count == 5)
+				decoder->avg_dec_time =
+					decoder->dec_time_sum / 3;
+		}
+		time_data->ddl_t1 = 0;
+	}
+}
+
+void ddl_calc_core_proc_time_cnt(const char *func_name, u32 index, u32 count)
 {
 	struct time_data *time_data = &proc_time[index];
 	if (time_data->ddl_t1) {
@@ -376,7 +454,7 @@
 		do_gettimeofday(&ddl_tv);
 		ddl_t2 = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
 		time_data->ddl_ttotal += (ddl_t2 - time_data->ddl_t1);
-		time_data->ddl_count++;
+		time_data->ddl_count += count;
 		DDL_MSG_TIME("\n%s(): cnt(%u) End Time (%u) Diff(%u) Avg(%u)",
 			func_name, time_data->ddl_count, ddl_t2,
 			ddl_t2 - time_data->ddl_t1,
@@ -385,9 +463,37 @@
 	}
 }
 
+void ddl_update_core_start_time(const char *func_name, u32 index)
+{
+	u32 act_time;
+	struct timeval ddl_tv;
+	struct time_data *time_data = &proc_time[index];
+	do_gettimeofday(&ddl_tv);
+	act_time = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+	time_data->ddl_t1 = act_time;
+	DDL_MSG_LOW("\n%s(): Start time updated Act(%u)",
+				func_name, act_time);
+}
+
 void ddl_reset_core_time_variables(u32 index)
 {
 	proc_time[index].ddl_t1 = 0;
 	proc_time[index].ddl_ttotal = 0;
 	proc_time[index].ddl_count = 0;
 }
+
+int ddl_get_core_decode_proc_time(u32 *ddl_handle)
+{
+	int avg_time = 0;
+	struct ddl_client_context *ddl =
+		(struct ddl_client_context *) ddl_handle;
+	avg_time = ddl_vidc_decode_get_avg_time(ddl);
+	return avg_time;
+}
+
+void ddl_reset_avg_dec_time(u32 *ddl_handle)
+{
+	struct ddl_client_context *ddl =
+		(struct ddl_client_context *) ddl_handle;
+	ddl_vidc_decode_reset_avg_time(ddl);
+}
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 10b3404..bbde7ae 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -24,6 +24,7 @@
 	DEC_OP_TIME,
 	DEC_IP_TIME,
 	ENC_OP_TIME,
+	ENC_SLICE_OP_TIME,
 	MAX_TIME_DATA
 };
 
@@ -65,9 +66,13 @@
 
 #define DDL_MIN(x, y)  ((x < y) ? x : y)
 #define DDL_MAX(x, y)  ((x > y) ? x : y)
+#define DDL_MEMCPY(dest, src, len)  memcpy((dest), (src), (len))
+#define DDL_MEMSET(src, value, len) memset((src), (value), (len))
 
 void ddl_set_core_start_time(const char *func_name, u32 index);
-void ddl_calc_core_proc_time(const char *func_name, u32 index);
 void ddl_reset_core_time_variables(u32 index);
-
+void ddl_calc_core_proc_time_cnt(const char *func_name, u32 index, u32 count);
+void ddl_update_core_start_time(const char *func_name, u32 index);
+int ddl_get_core_decode_proc_time(u32 *ddl_handle);
+void ddl_reset_avg_dec_time(u32 *ddl_handle);
 #endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index 66e129c..97c8d0d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -21,6 +21,7 @@
 #else
 #define DDL_PIX_CACHE_ENABLE  true
 #endif
+static unsigned int run_cnt;
 
 void ddl_vidc_core_init(struct ddl_context *ddl_context)
 {
@@ -57,6 +58,10 @@
 		vidc_1080p_encode_frame_start_ch0;
 	ddl_context->vidc_encode_frame_start[1] =
 		vidc_1080p_encode_frame_start_ch1;
+	ddl_context->vidc_encode_slice_batch_start[0] =
+		vidc_1080p_encode_slice_batch_start_ch0;
+	ddl_context->vidc_encode_slice_batch_start[1] =
+		vidc_1080p_encode_slice_batch_start_ch1;
 	vidc_1080p_release_sw_reset();
 	ddl_context->pix_cache_enable = DDL_PIX_CACHE_ENABLE;
 	if (ddl_context->pix_cache_enable) {
@@ -106,8 +111,7 @@
 	u32 pix_cache_ctrl, ctxt_mem_offset, ctxt_mem_size;
 
 	if (ddl->decoding) {
-		if (vidc_msg_timing)
-			ddl_set_core_start_time(__func__, DEC_OP_TIME);
+		ddl_set_core_start_time(__func__, DEC_OP_TIME);
 		vcd_codec = &(ddl->codec_data.decoder.codec.codec);
 		pix_cache_ctrl = (u32)dec_pix_cache;
 		ctxt_mem_offset = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
@@ -192,8 +196,7 @@
 	struct vidc_1080p_dec_seq_start_param seq_start_param;
 	u32 seq_size;
 
-	if (vidc_msg_timing)
-		ddl_set_core_start_time(__func__, DEC_OP_TIME);
+	ddl_set_core_start_time(__func__, DEC_OP_TIME);
 	vidc_1080p_set_decode_mpeg4_pp_filter(decoder->post_filter.post_filter);
 	vidc_sm_set_concealment_color(&ddl->shared_mem[ddl->command_channel],
 		DDL_CONCEALMENT_Y_COLOR, DDL_CONCEALMENT_C_COLOR);
@@ -515,6 +518,29 @@
 		i_multi_slice_size, i_multi_slice_byte);
 }
 
+static void ddl_vidc_encode_set_batch_slice_info(
+	struct ddl_client_context *ddl)
+{
+	struct ddl_context *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+	DDL_MSG_LOW("%s\n", __func__);
+	encoder->batch_frame.slice_batch_out.buffer_size =
+					encoder->output_buf_req.sz;
+	DDL_MSG_LOW("encoder->batch_frame.slice_batch_out.buffer_size = %d\n",
+			encoder->batch_frame.slice_batch_out.buffer_size);
+	vidc_sm_set_encoder_batch_config(
+			&ddl->shared_mem[ddl->command_channel],
+			1,
+			DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+			encoder->batch_frame.slice_batch_in),
+			DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+			encoder->batch_frame.slice_batch_out),
+			encoder->batch_frame.slice_batch_out.buffer_size);
+	vidc_sm_set_encoder_slice_batch_int_ctrl(
+			&ddl->shared_mem[ddl->command_channel],
+			0);
+}
+
 void ddl_vidc_encode_init_codec(struct ddl_client_context *ddl)
 {
 	struct ddl_context *ddl_context = ddl->ddl_context;
@@ -724,6 +750,7 @@
 	u32 dpb_addr_y[4], dpb_addr_c[4];
 	u32 index, y_addr, c_addr;
 
+	DDL_MSG_LOW("%s\n", __func__);
 	ddl_vidc_encode_set_metadata_output_buf(ddl);
 
 	encoder->enc_frame_info.meta_data_exists = false;
@@ -769,6 +796,7 @@
 	if (encoder->intra_frame_insertion)
 		encoder->intra_frame_insertion = false;
 	enc_param.input_flush = false;
+	enc_param.slice_enable = false;
 		vidc_sm_set_encoder_vop_time(
 			&ddl->shared_mem[ddl->command_channel], true,
 			encoder->vop_timing.vop_time_resolution,
@@ -800,6 +828,142 @@
 		&enc_param);
 }
 
+void ddl_vidc_encode_frame_continue(struct ddl_client_context *ddl)
+{
+	struct ddl_context *ddl_context = ddl->ddl_context;
+	struct vcd_frame_data *input_vcd_frm = &(ddl->input_frame.vcd_frm);
+	u32 address_offset;
+	address_offset = (u32)(ddl->output_frame.vcd_frm.physical -
+			ddl_context->dram_base_a.align_physical_addr) >>
+			DDL_VIDC_1080P_BASE_OFFSET_SHIFT;
+	DDL_MSG_LOW("%s\n", __func__);
+	if (VCD_FRAME_FLAG_EOS & input_vcd_frm->flags)
+		ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+	else
+		ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+	ddl->cmd_state = DDL_CMD_ENCODE_CONTINUE;
+	vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_CONTINUE_ENC,
+		address_offset,
+		0, 0, 0);
+}
+
+void ddl_vidc_encode_slice_batch_run(struct ddl_client_context *ddl)
+{
+	struct vidc_1080p_enc_frame_start_param enc_param;
+	struct ddl_context *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data  *encoder = &(ddl->codec_data.encoder);
+	struct ddl_enc_buffers *enc_buffers = &(encoder->hw_bufs);
+	struct vcd_frame_data *input_vcd_frm =
+		&(ddl->input_frame.vcd_frm);
+	u32 dpb_addr_y[4], dpb_addr_c[4];
+	u32 index, y_addr, c_addr;
+	u32 bitstream_size;
+	struct vidc_1080p_enc_slice_batch_in_param *slice_batch_in =
+		(struct vidc_1080p_enc_slice_batch_in_param *)
+		encoder->batch_frame.slice_batch_in.align_virtual_addr;
+	DDL_MSG_LOW("%s\n", __func__);
+	DDL_MEMSET(slice_batch_in, 0,
+		sizeof(struct vidc_1080p_enc_slice_batch_in_param));
+	DDL_MEMSET(encoder->batch_frame.slice_batch_in.align_virtual_addr, 0,
+		sizeof(struct vidc_1080p_enc_slice_batch_in_param));
+	encoder->batch_frame.out_frm_next_frmindex = 0;
+	bitstream_size = encoder->batch_frame.output_frame[0].vcd_frm.alloc_len;
+	encoder->output_buf_req.sz = bitstream_size;
+	y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
+			input_vcd_frm->physical);
+	c_addr = (y_addr + encoder->input_buf_size.size_y);
+	enc_param.encode = VIDC_1080P_ENC_TYPE_SLICE_BATCH_START;
+	DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+		"DDL_CLIENT_WAIT_FOR_FRAME_DONE",
+		ddl_get_state_string(ddl->client_state));
+	slice_batch_in->cmd_type = VIDC_1080P_ENC_TYPE_SLICE_BATCH_START;
+	ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+	ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+	vidc_1080p_set_encode_circular_intra_refresh(
+		encoder->intra_refresh.cir_mb_number);
+	ddl_vidc_encode_set_multi_slice_info(encoder);
+	enc_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+	enc_param.inst_id = ddl->instance_id;
+	enc_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+			ddl_context->dram_base_a,
+			ddl->shared_mem[ddl->command_channel]);
+	enc_param.current_y_addr_offset = y_addr;
+	enc_param.current_c_addr_offset = c_addr;
+	enc_param.stream_buffer_size = bitstream_size;
+	slice_batch_in->num_stream_buffer =
+		encoder->batch_frame.num_output_frames;
+	slice_batch_in->stream_buffer_size = bitstream_size;
+	DDL_MSG_LOW("%s slice_batch_in->num_stream_buffer = %u size = %u\n",
+			 __func__, slice_batch_in->num_stream_buffer,
+			slice_batch_in->stream_buffer_size);
+	for (index = 0; index < encoder->batch_frame.num_output_frames;
+		index++) {
+		slice_batch_in->stream_buffer_addr_offset[index] =
+		((DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
+		encoder->batch_frame.output_frame[index].vcd_frm.physical)) >>
+			DDL_VIDC_1080P_BASE_OFFSET_SHIFT);
+	}
+	slice_batch_in->input_size = VIDC_1080P_SLICE_BATCH_IN_SIZE(index);
+	enc_param.intra_frame = encoder->intra_frame_insertion;
+	if (encoder->intra_frame_insertion)
+		encoder->intra_frame_insertion = false;
+	enc_param.input_flush = false;
+	enc_param.slice_enable =
+		encoder->slice_delivery_info.enable;
+	vidc_sm_set_encoder_vop_time(
+			&ddl->shared_mem[ddl->command_channel], true,
+			encoder->vop_timing.vop_time_resolution,
+			ddl->input_frame.frm_delta);
+	vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+			ddl->input_frame.vcd_frm.ip_frm_tag);
+	DDL_MSG_LOW("%sdpb_count = %d\n", __func__, enc_buffers->dpb_count);
+	if (ddl_context->pix_cache_enable) {
+		for (index = 0; index < enc_buffers->dpb_count;
+			index++) {
+			dpb_addr_y[index] =
+				(u32) VIDC_1080P_DEC_DPB_RESET_VALUE;
+			dpb_addr_c[index] = (u32) enc_buffers->dpb_c
+				[index].align_physical_addr;
+		}
+
+		dpb_addr_y[index] = (u32) input_vcd_frm->physical;
+		dpb_addr_c[index] = (u32) input_vcd_frm->physical +
+				encoder->input_buf_size.size_y;
+
+		vidc_pix_cache_init_luma_chroma_base_addr(
+			enc_buffers->dpb_count + 1, dpb_addr_y, dpb_addr_c);
+		vidc_pix_cache_set_frame_size(encoder->frame_size.width,
+			encoder->frame_size.height);
+		vidc_pix_cache_set_frame_range(enc_buffers->sz_dpb_y,
+			enc_buffers->sz_dpb_c);
+		vidc_pix_cache_clear_cache_tags();
+	}
+	if ((!encoder->rc_level.frame_level_rc) &&
+		(!encoder->rc_level.mb_level_rc)) {
+		encoder->session_qp.p_frame_qp++;
+		if (encoder->session_qp.p_frame_qp > encoder->qp_range.max_qp)
+			encoder->session_qp.p_frame_qp =
+						encoder->qp_range.min_qp;
+		vidc_sm_set_pand_b_frame_qp(
+			&ddl->shared_mem[ddl->command_channel],
+				encoder->session_qp.b_frame_qp,
+				encoder->session_qp.p_frame_qp);
+	}
+
+	if (vidc_msg_timing) {
+		if (run_cnt < 2) {
+			ddl_reset_core_time_variables(ENC_OP_TIME);
+			ddl_reset_core_time_variables(ENC_SLICE_OP_TIME);
+			run_cnt++;
+		 }
+		ddl_update_core_start_time(__func__, ENC_SLICE_OP_TIME);
+		ddl_set_core_start_time(__func__, ENC_OP_TIME);
+	}
+	ddl_vidc_encode_set_batch_slice_info(ddl);
+	ddl_context->vidc_encode_slice_batch_start[ddl->command_channel] (
+			&enc_param);
+}
+
 u32 ddl_vidc_decode_set_buffers(struct ddl_client_context *ddl)
 {
 	struct ddl_context *ddl_context = ddl->ddl_context;
@@ -827,8 +991,7 @@
 #ifdef DDL_BUF_LOG
 	ddl_list_buffers(ddl);
 #endif
-	if (vidc_msg_timing)
-		ddl_set_core_start_time(__func__, DEC_OP_TIME);
+	ddl_set_core_start_time(__func__, DEC_OP_TIME);
 	ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_INIT);
 	if (ddl_decoder_dpb_init(ddl) == VCD_ERR_FAIL)
 		return VCD_ERR_FAIL;
@@ -875,10 +1038,8 @@
 	struct ddl_mask *dpb_mask = &ddl->codec_data.decoder.dpb_mask;
 	struct vidc_1080p_dec_frame_start_param dec_param;
 	u32 dpb_addr_y[32], index;
-	if (vidc_msg_timing) {
-		ddl_set_core_start_time(__func__, DEC_OP_TIME);
-		ddl_set_core_start_time(__func__, DEC_IP_TIME);
-	}
+	ddl_set_core_start_time(__func__, DEC_OP_TIME);
+	ddl_set_core_start_time(__func__, DEC_IP_TIME);
 	if ((!bit_stream->data_len) || (!bit_stream->physical)) {
 		ddl_vidc_decode_eos_run(ddl);
 		return;
@@ -976,3 +1137,44 @@
 	ddl_context->vidc_decode_frame_start[ddl->command_channel] (
 		&dec_param);
 }
+
+void ddl_vidc_encode_eos_run(struct ddl_client_context *ddl)
+{
+	struct vidc_1080p_enc_frame_start_param enc_param;
+	struct ddl_context *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+	DDL_MSG_LOW("%s\n", __func__);
+	ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+	ddl_vidc_encode_dynamic_property(ddl, true);
+	ddl->client_state = DDL_CMD_EOS;
+	DDL_MEMSET(&enc_param, 0, sizeof(enc_param));
+	enc_param.encode = VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA;
+	enc_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+	enc_param.inst_id = ddl->instance_id;
+	enc_param.shared_mem_addr_offset =
+		DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+		ddl->shared_mem[ddl->command_channel]);
+	enc_param.current_y_addr_offset = 0;
+	enc_param.current_c_addr_offset = 0;
+	enc_param.stream_buffer_size = 0;
+	enc_param.intra_frame = encoder->intra_frame_insertion;
+	vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+				ddl->input_frame.vcd_frm.ip_frm_tag);
+	ddl_context->vidc_encode_frame_start[ddl->command_channel](
+						&enc_param);
+}
+
+int ddl_vidc_decode_get_avg_time(struct ddl_client_context *ddl)
+{
+	int avg_time = 0;
+	struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+	avg_time = decoder->avg_dec_time;
+	return avg_time;
+}
+
+void ddl_vidc_decode_reset_avg_time(struct ddl_client_context *ddl)
+{
+	struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+	decoder->avg_dec_time = 0;
+	decoder->dec_time_sum = 0;
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c
index 75014cc..d399847 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/1080p/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
@@ -77,6 +77,10 @@
 #define VIDC_1080P_ENC_TYPE_FRAME_DATA       0x00020000
 #define VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA  0x00030000
 
+#define VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK   0x00004000
+#define VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT   14
+#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK      0x80000000
+#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT      31
 #define VIDC_1080P_MAX_INTRA_PERIOD 0xffff
 
 u8 *VIDC_BASE_PTR;
@@ -779,6 +783,7 @@
 void vidc_1080p_encode_frame_start_ch0(
 	struct vidc_1080p_enc_frame_start_param *param)
 {
+	u32 input_flush;
 	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
 	VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
 	VIDC_HWIO_OUT(REG_117192,
@@ -791,8 +796,15 @@
 		VIDC_1080P_BASE_OFFSET_SHIFT);
 	VIDC_HWIO_OUT(REG_190381, param->intra_frame);
 	VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
-	VIDC_HWIO_OUT(REG_404623, param->input_flush);
+	input_flush = VIDC_SETFIELD(param->input_flush,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+	input_flush |= VIDC_SETFIELD(param->slice_enable,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+	VIDC_HWIO_OUT(REG_404623, input_flush);
 	VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+
 	VIDC_HWIO_OUT(REG_666957, (u32)param->encode |
 		param->inst_id);
 }
@@ -800,7 +812,7 @@
 void vidc_1080p_encode_frame_start_ch1(
 	struct vidc_1080p_enc_frame_start_param *param)
 {
-
+	u32 input_flush;
 	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
 	VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
 	VIDC_HWIO_OUT(REG_980194,
@@ -813,12 +825,71 @@
 		VIDC_1080P_BASE_OFFSET_SHIFT);
 	VIDC_HWIO_OUT(REG_887095, param->intra_frame);
 	VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
-	VIDC_HWIO_OUT(REG_404623, param->input_flush);
+	input_flush = VIDC_SETFIELD(param->input_flush,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+	input_flush |= VIDC_SETFIELD(param->slice_enable,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+
+	VIDC_HWIO_OUT(REG_404623, input_flush);
 	VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
 	VIDC_HWIO_OUT(REG_313350, (u32)param->encode |
 		param->inst_id);
 }
 
+void vidc_1080p_encode_slice_batch_start_ch0(
+	struct vidc_1080p_enc_frame_start_param *param)
+{
+	u32 input_flush;
+	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+	VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+	VIDC_HWIO_OUT(REG_612810, param->current_y_addr_offset >>
+		VIDC_1080P_BASE_OFFSET_SHIFT);
+	VIDC_HWIO_OUT(REG_175608, param->current_c_addr_offset >>
+		VIDC_1080P_BASE_OFFSET_SHIFT);
+	VIDC_HWIO_OUT(REG_190381, param->intra_frame);
+	VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
+	input_flush = VIDC_SETFIELD(param->input_flush,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+	input_flush |= VIDC_SETFIELD(param->slice_enable,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+	VIDC_HWIO_OUT(REG_404623, input_flush);
+	VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+
+	VIDC_HWIO_OUT(REG_666957, (u32)param->encode |
+		param->inst_id);
+
+}
+
+void vidc_1080p_encode_slice_batch_start_ch1(
+	struct vidc_1080p_enc_frame_start_param *param)
+{
+	u32 input_flush;
+	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+	VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+	VIDC_HWIO_OUT(REG_655721, param->current_y_addr_offset >>
+		VIDC_1080P_BASE_OFFSET_SHIFT);
+	VIDC_HWIO_OUT(REG_548308,  param->current_c_addr_offset >>
+		VIDC_1080P_BASE_OFFSET_SHIFT);
+	VIDC_HWIO_OUT(REG_887095, param->intra_frame);
+	VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
+	input_flush = VIDC_SETFIELD(param->input_flush,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+	input_flush |= VIDC_SETFIELD(param->slice_enable,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+
+	VIDC_HWIO_OUT(REG_404623, input_flush);
+	VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
+	VIDC_HWIO_OUT(REG_313350, (u32)param->encode |
+		param->inst_id);
+
+}
+
 void vidc_1080p_set_encode_picture(u32 number_p, u32 number_b)
 {
 	u32 picture, ifrm_ctrl;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
index 7573ee8..7460ef3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -21,11 +21,13 @@
 #define VIDC_1080P_RISC2HOST_CMD_CLOSE_CH_RET        2
 #define VIDC_1080P_RISC2HOST_CMD_SEQ_DONE_RET        4
 #define VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET      5
+#define VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET      6
 #define VIDC_1080P_RISC2HOST_CMD_ENC_COMPLETE_RET    7
 #define VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET        8
 #define VIDC_1080P_RISC2HOST_CMD_FW_STATUS_RET       9
 #define VIDC_1080P_RISC2HOST_CMD_FLUSH_COMMAND_RET  12
 #define VIDC_1080P_RISC2HOST_CMD_ABORT_RET          13
+#define VIDC_1080P_RISC2HOST_CMD_BATCH_ENC_RET      14
 #define VIDC_1080P_RISC2HOST_CMD_INIT_BUFFERS_RET   15
 #define VIDC_1080P_RISC2HOST_CMD_EDFU_INT_RET       16
 #define VIDC_1080P_RISC2HOST_CMD_ERROR_RET          32
@@ -188,7 +190,9 @@
 #define VIDC_1080P_ITLB_MISS_EXCEPTION_HANDLER        0x100
 #define VIDC_1080P_DATA_PAGE_FAULT_EXCEPTION_HANDLER  0x200
 #define VIDC_1080P_INST_PAGE_FAULT_EXCEPTION_HANDLER  0x400
-
+#define VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR           8
+#define VIDC_1080P_SLICE_BATCH_IN_SIZE(idx)           (4 * sizeof(u32) + \
+							idx * sizeof(u32))
 enum vidc_1080p_reset{
 	VIDC_1080P_RESET_IN_SEQ_FIRST_STAGE   = 0x0,
 	VIDC_1080P_RESET_IN_SEQ_SECOND_STAGE  = 0x1,
@@ -318,10 +322,11 @@
 	VIDC_1080P_DEC_TYPE_32BIT            = 0x7FFFFFFF
 };
 enum vidc_1080p_encode{
-	VIDC_1080P_ENC_TYPE_SEQ_HEADER       = 0x00010000,
-	VIDC_1080P_ENC_TYPE_FRAME_DATA       = 0x00020000,
-	VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA  = 0x00030000,
-	VIDC_1080P_ENC_TYPE_32BIT            = 0x7FFFFFFF
+	VIDC_1080P_ENC_TYPE_SEQ_HEADER        = 0x00010000,
+	VIDC_1080P_ENC_TYPE_FRAME_DATA        = 0x00020000,
+	VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA   = 0x00030000,
+	VIDC_1080P_ENC_TYPE_SLICE_BATCH_START = 0x00070000,
+	VIDC_1080P_ENC_TYPE_32BIT             = 0x7FFFFFFF
 };
 struct vidc_1080p_dec_seq_start_param{
 	u32 cmd_seq_num;
@@ -391,6 +396,7 @@
 	u32 stream_buffer_size;
 	u32 intra_frame;
 	u32 input_flush;
+	u32 slice_enable;
 	enum vidc_1080p_encode encode;
 };
 struct vidc_1080p_enc_frame_info{
@@ -402,6 +408,23 @@
 	enum vidc_1080p_encode_frame enc_frame;
 	u32 meta_data_exists;
 };
+struct vidc_1080p_enc_slice_batch_in_param {
+	u32 cmd_type;
+	u32 input_size;
+	u32 num_stream_buffer;
+	u32 stream_buffer_size;
+	u32 stream_buffer_addr_offset[VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR];
+};
+struct vidc_1080p_enc_slice_info {
+	u32 stream_buffer_idx;
+	u32 stream_buffer_size;
+};
+struct vidc_1080p_enc_slice_batch_out_param {
+	u32 cmd_type;
+	u32 output_size;
+	struct vidc_1080p_enc_slice_info slice_info
+		[VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR];
+};
 struct vidc_1080p_dec_disp_info{
 	u32 disp_resl_change;
 	u32 dec_resl_change;
@@ -519,6 +542,10 @@
 	struct vidc_1080p_enc_frame_start_param *param);
 void vidc_1080p_encode_frame_start_ch1(
 	struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_encode_slice_batch_start_ch0(
+	struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_encode_slice_batch_start_ch1(
+	struct vidc_1080p_enc_frame_start_param *param);
 void vidc_1080p_set_encode_picture(u32 ifrm_ctrl, u32 number_b);
 void vidc_1080p_set_encode_multi_slice_control(
 	enum vidc_1080p_MSlice_selection multiple_slice_selection,
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 e94a302..e3815e8 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
@@ -25,6 +25,9 @@
 #include "vidc.h"
 #include "vcd_res_tracker.h"
 
+#define PIL_FW_BASE_ADDR 0xafe00000
+#define PIL_FW_SIZE 0x200000
+
 static unsigned int vidc_clk_table[3] = {
 	48000000, 133330000, 200000000
 };
@@ -64,7 +67,7 @@
 	unsigned long *kernel_vaddr = NULL;
 
 	ddl_context = ddl_get_context();
-	if (res_trk_get_enable_ion()) {
+	if (res_trk_get_enable_ion() && addr->alloc_handle) {
 		kernel_vaddr = (unsigned long *) ion_map_kernel(
 					ddl_context->video_ion_client,
 					addr->alloc_handle, UNCACHED);
@@ -97,31 +100,42 @@
 		addr->align_virtual_addr = addr->virtual_base_addr + offset;
 		addr->buffer_size = buffer_size;
 	} else {
-		if (!addr->alloced_phys_addr) {
-			pr_err(" %s() alloced addres NULL", __func__);
-			goto bail_out;
+		if (!res_trk_check_for_sec_session()) {
+			if (!addr->alloced_phys_addr) {
+				pr_err(" %s() alloced addres NULL", __func__);
+				goto bail_out;
+			}
+			flags = MSM_SUBSYSTEM_MAP_IOVA |
+				MSM_SUBSYSTEM_MAP_KADDR;
+			if (alignment == DDL_KILO_BYTE(128))
+					index = 1;
+			else if (alignment > SZ_4K)
+				flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K;
+			addr->mapped_buffer =
+			msm_subsystem_map_buffer(
+			(unsigned long)addr->alloced_phys_addr,
+			sz, flags, &restrk_mmu_subsystem[index],
+			sizeof(restrk_mmu_subsystem[index])/
+				sizeof(unsigned int));
+			if (IS_ERR(addr->mapped_buffer)) {
+				pr_err(" %s() buffer map failed", __func__);
+				goto bail_out;
+			}
+			mapped_buffer = addr->mapped_buffer;
+			if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
+				pr_err("%s() map buffers failed\n", __func__);
+				goto bail_out;
+			}
+			addr->physical_base_addr =
+				 (u8 *)mapped_buffer->iova[0];
+			addr->virtual_base_addr =
+					mapped_buffer->vaddr;
+		} else {
+			addr->physical_base_addr =
+				(u8 *) addr->alloced_phys_addr;
+			addr->virtual_base_addr =
+				(u8 *)addr->alloced_phys_addr;
 		}
-		flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
-		if (alignment == DDL_KILO_BYTE(128))
-				index = 1;
-		else if (alignment > SZ_4K)
-			flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K;
-
-		addr->mapped_buffer =
-		msm_subsystem_map_buffer((unsigned long)addr->alloced_phys_addr,
-		sz, flags, &restrk_mmu_subsystem[index],
-		sizeof(restrk_mmu_subsystem[index])/sizeof(unsigned int));
-		if (IS_ERR(addr->mapped_buffer)) {
-			pr_err(" %s() buffer map failed", __func__);
-			goto bail_out;
-		}
-		mapped_buffer = addr->mapped_buffer;
-		if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
-			pr_err("%s() map buffers failed\n", __func__);
-			goto bail_out;
-		}
-		addr->physical_base_addr = (u8 *)mapped_buffer->iova[0];
-		addr->virtual_base_addr = mapped_buffer->vaddr;
 		addr->align_physical_addr = (u8 *) DDL_ALIGN((u32)
 		addr->physical_base_addr, alignment);
 		offset = (u32)(addr->align_physical_addr -
@@ -131,7 +145,7 @@
 	}
 	return addr->virtual_base_addr;
 bail_out:
-	if (addr->mapped_buffer)
+	if (IS_ERR(addr->mapped_buffer))
 		msm_subsystem_unmap_buffer(addr->mapped_buffer);
 	return NULL;
 ion_unmap_bail_out:
@@ -143,62 +157,84 @@
 	return NULL;
 }
 
-static void *res_trk_pmem_alloc
+static void res_trk_pmem_free(struct ddl_buf_addr *addr)
+{
+	struct ddl_context *ddl_context;
+	ddl_context = ddl_get_context();
+	if (ddl_context->video_ion_client) {
+		if (addr && addr->alloc_handle) {
+			ion_free(ddl_context->video_ion_client,
+			 addr->alloc_handle);
+			addr->alloc_handle = NULL;
+		}
+	} else {
+		if (addr->mapped_buffer)
+			msm_subsystem_unmap_buffer(addr->mapped_buffer);
+		if (addr->alloced_phys_addr)
+			free_contiguous_memory_by_paddr(
+			(unsigned long)addr->alloced_phys_addr);
+	}
+	memset(addr, 0 , sizeof(struct ddl_buf_addr));
+}
+static int res_trk_pmem_alloc
 	(struct ddl_buf_addr *addr, size_t sz, u32 alignment)
 {
 	u32 alloc_size;
 	struct ddl_context *ddl_context;
+	int rc = 0;
 	DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz);
 	if (!addr) {
 		DDL_MSG_ERROR("\n%s() Invalid Parameters", __func__);
+		rc = -EINVAL;
 		goto bail_out;
 	}
 	ddl_context = ddl_get_context();
 	res_trk_set_mem_type(addr->mem_type);
 	alloc_size = (sz + alignment);
 	if (res_trk_get_enable_ion()) {
-		if (!ddl_context->video_ion_client)
-			ddl_context->video_ion_client =
-				res_trk_get_ion_client();
-		if (!ddl_context->video_ion_client) {
-			DDL_MSG_ERROR("%s() :DDL ION Client Invalid handle\n",
-						 __func__);
-			goto bail_out;
+		if (!res_trk_is_cp_enabled() ||
+			 !res_trk_check_for_sec_session()) {
+			if (!ddl_context->video_ion_client)
+				ddl_context->video_ion_client =
+					res_trk_get_ion_client();
+			if (!ddl_context->video_ion_client) {
+				DDL_MSG_ERROR(
+				"%s() :DDL ION Client Invalid handle\n",
+						__func__);
+				rc = -ENOMEM;
+				goto bail_out;
+			}
+			alloc_size = (alloc_size+4095) & ~4095;
+			addr->alloc_handle = ion_alloc(
+					ddl_context->video_ion_client,
+					 alloc_size, SZ_4K,
+					res_trk_get_mem_type());
+			if (IS_ERR_OR_NULL(addr->alloc_handle)) {
+				DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
+						__func__);
+				rc = -ENOMEM;
+				goto bail_out;
+			}
+		} else {
+			addr->alloc_handle = NULL;
+			addr->alloced_phys_addr = PIL_FW_BASE_ADDR;
+			addr->buffer_size = sz;
 		}
-		alloc_size = (alloc_size+4095) & ~4095;
-		addr->alloc_handle = ion_alloc(
-		ddl_context->video_ion_client, alloc_size, SZ_4K,
-			res_trk_get_mem_type());
-		if (IS_ERR_OR_NULL(addr->alloc_handle)) {
-			DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
-						 __func__);
-			goto free_acm_ion_alloc;
-		}
-		return (void *) addr->alloc_handle;
 	} else {
 		addr->alloced_phys_addr = (phys_addr_t)
-		allocate_contiguous_memory_nomap(alloc_size,
-			res_trk_get_mem_type(), SZ_4K);
+			allocate_contiguous_memory_nomap(alloc_size,
+					res_trk_get_mem_type(), SZ_4K);
 		if (!addr->alloced_phys_addr) {
 			DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n",
-					 __func__, alloc_size);
+					__func__, alloc_size);
+			rc = -ENOMEM;
 			goto bail_out;
 		}
 		addr->buffer_size = sz;
-		return (void *)addr->alloced_phys_addr;
-	}
-
-
-free_acm_ion_alloc:
-	if (ddl_context->video_ion_client) {
-		if (addr->alloc_handle) {
-			ion_free(ddl_context->video_ion_client,
-				addr->alloc_handle);
-			addr->alloc_handle = NULL;
-		}
+		return rc;
 	}
 bail_out:
-	return NULL;
+	return rc;
 }
 
 static void res_trk_pmem_unmap(struct ddl_buf_addr *addr)
@@ -388,7 +424,8 @@
 		VCDRES_MSG_ERROR("Error : pm_runtime_get failed\n");
 		goto bail_out;
 	}
-	resource_context.footswitch = regulator_get(NULL, "fs_ved");
+	if (!resource_context.footswitch)
+		resource_context.footswitch = regulator_get(NULL, "fs_ved");
 	if (IS_ERR(resource_context.footswitch)) {
 		VCDRES_MSG_ERROR("foot switch get failed\n");
 		resource_context.footswitch = NULL;
@@ -413,6 +450,35 @@
 	return video_client;
 }
 
+int res_trk_enable_footswitch(void)
+{
+	int rc = 0;
+	mutex_lock(&resource_context.lock);
+	if (!resource_context.footswitch)
+		resource_context.footswitch = regulator_get(NULL, "fs_ved");
+	if (IS_ERR(resource_context.footswitch)) {
+		VCDRES_MSG_ERROR("foot switch get failed\n");
+		resource_context.footswitch = NULL;
+		rc = -EINVAL;
+	} else
+		rc = regulator_enable(resource_context.footswitch);
+	mutex_unlock(&resource_context.lock);
+	return rc;
+}
+
+int res_trk_disable_footswitch(void)
+{
+	mutex_lock(&resource_context.lock);
+	if (resource_context.footswitch) {
+		if (regulator_disable(resource_context.footswitch))
+			VCDRES_MSG_ERROR("Regulator disable failed\n");
+		regulator_put(resource_context.footswitch);
+		resource_context.footswitch = NULL;
+	}
+	mutex_unlock(&resource_context.lock);
+	return 0;
+}
+
 u32 res_trk_power_up(void)
 {
 	VCDRES_MSG_LOW("clk_regime_rail_enable");
@@ -438,6 +504,7 @@
 {
 	VCDRES_MSG_LOW("clk_regime_rail_disable");
 	res_trk_pmem_unmap(&resource_context.firmware_addr);
+	res_trk_pmem_free(&resource_context.firmware_addr);
 #ifdef CONFIG_MSM_BUS_SCALING
 	msm_bus_scale_client_update_request(resource_context.pcl, 0);
 	msm_bus_scale_unregister_client(resource_context.pcl);
@@ -640,14 +707,6 @@
 		}
 		resource_context.core_type = VCD_CORE_1080P;
 		resource_context.firmware_addr.mem_type = DDL_FW_MEM;
-		if (!res_trk_pmem_alloc(&resource_context.firmware_addr,
-			VIDC_FW_SIZE, DDL_KILO_BYTE(128))) {
-			pr_err("%s() Firmware buffer allocation failed",
-				   __func__);
-			if (!res_trk_check_for_sec_session())
-				memset(&resource_context.firmware_addr, 0,
-				sizeof(resource_context.firmware_addr));
-		}
 	}
 }
 
@@ -657,20 +716,47 @@
 
 u32 res_trk_get_firmware_addr(struct ddl_buf_addr *firm_addr)
 {
+	int rc = 0;
+	size_t size = 0;
 	if (!firm_addr || resource_context.firmware_addr.mapped_buffer) {
 		pr_err("%s() invalid params", __func__);
 		return -EINVAL;
 	}
+	if (res_trk_is_cp_enabled() && res_trk_check_for_sec_session())
+		size = PIL_FW_SIZE;
+	else
+		size = VIDC_FW_SIZE;
+
+	if (res_trk_pmem_alloc(&resource_context.firmware_addr,
+				size, DDL_KILO_BYTE(128))) {
+		pr_err("%s() Firmware buffer allocation failed",
+				__func__);
+		memset(&resource_context.firmware_addr, 0,
+				sizeof(resource_context.firmware_addr));
+		rc = -ENOMEM;
+		goto fail_alloc;
+	}
 	if (!res_trk_pmem_map(&resource_context.firmware_addr,
 		resource_context.firmware_addr.buffer_size,
 		DDL_KILO_BYTE(128))) {
 		pr_err("%s() Firmware buffer mapping failed",
 			   __func__);
-		return -EINVAL;
+		rc = -ENOMEM;
+		goto fail_map;
 	}
 	memcpy(firm_addr, &resource_context.firmware_addr,
 		sizeof(struct ddl_buf_addr));
 	return 0;
+fail_map:
+	res_trk_pmem_free(&resource_context.firmware_addr);
+fail_alloc:
+	return rc;
+}
+
+void res_trk_release_fw_addr(void)
+{
+	res_trk_pmem_unmap(&resource_context.firmware_addr);
+	res_trk_pmem_free(&resource_context.firmware_addr);
 }
 
 int res_trk_check_for_sec_session(void)
@@ -702,15 +788,27 @@
 		return mem_type;
 	}
 	if (resource_context.vidc_platform_data->enable_ion) {
-		if (res_trk_check_for_sec_session())
-			mem_type = (ION_HEAP(mem_type) | ION_SECURE);
-		else
-			mem_type = (ION_HEAP(mem_type) |
-					ION_HEAP(ION_IOMMU_HEAP_ID));
+		if (res_trk_check_for_sec_session()) {
+			mem_type = ION_HEAP(mem_type);
+	if (resource_context.res_mem_type != DDL_FW_MEM)
+		mem_type |= ION_SECURE;
+	else if (res_trk_is_cp_enabled())
+		mem_type |= ION_SECURE;
+	} else
+		mem_type = (ION_HEAP(mem_type) |
+			ION_HEAP(ION_IOMMU_HEAP_ID));
 	}
 	return mem_type;
 }
 
+u32 res_trk_is_cp_enabled(void)
+{
+	if (resource_context.vidc_platform_data->cp_enabled)
+		return 1;
+	else
+		return 0;
+}
+
 u32 res_trk_get_enable_ion(void)
 {
 	if (resource_context.vidc_platform_data->enable_ion)
@@ -728,6 +826,10 @@
 	return resource_context.disable_dmx;
 }
 
+u32 res_trk_get_min_dpb_count(void){
+	return resource_context.vidc_platform_data->cont_mode_dpb_count;
+}
+
 void res_trk_set_mem_type(enum ddl_mem_area mem_type)
 {
 	resource_context.res_mem_type = mem_type;
@@ -840,8 +942,8 @@
 			pr_err("IOMMU clock enabled failed while close");
 			goto error_close;
 		}
-		msm_ion_unsecure_heap(ION_HEAP(resource_context.memtype));
 		msm_ion_unsecure_heap(ION_HEAP(resource_context.cmd_mem_type));
+		msm_ion_unsecure_heap(ION_HEAP(resource_context.memtype));
 		res_trk_disable_iommu_clocks();
 		mutex_unlock(&resource_context.secure_lock);
 	}
@@ -870,3 +972,17 @@
 	}
 	return res_trk_perf_level;
 }
+
+u32 res_trk_estimate_perf_level(u32 pn_perf_lvl)
+{
+	VCDRES_MSG_MED("%s(), req_perf_lvl = %d", __func__, pn_perf_lvl);
+	if ((pn_perf_lvl >= RESTRK_1080P_VGA_PERF_LEVEL) &&
+		(pn_perf_lvl < RESTRK_1080P_720P_PERF_LEVEL)) {
+		return RESTRK_1080P_720P_PERF_LEVEL;
+	} else if ((pn_perf_lvl >= RESTRK_1080P_720P_PERF_LEVEL) &&
+			(pn_perf_lvl < RESTRK_1080P_MAX_PERF_LEVEL)) {
+		return RESTRK_1080P_MAX_PERF_LEVEL;
+	} else {
+		return pn_perf_lvl;
+	}
+}
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
index 7d68412..99b123c 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
@@ -31,9 +31,11 @@
 u32 res_trk_get_firmware_addr(struct ddl_buf_addr *firm_addr);
 int res_trk_get_mem_type(void);
 u32 res_trk_get_enable_ion(void);
+u32 res_trk_is_cp_enabled(void);
 u32 res_trk_get_disable_fullhd(void);
 struct ion_client *res_trk_get_ion_client(void);
 u32 res_trk_get_disable_dmx(void);
+u32 res_trk_get_min_dpb_count(void);
 void res_trk_set_mem_type(enum ddl_mem_area mem_type);
 int res_trk_enable_iommu_clocks(void);
 int res_trk_disable_iommu_clocks(void);
@@ -43,4 +45,8 @@
 void res_trk_secure_set(void);
 void res_trk_secure_unset(void);
 u32 get_res_trk_perf_level(enum vcd_perf_level);
+int res_trk_enable_footswitch(void);
+int res_trk_disable_footswitch(void);
+void res_trk_release_fw_addr(void);
+u32 res_trk_estimate_perf_level(u32 pn_perf_lvl);
 #endif
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 9dc495b..7e201cf 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
@@ -57,6 +57,12 @@
 	u32 activity_region_flag;
 };
 
+struct vcd_property_slice_delivery_info {
+	u32  enable;
+	u32  num_slices;
+	u32  num_slices_enc;
+};
+
 struct ddl_frame_data_tag;
 
 struct ddl_property_dec_pic_buffers {
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 17dedb8..aa0d4b8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -231,3 +231,12 @@
 	proc_time[index].ddl_ttotal = 0;
 	proc_time[index].ddl_count = 0;
 }
+int ddl_get_core_decode_proc_time(u32 *ddl_handle)
+{
+	return 0;
+}
+
+void ddl_reset_avg_dec_time(u32 *ddl_handle)
+{
+	return;
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
index 539f753..59bb620 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
@@ -46,6 +46,10 @@
 
 void ddl_reset_core_time_variables(u32 index);
 
+int ddl_get_core_decode_proc_time(u32 *ddl_handle);
+
+void ddl_reset_avg_dec_time(u32 *ddl_handle);
+
 #define DDL_ASSERT(x)
 #define DDL_MEMSET(src, value, len) memset((src), (value), (len))
 #define DDL_MEMCPY(dest, src, len)  memcpy((dest), (src), (len))
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 f8ec0dc..e51bf45 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
@@ -757,3 +757,15 @@
 {
 	return -ENOTSUPP;
 }
+u32 res_trk_is_cp_enabled(void)
+{
+	if (resource_context.vidc_platform_data->cp_enabled)
+		return 1;
+	else
+		return 0;
+}
+u32 res_trk_estimate_perf_level(u32 pn_perf_lvl)
+{
+	return 0;
+}
+
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
index cc414e2..75fdb3e 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
@@ -30,6 +30,7 @@
 u32 res_trk_get_mem_type(void);
 u32 res_trk_get_disable_fullhd(void);
 u32 res_trk_get_enable_ion(void);
+u32 res_trk_is_cp_enabled(void);
 struct ion_client *res_trk_get_ion_client(void);
 void res_trk_set_mem_type(enum ddl_mem_area mem_type);
 int res_trk_check_for_sec_session(void);
@@ -38,4 +39,5 @@
 void res_trk_secure_set(void);
 void res_trk_secure_unset(void);
 u32 get_res_trk_perf_level(enum vcd_perf_level perf_level);
+u32 res_trk_estimate_perf_level(u32 pn_perf_lvl);
 #endif
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index d93d07e..5542856 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1604,6 +1604,20 @@
 		}
 		if (!result) {
 			ERR("setting VEN_IOCTL_(G)SET_LIVE_MODE failed\n");
+		}
+		break;
+	}
+	case VEN_IOCTL_SET_SLICE_DELIVERY_MODE:
+	{
+		struct vcd_property_hdr vcd_property_hdr;
+		u32 vcd_status = VCD_ERR_FAIL;
+		u32 enable = true;
+		vcd_property_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
+		vcd_property_hdr.sz = sizeof(u32);
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+						&vcd_property_hdr, &enable);
+		if (vcd_status) {
+			pr_err(" Setting slice delivery mode failed");
 			return -EIO;
 		}
 		break;
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 6fdb1c6..e641d62 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -63,7 +63,7 @@
 static irqreturn_t vidc_isr(int irq, void *dev);
 static spinlock_t vidc_spin_lock;
 
-u32 vidc_msg_timing, vidc_msg_pmem;
+u32 vidc_msg_timing, vidc_msg_pmem, vidc_msg_register;
 
 #ifdef VIDC_ENABLE_DBGFS
 struct dentry *vidc_debugfs_root;
@@ -311,6 +311,8 @@
 				(u32 *) &vidc_msg_timing);
 		vidc_debugfs_file_create(root, "vidc_msg_pmem",
 				(u32 *) &vidc_msg_pmem);
+		vidc_debugfs_file_create(root, "vidc_msg_register",
+				(u32 *) &vidc_msg_register);
 	}
 #endif
 	return 0;
@@ -343,28 +345,32 @@
 {
 	u32 status = true;
 
-	mutex_lock(&vidc_device_p->lock);
-	if (!vidc_device_p->get_firmware) {
-		status = res_trk_download_firmware();
-		if (!status)
-			goto error;
-		vidc_device_p->get_firmware = 1;
-	}
-	vidc_device_p->firmware_refcount++;
+	if (!res_trk_check_for_sec_session()) {
+		mutex_lock(&vidc_device_p->lock);
+		if (!vidc_device_p->get_firmware) {
+			status = res_trk_download_firmware();
+			if (!status)
+				goto error;
+			vidc_device_p->get_firmware = 1;
+		}
+		vidc_device_p->firmware_refcount++;
 error:
-	mutex_unlock(&vidc_device_p->lock);
+		mutex_unlock(&vidc_device_p->lock);
+	}
 	return status;
 }
 EXPORT_SYMBOL(vidc_load_firmware);
 
 void vidc_release_firmware(void)
 {
-	mutex_lock(&vidc_device_p->lock);
-	if (vidc_device_p->firmware_refcount > 0)
-		vidc_device_p->firmware_refcount--;
-	else
-		vidc_device_p->firmware_refcount = 0;
-	mutex_unlock(&vidc_device_p->lock);
+	if (!res_trk_check_for_sec_session()) {
+		mutex_lock(&vidc_device_p->lock);
+		if (vidc_device_p->firmware_refcount > 0)
+			vidc_device_p->firmware_refcount--;
+		else
+			vidc_device_p->firmware_refcount = 0;
+		mutex_unlock(&vidc_device_p->lock);
+	}
 }
 EXPORT_SYMBOL(vidc_release_firmware);
 
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index 0d1ff7e..3e02030 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -393,4 +393,8 @@
 u32 vcd_req_perf_level(struct vcd_clnt_ctxt *cctxt,
 	struct vcd_property_perf_level *);
 
+u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_update_decoder_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl);
+
 #endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index e33c8cd..d228146 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -185,6 +185,7 @@
 	u32 live;
 	u32 decoding;
 	u32 bframe;
+	u32 num_slices;
 
 	struct vcd_property_frame_rate frm_rate;
 	u32 frm_p_units;
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 01bd931..beaa872 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
@@ -297,6 +297,21 @@
 	return rc;
 }
 
+u32 vcd_update_decoder_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl)
+{
+	u32 rc = VCD_S_SUCCESS;
+
+	if (res_trk_set_perf_level(perf_lvl,
+		&dev_ctxt->curr_perf_lvl, dev_ctxt)) {
+		dev_ctxt->set_perf_lvl_pending = false;
+	} else {
+		rc = VCD_ERR_FAIL;
+		dev_ctxt->set_perf_lvl_pending = true;
+	}
+
+	return rc;
+}
+
 u32 vcd_update_clnt_perf_lvl(
 	struct vcd_clnt_ctxt *cctxt,
      struct vcd_property_frame_rate *fps, u32 frm_p_units)
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index fd8d02a..2df7144 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -19,6 +19,8 @@
 
 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
 #define MAP_TABLE_SZ 64
+#define VCD_ENC_MAX_OUTBFRS_PER_FRAME 8
+#define MAX_DEC_TIME 33
 
 struct vcd_msm_map_buffer {
 	phys_addr_t phy_addr;
@@ -942,7 +944,6 @@
 		list_del(&entry->list);
 		pool->q_len--;
 	}
-
 	return entry;
 }
 
@@ -1122,6 +1123,7 @@
 	cctxt->bframe = 0;
 	cctxt->cmd_q.pending_cmd = VCD_CMD_NONE;
 	cctxt->status.last_evt = VCD_EVT_RESP_BASE;
+	cctxt->num_slices = 1;
 	return rc;
 }
 
@@ -1293,6 +1295,7 @@
 		}
 
 	} else {
+		vcd_set_num_slices(transc->cctxt);
 		rc = ddl_encode_start(transc->cctxt->ddl_handle,
 					  (void *)transc);
 	}
@@ -1491,8 +1494,11 @@
 	struct vcd_buffer_entry *op_buf_entry = NULL;
 	u32 rc = VCD_S_SUCCESS;
 	u32 evcode = 0;
+	u32 perf_level = 0;
+	int decodeTime = 0;
 	struct ddl_frame_data_tag ddl_ip_frm;
-	struct ddl_frame_data_tag ddl_op_frm;
+	struct ddl_frame_data_tag *ddl_op_frm;
+	u32 out_buf_cnt = 0;
 
 	VCD_MSG_LOW("vcd_submit_frame:");
 	cctxt = transc->cctxt;
@@ -1504,34 +1510,62 @@
 	transc->flags = ip_frm_entry->flags;
 	ip_frm_entry->ip_frm_tag = (u32) transc;
 	memset(&ddl_ip_frm, 0, sizeof(ddl_ip_frm));
-	memset(&ddl_op_frm, 0, sizeof(ddl_op_frm));
 	if (cctxt->decoding) {
+		decodeTime = ddl_get_core_decode_proc_time(cctxt->ddl_handle);
+		if (decodeTime > MAX_DEC_TIME) {
+			if (res_trk_get_curr_perf_level(&perf_level)) {
+				vcd_update_decoder_perf_level(dev_ctxt,
+				   res_trk_estimate_perf_level(perf_level));
+				ddl_reset_avg_dec_time(cctxt->ddl_handle);
+			} else
+				VCD_MSG_ERROR("%s(): retrieve curr_perf_level"
+						"returned FALSE\n", __func__);
+		}
 		evcode = CLIENT_STATE_EVENT_NUMBER(decode_frame);
 		ddl_ip_frm.vcd_frm = *ip_frm_entry;
 		rc = ddl_decode_frame(cctxt->ddl_handle, &ddl_ip_frm,
-							   (void *) transc);
+							(void *) transc);
 	} else {
-		op_buf_entry = vcd_buffer_pool_entry_de_q(
-			&cctxt->out_buf_pool);
-		if (!op_buf_entry) {
-			VCD_MSG_ERROR("Sched provided frame when no"
-				"op buffer was present");
-			rc = VCD_ERR_FAIL;
-		} else {
+		ddl_op_frm = (struct ddl_frame_data_tag *)
+			kmalloc((sizeof(struct ddl_frame_data_tag) *
+			VCD_ENC_MAX_OUTBFRS_PER_FRAME), GFP_KERNEL);
+		if (!ddl_op_frm) {
+			VCD_MSG_ERROR("Memory allocation failure");
+			return VCD_ERR_ALLOC_FAIL;
+		}
+		memset(ddl_op_frm, 0, (sizeof(struct ddl_frame_data_tag) *
+			VCD_ENC_MAX_OUTBFRS_PER_FRAME));
+		for (out_buf_cnt = 0; out_buf_cnt < cctxt->num_slices ;
+				out_buf_cnt++) {
+			op_buf_entry = vcd_buffer_pool_entry_de_q(
+				&cctxt->out_buf_pool);
+			if (!op_buf_entry) {
+				VCD_MSG_ERROR("Sched provided frame when no"
+					"op buffer was present");
+				rc = VCD_ERR_FAIL;
+				break;
+			}
 			op_buf_entry->in_use = true;
 			cctxt->out_buf_pool.in_use++;
-			ddl_ip_frm.vcd_frm = *ip_frm_entry;
-			ddl_ip_frm.frm_delta =
-				vcd_calculate_frame_delta(cctxt,
-					ip_frm_entry);
-
-			ddl_op_frm.vcd_frm = op_buf_entry->frame;
-
-			evcode = CLIENT_STATE_EVENT_NUMBER(encode_frame);
-
-			rc = ddl_encode_frame(cctxt->ddl_handle,
-				&ddl_ip_frm, &ddl_op_frm, (void *) transc);
+			ddl_op_frm[out_buf_cnt].vcd_frm = op_buf_entry->frame;
+			VCD_MSG_LOW("%s : buffer_cnt = %d framebfr(virtual)"
+				" 0x%p", __func__, out_buf_cnt,
+				op_buf_entry->frame.virtual);
+			VCD_MSG_LOW("framebfr(physical) 0x%p bfrlength %d",
+				op_buf_entry->frame.physical,
+				op_buf_entry->frame.alloc_len);
 		}
+		ddl_ip_frm.vcd_frm = *ip_frm_entry;
+		ddl_ip_frm.frm_delta =
+			vcd_calculate_frame_delta(cctxt,
+				ip_frm_entry);
+		evcode = CLIENT_STATE_EVENT_NUMBER(encode_frame);
+
+		if (!VCD_FAILED(rc)) {
+			rc = ddl_encode_frame(cctxt->ddl_handle,
+				&ddl_ip_frm, &ddl_op_frm[0], (void *) transc);
+		}
+		kfree(ddl_op_frm);
 	}
 	ip_frm_entry->ip_frm_tag = transc->ip_frm_tag;
 	if (!VCD_FAILED(rc)) {
@@ -1875,8 +1909,10 @@
 
 void vcd_release_trans_tbl_entry(struct vcd_transc *trans_entry)
 {
-	if (trans_entry)
+	if (trans_entry) {
 		trans_entry->in_use = false;
+		VCD_MSG_LOW("%s in_use set to false\n", __func__);
+	}
 }
 
 u32 vcd_handle_input_done(
@@ -1888,6 +1924,7 @@
 		(struct ddl_frame_data_tag *) payload;
 	struct vcd_buffer_entry *orig_frame = NULL;
 	u32 rc;
+	VCD_MSG_LOW("%s\n", __func__);
 
 	if (!cctxt->status.frame_submitted &&
 		!cctxt->status.frame_delayed) {
@@ -1935,8 +1972,11 @@
 	transc->ip_buf_entry = NULL;
 	transc->input_done = true;
 
-	if (transc->input_done && transc->frame_done)
+	if (transc->input_done && transc->frame_done) {
+		VCD_MSG_LOW("%s Calling vcd_release_trans_tbl_entry\n",
+		__func__);
 		vcd_release_trans_tbl_entry(transc);
+	}
 
 	if (VCD_FAILED(status)) {
 		VCD_MSG_ERROR("INPUT_DONE returned err = 0x%x", status);
@@ -1975,6 +2015,7 @@
 		(struct ddl_frame_data_tag *) payload;
 	u32 rc = VCD_ERR_FAIL, codec_config = false;
 	u32 core_type = res_trk_get_core_type();
+	VCD_MSG_LOW("%s\n", __func__);
 	rc = vcd_validate_io_done_pyld(cctxt, payload, status);
 	if (rc == VCD_ERR_CLIENT_FATAL)
 		vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
@@ -2080,6 +2121,7 @@
 	struct ddl_frame_data_tag *frame =
 		(struct ddl_frame_data_tag *)payload;
 	u32 rc = VCD_S_SUCCESS;
+	VCD_MSG_LOW("%s\n", __func__);
 
 	if (!cctxt->status.frame_submitted &&
 		!cctxt->status.frame_delayed) {
@@ -2140,6 +2182,7 @@
 	struct vcd_transc *transc;
 	struct ddl_frame_data_tag *frame =
 		(struct ddl_frame_data_tag *)payload;
+	VCD_MSG_LOW("%s\n", __func__);
 
 	rc = vcd_validate_io_done_pyld(cctxt, payload, VCD_S_SUCCESS);
 	if (rc == VCD_ERR_CLIENT_FATAL)
@@ -2173,6 +2216,7 @@
 	struct vcd_transc *transc;
 	u32 rc;
 	s64 time_stamp;
+	VCD_MSG_LOW("%s\n", __func__);
 
 	rc = vcd_validate_io_done_pyld(cctxt, payload, status);
 	if (rc == VCD_ERR_CLIENT_FATAL)
@@ -2262,7 +2306,7 @@
 	struct ddl_frame_data_tag *frame =
 		(struct ddl_frame_data_tag *) payload;
 	u32 rc = VCD_S_SUCCESS;
-	VCD_MSG_LOW("vcd_handle_frame_done_in_eos:");
+	VCD_MSG_LOW("%s\n", __func__);
 	rc = vcd_validate_io_done_pyld(cctxt, payload, status);
 	if (rc == VCD_ERR_CLIENT_FATAL)
 		vcd_handle_clnt_fatal(cctxt, frame->frm_trans_end);
@@ -3326,3 +3370,24 @@
 		 0, cctxt, cctxt->client_data);
 	}
 }
+
+u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt)
+{
+	struct vcd_property_hdr prop_hdr;
+	struct vcd_property_slice_delivery_info slice_delivery_info;
+	u32 rc = VCD_S_SUCCESS;
+	prop_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
+	prop_hdr.sz = prop_hdr.sz =
+		sizeof(struct vcd_property_slice_delivery_info);
+	rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr,
+				&slice_delivery_info);
+	VCD_FAILED_RETURN(rc, "Failed: Get VCD_I_SLICE_DELIVERY_MODE");
+	if (slice_delivery_info.enable) {
+		cctxt->num_slices = slice_delivery_info.num_slices;
+		VCD_MSG_LOW("%s slice delivery mode num_slices = %u\n",
+					__func__, cctxt->num_slices);
+	} else {
+		cctxt->num_slices = 1;
+	}
+	return rc;
+}
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index ed1f112..01c5ca9 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -28,9 +28,18 @@
 #define IOMMU_CACHE	(4) /* DMA cache coherency */
 
 struct device;
+struct iommu_domain;
+
+/* iommu fault flags */
+#define IOMMU_FAULT_READ	0x0
+#define IOMMU_FAULT_WRITE	0x1
+
+typedef int (*iommu_fault_handler_t)(struct iommu_domain *,
+				struct device *, unsigned long, int);
 
 struct iommu_domain {
 	void *priv;
+	iommu_fault_handler_t handler;
 };
 
 #define IOMMU_CAP_CACHE_COHERENCY	0x1
@@ -79,6 +88,47 @@
 extern int iommu_domain_has_cap(struct iommu_domain *domain,
 				unsigned long cap);
 extern phys_addr_t iommu_get_pt_base_addr(struct iommu_domain *domain);
+extern void iommu_set_fault_handler(struct iommu_domain *domain,
+					iommu_fault_handler_t handler);
+
+/**
+ * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework
+ * @domain: the iommu domain where the fault has happened
+ * @dev: the device where the fault has happened
+ * @iova: the faulting address
+ * @flags: mmu fault flags (e.g. IOMMU_FAULT_READ/IOMMU_FAULT_WRITE/...)
+ *
+ * This function should be called by the low-level IOMMU implementations
+ * whenever IOMMU faults happen, to allow high-level users, that are
+ * interested in such events, to know about them.
+ *
+ * This event may be useful for several possible use cases:
+ * - mere logging of the event
+ * - dynamic TLB/PTE loading
+ * - if restarting of the faulting device is required
+ *
+ * Returns 0 on success and an appropriate error code otherwise (if dynamic
+ * PTE/TLB loading will one day be supported, implementations will be able
+ * to tell whether it succeeded or not according to this return value).
+ *
+ * Specifically, -ENOSYS is returned if a fault handler isn't installed
+ * (though fault handlers can also return -ENOSYS, in case they want to
+ * elicit the default behavior of the IOMMU drivers).
+ */
+static inline int report_iommu_fault(struct iommu_domain *domain,
+		struct device *dev, unsigned long iova, int flags)
+{
+	int ret = -ENOSYS;
+
+	/*
+	 * if upper layers showed interest and installed a fault handler,
+	 * invoke it.
+	 */
+	if (domain->handler)
+		ret = domain->handler(domain, dev, iova, flags);
+
+	return ret;
+}
 
 #else /* CONFIG_IOMMU_API */
 
@@ -152,6 +202,12 @@
 {
 	return 0;
 }
+
+static inline void iommu_set_fault_handler(struct iommu_domain *domain,
+					iommu_fault_handler_t handler)
+{
+}
+
 #endif /* CONFIG_IOMMU_API */
 
 #endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/mfd/pm8xxx/pm8038.h b/include/linux/mfd/pm8xxx/pm8038.h
index 4d3c78f..90557b9 100644
--- a/include/linux/mfd/pm8xxx/pm8038.h
+++ b/include/linux/mfd/pm8xxx/pm8038.h
@@ -32,6 +32,7 @@
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
 #include <linux/leds-pm8xxx.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
+#include <linux/mfd/pm8xxx/spk.h>
 
 #define PM8038_CORE_DEV_NAME "pm8038-core"
 
@@ -78,6 +79,7 @@
 	struct pm8xxx_adc_platform_data		*adc_pdata;
 	struct pm8xxx_led_platform_data		*leds_pdata;
 	struct pm8xxx_ccadc_platform_data	*ccadc_pdata;
+	struct pm8xxx_spk_platform_data		*spk_pdata;
 };
 
 #endif
diff --git a/include/linux/mfd/pm8xxx/spk.h b/include/linux/mfd/pm8xxx/spk.h
new file mode 100644
index 0000000..1155d2f
--- /dev/null
+++ b/include/linux/mfd/pm8xxx/spk.h
@@ -0,0 +1,47 @@
+/* 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 __SPK_PM8XXX_H__
+#define __SPK_PM8XXX_H__
+
+#define PM8XXX_SPK_DEV_NAME     "pm8xxx-spk"
+
+/**
+ * struct pm8xxx_spk_pdata - SPK driver platform data
+ * @spk_add_enable: variable stating SPK secondary input adding capability
+ */
+struct pm8xxx_spk_platform_data {
+	bool spk_add_enable;
+};
+
+/*
+ * pm8xxx_spk_mute - mute/unmute speaker pamp
+ *
+ * @mute: bool value for mute
+ */
+int pm8xxx_spk_mute(bool mute);
+
+/*
+ * pm8xxx_spk_gain - Set Speaker gain
+ *
+ * @gain: Speaker gain
+ */
+int pm8xxx_spk_gain(u8 gain);
+
+/*
+ * pm8xxx_spk_enable - Enable/Disable Speaker
+ *
+ * @enable: bool enable/disable Speaker
+ */
+int pm8xxx_spk_enable(int enable);
+
+#endif /* __SPK_PM8XXX_H__ */
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 244b957..e67190f 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -157,8 +157,18 @@
 #define KGSL_2D1_REG_MEMORY	"kgsl_2d1_reg_memory"
 #define KGSL_2D1_IRQ		"kgsl_2d1_irq"
 
+enum kgsl_iommu_context_id {
+	KGSL_IOMMU_CONTEXT_USER = 0,
+	KGSL_IOMMU_CONTEXT_PRIV = 1,
+};
+
+struct kgsl_iommu_ctx {
+	const char *iommu_ctx_name;
+	enum kgsl_iommu_context_id ctx_id;
+};
+
 struct kgsl_device_iommu_data {
-	const char **iommu_ctx_names;
+	const struct kgsl_iommu_ctx *iommu_ctxs;
 	int iommu_ctx_count;
 	unsigned int physstart;
 	unsigned int physend;
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index f5472ec..1b0d399 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -26,11 +26,13 @@
 	MSM_TYPE
 };
 
+#define TSENS_MAX_SENSORS		11
+
 struct tsens_platform_data {
+	int				slope[TSENS_MAX_SENSORS];
 	int				tsens_factor;
 	uint32_t			tsens_num_sensor;
 	enum platform_type		hw_type;
-	int				slope[11];
 };
 
 struct tsens_device {
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index bf149eb..519c537 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -454,6 +454,10 @@
 #define VEN_IOCTL_GET_EXTRADATA \
 	_IOR(VEN_IOCTLBASE_ENC, 49, struct venc_ioctl_msg)
 
+/*IOCTL params:SET: InputData - NULL, OutputData - NULL.*/
+#define VEN_IOCTL_SET_SLICE_DELIVERY_MODE \
+	_IO(VEN_IOCTLBASE_ENC, 50)
+
 struct venc_switch{
 	unsigned char	status;
 };
diff --git a/include/linux/usb/android.h b/include/linux/usb/android.h
index 9d7e4a8..6d3c3ad 100644
--- a/include/linux/usb/android.h
+++ b/include/linux/usb/android.h
@@ -19,6 +19,7 @@
 
 struct android_usb_platform_data {
 	int (*update_pid_and_serial_num)(uint32_t, const char *);
+	u32 swfi_latency;
 };
 
 #endif	/* __LINUX_USB_ANDROID_H */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 4c0ae07..14d49eb 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -23,7 +23,6 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 #include <linux/wakelock.h>
-#include <linux/pm_qos_params.h>
 
 /*
  * The following are bit fields describing the usb_request.udc_priv word.
@@ -188,7 +187,6 @@
  * @mhl_enable: indicates MHL connector or not.
  * @disable_reset_on_disconnect: perform USB PHY and LINK reset
  *              on USB cable disconnection.
- * @swfi_latency: miminum latency to allow swfi.
  * @enable_dcd: Enable Data Contact Detection circuit. if not set
  *              wait for 600msec before proceeding to primary
  *              detection.
@@ -206,7 +204,6 @@
 	int pmic_id_irq;
 	bool mhl_enable;
 	bool disable_reset_on_disconnect;
-	u32 swfi_latency;
 	bool enable_dcd;
 	struct msm_bus_scale_pdata *bus_scale_table;
 };
@@ -277,8 +274,6 @@
  *             connected. Useful only when ACA_A charger is
  *             connected.
  * @mA_port: The amount of current drawn by the attached B-device.
- * @pm_qos_req_dma: miminum DMA latency to vote against idle power
-	collapse when cable is connected.
  * @id_timer: The timer used for polling ID line to detect ACA states.
  * @xo_handle: TCXO buffer handle
  * @bus_perf_client: Bus performance client handle to request BUS bandwidth
@@ -341,7 +336,6 @@
 	unsigned long lpm_flags;
 #define PHY_PWR_COLLAPSED		BIT(0)
 #define PHY_RETENTIONED			BIT(1)
-	struct pm_qos_request_list pm_qos_req_dma;
 	int reset_counter;
 	unsigned long b_last_se0_sess;
 	unsigned long tmouts;
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 51cc78f..e776d41 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -52,6 +52,7 @@
 #define VCD_I_DISABLE_DMX_SUPPORT (VCD_START_BASE + 0x24)
 #define VCD_I_ENABLE_SPS_PPS_FOR_IDR (VCD_START_BASE + 0x25)
 #define VCD_REQ_PERF_LEVEL (VCD_START_BASE + 0x26)
+#define VCD_I_SLICE_DELIVERY_MODE (VCD_START_BASE + 0x27)
 
 #define VCD_START_REQ      (VCD_START_BASE + 0x1000)
 #define VCD_I_REQ_IFRAME   (VCD_START_REQ + 0x1)
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 7aae5e1..bf02b84 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -438,6 +438,7 @@
 #define CMD_AXI_CFG_ZSL_ALL_CHNLS 49
 #define CMD_AXI_CFG_VIDEO_ALL_CHNLS 50
 #define CMD_VFE_BUFFER_RELEASE 51
+#define CMD_VFE_PROCESS_IRQ 52
 
 #define CMD_AXI_CFG_PRIM		0xF1
 #define CMD_AXI_CFG_PRIM_ALL_CHNLS	0xF2
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index 381f5c4..52194f9 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -52,7 +52,7 @@
 #define SRCH_MASK                  (1 << SRCH200KHZ_OFFSET)
 
 /* Standard buffer size */
-#define STD_BUF_SIZE               (64)
+#define STD_BUF_SIZE               (128)
 /* Search direction */
 #define SRCH_DIR_UP                 (0)
 #define SRCH_DIR_DOWN               (1)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 7e9f5f4..d218fab 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -99,6 +99,28 @@
  */
 #define BT_AMP_POLICY_PREFER_AMP       2
 
+#define BT_LE_PARAMS	100
+
+#define BT_LE_SCAN_WINDOW_MIN		0x0004
+#define BT_LE_SCAN_WINDOW_MAX		0x4000
+#define BT_LE_SCAN_WINDOW_DEF		0x0004
+
+#define BT_LE_SCAN_INTERVAL_MIN		0x0004
+#define BT_LE_SCAN_INTERVAL_MAX		0x4000
+#define BT_LE_SCAN_INTERVAL_DEF		0x0008
+
+#define BT_LE_CONN_INTERVAL_MIN		0x0006
+#define BT_LE_CONN_INTERVAL_MAX		0x0C80
+#define BT_LE_CONN_INTERVAL_MIN_DEF	0x0008
+#define BT_LE_CONN_INTERVAL_MAX_DEF	0x0100
+
+#define BT_LE_LATENCY_MAX		0x01F4
+#define BT_LE_LATENCY_DEF		0x0000
+
+#define BT_LE_SUP_TO_MIN		0x000A
+#define BT_LE_SUP_TO_MAX		0x0C80
+#define BT_LE_SUP_TO_DEFAULT		0X03E8
+
 #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
 #define BT_ERR(fmt, arg...)  printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
 #define BT_DBG(fmt, arg...)  pr_debug("%s: " fmt "\n" , __func__ , ## arg)
@@ -142,6 +164,20 @@
 
 #define bt_sk(__sk) ((struct bt_sock *) __sk)
 
+struct bt_le_params {
+	__u8  prohibit_remote_chg;
+	__u8  filter_policy;
+	__u16 scan_interval;
+	__u16 scan_window;
+	__u16 interval_min;
+	__u16 interval_max;
+	__u16 latency;
+	__u16 supervision_timeout;
+	__u16 min_ce_len;
+	__u16 max_ce_len;
+	__u16 conn_timeout;
+};
+
 struct bt_sock {
 	struct sock sk;
 	bdaddr_t    src;
@@ -149,6 +185,7 @@
 	struct list_head accept_q;
 	struct sock *parent;
 	u32 defer_setup;
+	struct bt_le_params le_params;
 };
 
 struct bt_sock_list {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5053bd8..5749293 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -304,6 +304,7 @@
 	__u8		auth_initiator;
 	__u8		power_save;
 	__u16		disc_timeout;
+	__u16		conn_timeout;
 	unsigned long	pend;
 
 	__u8		remote_cap;
@@ -597,6 +598,10 @@
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
 					__u16 pkt_type, bdaddr_t *dst,
 					__u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_le_connect(struct hci_dev *hdev, __u16 pkt_type,
+					bdaddr_t *dst, __u8 sec_level,
+					__u8 auth_type,
+					struct bt_le_params *le_params);
 int hci_conn_check_link_mode(struct hci_conn *conn);
 int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
 int hci_conn_change_link_key(struct hci_conn *conn);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index b903c5c..a098f3e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -685,6 +685,7 @@
 int l2cap_ertm_tx(struct sock *sk, struct bt_l2cap_control *control,
 			struct sk_buff_head *skbs, u8 event);
 
+int l2cap_sock_le_params_valid(struct bt_le_params *le_params);
 void l2cap_sock_set_timer(struct sock *sk, long timeout);
 void l2cap_sock_clear_timer(struct sock *sk);
 void __l2cap_sock_close(struct sock *sk, int reason);
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 782ee8d..0007fd8 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -61,7 +61,7 @@
 #define RT_PROXY_PORT_001_TX	0x2001    /* index = 31 */
 
 #define AFE_PORT_INVALID 0xFFFF
-#define SLIMBUS_INVALID AFE_PORT_INVALID
+#define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
 
 #define AFE_PORT_CMD_START 0x000100ca
 
diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
index 472d0ac..e9f6748 100644
--- a/include/sound/snd_compress_params.h
+++ b/include/sound/snd_compress_params.h
@@ -236,6 +236,9 @@
 
 struct snd_enc_wma {
 	__u32 super_block_align; /* WMA Type-specific data */
+	__u32 bits_per_sample;
+	__u32 channelmask;
+	__u32 encodeopt;
 };
 
 
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d60bf00..25b559b1 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -44,33 +44,77 @@
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
 
-static void hci_le_connect(struct hci_conn *conn)
+struct hci_conn *hci_le_connect(struct hci_dev *hdev, __u16 pkt_type,
+				bdaddr_t *dst, __u8 sec_level, __u8 auth_type,
+				struct bt_le_params *le_params)
 {
-	struct hci_dev *hdev = conn->hdev;
+	struct hci_conn *le;
 	struct hci_cp_le_create_conn cp;
+	struct adv_entry *entry;
+	struct link_key *key;
 
-	BT_DBG("%p", conn);
+	BT_DBG("%p", hdev);
 
-	conn->state = BT_CONNECT;
-	conn->out = 1;
-	conn->link_mode |= HCI_LM_MASTER;
-	conn->sec_level = BT_SECURITY_LOW;
-	conn->type = LE_LINK;
+	le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
+	if (le) {
+		hci_conn_hold(le);
+		return le;
+	}
+
+	key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
+	if (!key) {
+		entry = hci_find_adv_entry(hdev, dst);
+		if (entry)
+			le = hci_le_conn_add(hdev, dst,
+					entry->bdaddr_type);
+		else
+			le = hci_le_conn_add(hdev, dst, 0);
+	} else {
+		le = hci_le_conn_add(hdev, dst, key->addr_type);
+	}
+
+	if (!le)
+		return ERR_PTR(-ENOMEM);
+
+	hci_conn_hold(le);
+
+	le->state = BT_CONNECT;
+	le->out = 1;
+	le->link_mode |= HCI_LM_MASTER;
+	le->sec_level = BT_SECURITY_LOW;
+	le->type = LE_LINK;
 
 	memset(&cp, 0, sizeof(cp));
-	cp.scan_interval = cpu_to_le16(0x0004);
-	cp.scan_window = cpu_to_le16(0x0004);
-	bacpy(&cp.peer_addr, &conn->dst);
-	cp.peer_addr_type = conn->dst_type;
-	cp.conn_interval_min = cpu_to_le16(0x0008);
-	cp.conn_interval_max = cpu_to_le16(0x0100);
-	cp.supervision_timeout = cpu_to_le16(1000);
-	cp.min_ce_len = cpu_to_le16(0x0001);
-	cp.max_ce_len = cpu_to_le16(0x0001);
+	if (l2cap_sock_le_params_valid(le_params)) {
+		cp.supervision_timeout =
+				cpu_to_le16(le_params->supervision_timeout);
+		cp.scan_interval = cpu_to_le16(le_params->scan_interval);
+		cp.scan_window = cpu_to_le16(le_params->scan_window);
+		cp.conn_interval_min = cpu_to_le16(le_params->interval_min);
+		cp.conn_interval_max = cpu_to_le16(le_params->interval_max);
+		cp.conn_latency = cpu_to_le16(le_params->latency);
+		cp.min_ce_len = cpu_to_le16(le_params->min_ce_len);
+		cp.max_ce_len = cpu_to_le16(le_params->max_ce_len);
+		le->conn_timeout = le_params->conn_timeout;
+	} else {
+		cp.supervision_timeout = cpu_to_le16(BT_LE_SUP_TO_DEFAULT);
+		cp.scan_interval = cpu_to_le16(BT_LE_SCAN_INTERVAL_DEF);
+		cp.scan_window = cpu_to_le16(BT_LE_SCAN_WINDOW_DEF);
+		cp.conn_interval_min = cpu_to_le16(BT_LE_CONN_INTERVAL_MIN_DEF);
+		cp.conn_interval_max = cpu_to_le16(BT_LE_CONN_INTERVAL_MAX_DEF);
+		cp.conn_latency = cpu_to_le16(BT_LE_LATENCY_DEF);
+		le->conn_timeout = 5;
+	}
+	bacpy(&cp.peer_addr, &le->dst);
+	cp.peer_addr_type = le->dst_type;
 
 	hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
+
+	return le;
 }
+EXPORT_SYMBOL(hci_le_connect);
 
 static void hci_le_connect_cancel(struct hci_conn *conn)
 {
@@ -685,41 +729,12 @@
 {
 	struct hci_conn *acl;
 	struct hci_conn *sco;
-	struct hci_conn *le;
 
 	BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
-	if (type == LE_LINK) {
-		struct adv_entry *entry;
-		struct link_key *key;
-
-		le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
-		if (le) {
-			hci_conn_hold(le);
-			return le;
-		}
-
-		key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
-		if (!key) {
-			entry = hci_find_adv_entry(hdev, dst);
-			if (entry)
-				le = hci_le_conn_add(hdev, dst,
-						entry->bdaddr_type);
-			else
-				le = hci_le_conn_add(hdev, dst, 0);
-		} else {
-			le = hci_le_conn_add(hdev, dst, key->addr_type);
-		}
-
-		if (!le)
-			return ERR_PTR(-ENOMEM);
-
-		hci_le_connect(le);
-
-		hci_conn_hold(le);
-
-		return le;
-	}
+	if (type == LE_LINK)
+		return hci_le_connect(hdev, pkt_type, dst, sec_level,
+							auth_type, NULL);
 
 	acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
 	if (!acl) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 598c310..395a95c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1368,6 +1368,7 @@
 {
 	struct hci_cp_le_create_conn *cp;
 	struct hci_conn *conn;
+	unsigned long exp = msecs_to_jiffies(5000);
 
 	BT_DBG("%s status 0x%x", hdev->name, status);
 
@@ -1396,11 +1397,11 @@
 				conn->out = 1;
 			else
 				BT_ERR("No memory for new connection");
-		}
+		} else
+			exp = msecs_to_jiffies(conn->conn_timeout * 1000);
 
-		if (conn)
-			mod_timer(&conn->disc_timer,
-					jiffies + msecs_to_jiffies(5000));
+		if (conn && exp)
+			mod_timer(&conn->disc_timer, jiffies + exp);
 	}
 
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 37ee9b1..9f9f17d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1277,8 +1277,9 @@
 		conn = hcon->l2cap_data;
 	} else {
 		if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
-			hcon = hci_connect(hdev, LE_LINK, 0, dst,
-					l2cap_pi(sk)->sec_level, auth_type);
+			hcon = hci_le_connect(hdev, 0, dst,
+					l2cap_pi(sk)->sec_level, auth_type,
+					&bt_sk(sk)->le_params);
 		else
 			hcon = hci_connect(hdev, ACL_LINK, 0, dst,
 					l2cap_pi(sk)->sec_level, auth_type);
@@ -1308,7 +1309,17 @@
 		sk->sk_state_change(sk);
 	} else {
 		sk->sk_state = BT_CONNECT;
-		l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+		/* If we have valid LE Params, let timeout override default */
+		if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA &&
+			l2cap_sock_le_params_valid(&bt_sk(sk)->le_params)) {
+			u16 timeout = bt_sk(sk)->le_params.conn_timeout;
+
+			if (timeout)
+				l2cap_sock_set_timer(sk,
+						msecs_to_jiffies(timeout*1000));
+		} else
+			l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+
 		sk->sk_state_change(sk);
 
 		if (hcon->state == BT_CONNECTED) {
@@ -5668,7 +5679,8 @@
 	struct hci_conn *hcon = conn->hcon;
 	struct l2cap_conn_param_update_req *req;
 	struct l2cap_conn_param_update_rsp rsp;
-	u16 min, max, latency, to_multiplier, cmd_len;
+	struct sock *sk;
+	u16 min, max, latency, timeout, cmd_len;
 	int err;
 
 	if (!(hcon->link_mode & HCI_LM_MASTER))
@@ -5678,28 +5690,32 @@
 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
 		return -EPROTO;
 
-	req = (struct l2cap_conn_param_update_req *) data;
-	min		= __le16_to_cpu(req->min);
-	max		= __le16_to_cpu(req->max);
-	latency		= __le16_to_cpu(req->latency);
-	to_multiplier	= __le16_to_cpu(req->to_multiplier);
-
-	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
-						min, max, latency, to_multiplier);
-
 	memset(&rsp, 0, sizeof(rsp));
+	rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
 
-	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
-	if (err)
-		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
-	else
-		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+	sk = l2cap_find_sock_by_fixed_cid_and_dir(4, conn->src, conn->dst, 0);
+
+	if (sk && !bt_sk(sk)->le_params.prohibit_remote_chg) {
+		req = (struct l2cap_conn_param_update_req *) data;
+		min = __le16_to_cpu(req->min);
+		max = __le16_to_cpu(req->max);
+		latency = __le16_to_cpu(req->latency);
+		timeout = __le16_to_cpu(req->to_multiplier);
+
+		err = l2cap_check_conn_param(min, max, latency, timeout);
+		if (!err) {
+			rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+			hci_le_conn_update(hcon, min, max, latency, timeout);
+			bt_sk(sk)->le_params.interval_min = min;
+			bt_sk(sk)->le_params.interval_max = max;
+			bt_sk(sk)->le_params.latency = latency;
+			bt_sk(sk)->le_params.supervision_timeout = timeout;
+		}
+	}
 
 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
 							sizeof(rsp), &rsp);
 
-	if (!err)
-		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
 
 	return 0;
 }
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 8eb1e16..33d5d22 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -78,6 +78,23 @@
 	sk_stop_timer(sk, &sk->sk_timer);
 }
 
+int l2cap_sock_le_params_valid(struct bt_le_params *le_params)
+{
+	if (!le_params || le_params->latency > BT_LE_LATENCY_MAX ||
+			le_params->scan_window > BT_LE_SCAN_WINDOW_MAX ||
+			le_params->scan_interval < BT_LE_SCAN_INTERVAL_MIN ||
+			le_params->scan_window > le_params->scan_interval ||
+			le_params->interval_min < BT_LE_CONN_INTERVAL_MIN ||
+			le_params->interval_max > BT_LE_CONN_INTERVAL_MAX ||
+			le_params->interval_min > le_params->interval_max ||
+			le_params->supervision_timeout < BT_LE_SUP_TO_MIN ||
+			le_params->supervision_timeout > BT_LE_SUP_TO_MAX) {
+		return 0;
+	}
+
+	return 1;
+}
+
 static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
 {
 	struct sock *sk;
@@ -547,6 +564,17 @@
 			err = -EFAULT;
 		break;
 
+	case BT_LE_PARAMS:
+		if (l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (copy_to_user(optval, (char *) &bt_sk(sk)->le_params,
+						sizeof(bt_sk(sk)->le_params)))
+			err = -EFAULT;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -671,6 +699,7 @@
 	struct sock *sk = sock->sk;
 	struct bt_security sec;
 	struct bt_power pwr;
+	struct bt_le_params le_params;
 	struct l2cap_conn *conn;
 	int len, err = 0;
 	u32 opt;
@@ -786,6 +815,41 @@
 
 		break;
 
+	case BT_LE_PARAMS:
+		if (l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user((char *) &le_params, optval,
+					sizeof(struct bt_le_params))) {
+			err = -EFAULT;
+			break;
+		}
+
+		conn = l2cap_pi(sk)->conn;
+		if (!conn || !conn->hcon ||
+				l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+			memcpy(&bt_sk(sk)->le_params, &le_params,
+							sizeof(le_params));
+			break;
+		}
+
+		if (!conn->hcon->out ||
+				!l2cap_sock_le_params_valid(&le_params)) {
+			err = -EINVAL;
+			break;
+		}
+
+		memcpy(&bt_sk(sk)->le_params, &le_params, sizeof(le_params));
+
+		hci_le_conn_update(conn->hcon,
+				le_params.interval_min,
+				le_params.interval_max,
+				le_params.latency,
+				le_params.supervision_timeout);
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e15609c..80f4bd6 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1623,8 +1623,8 @@
 
 	entry = hci_find_adv_entry(hdev, &cp->bdaddr);
 	if (entry && entry->flags & 0x04) {
-		conn = hci_connect(hdev, LE_LINK, 0, &cp->bdaddr, sec_level,
-								auth_type);
+		conn = hci_le_connect(hdev, 0, &cp->bdaddr, sec_level,
+							auth_type, NULL);
 	} else {
 		/* ACL-SSP does not support io_cap 0x04 (KeyboadDisplay) */
 		if (io_cap == 0x04)
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 3d489ff..392e05d 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -343,7 +343,7 @@
 
 		if (codec_clk) {
 			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
-			clk_enable(codec_clk);
+			clk_prepare_enable(codec_clk);
 			tabla_mclk_enable(codec, 1, dapm);
 		} else {
 			pr_err("%s: Error setting Tabla MCLK\n", __func__);
@@ -359,7 +359,7 @@
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
 			tabla_mclk_enable(codec, 0, dapm);
-			clk_disable(codec_clk);
+			clk_disable_unprepare(codec_clk);
 		}
 	}
 	return 0;
@@ -381,7 +381,7 @@
 
 		if (codec_clk) {
 			clk_set_rate(codec_clk, 12288000);
-			clk_enable(codec_clk);
+			clk_prepare_enable(codec_clk);
 			tabla_mclk_enable(w->codec, 1, true);
 
 		} else {
@@ -404,7 +404,7 @@
 					__func__, clk_users);
 
 			tabla_mclk_enable(w->codec, 0, true);
-			clk_disable(codec_clk);
+			clk_disable_unprepare(codec_clk);
 		}
 		break;
 	}
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index 760f13d..f02a7ef 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -321,7 +321,7 @@
 
 		if (codec_clk) {
 			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
-			clk_enable(codec_clk);
+			clk_prepare_enable(codec_clk);
 			tabla_mclk_enable(codec, 1, dapm);
 		} else {
 			pr_err("%s: Error setting Tabla MCLK\n", __func__);
@@ -337,7 +337,7 @@
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
 			tabla_mclk_enable(codec, 0, dapm);
-			clk_disable(codec_clk);
+			clk_disable_unprepare(codec_clk);
 		}
 	}
 	return 0;
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index ea05a58e..c32527c 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -134,6 +134,7 @@
 static int msm_ext_top_spk_pamp;
 static int msm_slim_0_rx_ch = 1;
 static int msm_slim_0_tx_ch = 1;
+static int msm_hdmi_rx_ch = 2;
 
 static struct clk *codec_clk;
 static int clk_users;
@@ -392,7 +393,7 @@
 
 		if (codec_clk) {
 			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
-			clk_enable(codec_clk);
+			clk_prepare_enable(codec_clk);
 			tabla_mclk_enable(codec, 1, dapm);
 		} else {
 			pr_err("%s: Error setting Tabla MCLK\n", __func__);
@@ -407,7 +408,7 @@
 		if (!clk_users) {
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
-			clk_disable(codec_clk);
+			clk_disable_unprepare(codec_clk);
 			tabla_mclk_enable(codec, 0, dapm);
 		}
 	}
@@ -430,7 +431,7 @@
 
 		if (codec_clk) {
 			clk_set_rate(codec_clk, 12288000);
-			clk_enable(codec_clk);
+			clk_prepare_enable(codec_clk);
 			tabla_mclk_enable(w->codec, 1, true);
 
 		} else {
@@ -452,7 +453,7 @@
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					__func__, clk_users);
 
-			clk_disable(codec_clk);
+			clk_disable_unprepare(codec_clk);
 			tabla_mclk_enable(w->codec, 0, true);
 		}
 		break;
@@ -515,11 +516,15 @@
 static const char *spk_function[] = {"Off", "On"};
 static const char *slim0_rx_ch_text[] = {"One", "Two"};
 static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+static const char *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five", "Six"};
+
 
 static const struct soc_enum msm_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, spk_function),
 	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
 	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+	SOC_ENUM_SINGLE_EXT(5, hdmi_rx_ch_text),
+
 };
 
 static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
@@ -560,6 +565,26 @@
 	return 1;
 }
 
+static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_hdmi_rx_ch  = %d\n", __func__,
+			msm_hdmi_rx_ch);
+	ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
+	return 0;
+}
+
+static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
+
+	pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
+		msm_hdmi_rx_ch);
+	return 1;
+}
+
+
 static const struct snd_kcontrol_new tabla_msm_controls[] = {
 	SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
 		msm_set_spk),
@@ -567,6 +592,9 @@
 		msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
 	SOC_ENUM_EXT("SLIM_0_TX Channels", msm_enum[2],
 		msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
+	SOC_ENUM_EXT("HDMI_RX Channels", msm_enum[3],
+		msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
+
 };
 
 static void *def_tabla_mbhc_cal(void)
@@ -861,6 +889,7 @@
 			channels->min, channels->max);
 
 	rate->min = rate->max = 48000;
+	channels->min =  channels->max = msm_hdmi_rx_ch;
 
 	return 0;
 }
@@ -985,12 +1014,12 @@
 {
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		if (sec_i2s_rx_bit_clk) {
-			clk_disable(sec_i2s_rx_bit_clk);
+			clk_disable_unprepare(sec_i2s_rx_bit_clk);
 			clk_put(sec_i2s_rx_bit_clk);
 			sec_i2s_rx_bit_clk = NULL;
 		}
 		if (sec_i2s_rx_osr_clk) {
-			clk_disable(sec_i2s_rx_osr_clk);
+			clk_disable_unprepare(sec_i2s_rx_osr_clk);
 			clk_put(sec_i2s_rx_osr_clk);
 			sec_i2s_rx_osr_clk = NULL;
 		}
@@ -1040,20 +1069,20 @@
 			return PTR_ERR(sec_i2s_rx_osr_clk);
 		}
 		clk_set_rate(sec_i2s_rx_osr_clk, I2S_MCLK_RATE);
-		clk_enable(sec_i2s_rx_osr_clk);
+		clk_prepare_enable(sec_i2s_rx_osr_clk);
 		sec_i2s_rx_bit_clk = clk_get(cpu_dai->dev, "bit_clk");
 		if (IS_ERR(sec_i2s_rx_bit_clk)) {
 			pr_err("Failed to get sec i2s osr_clk\n");
-			clk_disable(sec_i2s_rx_osr_clk);
+			clk_disable_unprepare(sec_i2s_rx_osr_clk);
 			clk_put(sec_i2s_rx_osr_clk);
 			return PTR_ERR(sec_i2s_rx_bit_clk);
 		}
 		clk_set_rate(sec_i2s_rx_bit_clk, 1);
-		ret = clk_enable(sec_i2s_rx_bit_clk);
+		ret = clk_prepare_enable(sec_i2s_rx_bit_clk);
 		if (ret != 0) {
 			pr_err("Unable to enable sec i2s rx_bit_clk\n");
 			clk_put(sec_i2s_rx_bit_clk);
-			clk_disable(sec_i2s_rx_osr_clk);
+			clk_disable_unprepare(sec_i2s_rx_osr_clk);
 			clk_put(sec_i2s_rx_osr_clk);
 			return ret;
 		}
@@ -1095,7 +1124,7 @@
 		.name = "MSM8960 Media2",
 		.stream_name = "MultiMedia2",
 		.cpu_dai_name	= "MultiMedia2",
-		.platform_name  = "msm-pcm-dsp",
+		.platform_name  = "msm-multi-ch-pcm-dsp",
 		.dynamic = 1,
 		.dsp_link = &fe_media,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index cb760fa..776337d 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -49,7 +49,7 @@
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
 	.formats =	      SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_8000_48000,
+	.rates =		SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
 	.rate_min =	     8000,
 	.rate_max =	     48000,
 	.channels_min =	 1,
@@ -191,6 +191,7 @@
 	struct compr_audio *compr = runtime->private_data;
 	struct msm_audio *prtd = &compr->prtd;
 	struct asm_aac_cfg aac_cfg;
+	struct asm_wma_cfg wma_cfg;
 	int ret;
 
 	pr_debug("compressed stream prepare\n");
@@ -219,7 +220,7 @@
 		aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
 		aac_cfg.format = 0x03;
 		aac_cfg.ch_cfg = runtime->channels;
-		aac_cfg.sample_rate =  runtime->rate;
+		aac_cfg.sample_rate = runtime->rate;
 		ret = q6asm_media_format_block_aac(prtd->audio_client,
 					&aac_cfg);
 		if (ret < 0)
@@ -229,6 +230,26 @@
 		pr_debug("compressd playback, no need to send"
 			" the decoder params\n");
 		break;
+	case SND_AUDIOCODEC_WMA:
+		pr_debug("SND_AUDIOCODEC_WMA\n");
+		memset(&wma_cfg, 0x0, sizeof(struct asm_wma_cfg));
+		wma_cfg.format_tag = compr->info.codec_param.codec.format;
+		wma_cfg.ch_cfg = runtime->channels;
+		wma_cfg.sample_rate = runtime->rate;
+		wma_cfg.avg_bytes_per_sec =
+			compr->info.codec_param.codec.bit_rate/8;
+		wma_cfg.block_align = compr->info.codec_param.codec.align;
+		wma_cfg.valid_bits_per_sample =
+		compr->info.codec_param.codec.options.wma.bits_per_sample;
+		wma_cfg.ch_mask =
+			compr->info.codec_param.codec.options.wma.channelmask;
+		wma_cfg.encode_opt =
+			compr->info.codec_param.codec.options.wma.encodeopt;
+		ret = q6asm_media_format_block_wma(prtd->audio_client,
+					&wma_cfg);
+		if (ret < 0)
+			pr_err("%s: CMD Format block failed\n", __func__);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -294,6 +315,7 @@
 	compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
 	compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
 	compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3_PASS_THROUGH;
+	compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_WMA;
 	/* Add new codecs here */
 }
 
@@ -612,6 +634,10 @@
 			pr_debug("SND_AUDIOCODEC_AC3_PASS_THROUGH\n");
 			compr->codec = FORMAT_AC3;
 			break;
+		case SND_AUDIOCODEC_WMA:
+			pr_debug("SND_AUDIOCODEC_WMA\n");
+			compr->codec = FORMAT_WMA_V9;
+			break;
 		default:
 			pr_debug("FORMAT_LINEAR_PCM\n");
 			compr->codec = FORMAT_LINEAR_PCM;
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 23134ea..6c44cba 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -50,7 +50,8 @@
 	{
 		.playback = {
 			.stream_name = "Multimedia1 Playback",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
 			.channels_max = 2,
@@ -59,20 +60,22 @@
 		},
 		.capture = {
 			.stream_name = "Multimedia1 Capture",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
 			.channels_max = 4,
 			.rate_min =     8000,
 			.rate_max =	48000,
 		},
-		.ops = &msm_fe_dai_ops,
+		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia1",
 	},
 	{
 		.playback = {
 			.stream_name = "Multimedia2 Playback",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
 			.channels_max = 6,
@@ -81,14 +84,15 @@
 		},
 		.capture = {
 			.stream_name = "Multimedia2 Capture",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
 			.channels_max = 2,
 			.rate_min =     8000,
 			.rate_max =	48000,
 		},
-		.ops = &msm_fe_dai_ops,
+		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia2",
 	},
 	{
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index c1304c8..69d7185 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -457,7 +457,7 @@
 	pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
 			dai->id, aux_pcm_count);
 
-	clk_disable(pcm_clk);
+	clk_disable_unprepare(pcm_clk);
 	rc = afe_close(PCM_RX); /* can block */
 	if (IS_ERR_VALUE(rc))
 		dev_err(dai->dev, "fail to close PCM_RX  AFE port\n");
@@ -559,7 +559,7 @@
 		return rc;
 	}
 
-	clk_enable(pcm_clk);
+	clk_prepare_enable(pcm_clk);
 	clk_reset(pcm_clk, CLK_RESET_DEASSERT);
 
 	mutex_unlock(&aux_pcm_mutex);
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 0a8282c..734d34f 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -45,10 +45,11 @@
 };
 static struct snd_msm_volume multi_ch_pcm_audio = {NULL, 0x2000};
 
-#define PLAYBACK_NUM_PERIODS	8
-#define PLAYBACK_PERIOD_SIZE	4032
-#define CAPTURE_NUM_PERIODS	16
-#define CAPTURE_PERIOD_SIZE	320
+#define PLAYBACK_NUM_PERIODS		8
+#define PLAYBACK_MAX_PERIOD_SIZE	4032
+#define PLAYBACK_MIN_PERIOD_SIZE        256
+#define CAPTURE_NUM_PERIODS		16
+#define CAPTURE_PERIOD_SIZE		320
 
 static struct snd_pcm_hardware msm_pcm_hardware_capture = {
 	.info =                 (SNDRV_PCM_INFO_MMAP |
@@ -77,14 +78,14 @@
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
 	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =                SNDRV_PCM_RATE_8000_48000,
+	.rates =                SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
 	.rate_min =             8000,
 	.rate_max =             48000,
 	.channels_min =         1,
 	.channels_max =         6,
-	.buffer_bytes_max =     PLAYBACK_NUM_PERIODS * PLAYBACK_PERIOD_SIZE,
-	.period_bytes_min =	PLAYBACK_PERIOD_SIZE,
-	.period_bytes_max =     PLAYBACK_PERIOD_SIZE,
+	.buffer_bytes_max =     PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
+	.period_bytes_min =     PLAYBACK_MIN_PERIOD_SIZE,
+	.period_bytes_max =     PLAYBACK_MAX_PERIOD_SIZE,
 	.periods_min =          PLAYBACK_NUM_PERIODS,
 	.periods_max =          PLAYBACK_NUM_PERIODS,
 	.fifo_size =            0,
@@ -378,6 +379,17 @@
 	if (ret < 0)
 		pr_err("snd_pcm_hw_constraint_integer failed\n");
 
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = snd_pcm_hw_constraint_minmax(runtime,
+			SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+			PLAYBACK_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
+			PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
+		if (ret < 0) {
+			pr_err("constraint for buffer bytes min max ret = %d\n",
+									ret);
+		}
+	}
+
 	prtd->dsp_cnt = 0;
 	runtime->private_data = prtd;
 	pr_debug("substream->pcm->device = %d\n", substream->pcm->device);
@@ -683,10 +695,22 @@
 	else
 		dir = OUT;
 
-	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
+	if (dir == OUT) {
+		ret = q6asm_audio_client_buf_alloc_contiguous(dir,
 			prtd->audio_client,
 			runtime->hw.period_bytes_min,
 			runtime->hw.periods_max);
+	} else {
+		/*
+		 *TODO : Need to Add Async IO changes. All period
+		 * size might not be supported.
+		 */
+		ret = q6asm_audio_client_buf_alloc_contiguous(dir,
+			prtd->audio_client,
+			(params_buffer_bytes(params) / params_periods(params)),
+			params_periods(params));
+	}
+
 	if (ret < 0) {
 		pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
 		return -ENOMEM;
@@ -699,7 +723,10 @@
 	dma_buf->private_data = NULL;
 	dma_buf->area = buf[0].data;
 	dma_buf->addr =  buf[0].phys;
-	dma_buf->bytes = runtime->hw.buffer_bytes_max;
+	if (dir == OUT)
+		dma_buf->bytes = runtime->hw.buffer_bytes_max;
+	else
+		dma_buf->bytes = params_buffer_bytes(params);
 	if (!dma_buf->area)
 		return -ENOMEM;
 
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index 2135a35..482cbee 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -29,6 +29,8 @@
 #include <sound/control.h>
 #include <sound/q6adm.h>
 #include <asm/dma.h>
+#include <linux/memory_alloc.h>
+#include <mach/msm_subsystem_map.h>
 #include "msm-pcm-afe.h"
 
 #define MIN_PERIOD_SIZE (128 * 2)
@@ -380,13 +382,18 @@
 	if (dma_buf == NULL) {
 		pr_debug("dma_buf is NULL\n");
 			goto done;
-		}
-	if (dma_buf->area != NULL) {
-		dma_free_coherent(substream->pcm->card->dev,
-			runtime->hw.buffer_bytes_max, dma_buf->area,
-			dma_buf->addr);
-		dma_buf->area = NULL;
 	}
+
+	if (dma_buf->area) {
+		if (msm_subsystem_unmap_buffer(prtd->mem_buffer) < 0) {
+			pr_err("%s: unmap buffer failed\n", __func__);
+			prtd->mem_buffer = NULL;
+			dma_buf->area = NULL;
+		}
+	}
+
+	if (dma_buf->addr)
+		free_contiguous_memory_by_paddr(dma_buf->addr);
 done:
 	pr_debug("%s: dai->id =%x\n", __func__, dai->id);
 	mutex_unlock(&prtd->lock);
@@ -416,14 +423,21 @@
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct pcm_afe_info *prtd = runtime->private_data;
+	int result = 0;
 
 	pr_debug("%s\n", __func__);
 	prtd->mmap_flag = 1;
-	dma_mmap_coherent(substream->pcm->card->dev, vma,
-				runtime->dma_area,
-				runtime->dma_addr,
-				runtime->dma_bytes);
-	return 0;
+	if (runtime->dma_addr && runtime->dma_bytes) {
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+		result = remap_pfn_range(vma, vma->vm_start,
+				runtime->dma_addr >> PAGE_SHIFT,
+				runtime->dma_bytes,
+				vma->vm_page_prot);
+	} else {
+		pr_err("Physical address or size of buf is NULL");
+		return -EINVAL;
+	}
+	return result;
 }
 static int msm_afe_trigger(struct snd_pcm_substream *substream, int cmd)
 {
@@ -457,6 +471,7 @@
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
 	struct pcm_afe_info *prtd = runtime->private_data;
 	int rc;
+	unsigned int flags = 0;
 
 	pr_debug("%s:\n", __func__);
 
@@ -465,17 +480,46 @@
 	dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
 	dma_buf->dev.dev = substream->pcm->card->dev;
 	dma_buf->private_data = NULL;
-	dma_buf->area = dma_alloc_coherent(dma_buf->dev.dev,
-				runtime->hw.buffer_bytes_max,
-				&dma_buf->addr, GFP_KERNEL);
 
-	pr_debug("%s: dma_buf->area: 0x%p, dma_buf->addr: 0x%x", __func__,
-			(unsigned int *) dma_buf->area, dma_buf->addr);
-	if (!dma_buf->area) {
-		pr_err("%s:MSM AFE memory allocation failed\n", __func__);
+	dma_buf->addr = allocate_contiguous_ebi_nomap(
+				runtime->hw.buffer_bytes_max, SZ_4K);
+	if (!dma_buf->addr) {
+		pr_err("%s:MSM AFE physical memory allocation failed\n",
+							__func__);
 		mutex_unlock(&prtd->lock);
 		return -ENOMEM;
 	}
+
+	flags = MSM_SUBSYSTEM_MAP_KADDR | MSM_SUBSYSTEM_MAP_CACHED;
+
+	prtd->mem_buffer = msm_subsystem_map_buffer(dma_buf->addr,
+				runtime->hw.buffer_bytes_max, flags,
+				NULL, 0);
+	if (IS_ERR((void *) prtd->mem_buffer)) {
+		pr_err("%s: map_buffer failed error = %ld\n", __func__,
+				PTR_ERR((void *)prtd->mem_buffer));
+		free_contiguous_memory_by_paddr(dma_buf->addr);
+		mutex_unlock(&prtd->lock);
+		return -ENOMEM;
+	}
+
+	dma_buf->area = prtd->mem_buffer->vaddr;
+
+	pr_debug("%s: dma_buf->area: 0x%p, dma_buf->addr: 0x%x", __func__,
+			(unsigned int *) dma_buf->area, dma_buf->addr);
+
+	if (!dma_buf->area) {
+		pr_err("%s: Invalid Virtual address\n", __func__);
+		if (prtd->mem_buffer) {
+			msm_subsystem_unmap_buffer(prtd->mem_buffer);
+			prtd->mem_buffer = NULL;
+			dma_buf->area = NULL;
+		}
+		free_contiguous_memory_by_paddr(dma_buf->addr);
+		mutex_unlock(&prtd->lock);
+		return -ENOMEM;
+	}
+
 	dma_buf->bytes = runtime->hw.buffer_bytes_max;
 	memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max);
 	prtd->dma_addr = (u32) dma_buf->addr;
diff --git a/sound/soc/msm/msm-pcm-afe.h b/sound/soc/msm/msm-pcm-afe.h
index 7a60a73..38026d5 100644
--- a/sound/soc/msm/msm-pcm-afe.h
+++ b/sound/soc/msm/msm-pcm-afe.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
@@ -30,6 +30,7 @@
 	int prepared;
 	struct hrtimer hrt;
 	int poll_time;
+	struct msm_mapped_buffer *mem_buffer;
 };
 
 
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 4686386..39ce436 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -71,7 +71,7 @@
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
 	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =                SNDRV_PCM_RATE_8000_48000,
+	.rates =                SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
 	.rate_min =             8000,
 	.rate_max =             48000,
 	.channels_min =         1,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 18001b0..4f0e952 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -134,7 +134,7 @@
 	{ SLIMBUS_1_TX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_4_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_4_TX, 0, 0, 0, 0, 0},
-	{ SLIMBUS_INVALID, 0, 0, 0, 0, 0},
+	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 };
 
 
@@ -161,10 +161,10 @@
 		MSM_AFE_PORT_TYPE_RX : MSM_AFE_PORT_TYPE_TX);
 
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((afe_get_port_type(msm_bedais[i].port_id) ==
-			port_type) &&
-			msm_bedais[i].active && (test_bit(fedai_id,
-				&msm_bedais[i].fe_sessions)))
+		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		    (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
+		    (msm_bedais[i].active) &&
+		    (test_bit(fedai_id, &msm_bedais[i].fe_sessions)))
 			payload.copp_ids[payload.num_copps++] =
 					msm_bedais[i].port_id;
 	}
@@ -200,14 +200,13 @@
 
 	fe_dai_map[fedai_id][session_type] = dspst_id;
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((afe_get_port_type(msm_bedais[i].port_id) ==
-			port_type) && msm_bedais[i].active &&
-			(test_bit(fedai_id,
-			&msm_bedais[i].fe_sessions))) {
-
+		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		    (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
+		    (msm_bedais[i].active) &&
+		    (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
 			mode = afe_get_port_type(msm_bedais[i].port_id);
 			adm_connect_afe_port(mode, dspst_id,
-				msm_bedais[i].port_id);
+					     msm_bedais[i].port_id);
 			break;
 		}
 	}
@@ -244,10 +243,10 @@
 	if (eq_data[fedai_id].enable)
 		msm_send_eq_values(fedai_id);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((afe_get_port_type(msm_bedais[i].port_id) ==
-			port_type) && msm_bedais[i].active &&
-			(test_bit(fedai_id,
-			&msm_bedais[i].fe_sessions))) {
+		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		    (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
+		    (msm_bedais[i].active) &&
+		    (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
 
 			channels = msm_bedais[i].channel;
 
@@ -297,10 +296,10 @@
 	mutex_lock(&routing_lock);
 
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((afe_get_port_type(msm_bedais[i].port_id) ==
-			port_type) && msm_bedais[i].active &&
-			(test_bit(fedai_id,
-			&msm_bedais[i].fe_sessions)))
+		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		    (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
+		    (msm_bedais[i].active) &&
+		    (test_bit(fedai_id, &msm_bedais[i].fe_sessions)))
 			adm_close(msm_bedais[i].port_id);
 	}
 
@@ -1156,7 +1155,7 @@
 };
 
 static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
-	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_INVALID,
+	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_EXTPROC_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
 };
@@ -1228,7 +1227,7 @@
 };
 
 static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
-	SOC_SINGLE_EXT("STUB_TX_HL", MSM_BACKEND_DAI_INVALID,
+	SOC_SINGLE_EXT("STUB_TX_HL", MSM_BACKEND_DAI_EXTPROC_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
 	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
@@ -2079,10 +2078,8 @@
 		return 0;
 	}
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((test_bit(fedai_id,
-			&msm_bedais[i].fe_sessions))) {
+		if (test_bit(fedai_id, &msm_bedais[i].fe_sessions))
 			return msm_bedais[i].active;
-		}
 	}
 	return 0;
 }
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 546c396..b7c7631 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -88,7 +88,7 @@
 	MSM_BACKEND_DAI_SLIMBUS_1_TX,
 	MSM_BACKEND_DAI_SLIMBUS_4_RX,
 	MSM_BACKEND_DAI_SLIMBUS_4_TX,
-	MSM_BACKEND_DAI_INVALID,
+	MSM_BACKEND_DAI_EXTPROC_RX,
 	MSM_BACKEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/msm8660-apq-wm8903.c b/sound/soc/msm/msm8660-apq-wm8903.c
index a163006..15a01d7 100644
--- a/sound/soc/msm/msm8660-apq-wm8903.c
+++ b/sound/soc/msm/msm8660-apq-wm8903.c
@@ -196,7 +196,7 @@
 		}
 		/* Master clock OSR 256 */
 		clk_set_rate(wm8903_mclk, 48000 * 256);
-		ret = clk_enable(wm8903_mclk);
+		ret = clk_prepare_enable(wm8903_mclk);
 		if (ret != 0) {
 			pr_err("Unable to enable i2s_mic_osr_clk\n");
 			gpio_free(MSM_CDC_MIC_I2S_MCLK);
@@ -205,7 +205,7 @@
 		}
 	} else {
 		if (wm8903_mclk) {
-			clk_disable(wm8903_mclk);
+			clk_disable_unprepare(wm8903_mclk);
 			clk_put(wm8903_mclk);
 			gpio_free(MSM_CDC_MIC_I2S_MCLK);
 			wm8903_mclk = NULL;
@@ -314,7 +314,7 @@
 			return PTR_ERR(spkr_osr_clk);
 		}
 		clk_set_rate(spkr_osr_clk, 48000 * 256);
-		ret = clk_enable(spkr_osr_clk);
+		ret = clk_prepare_enable(spkr_osr_clk);
 		if (ret != 0) {
 			pr_err("Unable to enable i2s_spkr_osr_clk\n");
 			clk_put(spkr_osr_clk);
@@ -323,15 +323,15 @@
 		spkr_bit_clk = clk_get(NULL, "i2s_spkr_bit_clk");
 		if (IS_ERR(spkr_bit_clk)) {
 			pr_err("Failed to get i2s_spkr_bit_clk\n");
-			clk_disable(spkr_osr_clk);
+			clk_disable_unprepare(spkr_osr_clk);
 			clk_put(spkr_osr_clk);
 			return PTR_ERR(spkr_bit_clk);
 		}
 		clk_set_rate(spkr_bit_clk, 0);
-		ret = clk_enable(spkr_bit_clk);
+		ret = clk_prepare_enable(spkr_bit_clk);
 		if (ret != 0) {
 			pr_err("Unable to enable i2s_spkr_bit_clk\n");
-			clk_disable(spkr_osr_clk);
+			clk_disable_unprepare(spkr_osr_clk);
 			clk_put(spkr_osr_clk);
 			clk_put(spkr_bit_clk);
 			return ret;
@@ -357,7 +357,7 @@
 			return PTR_ERR(mic_bit_clk);
 		}
 		clk_set_rate(mic_bit_clk, 0);
-		ret = clk_enable(mic_bit_clk);
+		ret = clk_prepare_enable(mic_bit_clk);
 		if (ret != 0) {
 			pr_err("Unable to enable i2s_mic_bit_clk\n");
 			clk_put(mic_bit_clk);
@@ -375,17 +375,17 @@
 		tx_hw_param_status = 0;
 		rx_hw_param_status = 0;
 		if (spkr_bit_clk) {
-			clk_disable(spkr_bit_clk);
+			clk_disable_unprepare(spkr_bit_clk);
 			clk_put(spkr_bit_clk);
 			spkr_bit_clk = NULL;
 		}
 		if (spkr_osr_clk) {
-			clk_disable(spkr_osr_clk);
+			clk_disable_unprepare(spkr_osr_clk);
 			clk_put(spkr_osr_clk);
 			spkr_osr_clk = NULL;
 		}
 		if (mic_bit_clk) {
-			clk_disable(mic_bit_clk);
+			clk_disable_unprepare(mic_bit_clk);
 			clk_put(mic_bit_clk);
 			mic_bit_clk = NULL;
 		}
diff --git a/sound/soc/msm/msm8660.c b/sound/soc/msm/msm8660.c
index 8469507..4cbfd45 100644
--- a/sound/soc/msm/msm8660.c
+++ b/sound/soc/msm/msm8660.c
@@ -170,7 +170,7 @@
 		/* Master clock OSR 256 */
 		/* Initially set to Lowest sample rate Needed */
 		clk_set_rate(rx_osr_clk, 8000 * 256);
-		ret = clk_enable(rx_osr_clk);
+		ret = clk_prepare_enable(rx_osr_clk);
 		if (ret != 0) {
 			pr_debug("Unable to enable i2s_spkr_osr_clk\n");
 			clk_put(rx_osr_clk);
@@ -179,16 +179,16 @@
 		rx_bit_clk = clk_get(NULL, "i2s_spkr_bit_clk");
 		if (IS_ERR(rx_bit_clk)) {
 			pr_debug("Failed to get i2s_spkr_bit_clk\n");
-			clk_disable(rx_osr_clk);
+			clk_disable_unprepare(rx_osr_clk);
 			clk_put(rx_osr_clk);
 			return PTR_ERR(rx_bit_clk);
 		}
 		clk_set_rate(rx_bit_clk, 8);
-		ret = clk_enable(rx_bit_clk);
+		ret = clk_prepare_enable(rx_bit_clk);
 		if (ret != 0) {
 			pr_debug("Unable to enable i2s_spkr_bit_clk\n");
 			clk_put(rx_bit_clk);
-			clk_disable(rx_osr_clk);
+			clk_disable_unprepare(rx_osr_clk);
 			clk_put(rx_osr_clk);
 			return ret;
 		}
@@ -203,7 +203,7 @@
 		}
 		/* Master clock OSR 256 */
 		clk_set_rate(tx_osr_clk, 8000 * 256);
-		ret = clk_enable(tx_osr_clk);
+		ret = clk_prepare_enable(tx_osr_clk);
 		if (ret != 0) {
 			pr_debug("Unable to enable i2s_mic_osr_clk\n");
 			clk_put(tx_osr_clk);
@@ -212,16 +212,16 @@
 		tx_bit_clk = clk_get(NULL, "i2s_mic_bit_clk");
 		if (IS_ERR(tx_bit_clk)) {
 			pr_debug("Failed to get i2s_mic_bit_clk\n");
-			clk_disable(tx_osr_clk);
+			clk_disable_unprepare(tx_osr_clk);
 			clk_put(tx_osr_clk);
 			return PTR_ERR(tx_bit_clk);
 		}
 		clk_set_rate(tx_bit_clk, 8);
-		ret = clk_enable(tx_bit_clk);
+		ret = clk_prepare_enable(tx_bit_clk);
 		if (ret != 0) {
 			pr_debug("Unable to enable i2s_mic_bit_clk\n");
 			clk_put(tx_bit_clk);
-			clk_disable(tx_osr_clk);
+			clk_disable_unprepare(tx_osr_clk);
 			clk_put(tx_osr_clk);
 			return ret;
 		}
@@ -243,12 +243,12 @@
 		timpani_poweramp_off();
 		msleep(30);
 		if (rx_bit_clk) {
-			clk_disable(rx_bit_clk);
+			clk_disable_unprepare(rx_bit_clk);
 			clk_put(rx_bit_clk);
 			rx_bit_clk = NULL;
 		}
 		if (rx_osr_clk) {
-			clk_disable(rx_osr_clk);
+			clk_disable_unprepare(rx_osr_clk);
 			clk_put(rx_osr_clk);
 			rx_osr_clk = NULL;
 		}
@@ -257,12 +257,12 @@
 		msm_snddev_disable_dmic_power();
 		msleep(30);
 		if (tx_bit_clk) {
-			clk_disable(tx_bit_clk);
+			clk_disable_unprepare(tx_bit_clk);
 			clk_put(tx_bit_clk);
 			tx_bit_clk = NULL;
 		}
 		if (tx_osr_clk) {
-			clk_disable(tx_osr_clk);
+			clk_disable_unprepare(tx_osr_clk);
 			clk_put(tx_osr_clk);
 			tx_osr_clk = NULL;
 		}
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 44fab3f..40f81e8 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -344,7 +344,7 @@
 		if (clk_users == 1) {
 			if (codec_clk) {
 				clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
-				clk_enable(codec_clk);
+				clk_prepare_enable(codec_clk);
 				tabla_mclk_enable(codec, 1, dapm);
 			} else {
 				pr_err("%s: Error setting Tabla MCLK\n",
@@ -361,7 +361,7 @@
 				pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
 				tabla_mclk_enable(codec, 0, dapm);
-				clk_disable(codec_clk);
+				clk_disable_unprepare(codec_clk);
 			}
 		} else {
 			pr_err("%s: Error releasing Tabla MCLK\n", __func__);