Merge "arm/dt: 8226: modify reg-names values in msm8226 dt nodes"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
index 5c6b804..2d83614 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
@@ -6,12 +6,19 @@
 type of heap ION must reserve memory using the msm specific memory reservation
 bindings (see Documentation/devicetree/bindings/arm/msm/memory-reserve.txt).
 
-Required properties
+Required properties for Ion
 
 - compatible: "qcom,msm-ion"
+
+
+All child nodes of a qcom,msm-ion node are interpreted as Ion heap
+configurations.
+
+Required properties for Ion heaps
+
 - reg: The ID of the ION heap.
 
-Optional properties
+Optional properties for Ion heaps
 
 - compatible: "qcom,msm-ion-reserve" This is required if memory is to be reserved
   as specified by qcom,memory-reservation-size below.
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
index d930799..3d70a9b 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
@@ -62,6 +62,28 @@
 				1.  This value shift is necessary to work around
 				limitations in the regulator framework which
 				treat 0 uV as an error.
+- qcom,use-voltage-floor-corner:  Flag that signifies if regulator_set_voltage
+				calls should modify the floor corner parameter
+				instead of the voltage parameter.  When used,
+				voltages specified inside of the regulator
+				framework represent corners that have been
+				incremented by 1.  The properties
+				qcom,use-voltage-corner and
+				qcom,use-voltage-floor-corner are mutually
+				exclusive.  Only one may be specified for a
+				given regulator.
+- qcom,always-send-voltage:    Flag which indicates that updates to the voltage
+				or voltage corner set point should always be
+				sent immediately to the RPM.  If this flag is
+				not specified, then voltage set point updates
+				are only sent if the given regulator has also
+				been enabled by a Linux consumer.
+- qcom,always-send-current:    Flag which indicates that updates to the load
+				current should always be sent immediately to the
+				RPM.  If this flag is not specified, then load
+				current updates are only sent if the given
+				regulator has also been enabled by a Linux
+				consumer.
 The following properties specify initial values for parameters to be sent to the
 RPM in regulator requests.
 - qcom,init-enable:            0 = regulator disabled
@@ -94,25 +116,9 @@
 					BIT(2) = follow HW2_EN signal
 					BIT(3) = follow HW3_EN signal
 					BIT(4) = follow PMIC awake state
-- qcom,init-frequency:         Switching frequency in MHz for SMPS regulators.
-				Supported values are:
-					 0 = Don't care about frequency used
-					 1 = 19.20
-					 2 = 9.60
-					 3 = 6.40
-					 4 = 4.80
-					 5 = 3.84
-					 6 = 3.20
-					 7 = 2.74
-					 8 = 2.40
-					 9 = 2.13
-					10 = 1.92
-					11 = 1.75
-					12 = 1.60
-					13 = 1.48
-					14 = 1.37
-					15 = 1.28
-					16 = 1.20
+- qcom,init-frequency:         Switching frequency divisor for SMPS regulators.
+				Supported values are n = 0 to 31 where
+				freq = 19.2 MHz / (n + 1).
 - qcom,init-head-room:         Voltage head room in mV required for the
 				regulator.  This head room value should be used
 				in situations where the device connected to the
@@ -165,6 +171,10 @@
 					0 = Allow RPM to utilize LDO bypass mode
 						if possible
 					1 = Disallow LDO bypass mode
+- qcom,init-voltage-floor-corner:  Minimum performance corner to use if any
+				processor in the system is awake.  This property
+				supports the same values as
+				qcom,init-voltage-corner.
 
 All properties specified within the core regulator framework can also be used in
 second level nodes.  These bindings can be found in:
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt b/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt
new file mode 100644
index 0000000..c012eec
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt
@@ -0,0 +1,32 @@
+Qualcomm SPM Regulators
+
+spm-regulator is a regulator device which supports PMIC processor supply
+regulators via the SPM module.
+
+Required properties:
+- compatible:      Must be "qcom,spm-regulator"
+- reg:             Specifies the SPMI address and size for this regulator device
+- regulator-name:  A string used as a descriptive name for the regulator
+
+Required structure:
+- A qcom,spm-regulator node must be a child of an SPMI node that has specified
+	the spmi-slave-container property
+
+All properties specified within the core regulator framework can also be used.
+These bindings can be found in regulator.txt.
+
+Example:
+	qcom,spmi@fc4c0000 {
+
+		qcom,pm8226@1 {
+			spmi-slave-container;
+
+			spm-regulator@1700 {
+				compatible = "qcom,spm-regulator";
+				regulator-name = "8226_s2";
+				reg = <0x1700 0x100>;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1275000>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index fa63cfc..25219cd 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -88,6 +88,23 @@
 - qcom,reset-flush-race : indicates if a race exists between flushing and ddr
 			  being put into self-refresh during watchdog reset
 - qcom,write-64bit : only 64bit data writes supported by stm
+- vdd-supply: phandle to the regulator device tree node. Used for tpiu component
+- qcom,vdd-voltage-level : specifies voltage level for vdd supply. Should be
+			   specified in pairs (min, max) with units being uV
+- qcom,vdd-current-level : specifies current load levels for vdd supply. Should
+			   be specified in paris (lpm, hpm) with units being uA
+- qcom,seta-gpios : specifies gpios included in set A that are routed to the
+		    mictor connector. Used for tpiu component
+- qcom,seta-gpios-func : active function select for set A gpios
+- qcom,seta-gpios-drv : active drive strength for set A gpios
+- qcom,seta-gpios-pull : active pull configuration for set A gpios
+- qcom,seta-gpios-dir : active direction for set A gpios
+- qcom,setb-gpios : specifies gpios included in set B that are routed to the
+		    mictor connector. Used for tpiu component
+- qcom,setb-gpios-func : active function select for set B gpios
+- qcom,setb-gpios-drv : active drive strength for set B gpios
+- qcom,setb-gpios-pull : active pull configuration for set B gpios
+- qcom,setb-gpios-dir : active direction for set B gpios
 
 Examples:
 
@@ -112,6 +129,11 @@
 		coresight-id = <1>;
 		coresight-name = "coresight-tpiu";
 		coresight-nr-inports = <1>;
+
+		vdd-supply = <&pm8941_l21>;
+
+		qcom,vdd-voltage-level = <2950000 2950000>;
+		qcom,vdd-current-level = <9000 800000>;
 	};
 
 2. Links
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index b9bac1d..812a895 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -51,12 +51,17 @@
 Required properties for RGB led:
 - qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
 - qcom,pwm-channel: pwm channel the led will operate on
+
+Required properties for PWM mode only:
 - qcom,pwm-us: time the pwm device will modulate at (us)
 
 Required properties for LPG mode only:
-- qcom,duty-ms: duty cycle time the led will operate at (ms)
 - qcom,duty-pcts: array of values for duty cycle to go through
 - qcom,start-idx: starting point duty-pcts array
+- qcom,pause-lo: pause at low end of cycle
+- qcom,pause-hi: pause at high end of cycle
+- qcom,ramp-step-ms: step between each cycle (ms)
+- qcom,lut-flags: flags to be used in lut configuration
 
 Optional properties for RGB led:
 - linux,default-trigger: trigger the led from external modules such as display
@@ -90,12 +95,14 @@
 			linux,name = "led:rgb_blue";
 			qcom,mode = <1>;
 			qcom,pwm-channel = <4>;
-			qcom,pwm-us = <1000>;
-			qcom,duty-ms = <20>;
 			qcom,start-idx = <1>;
 			qcom,idx-len = <10>;
 			qcom,duty-pcts = [00 19 32 4B 64
 					 64 4B 32 19 00];
+			qcom,lut-flags = <3>;
+			qcom,pause-lo = <0>;
+			qcom,pause-hi = <0>;
+			qcom,ramp-step-ms = <255>;
 			qcom,max-current = <12>;
 			qcom,default-state = "on";
 			qcom,turn-off-delay-ms = <500>;
diff --git a/Documentation/devicetree/bindings/misc/qpnp-misc.txt b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
new file mode 100644
index 0000000..34c344a
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
@@ -0,0 +1,27 @@
+QPNP-MISC
+
+QPNP-MISC provides a way to read the PMIC part number and revision.
+
+Required properties:
+- compatible : should be "qcom,qpnp-misc"
+- reg : offset and length of the PMIC peripheral register map.
+
+Example:
+	qcom,spmi@fc4c0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+
+		qcom,pm8941@0 {
+			spmi-slave-container;
+			reg = <0x0>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			qcom,misc@900 {
+				compatible = "qcom,qpnp-misc";
+				reg = <0x900 0x100>;
+			};
+		}
+	};
diff --git a/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt b/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
index 7b9feae..6c3e98e 100644
--- a/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
+++ b/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
@@ -2,15 +2,15 @@
 
 Required properties:
     - compatible: Can be "qca,ar6004-sdio" for SDIO device and
-    "qca,ar6004-hsic" for HSIC devcie.
+    "qca,ar6004-hsic" for HSIC device. For AR6003, "qca,ar6003-sdio" can be
+    used.
     - qca,chip-pwd-l-gpios: specify GPIO for CHIP_PWD_L.
 
 Optional Properties:
     - cell-index: WLAN Hardware index.
     - qca,pm-enable-gpios: Specify this GPIO if internal PMU needs to be used.
-    - qca,ar6004-vbatt-supply: Specify this if VBATT is provided through a
-    regulator.
-    - qca,ar6004-vdd-io-supply: Specify this if VDD-IO is provided through a
+    - qca,vbatt-supply: Specify this if VBATT is provided through a regulator.
+    - qca,vdd-io-supply: Specify this if VDD-IO is provided through a
     regulator.
 
 Example:
@@ -20,5 +20,5 @@
 		compatible = "qca,ar6004-sdio";
 		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
 		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
-		qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+		qca,vdd-io-supply = <&pm8019_l11>;
 	};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 320c3e4a..d174157 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -22,6 +22,11 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		pm8941_misc: qcom,misc@900 {
+			compatible = "qcom,qpnp-misc";
+			reg = <0x900 0x100>;
+		};
+
 		qcom,revid@100 {
 			compatible = "qcom,qpnp-revid";
 			reg = <0x100 0x100>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 800cd8f..c303061 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -89,6 +89,28 @@
 	};
 
 	sound {
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"AMIC1", "MIC BIAS1 Internal1",
+			"MIC BIAS1 Internal1", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic",
+			"DMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic1",
+			"DMIC2", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic2",
+			"DMIC3", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic3",
+			"DMIC4", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic4";
+
 		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
 		qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
 	};
diff --git a/arch/arm/boot/dts/msm8226-gpu.dtsi b/arch/arm/boot/dts/msm8226-gpu.dtsi
index 2734726..ebd7749 100644
--- a/arch/arm/boot/dts/msm8226-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8226-gpu.dtsi
@@ -24,9 +24,9 @@
 	qcom,msm-bus,num-paths = <2>;
 	qcom,msm-bus,vectors-KBps =
 			<26 512 0 0>, <89 604 0 0>,
-			<26 512 0 1600000>, <89 604 0 6400000>,
-			<26 512 0 3200000>, <89 604 0 12800000>,
-			<26 512 0 4264000>, <89 604 0 12800000>;
+			<26 512 0 1600000>, <89 604 0 3200000>,
+			<26 512 0 3200000>, <89 604 0 5120000>,
+			<26 512 0 4256000>, <89 604 0 6400000>;
 
 	/* GDSC oxili regulators */
 	vddcx-supply = "\0";
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 3d1fe19..a18bad3 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -89,6 +89,20 @@
 	};
 
 	sound {
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"AMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS1 External",
+			"MIC BIAS1 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic";
+
 		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
 		qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
 	};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index 4fa37d6..e137ee2 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -89,6 +89,20 @@
 	};
 
 	sound {
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"AMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS1 External",
+			"MIC BIAS1 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic";
+
 		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
 		qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
 	};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index c39d987..448a5be 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -10,18 +10,16 @@
  * GNU General Public License for more details.
  */
 
-/* QPNP controlled regulators: */
+/* SPM controlled regulators: */
 
 &spmi_bus {
 	qcom,pm8226@1 {
-		pm8226_s2: regulator@1700 {
-			status = "okay";
+		pm8226_s2: spm-regulator@1700 {
+			compatible = "qcom,spm-regulator";
 			regulator-name = "8226_s2";
-			qcom,enable-time = <500>;
-			qcom,system-load = <100000>;
-			regulator-min-microvolt = <1050000>;
-			regulator-max-microvolt = <1150000>;
-			regulator-always-on;
+			reg = <0x1700 0x100>;
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <1275000>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 5239f24..5f51520 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -227,29 +227,6 @@
 	sound {
 		compatible = "qcom,msm8226-audio-tapan";
 		qcom,model = "msm8226-tapan-snd-card";
-
-		qcom,audio-routing =
-			"RX_BIAS", "MCLK",
-			"LDO_H", "MCLK",
-			"SPK_OUT", "MCLK",
-			"SPK_OUT", "EXT_VDD_SPKR",
-			"AMIC1", "MIC BIAS1 Internal1",
-			"MIC BIAS1 Internal1", "Handset Mic",
-			"AMIC2", "MIC BIAS2 External",
-			"MIC BIAS2 External", "Headset Mic",
-			"AMIC3", "MIC BIAS2 External",
-			"MIC BIAS2 External", "ANCRight Headset Mic",
-			"AMIC4", "MIC BIAS2 External",
-			"MIC BIAS2 External", "ANCLeft Headset Mic",
-			"DMIC1", "MIC BIAS1 External",
-			"MIC BIAS1 External", "Digital Mic1",
-			"DMIC2", "MIC BIAS1 External",
-			"MIC BIAS1 External", "Digital Mic2",
-			"DMIC3", "MIC BIAS3 External",
-			"MIC BIAS3 External", "Digital Mic3",
-			"DMIC4", "MIC BIAS3 External",
-			"MIC BIAS3 External", "Digital Mic4";
-
 		qcom,tapan-mclk-clk-freq = <9600000>;
 	};
 
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
new file mode 100644
index 0000000..390c02a
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2013, The Linux Foundation. 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8610 CDP";
+	compatible = "qcom,msm8610-cdp", "qcom,msm8610";
+	qcom,msm-id = <147 1 0>;
+
+	serial@f991f000 {
+		status = "ok";
+	};
+};
+
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
new file mode 100644
index 0000000..70ac0e8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2013, The Linux Foundation. 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8610 MTP";
+	compatible = "qcom,msm8610-mtp", "qcom,msm8610";
+	qcom,msm-id = <147 8 0>;
+
+	serial@f991f000 {
+		status = "ok";
+	};
+};
+
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 53d0d5d..b6a6c74 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -429,6 +429,28 @@
 		compatible = "qcom,msm-pcm-hostless";
 	};
 
+	qcom,mss@fc880000 {
+		compatible = "qcom,pil-q6v5-mss";
+		reg = <0xfc880000 0x100>,
+		      <0xfd485000 0x400>,
+		      <0xfc820000 0x020>,
+		      <0xfc401680 0x004>,
+		      <0x0d1fc000 0x4000>,
+		      <0xfd485194 0x4>;
+		reg-names = "qdsp6_base", "halt_base", "rmb_base",
+			    "restart_reg", "metadata_base", "cxrail_bhs_reg";
+
+		interrupts = <0 24 1>;
+		vdd_mss-supply = <&pm8110_s1>;
+		vdd_cx-supply = <&pm8110_s1_corner>;
+		vdd_mx-supply = <&pm8110_l3>;
+		vdd_pll-supply = <&pm8110_l10>;
+		qcom,vdd_pll = <1800000>;
+		qcom,is-loadable;
+		qcom,firmware-name = "mba";
+		qcom,pil-self-auth;
+	};
+
 	qcom,lpass@fe200000 {
 		compatible = "qcom,pil-q6v5-lpass";
 		reg = <0xfe200000 0x00100>,
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
index 15a549c..3fb5b20 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
@@ -15,7 +15,7 @@
 
 	actuator0: qcom,actuator@18 {
 		cell-index = <0>;
-		reg = <0x18 0x0>;
+		reg = <0x18>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
@@ -27,6 +27,7 @@
 		qcom,csiphy-sd-index = <0>;
 		qcom,csid-sd-index = <0>;
 		qcom,actuator-src = <&actuator0>;
+		qcom,led-flash-src = <&led_flash0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "s5k3l1yx";
 		cam_vdig-supply = <&pm8941_l3>;
@@ -136,7 +137,7 @@
 
 	qcom,camera@90 {
 		compatible = "qcom,mt9m114";
-		reg = <0x90 0x0>;
+		reg = <0x90>;
 		qcom,slave-id = <0x90 0x0 0x2481>;
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 1a57534..9d98476 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -617,6 +617,55 @@
 	};
 };
 
+/* CoreSight */
+&tpiu {
+	qcom,seta-gpios = <&msmgpio 31 0>,
+			  <&msmgpio 32 0>,
+			  <&msmgpio 33 0>,
+			  <&msmgpio 34 0>,
+			  <&msmgpio 35 0>,
+			  <&msmgpio 36 0>,
+			  <&msmgpio 37 0>,
+			  <&msmgpio 38 0>,
+			  <&msmgpio 39 0>,
+			  <&msmgpio 40 0>,
+			  <&msmgpio 41 0>,
+			  <&msmgpio 42 0>,
+			  <&msmgpio 43 0>,
+			  <&msmgpio 44 0>,
+			  <&msmgpio 45 0>,
+			  <&msmgpio 46 0>,
+			  <&msmgpio 47 0>,
+			  <&msmgpio 48 0>;
+	qcom,seta-gpios-func = <4 4 4 3 4 4 4 3 4 3 5 5 5 5 4 4 5 5>;
+	qcom,seta-gpios-drv =  <7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7>;
+	qcom,seta-gpios-pull = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>;
+	qcom,seta-gpios-dir =  <2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2>;
+
+	qcom,setb-gpios = <&msmgpio 15 0>,
+			  <&msmgpio 16 0>,
+			  <&msmgpio 17 0>,
+			  <&msmgpio 18 0>,
+			  <&msmgpio 19 0>,
+			  <&msmgpio 20 0>,
+			  <&msmgpio 21 0>,
+			  <&msmgpio 22 0>,
+			  <&msmgpio 23 0>,
+			  <&msmgpio 24 0>,
+			  <&msmgpio 25 0>,
+			  <&msmgpio 26 0>,
+			  <&msmgpio 27 0>,
+			  <&msmgpio 28 0>,
+			  <&msmgpio 89 0>,
+			  <&msmgpio 90 0>,
+			  <&msmgpio 91 0>,
+			  <&msmgpio 92 0>;
+	qcom,setb-gpios-func = <2 2 2 2 5 5 5 5 6 6 6 7 7 5 2 3 3 3>;
+	qcom,setb-gpios-drv =  <7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7>;
+	qcom,setb-gpios-pull = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>;
+	qcom,setb-gpios-dir =  <2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2>;
+};
+
 &slim_msm {
 	taiko_codec {
 		qcom,cdc-micbias1-ext-cap;
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index e325693..c064b59 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -34,6 +34,11 @@
 		coresight-id = <1>;
 		coresight-name = "coresight-tpiu";
 		coresight-nr-inports = <1>;
+
+		vdd-supply = <&pm8941_l21>;
+
+		qcom,vdd-voltage-level = <2950000 2950000>;
+		qcom,vdd-current-level = <9000 800000>;
 	};
 
 	replicator: replicator@fc31c000 {
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index b1f39d1..31afd9c 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -20,6 +20,10 @@
 			reg = <30>;
 		};
 
+		qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+			reg = <21>;
+		};
+
 		qcom,ion-heap@8 { /* CP_MM HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <8>;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 5eff79c..b125138 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -93,6 +93,15 @@
 			qcom,use-voltage-corner;
 			compatible = "qcom,rpm-regulator-smd";
 		};
+		pm8841_s2_floor_corner: regulator-s2-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8841_s2_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
 	};
 
 	rpm-regulator-smpb3 {
@@ -121,6 +130,15 @@
 			regulator-max-microvolt = <7>;
 			qcom,init-voltage-corner = <3>; /* SVS SOC */
 		};
+		pm8841_s4_floor_corner: regulator-s4-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8841_s4_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
 	};
 
 	rpm-regulator-smpa1 {
diff --git a/arch/arm/boot/dts/msm9625-v1-cdp.dts b/arch/arm/boot/dts/msm9625-v1-cdp.dts
index 6221ba1..cc7a758 100644
--- a/arch/arm/boot/dts/msm9625-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-cdp.dts
@@ -45,7 +45,15 @@
 		compatible = "qca,ar6004-sdio";
 		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
 		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
-		qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+		qca,vdd-io-supply = <&pm8019_l11>;
+	};
+
+	qca,wlan_ar6003 {
+		cell-index = <0>;
+		compatible = "qca,ar6003-sdio";
+		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+		qca,vdd-io-supply = <&pm8019_l11>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm9625-v1-mtp.dts b/arch/arm/boot/dts/msm9625-v1-mtp.dts
index 5ff9e92..d78bb77 100644
--- a/arch/arm/boot/dts/msm9625-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-mtp.dts
@@ -45,7 +45,15 @@
 		compatible = "qca,ar6004-sdio";
 		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
 		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
-		qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+		qca,vdd-io-supply = <&pm8019_l11>;
+	};
+
+	qca,wlan_ar6003 {
+		cell-index = <0>;
+		compatible = "qca,ar6003-sdio";
+		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+		qca,vdd-io-supply = <&pm8019_l11>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm9625-v2-cdp.dts b/arch/arm/boot/dts/msm9625-v2-cdp.dts
index 919c6d5..94fe019 100644
--- a/arch/arm/boot/dts/msm9625-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-cdp.dts
@@ -47,7 +47,15 @@
 		compatible = "qca,ar6004-hsic";
 		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
 		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
-		qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+		qca,vdd-io-supply = <&pm8019_l11>;
+	};
+
+	qca,wlan_ar6003 {
+		cell-index = <0>;
+		compatible = "qca,ar6003-sdio";
+		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+		qca,vdd-io-supply = <&pm8019_l11>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm9625-v2-mtp.dts b/arch/arm/boot/dts/msm9625-v2-mtp.dts
index 7949080..2840024 100644
--- a/arch/arm/boot/dts/msm9625-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-mtp.dts
@@ -45,7 +45,15 @@
 		compatible = "qca,ar6004-hsic";
 		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
 		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
-		qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+		qca,vdd-io-supply = <&pm8019_l11>;
+	};
+
+	qca,wlan_ar6003 {
+		cell-index = <0>;
+		compatible = "qca,ar6003-sdio";
+		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+		qca,vdd-io-supply = <&pm8019_l11>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 9172029..b06419d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -140,31 +140,27 @@
 
 		qcom,pipe0 {
 			label = "hsusb-ipa-out-0";
-			qcom,usb-bam-mem-type = <0>;
+			qcom,usb-bam-mem-type = <2>;
 			qcom,bam-type = <1>;
 			qcom,dir = <0>;
 			qcom,pipe-num = <0>;
 			qcom,peer-bam = <2>;
 			qcom,src-bam-physical-address = <0xf9a44000>;
 			qcom,src-bam-pipe-index = <1>;
-			qcom,data-fifo-offset = <0x2200>;
-			qcom,data-fifo-size = <0x1e00>;
-			qcom,descriptor-fifo-offset = <0x2100>;
-			qcom,descriptor-fifo-size = <0x100>;
+			qcom,data-fifo-size = <0x8000>;
+			qcom,descriptor-fifo-size = <0x2000>;
 		};
 		qcom,pipe1 {
 			label = "hsusb-ipa-in-0";
-			qcom,usb-bam-mem-type = <0>;
+			qcom,usb-bam-mem-type = <2>;
 			qcom,bam-type = <1>;
 			qcom,dir = <1>;
 			qcom,pipe-num = <0>;
 			qcom,peer-bam = <2>;
 			qcom,dst-bam-physical-address = <0xf9a44000>;
 			qcom,dst-bam-pipe-index = <0>;
-			qcom,data-fifo-offset = <0x300>;
-			qcom,data-fifo-size = <0x1e00>;
-			qcom,descriptor-fifo-offset = <0>;
-			qcom,descriptor-fifo-size = <0x300>;
+			qcom,data-fifo-size = <0x8000>;
+			qcom,descriptor-fifo-size = <0x2000>;
 		};
 		qcom,pipe2 {
 			label = "hsusb-qdss-in-0";
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 663e937..d2c97b1 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -226,6 +226,8 @@
 CONFIG_BT_BNEP_PROTO_FILTER=y
 CONFIG_BT_HIDP=y
 CONFIG_BT_HCISMD=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_ATH3K=y
 CONFIG_MSM_BT_POWER=y
 CONFIG_CFG80211=y
 CONFIG_NL80211_TESTMODE=y
@@ -292,6 +294,7 @@
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
 CONFIG_QPNP_REVID=y
+CONFIG_QPNP_MISC=y
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 2de81d4d1..c9d6112 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -230,6 +230,8 @@
 CONFIG_BT_BNEP_PROTO_FILTER=y
 CONFIG_BT_HIDP=y
 CONFIG_BT_HCISMD=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_ATH3K=y
 CONFIG_MSM_BT_POWER=y
 CONFIG_CFG80211=y
 CONFIG_NL80211_TESTMODE=y
@@ -297,6 +299,7 @@
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
 CONFIG_QPNP_REVID=y
+CONFIG_QPNP_MISC=y
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 048e191..18b1c5a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -428,6 +428,7 @@
 	select ARM_HAS_SG_CHAIN
 	select REGULATOR
 	select MSM_RPM_REGULATOR_SMD
+	select MSM_SPM_REGULATOR
 
 config ARCH_MSM8226
 	bool "MSM8226"
@@ -463,6 +464,7 @@
 	select ARM_HAS_SG_CHAIN
 	select REGULATOR
 	select MSM_RPM_REGULATOR_SMD
+	select MSM_SPM_REGULATOR
 	select MSM_JTAG_MM if CORESIGHT_ETM
 endmenu
 
@@ -1823,7 +1825,6 @@
 config MSM_HW3D
 	tristate "MSM Hardware 3D Register Driver"
 	depends on ANDROID_PMEM
-	default y
 	help
 	  Provides access to registers needed by the userspace OpenGL|ES
 	  library.
@@ -2062,6 +2063,16 @@
 	  be used on systems which contain an RPM which communicates with the
 	  application processor over SMD.
 
+config MSM_SPM_REGULATOR
+	bool "SPM regulator driver"
+	depends on REGULATOR && SPMI && OF_SPMI
+	help
+	  Enable support for the SPM regulator driver which is used for
+	  setting voltages of processor supply regulators via the SPM module
+	  found inside of the MSM chips.  The SPM regulator driver can be used
+	  on MSM systems where the APSS processor cores are supplied by their
+	  own PMIC regulator.
+
 config MSM_SMCMOD
 	tristate "Secure Monitor Call (SMC) Module"
 	default n
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f7b6503..d3acbc7 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -210,6 +210,7 @@
 endif
 
 obj-$(CONFIG_MSM_RPM_REGULATOR_SMD) += rpm-regulator-smd.o
+obj-$(CONFIG_MSM_SPM_REGULATOR) += spm-regulator.o
 
 ifdef CONFIG_MSM_SUBSYSTEM_RESTART
 	obj-y += subsystem_notif.o
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index fcbd74d..73ea435 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -57,7 +57,7 @@
 	{ 1,  300000, PLL0,    4, 2,   1150000,   1150000, 4 },
 	{ 1,  384000, ACPUPLL, 5, 0,   1150000,   1150000, 4 },
 	{ 1,  600000, PLL0,    4, 0,   1150000,   1150000, 6 },
-	{ 1,  787200, ACPUPLL, 5, 0,   1150000,   1150000, 6 },
+	{ 1,  787200, ACPUPLL, 5, 0,   1150000,   1150000, 7 },
 	{ 0,  998400, ACPUPLL, 5, 0,   1150000,   1150000, 7 },
 	{ 0, 1190400, ACPUPLL, 5, 0,   1150000,   1150000, 7 },
 	{ 0 }
diff --git a/arch/arm/mach-msm/audio-7627a-devices.c b/arch/arm/mach-msm/audio-7627a-devices.c
index 61d06e7..95727de 100644
--- a/arch/arm/mach-msm/audio-7627a-devices.c
+++ b/arch/arm/mach-msm/audio-7627a-devices.c
@@ -13,7 +13,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/android_pmem.h>
 #include <mach/board.h>
 
 #include "board-msm7627a.h"
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index dcab9ca..872fabe 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -24,9 +24,6 @@
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/memory.h>
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
 #include <linux/regulator/qpnp-regulator.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/gic.h>
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 74ed119..e624e3f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -20,9 +20,6 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/memory.h>
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
 #include <linux/regulator/machine.h>
 #include <linux/regulator/krait-regulator.h>
 #include <linux/msm_thermal.h>
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 5f0d75f..cca38b0 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -54,7 +54,6 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/i2c.h>
-#include <linux/android_pmem.h>
 #include <mach/camera.h>
 
 #ifdef CONFIG_USB_G_ANDROID
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 0654a0d..be3c1a3 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -39,7 +39,6 @@
 #include <linux/msm_adc.h>
 #include <linux/dma-mapping.h>
 #include <linux/regulator/consumer.h>
-
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
@@ -54,7 +53,6 @@
 #include <mach/msm_spi.h>
 #include <mach/qdsp5v2/msm_lpa.h>
 #include <mach/dma.h>
-#include <linux/android_pmem.h>
 #include <linux/input/msm_ts.h>
 #include <mach/pmic.h>
 #include <mach/rpc_pmapp.h>
@@ -3531,19 +3529,6 @@
 }
 #endif
 
-static struct android_pmem_platform_data android_pmem_pdata = {
-	.name = "pmem",
-	.allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI0,
-};
-
-static struct platform_device android_pmem_device = {
-	.name = "android_pmem",
-	.id = 0,
-	.dev = { .platform_data = &android_pmem_pdata },
-};
-
 #ifndef CONFIG_SPI_QSD
 static int lcdc_gpio_array_num[] = {
 				45, /* spi_clk */
@@ -4021,32 +4006,6 @@
 	.id     = -1,
 };
 
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
-       .name = "pmem_adsp",
-       .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-       .cached = 0,
-	.memory_type = MEMTYPE_EBI0,
-};
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
-       .name = "pmem_audio",
-       .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-       .cached = 0,
-	.memory_type = MEMTYPE_EBI0,
-};
-
-static struct platform_device android_pmem_adsp_device = {
-       .name = "android_pmem",
-       .id = 2,
-       .dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-static struct platform_device android_pmem_audio_device = {
-       .name = "android_pmem",
-       .id = 4,
-       .dev = { .platform_data = &android_pmem_audio_pdata },
-};
-
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
 		defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -5395,7 +5354,6 @@
 #ifdef CONFIG_I2C_SSBI
 	&msm_device_ssbi7,
 #endif
-	&android_pmem_device,
 	&msm_fb_device,
 #ifdef CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE
 	&msm_v4l2_video_overlay_device,
@@ -5407,8 +5365,6 @@
 	&msm_rotator_device,
 #endif
 	&lcdc_sharp_panel_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
 	&msm_device_i2c,
 	&msm_device_i2c_2,
 	&msm_device_uart_dm1,
@@ -7234,39 +7190,6 @@
 #endif
 }
 
-static void __init size_pmem_devices(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-
-	android_pmem_adsp_pdata.size = size;
-	android_pmem_audio_pdata.size = pmem_audio_size;
-	android_pmem_pdata.size = pmem_sf_size;
-#endif
-#endif
-}
-
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
-	msm7x30_reserve_table[p->memory_type].size += p->size;
-}
-#endif
-#endif
-
-static void __init reserve_pmem_memory(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	reserve_memory_for(&android_pmem_adsp_pdata);
-	reserve_memory_for(&android_pmem_audio_pdata);
-	reserve_memory_for(&android_pmem_pdata);
-	msm7x30_reserve_table[MEMTYPE_EBI0].size += pmem_kernel_ebi0_size;
-#endif
-#endif
-}
-
 static void __init reserve_mdp_memory(void)
 {
 	mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
@@ -7294,8 +7217,6 @@
 static void __init msm7x30_calculate_reserve_sizes(void)
 {
 	fix_sizes();
-	size_pmem_devices();
-	reserve_pmem_memory();
 	reserve_mdp_memory();
 	size_ion_devices();
 	reserve_ion_memory();
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 02a753a..6b98393 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -41,10 +41,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/i2c/bq27520.h>
 
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
-
 #if defined(CONFIG_SMB137B_CHARGER) || defined(CONFIG_SMB137B_CHARGER_MODULE)
 #include <linux/i2c/smb137b.h>
 #endif
@@ -2808,47 +2804,6 @@
 	.dev.platform_data = &msm_fb_pdata,
 };
 
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct android_pmem_platform_data android_pmem_pdata = {
-	.name = "pmem",
-	.allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_device = {
-	.name = "android_pmem",
-	.id = 0,
-	.dev = {.platform_data = &android_pmem_pdata},
-};
-
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
-	.name = "pmem_adsp",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 0,
-	.memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_adsp_device = {
-	.name = "android_pmem",
-	.id = 2,
-	.dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
-	.name = "pmem_audio",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 0,
-	.memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_audio_device = {
-	.name = "android_pmem",
-	.id = 4,
-	.dev = { .platform_data = &android_pmem_audio_pdata },
-};
-#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
 #define PMEM_BUS_WIDTH(_bw) \
 	{ \
 		.vectors = &(struct msm_bus_vectors){ \
@@ -2891,6 +2846,49 @@
 {
 	return (void *)msm_bus_scale_register_client(&smi_client_pdata);
 }
+
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+static struct android_pmem_platform_data android_pmem_pdata = {
+	.name = "pmem",
+	.allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
+	.cached = 1,
+	.memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_device = {
+	.name = "android_pmem",
+	.id = 0,
+	.dev = {.platform_data = &android_pmem_pdata},
+};
+
+static struct android_pmem_platform_data android_pmem_adsp_pdata = {
+	.name = "pmem_adsp",
+	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+	.cached = 0,
+	.memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_adsp_device = {
+	.name = "android_pmem",
+	.id = 2,
+	.dev = { .platform_data = &android_pmem_adsp_pdata },
+};
+
+static struct android_pmem_platform_data android_pmem_audio_pdata = {
+	.name = "pmem_audio",
+	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+	.cached = 0,
+	.memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_audio_device = {
+	.name = "android_pmem",
+	.id = 4,
+	.dev = { .platform_data = &android_pmem_audio_pdata },
+};
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
 static struct android_pmem_platform_data android_pmem_smipool_pdata = {
 	.name = "pmem_smipool",
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index cc478da..a690033 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -169,22 +169,14 @@
 	VDD_DIG_NUM
 };
 
-static const int vdd_corner[] = {
-	[VDD_DIG_NONE]	  = RPM_REGULATOR_CORNER_NONE,
-	[VDD_DIG_LOW]	  = RPM_REGULATOR_CORNER_SVS_SOC,
-	[VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
-	[VDD_DIG_HIGH]	  = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
-	return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
-					RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
 
 #define RPM_MISC_CLK_TYPE	0x306b6c63
 #define RPM_BUS_CLK_TYPE	0x316b6c63
@@ -2760,19 +2752,12 @@
 	VDD_SR2_PLL_NUM
 };
 
-static struct regulator *vdd_sr2_reg;
-static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
-{
-	if (level == VDD_SR2_PLL_ON) {
-		return regulator_set_voltage(vdd_sr2_reg, 1800000,
-		1800000);
-	} else {
-		return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
-	}
-}
+static const int *vdd_sr2_levels[] = {
+	[VDD_SR2_PLL_OFF] = VDD_UV(0),
+	[VDD_SR2_PLL_ON]  = VDD_UV(1800000),
+};
 
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
-			VDD_SR2_PLL_NUM);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1, vdd_sr2_levels);
 
 static struct pll_freq_tbl apcs_pll_freq[] = {
 	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -3511,23 +3496,23 @@
 
 	clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
 
-	vdd_dig_reg = regulator_get(NULL, "vdd_dig");
-	if (IS_ERR(vdd_dig_reg))
+	vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+	if (IS_ERR(vdd_dig.regulator[0]))
 		panic("clock-8226: Unable to get the vdd_dig regulator!");
 
-	vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
-	if (IS_ERR(vdd_dig_reg))
+	vdd_sr2_pll.regulator[0] = regulator_get(NULL, "vdd_sr2_pll");
+	if (IS_ERR(vdd_sr2_pll.regulator[0]))
 		panic("clock-8226: Unable to get the sr2_pll regulator!");
 
 	/*
 	 * These regulators are used at boot. Ensure they stay on
 	 * while the clock framework comes online.
 	 */
-	regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
-	regulator_enable(vdd_sr2_reg);
+	regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+	regulator_enable(vdd_sr2_pll.regulator[0]);
 
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig_reg);
+	regulator_enable(vdd_dig.regulator[0]);
 
 	/*
 	 * Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index c517c10..930f9e3 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -445,22 +445,14 @@
 	VDD_DIG_NUM
 };
 
-static const int vdd_corner[] = {
-	[VDD_DIG_NONE]	  = RPM_REGULATOR_CORNER_NONE,
-	[VDD_DIG_LOW]	  = RPM_REGULATOR_CORNER_SVS_SOC,
-	[VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
-	[VDD_DIG_HIGH]	  = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
-	return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
-					RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
 
 #define RPM_MISC_CLK_TYPE	0x306b6c63
 #define RPM_BUS_CLK_TYPE	0x316b6c63
@@ -550,20 +542,13 @@
 	VDD_SR2_PLL_NUM
 };
 
-static struct regulator *vdd_sr2_reg;
+static const int *vdd_sr2_pll_levels[] = {
+	[VDD_SR2_PLL_OFF] = VDD_UV(0),
+	[VDD_SR2_PLL_ON]  = VDD_UV(1800000),
+};
 
-static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
-{
-	if (level == VDD_SR2_PLL_ON) {
-		return regulator_set_voltage(vdd_sr2_reg, 1800000,
-		1800000);
-	} else {
-		return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
-	}
-}
-
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
-			VDD_SR2_PLL_NUM);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1,
+		vdd_sr2_pll_levels);
 
 static struct pll_freq_tbl apcs_pll_freq[] = {
 	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -3546,16 +3531,16 @@
 
 	clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
 
-	vdd_dig_reg = regulator_get(NULL, "vdd_dig");
-	if (IS_ERR(vdd_dig_reg))
+	vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+	if (IS_ERR(vdd_dig.regulator[0]))
 		panic("clock-8610: Unable to get the vdd_dig regulator!");
 
-	vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
-	if (IS_ERR(vdd_sr2_reg))
+	vdd_sr2_pll.regulator[0] = regulator_get(NULL, "vdd_sr2_pll");
+	if (IS_ERR(vdd_sr2_pll.regulator[0]))
 		panic("clock-8610: Unable to get the vdd_sr2_pll regulator!");
 
-	regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
-	regulator_enable(vdd_sr2_reg);
+	regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+	regulator_enable(vdd_sr2_pll.regulator[0]);
 
 	/*
 	 * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
@@ -3564,7 +3549,7 @@
 	 * its necessity.
 	 */
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig_reg);
+	regulator_enable(vdd_dig.regulator[0]);
 
 	enable_rpm_scaling();
 
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e9824a6..e040d7f 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -638,22 +638,14 @@
 	VDD_DIG_NUM
 };
 
-static const int vdd_corner[] = {
-	[VDD_DIG_NONE]	  = RPM_REGULATOR_CORNER_NONE,
-	[VDD_DIG_LOW]	  = RPM_REGULATOR_CORNER_SVS_SOC,
-	[VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
-	[VDD_DIG_HIGH]	  = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
-	return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
-					RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
 
 #define RPM_MISC_CLK_TYPE	0x306b6c63
 #define RPM_BUS_CLK_TYPE	0x316b6c63
@@ -5490,8 +5482,8 @@
 
 	clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
 
-	vdd_dig_reg = regulator_get(NULL, "vdd_dig");
-	if (IS_ERR(vdd_dig_reg))
+	vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+	if (IS_ERR(vdd_dig.regulator[0]))
 		panic("clock-8974: Unable to get the vdd_dig regulator!");
 
 	/*
@@ -5501,7 +5493,7 @@
 	 * its necessity.
 	 */
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig_reg);
+	regulator_enable(vdd_dig.regulator[0]);
 
 	enable_rpm_scaling();
 
@@ -5556,8 +5548,8 @@
 	sdcc3_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
 	sdcc4_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
 
-	vdd_dig_reg = regulator_get(NULL, "vdd_dig");
-	if (IS_ERR(vdd_dig_reg))
+	vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+	if (IS_ERR(vdd_dig.regulator[0]))
 		panic("clock-8974: Unable to get the vdd_dig regulator!");
 
 	/*
@@ -5567,7 +5559,7 @@
 	 * its necessity.
 	 */
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig_reg);
+	regulator_enable(vdd_dig.regulator[0]);
 }
 
 struct clock_init_data msm8974_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 9648320..d8e4ed5 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -278,22 +278,14 @@
 	VDD_DIG_NUM
 };
 
-static const int vdd_corner[] = {
-	[VDD_DIG_NONE]	  = RPM_REGULATOR_CORNER_NONE,
-	[VDD_DIG_LOW]	  = RPM_REGULATOR_CORNER_SVS_SOC,
-	[VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
-	[VDD_DIG_HIGH]	  = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static struct regulator *vdd_dig_reg;
-
-int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
-	return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
-					RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
 
 /* TODO: Needs to confirm the below values */
 #define RPM_MISC_CLK_TYPE	0x306b6c63
@@ -344,6 +336,7 @@
 
 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),
 	.soft_vote = &soft_vote_gpll0,
@@ -360,6 +353,7 @@
 
 static struct pll_vote_clk gpll0_activeonly_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),
 	.soft_vote = &soft_vote_gpll0,
@@ -2060,12 +2054,12 @@
 
 	clk_ops_local_pll.enable = sr_pll_clk_enable_9625;
 
-	vdd_dig_reg = regulator_get(NULL, "vdd_dig");
-	if (IS_ERR(vdd_dig_reg))
+	vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+	if (IS_ERR(vdd_dig.regulator[0]))
 		panic("clock-9625: Unable to get the vdd_dig regulator!");
 
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig_reg);
+	regulator_enable(vdd_dig.regulator[0]);
 
 	enable_rpm_scaling();
 
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index e0ee084..ecd25fc 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -22,6 +22,7 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/list.h>
+#include <linux/regulator/consumer.h>
 #include <trace/events/power.h>
 #include <mach/clk-provider.h>
 #include "clock.h"
@@ -53,20 +54,39 @@
 /* Update voltage level given the current votes. */
 static int update_vdd(struct clk_vdd_class *vdd_class)
 {
-	int level, rc;
+	int level, rc = 0, i;
+	struct regulator **r = vdd_class->regulator;
+	const int **vdd_uv = vdd_class->vdd_uv;
+	int max_level = vdd_class->num_levels - 1;
 
-	for (level = vdd_class->num_levels-1; level > 0; level--)
+	for (level = max_level; level > 0; level--)
 		if (vdd_class->level_votes[level])
 			break;
 
 	if (level == vdd_class->cur_level)
 		return 0;
 
-	rc = vdd_class->set_vdd(vdd_class, level);
+	for (i = 0; i < vdd_class->num_regulators; i++) {
+		rc = regulator_set_voltage(r[i], vdd_uv[level][i],
+			vdd_uv[max_level][i]);
+		if (rc)
+			goto set_voltage_fail;
+	}
+	if (vdd_class->set_vdd && !vdd_class->num_regulators)
+		rc = vdd_class->set_vdd(vdd_class, level);
+
 	if (!rc)
 		vdd_class->cur_level = level;
 
 	return rc;
+
+set_voltage_fail:
+	level = vdd_class->cur_level;
+	for (i--; i >= 0; i--)
+		regulator_set_voltage(r[i], vdd_uv[level][i],
+			vdd_uv[max_level][i]);
+
+	return rc;
 }
 
 /* Vote for a voltage level. */
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 2bd9dfe..24b579f 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -21,7 +21,6 @@
 #include <asm/clkdev.h>
 #include <mach/gpio.h>
 #include <mach/kgsl.h>
-#include <linux/android_pmem.h>
 #include <mach/irqs-8960.h>
 #include <mach/dma.h>
 #include <linux/dma-mapping.h>
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 5152918..397a9d4 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -18,7 +18,6 @@
 #include <linux/msm_rotator.h>
 #include <linux/dma-mapping.h>
 #include <mach/kgsl.h>
-#include <linux/android_pmem.h>
 #include <linux/regulator/machine.h>
 #include <linux/init.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index f9e7863..91a7394 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -45,7 +45,6 @@
 #ifdef CONFIG_MSM_DSPS
 #include <mach/msm_dsps.h>
 #endif
-#include <linux/android_pmem.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
 #include <mach/mdm.h>
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 53a6616..6240195 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -33,7 +33,7 @@
 
 /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
 #define EN_REST_WAIT_VAL	(0x2 << 20)
-#define EN_FEW_WAIT_VAL		(0x2 << 16)
+#define EN_FEW_WAIT_VAL		(0x8 << 16)
 #define CLK_DIS_WAIT_VAL	(0x2 << 12)
 
 #define TIMEOUT_US		10
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
index 4714210..1f7d56a 100644
--- a/arch/arm/mach-msm/gpiomux.c
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -13,7 +13,9 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/io.h>
 #include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
 
 struct msm_gpiomux_rec {
 	struct gpiomux_setting *sets[GPIOMUX_NSETTINGS];
@@ -121,6 +123,13 @@
 }
 EXPORT_SYMBOL(msm_gpiomux_put);
 
+void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val)
+{
+	writel_relaxed(val, MSM_TLMM_BASE + misc_reg);
+	/* ensure the write completes before returning */
+	mb();
+}
+
 int msm_gpiomux_init(size_t ngpio)
 {
 	if (!ngpio)
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 475b483..528e9d5 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -21,6 +21,7 @@
 #include <linux/clkdev.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
 #include <mach/clk.h>
 
 /*
@@ -42,14 +43,23 @@
 /**
  * struct clk_vdd_class - Voltage scaling class
  * @class_name: name of the class
- * @set_vdd: function to call when applying a new voltage setting
- * @level_votes: array of votes for each level
+ * @regulator: array of regulators.
+ * @num_regulators: size of regulator array. Standard regulator APIs will be
+			used if this field > 0.
+ * @set_vdd: function to call when applying a new voltage setting.
+ * @vdd_uv: sorted 2D array of legal voltage settings. Indexed by level, then
+		regulator.
+ * @level_votes: array of votes for each level.
+ * @num_levels: specifies the size of level_votes array.
  * @cur_level: the currently set voltage level
  * @lock: lock to protect this struct
  */
 struct clk_vdd_class {
 	const char *class_name;
+	struct regulator **regulator;
+	int num_regulators;
 	int (*set_vdd)(struct clk_vdd_class *v_class, int level);
+	const int **vdd_uv;
 	int *level_votes;
 	int num_levels;
 	unsigned long cur_level;
@@ -66,6 +76,20 @@
 		.lock = __MUTEX_INITIALIZER(_name.lock) \
 	}
 
+#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv) \
+	struct clk_vdd_class _name = { \
+		.class_name = #_name, \
+		.vdd_uv = _vdd_uv, \
+		.regulator = (struct regulator * [_num_regulators]) {}, \
+		.num_regulators = _num_regulators, \
+		.level_votes = (int [_num_levels]) {}, \
+		.num_levels = _num_levels, \
+		.cur_level = _num_levels, \
+		.lock = __MUTEX_INITIALIZER(_name.lock) \
+	}
+
+#define VDD_UV(...) ((int []){__VA_ARGS__})
+
 enum handoff {
 	HANDOFF_ENABLED_CLK,
 	HANDOFF_DISABLED_CLK,
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
index 5ffcabb..9aae3fb 100644
--- a/arch/arm/mach-msm/include/mach/gpiomux.h
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -109,6 +109,14 @@
 	size_t                     ncfg;
 };
 
+/* Provide an enum and an API to write to misc TLMM registers */
+enum msm_tlmm_misc_reg {
+	TLMM_ETM_MODE_REG = 0x2014,
+	TLMM_SDC2_HDRV_PULL_CTL = 0x2048,
+};
+
+void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);
+
 #ifdef CONFIG_MSM_GPIOMUX
 
 /* Before using gpiomux, initialize the subsystem by telling it how many
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
index 2fdd99c..f460a4e 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
@@ -28,12 +28,6 @@
 #define MPQ8092_QGIC_DIST_PHYS	0xF9000000
 #define MPQ8092_QGIC_DIST_SIZE	SZ_4K
 
-#define MPQ8092_QGIC_CPU_PHYS	0xF9002000
-#define MPQ8092_QGIC_CPU_SIZE	SZ_4K
-
-#define MPQ8092_APCS_GCC_PHYS	0xF9011000
-#define MPQ8092_APCS_GCC_SIZE	SZ_4K
-
 #define MPQ8092_TLMM_PHYS	0xFD510000
 #define MPQ8092_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
index 81b3c48..ac3e912 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
@@ -28,9 +28,6 @@
 #define MSM8226_QGIC_DIST_PHYS	0xF9000000
 #define MSM8226_QGIC_DIST_SIZE	SZ_4K
 
-#define MSM8226_QGIC_CPU_PHYS	0xF9002000
-#define MSM8226_QGIC_CPU_SIZE	SZ_4K
-
 #define MSM8226_APCS_GCC_PHYS	0xF9011000
 #define MSM8226_APCS_GCC_SIZE	SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index 594b1cc..ec3c210 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -28,12 +28,6 @@
 #define MSM8974_QGIC_DIST_PHYS	0xF9000000
 #define MSM8974_QGIC_DIST_SIZE	SZ_4K
 
-#define MSM8974_QGIC_CPU_PHYS	0xF9002000
-#define MSM8974_QGIC_CPU_SIZE	SZ_4K
-
-#define MSM8974_APCS_GCC_PHYS	0xF9011000
-#define MSM8974_APCS_GCC_SIZE	SZ_4K
-
 #define MSM8974_TLMM_PHYS	0xFD510000
 #define MSM8974_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 341bbe3..9a8bfc1 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -28,12 +28,6 @@
 #define MSM9625_QGIC_DIST_PHYS	0xF9000000
 #define MSM9625_QGIC_DIST_SIZE	SZ_4K
 
-#define MSM9625_QGIC_CPU_PHYS	0xF9002000
-#define MSM9625_QGIC_CPU_SIZE	SZ_4K
-
-#define MSM9625_APCS_GCC_PHYS	0xF9011000
-#define MSM9625_APCS_GCC_SIZE	SZ_4K
-
 #define MSM9625_TMR_PHYS	0xF9021000
 #define MSM9625_TMR_SIZE	SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
index 8283622..0a33055 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
@@ -28,9 +28,6 @@
 #define MSMZINC_QGIC_DIST_PHYS	0xF9000000
 #define MSMZINC_QGIC_DIST_SIZE	SZ_4K
 
-#define MSMZINC_QGIC_CPU_PHYS	0xF9002000
-#define MSMZINC_QGIC_CPU_SIZE	SZ_4K
-
 #define MSMZINC_TLMM_PHYS	0xFD510000
 #define MSMZINC_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 9cf9517..d3706cd 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,15 +47,14 @@
 
 #define MSM8625_WARM_BOOT_PHYS  0x0FD00000
 
-
-#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
-	defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
-	defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM7X27) || \
-	defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
-	defined(CONFIG_ARCH_MSM8625) || defined(CONFIG_ARCH_MSM7X30) || \
-	defined(CONFIG_ARCH_MSM9625) || defined(CONFIG_ARCH_MPQ8092) || \
-	defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8610) || \
-	defined(CONFIG_ARCH_MSMZINC)
+/* Legacy single-target iomap */
+#if defined(CONFIG_ARCH_QSD8X50)
+#include "msm_iomap-8x50.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "msm_iomap-8x60.h"
+#elif defined(CONFIG_ARCH_FSM9XXX)
+#include "msm_iomap-fsm9xxx.h"
+#else
 
 /* Unified iomap */
 
@@ -136,18 +135,6 @@
 #include "msm_iomap-8226.h"
 #include "msm_iomap-8610.h"
 
-#else
-/* Legacy single-target iomap */
-#if defined(CONFIG_ARCH_QSD8X50)
-#include "msm_iomap-8x50.h"
-#elif defined(CONFIG_ARCH_MSM8X60)
-#include "msm_iomap-8x60.h"
-#elif defined(CONFIG_ARCH_FSM9XXX)
-#include "msm_iomap-fsm9xxx.h"
-#else
-#error "Target compiled without IO map\n"
-#endif
-
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index ff1b3c5..45f2646 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -74,6 +74,10 @@
 	of_machine_is_compatible("qcom,msm8610-sim")
 #define machine_is_msm8610_rumi()		\
 	of_machine_is_compatible("qcom,msm8610-rumi")
+#define machine_is_msm8610_mtp()		\
+	of_machine_is_compatible("qcom,msm8610-mtp")
+#define machine_is_msm8610_cdp()		\
+	of_machine_is_compatible("qcom,msm8610-cdp")
 #define early_machine_is_msmzinc()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzinc")
 #define machine_is_msmzinc_sim()		\
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index c71a79a..19c7acd 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -301,8 +301,6 @@
 #ifdef CONFIG_ARCH_MSM8974
 static struct map_desc msm_8974_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM8974),
-	MSM_CHIP_DEVICE(QGIC_CPU, MSM8974),
-	MSM_CHIP_DEVICE(APCS_GCC, MSM8974),
 	MSM_CHIP_DEVICE(TLMM, MSM8974),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8974),
 	{
@@ -326,7 +324,6 @@
 #ifdef CONFIG_ARCH_MSMZINC
 static struct map_desc msm_zinc_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSMZINC),
-	MSM_CHIP_DEVICE(QGIC_CPU, MSMZINC),
 	MSM_CHIP_DEVICE(TLMM, MSMZINC),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
@@ -488,9 +485,7 @@
 
 #ifdef CONFIG_ARCH_MSM9625
 static struct map_desc msm9625_io_desc[] __initdata = {
-	MSM_CHIP_DEVICE(APCS_GCC, MSM9625),
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM9625),
-	MSM_CHIP_DEVICE(QGIC_CPU, MSM9625),
 	MSM_CHIP_DEVICE(TLMM, MSM9625),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM9625),
 	MSM_CHIP_DEVICE(TMR, MSM9625),
@@ -515,8 +510,6 @@
 #ifdef CONFIG_ARCH_MPQ8092
 static struct map_desc mpq8092_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
-	MSM_CHIP_DEVICE(QGIC_CPU, MPQ8092),
-	MSM_CHIP_DEVICE(APCS_GCC, MPQ8092),
 	MSM_CHIP_DEVICE(TLMM, MPQ8092),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
@@ -538,7 +531,6 @@
 #ifdef CONFIG_ARCH_MSM8226
 static struct map_desc msm_8226_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM8226),
-	MSM_CHIP_DEVICE(QGIC_CPU, MSM8226),
 	MSM_CHIP_DEVICE(APCS_GCC, MSM8226),
 	MSM_CHIP_DEVICE(TLMM, MSM8226),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8226),
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 5f11806..edfb45b 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -34,7 +34,6 @@
 #include <linux/completion.h>
 #include <linux/err.h>
 #endif
-#include <linux/android_pmem.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
 #include <linux/sched.h>
@@ -191,6 +190,10 @@
 		BUG_ON(mr_candidate == NULL);
 		/* bump mt up against the top of the region */
 		mt->start = mr_candidate->base + mr_candidate->size - mt->size;
+		ret = memblock_reserve(mt->start, mt->size);
+		BUG_ON(ret);
+		ret = memblock_free(mt->start, mt->size);
+		BUG_ON(ret);
 		ret = memblock_remove(mt->start, mt->size);
 		BUG_ON(ret);
 	}
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 2ceb06d..599b24c 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -58,6 +58,7 @@
 #define RMB_PMI_CODE_LENGTH		0x18
 
 #define VDD_MSS_UV			1050000
+#define MAX_VDD_MSS_UV			1150000
 #define MAX_VDD_MX_UV			1150000
 
 #define PROXY_TIMEOUT_MS		10000
@@ -739,7 +740,7 @@
 	if (IS_ERR(q6->vreg_mx))
 		return PTR_ERR(q6->vreg_mx);
 
-	ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, VDD_MSS_UV);
+	ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, MAX_VDD_MSS_UV);
 	if (ret)
 		dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
 
diff --git a/arch/arm/mach-msm/qdsp5/adsp_driver.c b/arch/arm/mach-msm/qdsp5/adsp_driver.c
index d83a140..eb9c388 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_driver.c
@@ -25,7 +25,6 @@
 #include <linux/module.h>
 #include "adsp.h"
 #include <linux/msm_adsp.h>
-#include <linux/android_pmem.h>
 #include <mach/debug_mm.h>
 
 struct adsp_ion_info {
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index 4d03dca..62d6d58 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/android_pmem.h>
 
 #include <mach/qdsp5/qdsp5vdeccmdi.h>
 #include "adsp.h"
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
index 7819395..608f544 100644
--- a/arch/arm/mach-msm/qdsp5/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -16,7 +16,6 @@
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/uaccess.h>
@@ -110,7 +109,6 @@
 	audpp_cmd_cfg_object_params_eqalizer eq;
 	struct audrec_session_info session_info;
 	/*pmem info*/
-	int pmem_fd;
 	unsigned long paddr;
 	unsigned long kvaddr;
 	unsigned long pmem_len;
@@ -1136,7 +1134,6 @@
 {
 	int rc = 0;
 	unsigned long flags = 0;
-	struct msm_audio_pmem_info info;
 
 	MM_DBG("%s\n", __func__);
 
@@ -1156,23 +1153,6 @@
 			MM_ERR("AUDPP returned err =%d\n", rc);
 		spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
 		break;
-	case AUDIO_REGISTER_PMEM:
-		MM_DBG("AUDIO_REGISTER_PMEM\n");
-		if (copy_from_user(&info, (void *) arg, sizeof(info))) {
-			MM_ERR("Cannot copy from user\n");
-			return -EFAULT;
-		}
-		rc = get_pmem_file(info.fd, &acdb_data.paddr,
-					&acdb_data.kvaddr,
-					&acdb_data.pmem_len,
-					&acdb_data.file);
-		if (rc == 0)
-			acdb_data.pmem_fd = info.fd;
-		break;
-	case AUDIO_DEREGISTER_PMEM:
-		if (acdb_data.pmem_fd)
-			put_pmem_file(acdb_data.file);
-		break;
 	case AUDIO_SET_ACDB_BLK:
 		MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
 		rc = acdb_set_calibration_blk(arg);
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp_driver.c b/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
index 7249bb1..ad74ca3 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <linux/msm_adsp.h>
-#include <linux/android_pmem.h>
 #include <linux/export.h>
 #include "adsp.h"
 #include <mach/debug_mm.h>
@@ -87,71 +86,6 @@
 	res;							\
 })
 
-static int adsp_pmem_check(struct msm_adsp_module *module,
-		void *vaddr, unsigned long len)
-{
-	struct adsp_pmem_region *region_elt;
-	struct hlist_node *node;
-	struct adsp_pmem_region t = { .vaddr = vaddr, .len = len };
-
-	hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
-		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
-		    OVERLAPS(region_elt, &t)) {
-			MM_ERR("module %s:"
-				" region (vaddr %p len %ld)"
-				" clashes with registered region"
-				" (vaddr %p paddr %p len %ld)\n",
-				module->name,
-				vaddr, len,
-				region_elt->vaddr,
-				(void *)region_elt->paddr,
-				region_elt->len);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int adsp_pmem_add(struct msm_adsp_module *module,
-			 struct adsp_pmem_info *info)
-{
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct adsp_pmem_region *region;
-	int rc = -EINVAL;
-
-	mutex_lock(&module->pmem_regions_lock);
-	region = kmalloc(sizeof(*region), GFP_KERNEL);
-	if (!region) {
-		rc = -ENOMEM;
-		goto end;
-	}
-	INIT_HLIST_NODE(&region->list);
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
-		kfree(region);
-		goto end;
-	}
-
-	rc = adsp_pmem_check(module, info->vaddr, len);
-	if (rc < 0) {
-		put_pmem_file(file);
-		kfree(region);
-		goto end;
-	}
-
-	region->vaddr = info->vaddr;
-	region->paddr = paddr;
-	region->kvaddr = kvaddr;
-	region->len = len;
-	region->file = file;
-
-	hlist_add_head(&region->list, &module->pmem_regions);
-end:
-	mutex_unlock(&module->pmem_regions_lock);
-	return rc;
-}
-
 static int adsp_pmem_lookup_vaddr(struct msm_adsp_module *module, void **addr,
 		     unsigned long len, struct adsp_pmem_region **region)
 {
@@ -417,24 +351,6 @@
 	return rc;
 }
 
-static int adsp_pmem_del(struct msm_adsp_module *module)
-{
-	struct hlist_node *node, *tmp;
-	struct adsp_pmem_region *region;
-
-	mutex_lock(&module->pmem_regions_lock);
-	hlist_for_each_safe(node, tmp, &module->pmem_regions) {
-		region = hlist_entry(node, struct adsp_pmem_region, list);
-		hlist_del(node);
-		put_pmem_file(region->file);
-		kfree(region);
-	}
-	mutex_unlock(&module->pmem_regions_lock);
-	BUG_ON(!hlist_empty(&module->pmem_regions));
-
-	return 0;
-}
-
 static long adsp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct adsp_device *adev = filp->private_data;
@@ -466,21 +382,11 @@
 		return adsp_set_clkrate(adev->module, clk_rate);
 	}
 
-	case ADSP_IOCTL_REGISTER_PMEM: {
-		struct adsp_pmem_info info;
-		if (copy_from_user(&info, (void *) arg, sizeof(info)))
-			return -EFAULT;
-		return adsp_pmem_add(adev->module, &info);
-	}
-
 	case ADSP_IOCTL_ABORT_EVENT_READ:
 		adev->abort = 1;
 		wake_up(&adev->event_wait);
 		break;
 
-	case ADSP_IOCTL_UNREGISTER_PMEM:
-		return adsp_pmem_del(adev->module);
-
 	default:
 		break;
 	}
@@ -498,8 +404,6 @@
 	/* clear module before putting it to avoid race with open() */
 	adev->module = NULL;
 
-	rc = adsp_pmem_del(module);
-
 	msm_adsp_put(module);
 	return rc;
 }
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_aac.c b/arch/arm/mach-msm/qdsp5v2/audio_aac.c
index 883da2b..fbce5d6 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_aac.c
@@ -30,7 +30,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/msm_audio_aac.h>
 #include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c b/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
index a878e12..cf1f58d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
@@ -26,7 +26,6 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/msm_audio_aac.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <mach/msm_memtypes.h>
 
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_acdb.c b/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
index 5d7cfd7..85378be 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
@@ -16,7 +16,6 @@
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/uaccess.h>
@@ -1287,7 +1286,6 @@
 {
 	int rc = 0;
 	unsigned long flags = 0;
-	struct msm_audio_pmem_info info;
 
 	MM_DBG("%s\n", __func__);
 
@@ -1308,23 +1306,6 @@
 			MM_ERR("AUDPP returned err =%d\n", rc);
 		spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
 		break;
-	case AUDIO_REGISTER_PMEM:
-		MM_DBG("AUDIO_REGISTER_PMEM\n");
-		if (copy_from_user(&info, (void *) arg, sizeof(info))) {
-			MM_ERR("Cannot copy from user\n");
-			return -EFAULT;
-		}
-		rc = get_pmem_file(info.fd, &acdb_data.paddr,
-					&acdb_data.kvaddr,
-					&acdb_data.pmem_len,
-					&acdb_data.file);
-		if (rc == 0)
-			acdb_data.pmem_fd = info.fd;
-		break;
-	case AUDIO_DEREGISTER_PMEM:
-		if (acdb_data.pmem_fd)
-			put_pmem_file(acdb_data.file);
-		break;
 	case AUDIO_SET_ACDB_BLK:
 		MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
 		rc = acdb_set_calibration_blk(arg);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
index 7cc3e29..632aa0d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
@@ -34,7 +34,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
index c8b4171..bd4f6e1 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
@@ -37,7 +37,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
 #include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
index 66d0a9e..e5706c7 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
@@ -37,7 +37,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
 #include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
index 2d9327e..ed946f9 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
@@ -32,7 +32,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
 #include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_fm.c b/arch/arm/mach-msm/qdsp5v2/audio_fm.c
index cffa7e7..27548ac 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_fm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_fm.c
@@ -29,7 +29,6 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
-#include <linux/android_pmem.h>
 #include <linux/msm_audio.h>
 #include <asm/atomic.h>
 #include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
index 0390edf..bda2e4d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 #include <linux/earlysuspend.h>
 #include <linux/list.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
@@ -1095,103 +1094,6 @@
 	return rc;
 }
 
-static int audmp3_pmem_check(struct audio *audio,
-		void *vaddr, unsigned long len)
-{
-	struct audmp3_pmem_region *region_elt;
-	struct audmp3_pmem_region t = { .vaddr = vaddr, .len = len };
-
-	list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
-		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
-		    OVERLAPS(region_elt, &t)) {
-			MM_ERR("region (vaddr %p len %ld)"
-				" clashes with registered region"
-				" (vaddr %p paddr %p len %ld)\n",
-				vaddr, len,
-				region_elt->vaddr,
-				(void *)region_elt->paddr,
-				region_elt->len);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int audmp3_pmem_add(struct audio *audio,
-	struct msm_audio_pmem_info *info)
-{
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct audmp3_pmem_region *region;
-	int rc = -EINVAL;
-
-	MM_DBG("\n"); /* Macro prints the file name and function */
-	region = kmalloc(sizeof(*region), GFP_KERNEL);
-
-	if (!region) {
-		rc = -ENOMEM;
-		goto end;
-	}
-
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
-		kfree(region);
-		goto end;
-	}
-
-	rc = audmp3_pmem_check(audio, info->vaddr, len);
-	if (rc < 0) {
-		put_pmem_file(file);
-		kfree(region);
-		goto end;
-	}
-
-	region->vaddr = info->vaddr;
-	region->fd = info->fd;
-	region->paddr = paddr;
-	region->kvaddr = kvaddr;
-	region->len = len;
-	region->file = file;
-	region->ref_cnt = 0;
-	MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
-			region->vaddr, region->len);
-	list_add_tail(&region->list, &audio->pmem_region_queue);
-end:
-	return rc;
-}
-
-static int audmp3_pmem_remove(struct audio *audio,
-	struct msm_audio_pmem_info *info)
-{
-	struct audmp3_pmem_region *region;
-	struct list_head *ptr, *next;
-	int rc = -EINVAL;
-
-	MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
-
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audmp3_pmem_region, list);
-
-		if ((region->fd == info->fd) &&
-		    (region->vaddr == info->vaddr)) {
-			if (region->ref_cnt) {
-				MM_DBG("region %p in use ref_cnt %d\n",
-						region, region->ref_cnt);
-				break;
-			}
-			MM_DBG("remove region fd %d vaddr %p \n",
-					info->fd, info->vaddr);
-			list_del(&region->list);
-			put_pmem_file(region->file);
-			kfree(region);
-			rc = 0;
-			break;
-		}
-	}
-
-	return rc;
-}
-
 static int audmp3_pmem_lookup_vaddr(struct audio *audio, void *addr,
 		     unsigned long len, struct audmp3_pmem_region **region)
 {
@@ -1688,25 +1590,6 @@
 		break;
 	}
 
-	case AUDIO_REGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			MM_DBG("AUDIO_REGISTER_PMEM\n");
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audmp3_pmem_add(audio, &info);
-			break;
-		}
-
-	case AUDIO_DEREGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			MM_DBG("AUDIO_DEREGISTER_PMEM\n");
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audmp3_pmem_remove(audio, &info);
-			break;
-		}
 	case AUDIO_ASYNC_WRITE:
 		if (audio->drv_status & ADRV_STATUS_FSYNC)
 			rc = -EBUSY;
@@ -2105,21 +1988,6 @@
 	return rc;
 }
 
-static void audmp3_reset_pmem_region(struct audio *audio)
-{
-	struct audmp3_pmem_region *region;
-	struct list_head *ptr, *next;
-
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audmp3_pmem_region, list);
-		list_del(&region->list);
-		put_pmem_file(region->file);
-		kfree(region);
-	}
-
-	return;
-}
-
 static int audio_release(struct inode *inode, struct file *file)
 {
 	struct audio *audio = file->private_data;
@@ -2130,7 +1998,6 @@
 	audio_disable(audio);
 	audio->drv_ops.out_flush(audio);
 	audio->drv_ops.in_flush(audio);
-	audmp3_reset_pmem_region(audio);
 
 	msm_adsp_put(audio->audplay);
 	audpp_adec_free(audio->dec_id);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_out.c b/arch/arm/mach-msm/qdsp5v2/audio_out.c
index e5c59ba..712c9f3 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_out.c
@@ -30,7 +30,6 @@
 #include <linux/wakelock.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
 #include <linux/pm_qos.h>
 
 #include <mach/msm_adsp.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
index ea8fc83..cbd2913 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
@@ -30,7 +30,6 @@
 #include <linux/delay.h>
 #include <linux/earlysuspend.h>
 #include <linux/list.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
@@ -743,99 +742,6 @@
 	return rc;
 }
 
-static int audpcm_pmem_check(struct audio *audio,
-		void *vaddr, unsigned long len)
-{
-	struct audpcm_pmem_region *region_elt;
-	struct audpcm_pmem_region t = { .vaddr = vaddr, .len = len };
-
-	list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
-		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
-		    OVERLAPS(region_elt, &t)) {
-			MM_ERR("region (vaddr %p len %ld)"
-				" clashes with registered region"
-				" (vaddr %p paddr %p len %ld)\n",
-				vaddr, len,
-				region_elt->vaddr,
-				(void *)region_elt->paddr,
-				region_elt->len);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int audpcm_pmem_add(struct audio *audio,
-	struct msm_audio_pmem_info *info)
-{
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct audpcm_pmem_region *region;
-	int rc = -EINVAL;
-
-	MM_DBG("\n"); /* Macro prints the file name and function */
-	region = kmalloc(sizeof(*region), GFP_KERNEL);
-	if (!region)
-		return -ENOMEM;
-
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
-		kfree(region);
-		return -EINVAL;
-	}
-
-	rc = audpcm_pmem_check(audio, info->vaddr, len);
-	if (rc < 0) {
-		put_pmem_file(file);
-		kfree(region);
-		return rc;
-	}
-
-	region->vaddr = info->vaddr;
-	region->fd = info->fd;
-	region->paddr = paddr;
-	region->kvaddr = kvaddr;
-	region->len = len;
-	region->file = file;
-	region->ref_cnt = 0;
-	MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
-			region->vaddr, region->len);
-	list_add_tail(&region->list, &audio->pmem_region_queue);
-	return rc;
-}
-
-static int audpcm_pmem_remove(struct audio *audio,
-	struct msm_audio_pmem_info *info)
-{
-	struct audpcm_pmem_region *region;
-	struct list_head *ptr, *next;
-	int rc = -EINVAL;
-
-	MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
-
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audpcm_pmem_region, list);
-
-		if ((region->fd == info->fd) &&
-		    (region->vaddr == info->vaddr)) {
-			if (region->ref_cnt) {
-				MM_DBG("region %p in use ref_cnt %d\n", region,
-						region->ref_cnt);
-				break;
-			}
-			MM_DBG("remove region fd %d vaddr %p \n", info->fd,
-					info->vaddr);
-			list_del(&region->list);
-			put_pmem_file(region->file);
-			kfree(region);
-			rc = 0;
-			break;
-		}
-	}
-
-	return rc;
-}
-
 static int audpcm_pmem_lookup_vaddr(struct audio *audio, void *addr,
 		     unsigned long len, struct audpcm_pmem_region **region)
 {
@@ -1124,26 +1030,6 @@
 		rc = audpp_pause(audio->dec_id, (int) arg);
 		break;
 
-	case AUDIO_REGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			MM_DBG("AUDIO_REGISTER_PMEM\n");
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audpcm_pmem_add(audio, &info);
-			break;
-		}
-
-	case AUDIO_DEREGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			MM_DBG("AUDIO_DEREGISTER_PMEM\n");
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audpcm_pmem_remove(audio, &info);
-			break;
-		}
-
 	case AUDIO_ASYNC_WRITE:
 		if (audio->drv_status & ADRV_STATUS_FSYNC)
 			rc = -EBUSY;
@@ -1344,21 +1230,6 @@
 	return rc;
 }
 
-static void audpcm_reset_pmem_region(struct audio *audio)
-{
-	struct audpcm_pmem_region *region;
-	struct list_head *ptr, *next;
-
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audpcm_pmem_region, list);
-		list_del(&region->list);
-		put_pmem_file(region->file);
-		kfree(region);
-	}
-
-	return;
-}
-
 static int audio_release(struct inode *inode, struct file *file)
 {
 	struct audio *audio = file->private_data;
@@ -1369,7 +1240,6 @@
 	auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->dec_id);
 	audio_disable(audio);
 	audio->drv_ops.out_flush(audio);
-	audpcm_reset_pmem_region(audio);
 
 	msm_adsp_put(audio->audplay);
 	audpp_adec_free(audio->dec_id);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
index bb360be..33ca7a1 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
@@ -33,7 +33,6 @@
 #include <linux/debugfs.h>
 #include <linux/earlysuspend.h>
 #include <linux/list.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
index 84cfed6..44fc10f 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
@@ -35,7 +35,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/msm_audio.h>
 #include <linux/slab.h>
 #include <linux/msm_audio_wmapro.h>
diff --git a/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c b/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
index 5895867..9143b5a 100644
--- a/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
+++ b/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
@@ -23,7 +23,6 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/wakelock.h>
-#include <linux/android_pmem.h>
 #include <linux/gpio.h>
 #include <linux/pm_qos.h>
 
diff --git a/arch/arm/mach-msm/qdsp6/msm_q6vdec.c b/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
index 24d2117..1cb9775 100644
--- a/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
+++ b/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
@@ -32,7 +32,6 @@
 #include <linux/wakelock.h>
 #include <linux/pm_qos.h>
 
-#include <linux/android_pmem.h>
 #include <linux/msm_q6vdec.h>
 
 #include <mach/cpuidle.h>
diff --git a/arch/arm/mach-msm/qdsp6/msm_q6venc.c b/arch/arm/mach-msm/qdsp6/msm_q6venc.c
index 4704ae7..a2b4b6e 100644
--- a/arch/arm/mach-msm/qdsp6/msm_q6venc.c
+++ b/arch/arm/mach-msm/qdsp6/msm_q6venc.c
@@ -22,7 +22,6 @@
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 #include <linux/wakelock.h>
-#include <linux/android_pmem.h>
 #include <linux/msm_q6venc.h>
 #include <linux/pm_qos.h>
 
diff --git a/arch/arm/mach-msm/qdsp6/q6audio.c b/arch/arm/mach-msm/qdsp6/q6audio.c
index f660bdc..9404c3d 100644
--- a/arch/arm/mach-msm/qdsp6/q6audio.c
+++ b/arch/arm/mach-msm/qdsp6/q6audio.c
@@ -22,7 +22,6 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/wakelock.h>
-#include <linux/android_pmem.h>
 #include <linux/firmware.h>
 #include <linux/miscdevice.h>
 #include <linux/pm_qos.h>
diff --git a/arch/arm/mach-msm/qdsp6v2/fm.c b/arch/arm/mach-msm/qdsp6v2/fm.c
index 3d72b97..23bb716 100644
--- a/arch/arm/mach-msm/qdsp6v2/fm.c
+++ b/arch/arm/mach-msm/qdsp6v2/fm.c
@@ -30,7 +30,6 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
-#include <linux/android_pmem.h>
 #include <linux/msm_audio.h>
 #include <asm/atomic.h>
 #include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 8c96b1a..55ce4b1 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. 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
@@ -69,6 +69,7 @@
 	RPM_REGULATOR_PARAM_FREQ_REASON,
 	RPM_REGULATOR_PARAM_CORNER,
 	RPM_REGULATOR_PARAM_BYPASS,
+	RPM_REGULATOR_PARAM_FLOOR_CORNER,
 	RPM_REGULATOR_PARAM_MAX,
 };
 
@@ -108,12 +109,13 @@
 	PARAM(MODE_SMPS,       0,  1,  0,  0, "ssmd", 0, 2,          "qcom,init-smps-mode"),
 	PARAM(PIN_CTRL_ENABLE, 1,  1,  1,  0, "pcen", 0, 0xF,        "qcom,init-pin-ctrl-enable"),
 	PARAM(PIN_CTRL_MODE,   1,  1,  1,  0, "pcmd", 0, 0x1F,       "qcom,init-pin-ctrl-mode"),
-	PARAM(FREQUENCY,       0,  1,  0,  1, "freq", 0, 16,         "qcom,init-frequency"),
+	PARAM(FREQUENCY,       0,  1,  0,  1, "freq", 0, 31,         "qcom,init-frequency"),
 	PARAM(HEAD_ROOM,       1,  0,  0,  1, "hr",   0, 0x7FFFFFFF, "qcom,init-head-room"),
 	PARAM(QUIET_MODE,      0,  1,  0,  0, "qm",   0, 2,          "qcom,init-quiet-mode"),
 	PARAM(FREQ_REASON,     0,  1,  0,  1, "resn", 0, 8,          "qcom,init-freq-reason"),
 	PARAM(CORNER,          1,  1,  0,  0, "corn", 0, 6,          "qcom,init-voltage-corner"),
 	PARAM(BYPASS,          1,  0,  0,  0, "bypa", 0, 1,          "qcom,init-disallow-bypass"),
+	PARAM(FLOOR_CORNER,    1,  1,  0,  0, "vfc",  0, 6,          "qcom,init-voltage-floor-corner"),
 };
 
 struct rpm_vreg_request {
@@ -147,6 +149,8 @@
 	struct list_head	list;
 	bool			set_active;
 	bool			set_sleep;
+	bool			always_send_voltage;
+	bool			always_send_current;
 	struct rpm_vreg_request	req;
 	int			system_load;
 	int			min_uV;
@@ -390,6 +394,13 @@
 	return rc;
 }
 
+#define RPM_VREG_AGGR_MIN(_idx, _param_aggr, _param_reg) \
+{ \
+	_param_aggr[RPM_REGULATOR_PARAM_##_idx] \
+	 = min(_param_aggr[RPM_REGULATOR_PARAM_##_idx], \
+		_param_reg[RPM_REGULATOR_PARAM_##_idx]); \
+}
+
 #define RPM_VREG_AGGR_MAX(_idx, _param_aggr, _param_reg) \
 { \
 	_param_aggr[RPM_REGULATOR_PARAM_##_idx] \
@@ -410,20 +421,6 @@
 }
 
 /*
- * The RPM treats freq=0 as a special value meaning that this consumer does not
- * care what the SMPS switching freqency is.
- */
-#define RPM_REGULATOR_FREQ_DONT_CARE 0
-
-static inline void rpm_vreg_freqency_aggr(u32 *freq, u32 consumer_freq)
-{
-	if (consumer_freq != RPM_REGULATOR_FREQ_DONT_CARE
-		&& (consumer_freq < *freq
-			|| *freq == RPM_REGULATOR_FREQ_DONT_CARE))
-		*freq = consumer_freq;
-}
-
-/*
  * Aggregation is performed on each parameter based on the way that the RPM
  * aggregates that type internally between RPM masters.
  */
@@ -436,13 +433,13 @@
 	RPM_VREG_AGGR_MAX(MODE_SMPS, param_aggr, param_reg);
 	RPM_VREG_AGGR_OR(PIN_CTRL_ENABLE, param_aggr, param_reg);
 	RPM_VREG_AGGR_OR(PIN_CTRL_MODE, param_aggr, param_reg);
-	rpm_vreg_freqency_aggr(&param_aggr[RPM_REGULATOR_PARAM_FREQUENCY],
-		param_reg[RPM_REGULATOR_PARAM_FREQUENCY]);
+	RPM_VREG_AGGR_MIN(FREQUENCY, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(HEAD_ROOM, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(QUIET_MODE, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(FREQ_REASON, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(CORNER, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(BYPASS, param_aggr, param_reg);
+	RPM_VREG_AGGR_MAX(FLOOR_CORNER, param_aggr, param_reg);
 }
 
 static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
@@ -633,8 +630,12 @@
 	prev_voltage = reg->req.param[RPM_REGULATOR_PARAM_VOLTAGE];
 	RPM_VREG_SET_PARAM(reg, VOLTAGE, min_uV);
 
-	/* Only send a new voltage if the regulator is currently enabled. */
-	if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	/*
+	 * Only send a new voltage if the regulator is currently enabled or
+	 * if the regulator has been configured to always send voltage updates.
+	 */
+	if (reg->always_send_voltage
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -687,8 +688,13 @@
 	prev_corner = reg->req.param[RPM_REGULATOR_PARAM_CORNER];
 	RPM_VREG_SET_PARAM(reg, CORNER, corner);
 
-	/* Only send a new voltage if the regulator is currently enabled. */
-	if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	/*
+	 * Only send a new voltage corner if the regulator is currently enabled
+	 * or if the regulator has been configured to always send voltage
+	 * updates.
+	 */
+	if (reg->always_send_voltage
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -709,6 +715,61 @@
 		+ RPM_REGULATOR_CORNER_NONE;
 }
 
+static int rpm_vreg_set_voltage_floor_corner(struct regulator_dev *rdev,
+				int min_uV, int max_uV, unsigned *selector)
+{
+	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+	int rc = 0;
+	int corner;
+	u32 prev_corner;
+
+	/*
+	 * Translate from values which work as inputs in the
+	 * regulator_set_voltage function to the actual corner values
+	 * sent to the RPM.
+	 */
+	corner = min_uV - RPM_REGULATOR_CORNER_NONE;
+
+	if (corner < params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min
+	    || corner > params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max) {
+		vreg_err(reg, "corner=%d is not within allowed range: [%u, %u]\n",
+			corner, params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min,
+			params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max);
+		return -EINVAL;
+	}
+
+	rpm_vreg_lock(reg->rpm_vreg);
+
+	prev_corner = reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER];
+	RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, corner);
+
+	/*
+	 * Only send a new voltage floor corner if the regulator is currently
+	 * enabled or if the regulator has been configured to always send
+	 * voltage updates.
+	 */
+	if (reg->always_send_voltage
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+		rc = rpm_vreg_aggregate_requests(reg);
+
+	if (rc) {
+		vreg_err(reg, "set voltage corner failed, rc=%d", rc);
+		RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, prev_corner);
+	}
+
+	rpm_vreg_unlock(reg->rpm_vreg);
+
+	return rc;
+}
+
+static int rpm_vreg_get_voltage_floor_corner(struct regulator_dev *rdev)
+{
+	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+
+	return reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER]
+		+ RPM_REGULATOR_CORNER_NONE;
+}
+
 static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
 	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
@@ -737,8 +798,13 @@
 		return -EINVAL;
 	}
 
-	/* Only send a new mode value if the regulator is currently enabled. */
-	if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	/*
+	 * Only send a new load current value if the regulator is currently
+	 * enabled or if the regulator has been configured to always send
+	 * current updates.
+	 */
+	if (reg->always_send_current
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -1035,6 +1101,18 @@
 	.enable_time		= rpm_vreg_enable_time,
 };
 
+static struct regulator_ops ldo_floor_corner_ops = {
+	.enable			= rpm_vreg_enable,
+	.disable		= rpm_vreg_disable,
+	.is_enabled		= rpm_vreg_is_enabled,
+	.set_voltage		= rpm_vreg_set_voltage_floor_corner,
+	.get_voltage		= rpm_vreg_get_voltage_floor_corner,
+	.set_mode		= rpm_vreg_set_mode,
+	.get_mode		= rpm_vreg_get_mode,
+	.get_optimum_mode	= rpm_vreg_get_optimum_mode,
+	.enable_time		= rpm_vreg_enable_time,
+};
+
 static struct regulator_ops smps_ops = {
 	.enable			= rpm_vreg_enable,
 	.disable		= rpm_vreg_disable,
@@ -1059,6 +1137,18 @@
 	.enable_time		= rpm_vreg_enable_time,
 };
 
+static struct regulator_ops smps_floor_corner_ops = {
+	.enable			= rpm_vreg_enable,
+	.disable		= rpm_vreg_disable,
+	.is_enabled		= rpm_vreg_is_enabled,
+	.set_voltage		= rpm_vreg_set_voltage_floor_corner,
+	.get_voltage		= rpm_vreg_get_voltage_floor_corner,
+	.set_mode		= rpm_vreg_set_mode,
+	.get_mode		= rpm_vreg_get_mode,
+	.get_optimum_mode	= rpm_vreg_get_optimum_mode,
+	.enable_time		= rpm_vreg_enable_time,
+};
+
 static struct regulator_ops switch_ops = {
 	.enable			= rpm_vreg_enable,
 	.disable		= rpm_vreg_disable,
@@ -1192,12 +1282,30 @@
 	 * is specified in the device node (SMPS and LDO only).
 	 */
 	if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
+		if (of_property_read_bool(node,
+				"qcom,use-voltage-floor-corner")) {
+			dev_err(dev, "%s: invalid properties: both qcom,use-voltage-corner and qcom,use-voltage-floor-corner specified\n",
+				__func__);
+			goto fail_free_reg;
+		}
+
 		if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
 			reg->rdesc.ops = &smps_corner_ops;
 		else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
 			reg->rdesc.ops = &ldo_corner_ops;
+	} else if (of_property_read_bool(node,
+			"qcom,use-voltage-floor-corner")) {
+		if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
+			reg->rdesc.ops = &smps_floor_corner_ops;
+		else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
+			reg->rdesc.ops = &ldo_floor_corner_ops;
 	}
 
+	reg->always_send_voltage
+		= of_property_read_bool(node, "qcom,always-send-voltage");
+	reg->always_send_current
+		= of_property_read_bool(node, "qcom,always-send-current");
+
 	if (regulator_type == RPM_REGULATOR_SMD_TYPE_VS)
 		reg->rdesc.n_voltages = 0;
 	else
diff --git a/arch/arm/mach-msm/spm-regulator.c b/arch/arm/mach-msm/spm-regulator.c
new file mode 100644
index 0000000..00817c0
--- /dev/null
+++ b/arch/arm/mach-msm/spm-regulator.c
@@ -0,0 +1,405 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include "spm.h"
+#include "spm-regulator.h"
+
+#define SPM_REGULATOR_DRIVER_NAME "qcom,spm-regulator"
+
+struct voltage_range {
+	int min_uV;
+	int set_point_min_uV;
+	int max_uV;
+	int step_uV;
+};
+
+/* Properties for FTS2 type QPNP PMIC regulators. */
+
+static const struct voltage_range fts2_range0 = {0, 350000, 1275000,  5000};
+static const struct voltage_range fts2_range1 = {0, 700000, 2040000, 10000};
+
+/* Specifies the PMIC internal slew rate in uV/us. */
+#define QPNP_FTS2_SLEW_RATE		6000
+
+#define QPNP_FTS2_REG_TYPE		0x04
+#define QPNP_FTS2_REG_SUBTYPE		0x05
+#define QPNP_FTS2_REG_VOLTAGE_RANGE	0x40
+#define QPNP_FTS2_REG_VOLTAGE_SETPOINT	0x41
+
+#define QPNP_FTS2_TYPE			0x1C
+#define QPNP_FTS2_SUBTYPE		0x08
+
+struct spm_vreg {
+	struct regulator_desc		rdesc;
+	struct regulator_dev		*rdev;
+	struct spmi_device		*spmi_dev;
+	const struct voltage_range	*range;
+	int				uV;
+	int				last_set_uV;
+	unsigned			vlevel;
+	unsigned			last_set_vlevel;
+	bool				online;
+	u16				spmi_base_addr;
+};
+
+static int _spm_regulator_set_voltage(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+	int rc;
+
+	if (vreg->vlevel == vreg->last_set_vlevel)
+		return 0;
+
+	rc = msm_spm_apcs_set_vdd(vreg->vlevel);
+	if (rc) {
+		pr_err("%s: msm_spm_set_vdd failed %d\n", vreg->rdesc.name, rc);
+		return rc;
+	}
+
+	if (vreg->uV > vreg->last_set_uV) {
+		/* Wait for voltage to stabalize. */
+		udelay(DIV_ROUND_UP(vreg->uV - vreg->last_set_uV,
+					QPNP_FTS2_SLEW_RATE));
+	}
+	vreg->last_set_uV = vreg->uV;
+	vreg->last_set_vlevel = vreg->vlevel;
+
+	return rc;
+}
+
+static int spm_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
+					int max_uV, unsigned *selector)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+	const struct voltage_range *range = vreg->range;
+	int uV = min_uV;
+	unsigned vlevel;
+
+	if (uV < range->set_point_min_uV && max_uV >= range->set_point_min_uV)
+		uV = range->set_point_min_uV;
+
+	if (uV < range->set_point_min_uV || uV > range->max_uV) {
+		pr_err("%s: request v=[%d, %d] is outside possible v=[%d, %d]\n",
+			vreg->rdesc.name, min_uV, max_uV,
+			range->set_point_min_uV, range->max_uV);
+		return -EINVAL;
+	}
+
+	vlevel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV);
+	uV = vlevel * range->step_uV + range->min_uV;
+
+	if (uV > max_uV) {
+		pr_err("%s: request v=[%d, %d] cannot be met by any set point\n",
+			vreg->rdesc.name, min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	vreg->vlevel = vlevel;
+	vreg->uV = uV;
+	*selector = vlevel -
+		(vreg->range->set_point_min_uV - vreg->range->min_uV)
+			/ vreg->range->step_uV;
+
+	if (!vreg->online)
+		return 0;
+
+	return _spm_regulator_set_voltage(rdev);
+}
+
+static int spm_regulator_get_voltage(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+	return vreg->uV;
+}
+
+static int spm_regulator_list_voltage(struct regulator_dev *rdev,
+					unsigned selector)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+	if (selector >= vreg->rdesc.n_voltages)
+		return 0;
+
+	return selector * vreg->range->step_uV + vreg->range->set_point_min_uV;
+}
+
+static int spm_regulator_enable(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+	int rc;
+
+	rc = _spm_regulator_set_voltage(rdev);
+
+	if (!rc)
+		vreg->online = true;
+
+	return rc;
+}
+
+static int spm_regulator_disable(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+	vreg->online = false;
+
+	return 0;
+}
+
+static int spm_regulator_is_enabled(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+	return vreg->online;
+}
+
+static struct regulator_ops spm_regulator_ops = {
+	.get_voltage	= spm_regulator_get_voltage,
+	.set_voltage	= spm_regulator_set_voltage,
+	.list_voltage	= spm_regulator_list_voltage,
+	.enable		= spm_regulator_enable,
+	.disable	= spm_regulator_disable,
+	.is_enabled	= spm_regulator_is_enabled,
+};
+
+static int qpnp_fts2_check_type(struct spm_vreg *vreg)
+{
+	int rc;
+	u8 type[2];
+
+	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_TYPE, type, 2);
+	if (rc) {
+		dev_err(&vreg->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	if (type[0] != QPNP_FTS2_TYPE || type[1] != QPNP_FTS2_SUBTYPE) {
+		dev_err(&vreg->spmi_dev->dev, "%s: invalid type=0x%02X or subtype=0x%02X register value\n",
+			__func__, type[0], type[1]);
+		return -ENODEV;
+	}
+
+	return rc;
+}
+
+static int qpnp_fts2_init_range(struct spm_vreg *vreg)
+{
+	int rc;
+	u8 reg = 0;
+
+	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_VOLTAGE_RANGE, &reg, 1);
+	if (rc) {
+		dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage range register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	if (reg == 0x00) {
+		vreg->range = &fts2_range0;
+	} else if (reg == 0x01) {
+		vreg->range = &fts2_range1;
+	} else {
+		dev_err(&vreg->spmi_dev->dev, "%s: voltage range=%d is invalid\n",
+			__func__, reg);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int qpnp_fts2_init_voltage(struct spm_vreg *vreg)
+{
+	int rc;
+	u8 reg = 0;
+
+	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_VOLTAGE_SETPOINT, &reg, 1);
+	if (rc) {
+		dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	vreg->vlevel = reg;
+	vreg->uV = vreg->vlevel * vreg->range->step_uV + vreg->range->min_uV;
+	vreg->last_set_uV = vreg->uV;
+
+	return rc;
+}
+
+static int __devinit spm_regulator_probe(struct spmi_device *spmi)
+{
+	struct device_node *node = spmi->dev.of_node;
+	struct regulator_init_data *init_data;
+	struct spm_vreg *vreg;
+	struct resource *res;
+	int rc;
+
+	if (!node) {
+		dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+		return -ENODEV;
+	}
+
+	vreg = devm_kzalloc(&spmi->dev, sizeof(*vreg), GFP_KERNEL);
+	if (!vreg) {
+		pr_err("allocation failed.\n");
+		return -ENOMEM;
+	}
+	vreg->spmi_dev = spmi;
+
+	res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&spmi->dev, "%s: node is missing base address\n",
+			__func__);
+		return -EINVAL;
+	}
+	vreg->spmi_base_addr = res->start;
+
+	rc = qpnp_fts2_check_type(vreg);
+	if (rc)
+		return rc;
+
+	/*
+	 * The FTS2 regulator must be initialized to range 0 or range 1 during
+	 * PMIC power on sequence.  Once it is set, it cannot be changed
+	 * dynamically.
+	 */
+	rc = qpnp_fts2_init_range(vreg);
+	if (rc)
+		return rc;
+
+	rc = qpnp_fts2_init_voltage(vreg);
+	if (rc)
+		return rc;
+
+	init_data = of_get_regulator_init_data(&spmi->dev, node);
+	if (!init_data) {
+		dev_err(&spmi->dev, "%s: unable to allocate memory\n",
+				__func__);
+		return -ENOMEM;
+	}
+	init_data->constraints.input_uV = init_data->constraints.max_uV;
+	init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS
+						| REGULATOR_CHANGE_VOLTAGE;
+
+	if (!init_data->constraints.name) {
+		dev_err(&spmi->dev, "%s: node is missing regulator name\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	vreg->rdesc.name	= init_data->constraints.name;
+	vreg->rdesc.type	= REGULATOR_VOLTAGE;
+	vreg->rdesc.owner	= THIS_MODULE;
+	vreg->rdesc.ops		= &spm_regulator_ops;
+	vreg->rdesc.n_voltages
+		= (vreg->range->max_uV - vreg->range->set_point_min_uV)
+			/ vreg->range->step_uV + 1;
+
+	vreg->rdev = regulator_register(&vreg->rdesc, &spmi->dev,
+					init_data, vreg, node);
+	if (IS_ERR(vreg->rdev)) {
+		rc = PTR_ERR(vreg->rdev);
+		dev_err(&spmi->dev, "%s: regulator_register failed, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	dev_set_drvdata(&spmi->dev, vreg);
+
+	pr_info("name=%s, range=%d\n", vreg->rdesc.name,
+		(vreg->range == &fts2_range0) ? 0 : 1);
+
+	return rc;
+}
+
+static int __devexit spm_regulator_remove(struct spmi_device *spmi)
+{
+	struct spm_vreg *vreg = dev_get_drvdata(&spmi->dev);
+
+	regulator_unregister(vreg->rdev);
+
+	return 0;
+}
+
+static struct of_device_id spm_regulator_match_table[] = {
+	{ .compatible = SPM_REGULATOR_DRIVER_NAME, },
+	{}
+};
+
+static const struct spmi_device_id spm_regulator_id[] = {
+	{ SPM_REGULATOR_DRIVER_NAME, 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(spmi, spm_regulator_id);
+
+static struct spmi_driver spm_regulator_driver = {
+	.driver = {
+		.name		= SPM_REGULATOR_DRIVER_NAME,
+		.of_match_table = spm_regulator_match_table,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= spm_regulator_probe,
+	.remove		= __devexit_p(spm_regulator_remove),
+	.id_table	= spm_regulator_id,
+};
+
+/**
+ * spm_regulator_init() - register spmi driver for spm-regulator
+ *
+ * This initialization function should be called in systems in which driver
+ * registration ordering must be controlled precisely.
+ *
+ * Returns 0 on success or errno on failure.
+ */
+int __init spm_regulator_init(void)
+{
+	static bool has_registered;
+
+	if (has_registered)
+		return 0;
+	else
+		has_registered = true;
+
+	return spmi_driver_register(&spm_regulator_driver);
+}
+EXPORT_SYMBOL(spm_regulator_init);
+
+static void __exit spm_regulator_exit(void)
+{
+	spmi_driver_unregister(&spm_regulator_driver);
+}
+
+arch_initcall(spm_regulator_init);
+module_exit(spm_regulator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SPM regulator driver");
+MODULE_ALIAS("platform:spm-regulator");
diff --git a/arch/arm/mach-msm/spm-regulator.h b/arch/arm/mach-msm/spm-regulator.h
new file mode 100644
index 0000000..394aecc
--- /dev/null
+++ b/arch/arm/mach-msm/spm-regulator.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ARCH_ARM_MACH_MSM_SPM_REGULATOR_H
+#define _ARCH_ARM_MACH_MSM_SPM_REGULATOR_H
+
+#include <linux/err.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_MSM_SPM_REGULATOR
+int __init spm_regulator_init(void);
+#else
+static inline int __init spm_regulator_init(void) { return -ENODEV; }
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/tz_log.c b/arch/arm/mach-msm/tz_log.c
index 11dc436..84e8df5 100644
--- a/arch/arm/mach-msm/tz_log.c
+++ b/arch/arm/mach-msm/tz_log.c
@@ -708,23 +708,18 @@
 	 */
 	tzdiag_phy_iobase = readl_relaxed(virt_iobase);
 
-	if (!pdev->dev.of_node) {
+	/*
+	 * Map the 4KB diagnostic information area
+	 */
+	tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
+				tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
 
-		/*
-		 * Map the 4KB diagnostic information area
-		 */
-		tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
-					tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
-
-		if (!tzdbg.virt_iobase) {
-			dev_err(&pdev->dev,
-				"%s: ERROR could not ioremap: start=%p, len=%u\n",
-				__func__, (void *) tzdiag_phy_iobase,
-				DEBUG_MAX_RW_BUF);
-			return -ENXIO;
-		}
-	} else {
-		tzdbg.virt_iobase = virt_iobase;
+	if (!tzdbg.virt_iobase) {
+		dev_err(&pdev->dev,
+			"%s: ERROR could not ioremap: start=%p, len=%u\n",
+			__func__, (void *) tzdiag_phy_iobase,
+			DEBUG_MAX_RW_BUF);
+		return -ENXIO;
 	}
 
 	ptr = kzalloc(DEBUG_MAX_RW_BUF, GFP_KERNEL);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f385fc4..1c8a25d 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -708,12 +708,12 @@
 
 	if (arch_is_coherent() || nommu()) {
 		__dma_free_buffer(page, size);
+	} else if (__free_from_pool(cpu_addr, size)) {
+		return;
 	} else if (!IS_ENABLED(CONFIG_CMA)) {
 		__dma_free_remap(cpu_addr, size, false);
 		__dma_free_buffer(page, size);
 	} else {
-		if (__free_from_pool(cpu_addr, size))
-			return;
 		/*
 		 * Non-atomic allocations cannot be freed with IRQs disabled
 		 */
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index ed91480..45c9023 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -227,7 +227,7 @@
 
 	pr_info("Found %s, memory base %lx, size %ld MiB\n", uname,
 		(unsigned long)base, (unsigned long)size / SZ_1M);
-	dma_contiguous_reserve_area(size, &base, 0, name);
+	dma_contiguous_reserve_area(size, &base, MEMBLOCK_ALLOC_ANYWHERE, name);
 
 	return 0;
 }
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index 3726a0d..73800dd 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,9 +18,15 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/of_coresight.h>
 #include <linux/coresight.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <mach/gpiomux.h>
 
 #include "coresight-priv.h"
 
@@ -58,20 +64,194 @@
 #define TPIU_ITATBCTR1		(0xEF4)
 #define TPIU_ITATBCTR0		(0xEF8)
 
+enum tpiu_out_mode {
+	TPIU_OUT_MODE_NONE,
+	TPIU_OUT_MODE_MICTOR,
+	TPIU_OUT_MODE_SDC,
+};
+
+enum tpiu_set {
+	TPIU_SET_NONE,
+	TPIU_SET_A,
+	TPIU_SET_B,
+};
+
 struct tpiu_drvdata {
 	void __iomem		*base;
 	struct device		*dev;
 	struct coresight_device	*csdev;
 	struct clk		*clk;
+	struct mutex		mutex;
+	enum tpiu_out_mode	out_mode;
+	struct regulator	*reg;
+	unsigned int		reg_low;
+	unsigned int		reg_high;
+	unsigned int		reg_lpm;
+	unsigned int		reg_hpm;
+	enum tpiu_set		set;
+	unsigned int		seta_gpiocnt;
+	unsigned int		*seta_gpios;
+	struct gpiomux_setting	*seta_cfgs;
+	unsigned int		setb_gpiocnt;
+	unsigned int		*setb_gpios;
+	struct gpiomux_setting	*setb_cfgs;
+	bool			enable;
 };
 
-static void __tpiu_enable(struct tpiu_drvdata *drvdata)
+struct gpiomux_setting old_cfg;
+
+static void tpiu_flush_and_stop(struct tpiu_drvdata *drvdata)
 {
+	int count;
+	uint32_t ffcr;
+
+	ffcr = tpiu_readl(drvdata, TPIU_FFCR);
+	ffcr |= BIT(12);
+	tpiu_writel(drvdata, ffcr, TPIU_FFCR);
+	ffcr |= BIT(6);
+	tpiu_writel(drvdata, ffcr, TPIU_FFCR);
+	/* Ensure flush completes */
+	for (count = TIMEOUT_US; BVAL(tpiu_readl(drvdata, TPIU_FFCR), 6) != 0
+				&& count > 0; count--)
+		udelay(1);
+	WARN(count == 0, "timeout while flushing TPIU, TPIU_FFCR: %#x\n",
+	     tpiu_readl(drvdata, TPIU_FFCR));
+}
+
+static int __tpiu_enable_seta(struct tpiu_drvdata *drvdata)
+{
+	int i, ret;
+
+	if (!drvdata->seta_gpiocnt)
+		return -EINVAL;
+
+	for (i = 0; i < drvdata->seta_gpiocnt; i++) {
+		ret = gpio_request(drvdata->seta_gpios[i], NULL);
+		if (ret) {
+			dev_err(drvdata->dev,
+				"gpio_request failed for seta_gpio: %u\n",
+				drvdata->seta_gpios[i]);
+			goto err0;
+		}
+		ret = msm_gpiomux_write(drvdata->seta_gpios[i],
+					GPIOMUX_ACTIVE,
+					&drvdata->seta_cfgs[i],
+					&old_cfg);
+		if (ret < 0) {
+			dev_err(drvdata->dev,
+				"gpio write failed for seta_gpio: %u\n",
+				drvdata->seta_gpios[i]);
+			goto err1;
+		}
+	}
+	return 0;
+err1:
+	gpio_free(drvdata->seta_gpios[i]);
+err0:
+	i--;
+	while (i >= 0) {
+		gpio_free(drvdata->seta_gpios[i]);
+		i--;
+	}
+	return ret;
+}
+
+static int __tpiu_enable_setb(struct tpiu_drvdata *drvdata)
+{
+	int i, ret;
+
+	if (!drvdata->setb_gpiocnt)
+		return -EINVAL;
+
+	for (i = 0; i < drvdata->setb_gpiocnt; i++) {
+		ret = gpio_request(drvdata->setb_gpios[i], NULL);
+		if (ret) {
+			dev_err(drvdata->dev,
+				"gpio_request failed for setb_gpio: %u\n",
+				drvdata->setb_gpios[i]);
+			goto err0;
+		}
+		ret = msm_gpiomux_write(drvdata->setb_gpios[i],
+					GPIOMUX_ACTIVE,
+					&drvdata->setb_cfgs[i],
+					&old_cfg);
+		if (ret < 0) {
+			dev_err(drvdata->dev,
+				"gpio write failed for setb_gpio: %u\n",
+				drvdata->setb_gpios[i]);
+			goto err1;
+		}
+	}
+	return 0;
+err1:
+	gpio_free(drvdata->setb_gpios[i]);
+err0:
+	i--;
+	while (i >= 0) {
+		gpio_free(drvdata->setb_gpios[i]);
+		i--;
+	}
+	return ret;
+}
+
+static int __tpiu_enable_to_mictor(struct tpiu_drvdata *drvdata)
+{
+	int ret;
+
+	if (drvdata->set == TPIU_SET_A) {
+		ret = __tpiu_enable_seta(drvdata);
+		if (ret)
+			return ret;
+	} else if (drvdata->set == TPIU_SET_B) {
+		ret = __tpiu_enable_setb(drvdata);
+		if (ret)
+			return ret;
+	}
+
 	TPIU_UNLOCK(drvdata);
 
-	/* TODO: fill this up */
+	tpiu_writel(drvdata, 0x8000, TPIU_CURR_PORTSZ);
+	tpiu_writel(drvdata, 0x101, TPIU_FFCR);
 
 	TPIU_LOCK(drvdata);
+
+	return 0;
+}
+
+static int __tpiu_enable_to_sdc(struct tpiu_drvdata *drvdata)
+{
+	int ret;
+
+	if (!drvdata->reg)
+		return -EINVAL;
+
+	ret = regulator_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
+	if (ret < 0)
+		return ret;
+	ret = regulator_set_voltage(drvdata->reg, drvdata->reg_low,
+				    drvdata->reg_high);
+	if (ret)
+		goto err0;
+	ret = regulator_enable(drvdata->reg);
+	if (ret)
+		goto err1;
+
+	msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x16D);
+	msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);
+
+	TPIU_UNLOCK(drvdata);
+
+	tpiu_writel(drvdata, 0x8, TPIU_CURR_PORTSZ);
+	tpiu_writel(drvdata, 0x103, TPIU_FFCR);
+
+	TPIU_LOCK(drvdata);
+
+	return 0;
+err1:
+	regulator_set_voltage(drvdata->reg, 0, drvdata->reg_high);
+err0:
+	regulator_set_optimum_mode(drvdata->reg, 0);
+	return ret;
 }
 
 static int tpiu_enable(struct coresight_device *csdev)
@@ -83,27 +263,85 @@
 	if (ret)
 		return ret;
 
-	__tpiu_enable(drvdata);
+	mutex_lock(&drvdata->mutex);
+
+	if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
+		ret = __tpiu_enable_to_mictor(drvdata);
+	else
+		ret = __tpiu_enable_to_sdc(drvdata);
+	if (ret)
+		goto err;
+	drvdata->enable = true;
+
+	mutex_unlock(&drvdata->mutex);
 
 	dev_info(drvdata->dev, "TPIU enabled\n");
 	return 0;
+err:
+	mutex_unlock(&drvdata->mutex);
+	clk_disable_unprepare(drvdata->clk);
+	return ret;
 }
 
 static void __tpiu_disable(struct tpiu_drvdata *drvdata)
 {
 	TPIU_UNLOCK(drvdata);
 
-	tpiu_writel(drvdata, 0x3000, TPIU_FFCR);
-	tpiu_writel(drvdata, 0x3040, TPIU_FFCR);
+	tpiu_flush_and_stop(drvdata);
 
 	TPIU_LOCK(drvdata);
 }
 
+static void __tpiu_disable_seta(struct tpiu_drvdata *drvdata)
+{
+	int i;
+
+	for (i = 0; i < drvdata->seta_gpiocnt; i++)
+		gpio_free(drvdata->seta_gpios[i]);
+}
+
+static void __tpiu_disable_setb(struct tpiu_drvdata *drvdata)
+{
+	int i;
+
+	for (i = 0; i < drvdata->setb_gpiocnt; i++)
+		gpio_free(drvdata->setb_gpios[i]);
+}
+
+static void __tpiu_disable_to_mictor(struct tpiu_drvdata *drvdata)
+{
+	__tpiu_disable(drvdata);
+
+	if (drvdata->set == TPIU_SET_A)
+		__tpiu_disable_seta(drvdata);
+	else if (drvdata->set == TPIU_SET_B)
+		__tpiu_disable_setb(drvdata);
+}
+
+static void __tpiu_disable_to_sdc(struct tpiu_drvdata *drvdata)
+{
+	__tpiu_disable(drvdata);
+
+	msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 0);
+
+	regulator_disable(drvdata->reg);
+	regulator_set_optimum_mode(drvdata->reg, 0);
+	regulator_set_voltage(drvdata->reg, 0, drvdata->reg_high);
+}
+
 static void tpiu_disable(struct coresight_device *csdev)
 {
 	struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	__tpiu_disable(drvdata);
+	mutex_lock(&drvdata->mutex);
+
+	if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
+		__tpiu_disable_to_mictor(drvdata);
+	else
+		__tpiu_disable_to_sdc(drvdata);
+	drvdata->enable = false;
+
+	mutex_unlock(&drvdata->mutex);
 
 	clk_disable_unprepare(drvdata->clk);
 
@@ -125,10 +363,331 @@
 	.abort		= tpiu_abort,
 };
 
+static ssize_t tpiu_show_out_mode(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+			 drvdata->out_mode == TPIU_OUT_MODE_MICTOR ?
+			 "mictor" : "sdc");
+}
+
+static ssize_t tpiu_store_out_mode(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t size)
+{
+	struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	char str[10] = "";
+	int ret;
+
+	if (strlen(buf) >= 10)
+		return -EINVAL;
+	if (sscanf(buf, "%s", str) != 1)
+		return -EINVAL;
+
+	mutex_lock(&drvdata->mutex);
+	if (!strcmp(str, "mictor")) {
+		if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
+			goto out;
+
+		if (!drvdata->enable) {
+			drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
+			goto out;
+		}
+		__tpiu_disable_to_sdc(drvdata);
+		ret = __tpiu_enable_to_mictor(drvdata);
+		if (ret) {
+			dev_err(drvdata->dev, "failed to enable mictor\n");
+			goto err;
+		}
+		drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
+	} else if (!strcmp(str, "sdc")) {
+		if (drvdata->out_mode == TPIU_OUT_MODE_SDC)
+			goto out;
+
+		if (!drvdata->enable) {
+			drvdata->out_mode = TPIU_OUT_MODE_SDC;
+			goto out;
+		}
+		__tpiu_disable_to_mictor(drvdata);
+		ret = __tpiu_enable_to_sdc(drvdata);
+		if (ret) {
+			dev_err(drvdata->dev, "failed to enable sdc\n");
+			goto err;
+		}
+		drvdata->out_mode = TPIU_OUT_MODE_SDC;
+	}
+out:
+	mutex_unlock(&drvdata->mutex);
+	return size;
+err:
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+}
+static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tpiu_show_out_mode,
+		   tpiu_store_out_mode);
+
 static const struct coresight_ops tpiu_cs_ops = {
 	.sink_ops	= &tpiu_sink_ops,
 };
 
+static ssize_t tpiu_show_set(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+			 drvdata->set == TPIU_SET_A ?
+			 "a" : "b");
+}
+
+static ssize_t tpiu_store_set(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	char str[10] = "";
+	int ret;
+
+	if (strlen(buf) >= 10)
+		return -EINVAL;
+	if (sscanf(buf, "%s", str) != 1)
+		return -EINVAL;
+
+	mutex_lock(&drvdata->mutex);
+	if (!strcmp(str, "a")) {
+		if (drvdata->set == TPIU_SET_A)
+			goto out;
+
+		if (!drvdata->enable || drvdata->out_mode !=
+					TPIU_OUT_MODE_MICTOR) {
+			drvdata->set = TPIU_SET_A;
+			goto out;
+		}
+		__tpiu_disable_setb(drvdata);
+		ret = __tpiu_enable_seta(drvdata);
+		if (ret) {
+			dev_err(drvdata->dev, "failed to enable set A\n");
+			goto err;
+		}
+		drvdata->set = TPIU_SET_A;
+	} else if (!strcmp(str, "b")) {
+		if (drvdata->set == TPIU_SET_B)
+			goto out;
+
+		if (!drvdata->enable || drvdata->out_mode !=
+					TPIU_OUT_MODE_MICTOR) {
+			drvdata->set = TPIU_SET_B;
+			goto out;
+		}
+		__tpiu_disable_seta(drvdata);
+		ret = __tpiu_enable_setb(drvdata);
+		if (ret) {
+			dev_err(drvdata->dev, "failed to enable set B\n");
+			goto err;
+		}
+		drvdata->set = TPIU_SET_B;
+	}
+out:
+	mutex_unlock(&drvdata->mutex);
+	return size;
+err:
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+}
+static DEVICE_ATTR(set, S_IRUGO | S_IWUSR, tpiu_show_set, tpiu_store_set);
+
+static struct attribute *tpiu_attrs[] = {
+	&dev_attr_out_mode.attr,
+	&dev_attr_set.attr,
+	NULL,
+};
+
+static struct attribute_group tpiu_attr_grp = {
+	.attrs = tpiu_attrs,
+};
+
+static const struct attribute_group *tpiu_attr_grps[] = {
+	&tpiu_attr_grp,
+	NULL,
+};
+
+static int __devinit tpiu_parse_of_data(struct platform_device *pdev,
+					struct tpiu_drvdata *drvdata)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *reg_node = NULL;
+	struct device *dev = &pdev->dev;
+	const __be32 *prop;
+	int i, len, gpio, ret;
+	uint32_t *seta_cfgs, *setb_cfgs;
+
+	reg_node = of_parse_phandle(node, "vdd-supply", 0);
+	if (reg_node) {
+		drvdata->reg = devm_regulator_get(dev, "vdd");
+		if (IS_ERR(drvdata->reg))
+			return PTR_ERR(drvdata->reg);
+
+		prop = of_get_property(node, "qcom,vdd-voltage-level", &len);
+		if (!prop || (len != (2 * sizeof(__be32)))) {
+			of_node_put(reg_node);
+			return -EINVAL;
+		} else {
+			drvdata->reg_low = be32_to_cpup(&prop[0]);
+			drvdata->reg_high = be32_to_cpup(&prop[1]);
+		}
+
+		prop = of_get_property(node, "qcom,vdd-current-level", &len);
+		if (!prop || (len != (2 * sizeof(__be32)))) {
+			of_node_put(reg_node);
+			return -EINVAL;
+		} else {
+			drvdata->reg_lpm = be32_to_cpup(&prop[0]);
+			drvdata->reg_hpm = be32_to_cpup(&prop[1]);
+		}
+		of_node_put(reg_node);
+	} else {
+		dev_err(dev, "sdc voltage supply not specified or available\n");
+	}
+
+	drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
+	drvdata->set = TPIU_SET_B;
+
+	drvdata->seta_gpiocnt = of_gpio_named_count(node, "qcom,seta-gpios");
+	if (drvdata->seta_gpiocnt) {
+		drvdata->seta_gpios = devm_kzalloc(dev,
+				sizeof(*drvdata->seta_gpios) *
+				drvdata->seta_gpiocnt, GFP_KERNEL);
+		if (!drvdata->seta_gpios)
+			return -ENOMEM;
+
+		for (i = 0; i < drvdata->seta_gpiocnt; i++) {
+			gpio = of_get_named_gpio(node, "qcom,seta-gpios", i);
+			if (!gpio_is_valid(gpio))
+				return gpio;
+
+			drvdata->seta_gpios[i] = gpio;
+		}
+
+		drvdata->seta_cfgs = devm_kzalloc(dev,
+				sizeof(*drvdata->seta_cfgs) *
+				drvdata->seta_gpiocnt, GFP_KERNEL);
+		if (!drvdata->seta_cfgs)
+			return -ENOMEM;
+
+		seta_cfgs = devm_kzalloc(dev, sizeof(*seta_cfgs) *
+					 drvdata->seta_gpiocnt, GFP_KERNEL);
+		if (!seta_cfgs)
+			return -ENOMEM;
+
+		ret = of_property_read_u32_array(node, "qcom,seta-gpios-func",
+						 (u32 *)seta_cfgs,
+						 drvdata->seta_gpiocnt);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < drvdata->seta_gpiocnt; i++)
+			drvdata->seta_cfgs[i].func = seta_cfgs[i];
+
+		ret = of_property_read_u32_array(node, "qcom,seta-gpios-drv",
+						 (u32 *)seta_cfgs,
+						 drvdata->seta_gpiocnt);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < drvdata->seta_gpiocnt; i++)
+			drvdata->seta_cfgs[i].drv = seta_cfgs[i];
+
+		ret = of_property_read_u32_array(node, "qcom,seta-gpios-pull",
+						 (u32 *)seta_cfgs,
+						 drvdata->seta_gpiocnt);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < drvdata->seta_gpiocnt; i++)
+			drvdata->seta_cfgs[i].pull = seta_cfgs[i];
+
+		ret = of_property_read_u32_array(node, "qcom,seta-gpios-dir",
+						 (u32 *)seta_cfgs,
+						 drvdata->seta_gpiocnt);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < drvdata->seta_gpiocnt; i++)
+			drvdata->seta_cfgs[i].dir = seta_cfgs[i];
+	} else {
+		dev_err(dev, "seta gpios not specified\n");
+	}
+
+	drvdata->setb_gpiocnt = of_gpio_named_count(node, "qcom,setb-gpios");
+	if (drvdata->setb_gpiocnt) {
+		drvdata->setb_gpios = devm_kzalloc(dev,
+				sizeof(*drvdata->setb_gpios) *
+				drvdata->setb_gpiocnt, GFP_KERNEL);
+		if (!drvdata->setb_gpios)
+			return -ENOMEM;
+
+		for (i = 0; i < drvdata->setb_gpiocnt; i++) {
+			gpio = of_get_named_gpio(node, "qcom,setb-gpios", i);
+			if (!gpio_is_valid(gpio))
+				return gpio;
+
+			drvdata->setb_gpios[i] = gpio;
+		}
+
+		drvdata->setb_cfgs = devm_kzalloc(dev,
+				sizeof(*drvdata->setb_cfgs) *
+				drvdata->setb_gpiocnt, GFP_KERNEL);
+		if (!drvdata->setb_cfgs)
+			return -ENOMEM;
+
+		setb_cfgs = devm_kzalloc(dev, sizeof(*setb_cfgs) *
+					 drvdata->setb_gpiocnt, GFP_KERNEL);
+		if (!setb_cfgs)
+			return -ENOMEM;
+
+		ret = of_property_read_u32_array(node, "qcom,setb-gpios-func",
+						 (u32 *)setb_cfgs,
+						 drvdata->setb_gpiocnt);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < drvdata->setb_gpiocnt; i++)
+			drvdata->setb_cfgs[i].func = setb_cfgs[i];
+
+		ret = of_property_read_u32_array(node, "qcom,setb-gpios-drv",
+						 (u32 *)setb_cfgs,
+						 drvdata->setb_gpiocnt);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < drvdata->setb_gpiocnt; i++)
+			drvdata->setb_cfgs[i].drv = setb_cfgs[i];
+
+		ret = of_property_read_u32_array(node, "qcom,setb-gpios-pull",
+						 (u32 *)setb_cfgs,
+						 drvdata->setb_gpiocnt);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < drvdata->setb_gpiocnt; i++)
+			drvdata->setb_cfgs[i].pull = setb_cfgs[i];
+
+		ret = of_property_read_u32_array(node, "qcom,setb-gpios-dir",
+						 (u32 *)setb_cfgs,
+						 drvdata->setb_gpiocnt);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < drvdata->setb_gpiocnt; i++)
+			drvdata->setb_cfgs[i].dir = setb_cfgs[i];
+	} else {
+		dev_err(dev, "setb gpios not specified\n");
+	}
+
+	return 0;
+}
+
 static int __devinit tpiu_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -159,6 +718,8 @@
 	if (!drvdata->base)
 		return -ENOMEM;
 
+	mutex_init(&drvdata->mutex);
+
 	drvdata->clk = devm_clk_get(dev, "core_clk");
 	if (IS_ERR(drvdata->clk))
 		return PTR_ERR(drvdata->clk);
@@ -176,6 +737,12 @@
 
 	clk_disable_unprepare(drvdata->clk);
 
+	if (pdev->dev.of_node) {
+		ret = tpiu_parse_of_data(pdev, drvdata);
+		if (ret)
+			return ret;
+	}
+
 	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
 	if (!desc)
 		return -ENOMEM;
@@ -184,6 +751,7 @@
 	desc->ops = &tpiu_cs_ops;
 	desc->pdata = pdev->dev.platform_data;
 	desc->dev = &pdev->dev;
+	desc->groups = tpiu_attr_grps;
 	desc->owner = THIS_MODULE;
 	drvdata->csdev = coresight_register(desc);
 	if (IS_ERR(drvdata->csdev))
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index fe8cf57..583add9 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -41,6 +41,7 @@
 #define CRYPTO_CONFIG_RESET 0xE001F
 #define QCE_MAX_NUM_DSCR    0x400
 #define QCE_SIZE_BAM_DSCR   0x08
+#define QCE_SECTOR_SIZE	    0x200
 
 static DEFINE_MUTEX(bam_register_cnt);
 struct bam_registration_info {
@@ -445,6 +446,7 @@
 	uint32_t enck_size_in_word = 0;
 	uint32_t key_size;
 	bool use_hw_key = false;
+	bool use_pipe_key = false;
 	uint32_t encr_cfg = 0;
 	uint32_t ivsize = creq->ivsize;
 	int i;
@@ -456,6 +458,7 @@
 		key_size = creq->encklen;
 
 	_byte_stream_to_net_words(enckey32, creq->enckey, key_size);
+	pce = cmdlistinfo->go_proc;
 
 	/* check for null key. If null, use hw key*/
 	enck_size_in_word = key_size/sizeof(uint32_t);
@@ -463,15 +466,22 @@
 		if (enckey32[i] != 0)
 			break;
 	}
-	pce = cmdlistinfo->go_proc;
 	if (i == enck_size_in_word) {
 		use_hw_key = true;
 		pce->addr = (uint32_t)(CRYPTO_GOPROC_QC_KEY_REG +
 						pce_dev->phy_iobase);
-	} else {
+	}
+	if (use_hw_key == false) {
+		for (i = 0; i < enck_size_in_word; i++) {
+			if (enckey32[i] != 0xFFFFFFFF)
+				break;
+		}
+		if (i == enck_size_in_word)
+			use_pipe_key = true;
+	}
+	if (use_hw_key == false)
 		pce->addr = (uint32_t)(CRYPTO_GOPROC_REG +
 						pce_dev->phy_iobase);
-	}
 
 	if ((creq->op == QCE_REQ_AEAD) && (creq->mode == QCE_MODE_CCM)) {
 		uint32_t authklen32 = creq->encklen/sizeof(uint32_t);
@@ -600,7 +610,10 @@
 
 			/* write xts du size */
 			pce = cmdlistinfo->encr_xts_du_size;
-			pce->data = creq->cryptlen;
+			if (use_pipe_key == true)
+				pce->data = QCE_SECTOR_SIZE;
+			else
+				pce->data = creq->cryptlen;
 		}
 		if (creq->mode !=  QCE_MODE_ECB) {
 			if (creq->mode ==  QCE_MODE_XTS)
@@ -653,6 +666,10 @@
 		break;
 	} /* end of switch (creq->mode)  */
 
+	if (use_pipe_key)
+		encr_cfg |= (CRYPTO_USE_PIPE_KEY_ENCR_ENABLED
+					<< CRYPTO_USE_PIPE_KEY_ENCR);
+
 	/* write encr seg cfg */
 	pce = cmdlistinfo->encr_seg_cfg;
 	if ((creq->alg == CIPHER_ALG_DES) || (creq->alg == CIPHER_ALG_3DES)) {
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 1f73d47..33e6fed 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -54,6 +54,11 @@
 		.name	= ION_VMALLOC_HEAP_NAME,
 	},
 	{
+		.id	= ION_SYSTEM_CONTIG_HEAP_ID,
+		.type	= ION_HEAP_TYPE_SYSTEM_CONTIG,
+		.name	= ION_KMALLOC_HEAP_NAME,
+	},
+	{
 		.id	= ION_CP_MM_HEAP_ID,
 		.type	= ION_HEAP_TYPE_SECURE_DMA,
 		.name	= ION_MM_HEAP_NAME,
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index d7bf36e..a76ed87 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -470,7 +470,7 @@
 	int offset = type0_pkt_offset(*ptr);
 	int i;
 
-	for (i = 0; i < size; i++, offset++) {
+	for (i = 0; i < size - 1; i++, offset++) {
 
 		/* Visiblity stream buffer */
 
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 9e0a147..202edc0 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -142,6 +142,7 @@
 #define RGB_LED_ENABLE_MASK		0xE0
 #define RGB_LED_SRC_MASK		0x03
 #define QPNP_LED_PWM_FLAGS	(PM_PWM_LUT_LOOP | PM_PWM_LUT_RAMP_UP)
+#define QPNP_LUT_RAMP_STEP_DEFAULT	255
 #define	PWM_LUT_MAX_SIZE		63
 #define RGB_LED_DISABLE			0x00
 
@@ -957,7 +958,7 @@
 				return -EINVAL;
 			}
 			rc = pwm_lut_config(led->rgb_cfg->pwm_dev,
-				led->rgb_cfg->pwm_period_us,
+				PM_PWM_PERIOD_MIN, /* ignored by hardware */
 				led->rgb_cfg->duty_cycles->duty_pcts,
 				led->rgb_cfg->lut_params);
 			if (rc < 0) {
@@ -1227,11 +1228,13 @@
 	else
 		return rc;
 
-	rc = of_property_read_u32(node, "qcom,pwm-us", &val);
-	if (!rc)
-		led->rgb_cfg->pwm_period_us = val;
-	else
-		return rc;
+	if (led->rgb_cfg->mode == RGB_MODE_PWM) {
+		rc = of_property_read_u32(node, "qcom,pwm-us", &val);
+		if (!rc)
+			led->rgb_cfg->pwm_period_us = val;
+		else
+			return rc;
+	}
 
 	if (led->rgb_cfg->mode == RGB_MODE_LPG) {
 		led->rgb_cfg->duty_cycles =
@@ -1243,12 +1246,6 @@
 			return -ENOMEM;
 		}
 
-		rc = of_property_read_u32(node, "qcom,duty-ms", &val);
-		if (!rc)
-			led->rgb_cfg->duty_cycles->duty_ms = (u8) val;
-		else
-			return rc;
-
 		prop = of_find_property(node, "qcom,duty-pcts",
 			&led->rgb_cfg->duty_cycles->num_duty_pcts);
 		if (!prop) {
@@ -1294,12 +1291,37 @@
 		} else
 			return rc;
 
+		led->rgb_cfg->lut_params.lut_pause_hi = 0;
+		rc = of_property_read_u32(node, "qcom,pause-hi", &val);
+		if (!rc)
+			led->rgb_cfg->lut_params.lut_pause_hi = (u8) val;
+		else if (rc != -EINVAL)
+			return rc;
+
+		led->rgb_cfg->lut_params.lut_pause_lo = 0;
+		rc = of_property_read_u32(node, "qcom,pause-lo", &val);
+		if (!rc)
+			led->rgb_cfg->lut_params.lut_pause_lo = (u8) val;
+		else if (rc != -EINVAL)
+			return rc;
+
+		led->rgb_cfg->lut_params.ramp_step_ms =
+				QPNP_LUT_RAMP_STEP_DEFAULT;
+		rc = of_property_read_u32(node, "qcom,ramp-step-ms", &val);
+		if (!rc)
+			led->rgb_cfg->lut_params.ramp_step_ms = (u8) val;
+		else if (rc != -EINVAL)
+			return rc;
+
+		led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
+		rc = of_property_read_u32(node, "qcom,lut-flags", &val);
+		if (!rc)
+			led->rgb_cfg->lut_params.flags = (u8) val;
+		else if (rc != -EINVAL)
+			return rc;
+
 		led->rgb_cfg->lut_params.idx_len =
 			led->rgb_cfg->duty_cycles->num_duty_pcts;
-		led->rgb_cfg->lut_params.lut_pause_hi = 0;
-		led->rgb_cfg->lut_params.lut_pause_lo = 0;
-		led->rgb_cfg->lut_params.ramp_step_ms = 255;
-		led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
 	}
 
 	return 0;
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index e4777e6..d1e9b9e 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -109,6 +109,15 @@
 		1280 * 270. It does not support auto focus. It supports
 		few special effects like saturation.
 
+config OV8825
+	bool "OmniVision OV8825 (BAYER 8MP)"
+	depends on MSMB_CAMERA
+	---help---
+		OmniVision 8 MP Bayer Sensor with auto focus.uses
+		2 mipi lanes, preview config = 1632*1224 30 fps,
+		snapshot config = 3264 * 2448 at 18 fps.
+		2 lanes max fps is 18, 4 lanes max fps is 24.
+
 config MSM_V4L2_VIDEO_OVERLAY_DEVICE
 	tristate "Qualcomm MSM V4l2 video overlay device"
 	---help---
@@ -119,7 +128,7 @@
 
 config MSMB_JPEG
 	tristate "Qualcomm MSM Jpeg Encoder Engine support"
-	depends on MSMB_CAMERA && ARCH_MSM8974
+	depends on MSMB_CAMERA && (ARCH_MSM8974 || ARCH_MSM8226)
 	---help---
 	  Enable support for Jpeg Encoder/Decoder
 	  Engine for 8974.
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 6b27048..32aa4ef 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -42,7 +42,7 @@
 };
 
 static void camera_pack_event(struct file *filep, int evt_id,
-	int command, struct v4l2_event *event)
+	int command, int value, struct v4l2_event *event)
 {
 	struct msm_v4l2_event_data *event_data =
 		(struct msm_v4l2_event_data *)&event->u.data[0];
@@ -55,6 +55,7 @@
 	event_data->command = command;
 	event_data->session_id = pvdev->vdev->num;
 	event_data->stream_id = sp->stream_id;
+	event_data->arg_value = value;
 }
 
 static int camera_check_event_status(struct v4l2_event *event)
@@ -76,7 +77,7 @@
 
 	/* can use cap->driver to make differentiation */
 	camera_pack_event(filep, MSM_CAMERA_GET_PARM,
-		MSM_CAMERA_PRIV_QUERY_CAP, &event);
+		MSM_CAMERA_PRIV_QUERY_CAP, -1, &event);
 
 	rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 	if (rc < 0)
@@ -96,7 +97,7 @@
 	if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 
 		camera_pack_event(filep, MSM_CAMERA_SET_PARM,
-			MSM_CAMERA_PRIV_S_CROP, &event);
+			MSM_CAMERA_PRIV_S_CROP, -1, &event);
 
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 		if (rc < 0)
@@ -116,7 +117,7 @@
 
 	if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		camera_pack_event(filep, MSM_CAMERA_GET_PARM,
-			MSM_CAMERA_PRIV_G_CROP, &event);
+			MSM_CAMERA_PRIV_G_CROP, -1, &event);
 
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 		if (rc < 0)
@@ -137,7 +138,7 @@
 	if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
 
 		camera_pack_event(filep, MSM_CAMERA_GET_PARM,
-			ctrl->id, &event);
+			ctrl->id, -1, &event);
 
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 		if (rc < 0)
@@ -156,7 +157,8 @@
 	struct v4l2_event event;
 
 	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
-		camera_pack_event(filep, MSM_CAMERA_GET_PARM, ctrl->id, &event);
+		camera_pack_event(filep, MSM_CAMERA_GET_PARM, ctrl->id, -1,
+			&event);
 
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 		if (rc < 0)
@@ -173,13 +175,16 @@
 {
 	int rc = 0;
 	struct v4l2_event event;
+	struct msm_v4l2_event_data *event_data;
 	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
-		camera_pack_event(filep, MSM_CAMERA_SET_PARM, ctrl->id, &event);
+		camera_pack_event(filep, MSM_CAMERA_SET_PARM, ctrl->id,
+		ctrl->value, &event);
 
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 		if (rc < 0)
 			return rc;
-
+		event_data = (struct msm_v4l2_event_data *)event.u.data;
+		ctrl->value = event_data->ret_value;
 		rc = camera_check_event_status(&event);
 	}
 
@@ -225,7 +230,7 @@
 
 	rc = vb2_streamon(&sp->vb2_q, buf_type);
 	camera_pack_event(filep, MSM_CAMERA_SET_PARM,
-		MSM_CAMERA_PRIV_STREAM_ON, &event);
+		MSM_CAMERA_PRIV_STREAM_ON, -1, &event);
 
 	rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 	if (rc < 0)
@@ -243,7 +248,7 @@
 	struct camera_v4l2_private *sp = fh_to_private(fh);
 
 	camera_pack_event(filep, MSM_CAMERA_SET_PARM,
-		MSM_CAMERA_PRIV_STREAM_OFF, &event);
+		MSM_CAMERA_PRIV_STREAM_OFF, -1, &event);
 
 	rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 	if (rc < 0)
@@ -263,7 +268,7 @@
 		struct v4l2_event event;
 
 		camera_pack_event(filep, MSM_CAMERA_GET_PARM,
-			MSM_CAMERA_PRIV_G_FMT, &event);
+			MSM_CAMERA_PRIV_G_FMT, -1, &event);
 
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 		if (rc < 0)
@@ -300,7 +305,7 @@
 					user_fmt->plane_sizes[i]);
 
 		camera_pack_event(filep, MSM_CAMERA_SET_PARM,
-			MSM_CAMERA_PRIV_S_FMT, &event);
+			MSM_CAMERA_PRIV_S_FMT, -1, &event);
 
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 		if (rc < 0)
@@ -342,7 +347,7 @@
 	struct camera_v4l2_private *sp = fh_to_private(fh);
 
 	camera_pack_event(filep, MSM_CAMERA_SET_PARM,
-		MSM_CAMERA_PRIV_NEW_STREAM, &event);
+		MSM_CAMERA_PRIV_NEW_STREAM, -1, &event);
 
 	rc = msm_create_stream(event_data->session_id,
 		event_data->stream_id, &sp->vb2_q);
@@ -510,7 +515,7 @@
 		if (rc < 0)
 			goto command_ack_q_fail;
 
-		camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, &event);
+		camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, -1, &event);
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
 		if (rc < 0)
 			goto post_fail;
@@ -568,7 +573,7 @@
 
 	if (atomic_read(&pvdev->opened) == 0) {
 
-		camera_pack_event(filep, MSM_CAMERA_DEL_SESSION, 0, &event);
+		camera_pack_event(filep, MSM_CAMERA_DEL_SESSION, 0, -1, &event);
 
 		/* Donot wait, imaging server may have crashed */
 		msm_post_event(&event, -1);
@@ -579,7 +584,7 @@
 
 	} else {
 		camera_pack_event(filep, MSM_CAMERA_SET_PARM,
-			MSM_CAMERA_PRIV_DEL_STREAM, &event);
+			MSM_CAMERA_PRIV_DEL_STREAM, -1, &event);
 
 		/* Donot wait, imaging server may have crashed */
 		msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index 6f941f7..62911bf 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -7,5 +7,6 @@
 obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
 obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
 obj-$(CONFIG_IMX135) += imx135.o
+obj-$(CONFIG_OV8825) += ov8825.o
 obj-$(CONFIG_OV2720) += ov2720.o
 obj-$(CONFIG_MT9M114) += mt9m114.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index e939c2b..e1b978f 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -27,7 +27,6 @@
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
 #endif
 
-static struct msm_actuator_ctrl_t msm_actuator_t;
 static struct msm_actuator msm_vcm_actuator_table;
 static struct msm_actuator msm_piezo_actuator_table;
 
@@ -618,103 +617,21 @@
 	.close = msm_actuator_close,
 };
 
-static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
-	const struct i2c_device_id *id)
+static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
 {
-	int rc = 0;
-	struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+	struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
+	void __user *argp = (void __user *)arg;
 	CDBG("Enter\n");
-
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		pr_err("i2c_check_functionality failed\n");
-		goto probe_failure;
+	CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
+	switch (cmd) {
+	case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+		return msm_actuator_get_subdev_id(a_ctrl, argp);
+	case VIDIOC_MSM_ACTUATOR_CFG:
+		return msm_actuator_config(a_ctrl, argp);
+	default:
+		return -ENOIOCTLCMD;
 	}
-
-	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
-	CDBG("client = %x\n", (unsigned int) client);
-	act_ctrl_t->i2c_client.client = client;
-	/* Set device type as I2C */
-	act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
-	act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
-
-	/* Assign name for sub device */
-	snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
-		"%s", act_ctrl_t->i2c_driver->driver.name);
-
-	/* Initialize sub device */
-	v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
-		act_ctrl_t->i2c_client.client,
-		act_ctrl_t->act_v4l2_subdev_ops);
-	v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
-	act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
-	act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-	media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
-	act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
-	act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
-	msm_sd_register(&act_ctrl_t->msm_sd);
-	CDBG("succeeded\n");
-	CDBG("Exit\n");
-
-probe_failure:
-	return rc;
-}
-
-static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
-{
-	int32_t rc = 0;
-	struct msm_camera_cci_client *cci_client = NULL;
-	CDBG("Enter\n");
-
-	if (!pdev->dev.of_node) {
-		pr_err("of_node NULL\n");
-		return -EINVAL;
-	}
-
-	rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
-		&pdev->id);
-	CDBG("cell-index %d, rc %d\n", pdev->id, rc);
-	if (rc < 0) {
-		pr_err("failed rc %d\n", rc);
-		return rc;
-	}
-
-	rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
-		&msm_actuator_t.cci_master);
-	CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t.cci_master, rc);
-	if (rc < 0) {
-		pr_err("failed rc %d\n", rc);
-		return rc;
-	}
-
-	msm_actuator_t.cam_name = pdev->id;
-
-	/* Set platform device handle */
-	msm_actuator_t.pdev = pdev;
-	/* Set device type as platform device */
-	msm_actuator_t.act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
-	msm_actuator_t.i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
-	msm_actuator_t.i2c_client.cci_client = kzalloc(sizeof(
-		struct msm_camera_cci_client), GFP_KERNEL);
-	if (!msm_actuator_t.i2c_client.cci_client) {
-		pr_err("failed no memory\n");
-		return -ENOMEM;
-	}
-
-	cci_client = msm_actuator_t.i2c_client.cci_client;
-	cci_client->cci_subdev = msm_cci_get_subdev();
-	v4l2_subdev_init(&msm_actuator_t.msm_sd.sd,
-		msm_actuator_t.act_v4l2_subdev_ops);
-	v4l2_set_subdevdata(&msm_actuator_t.msm_sd.sd, &msm_actuator_t);
-	msm_actuator_t.msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
-	msm_actuator_t.msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-	snprintf(msm_actuator_t.msm_sd.sd.name,
-		ARRAY_SIZE(msm_actuator_t.msm_sd.sd.name), "msm_actuator");
-	media_entity_init(&msm_actuator_t.msm_sd.sd.entity, 0, NULL, 0);
-	msm_actuator_t.msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
-	msm_actuator_t.msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
-	msm_sd_register(&msm_actuator_t.msm_sd);
-	CDBG("Exit\n");
-	return rc;
 }
 
 static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
@@ -735,64 +652,6 @@
 	return rc;
 }
 
-static const struct i2c_device_id msm_actuator_i2c_id[] = {
-	{"msm_actuator", (kernel_ulong_t)&msm_actuator_t},
-	{ }
-};
-
-static struct i2c_driver msm_actuator_i2c_driver = {
-	.id_table = msm_actuator_i2c_id,
-	.probe  = msm_actuator_i2c_probe,
-	.remove = __exit_p(msm_actuator_i2c_remove),
-	.driver = {
-		.name = "msm_actuator",
-	},
-};
-
-static const struct of_device_id msm_actuator_dt_match[] = {
-	{.compatible = "qcom,actuator", .data = &msm_actuator_t},
-	{}
-};
-
-MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
-
-static struct platform_driver msm_actuator_platform_driver = {
-	.driver = {
-		.name = "qcom,actuator",
-		.owner = THIS_MODULE,
-		.of_match_table = msm_actuator_dt_match,
-	},
-};
-
-static int __init msm_actuator_init_module(void)
-{
-	int32_t rc = 0;
-	CDBG("Enter\n");
-	rc = platform_driver_probe(msm_actuator_t.pdriver,
-		msm_actuator_platform_probe);
-	if (!rc)
-		return rc;
-	CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
-	return i2c_add_driver(msm_actuator_t.i2c_driver);
-}
-
-static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
-			unsigned int cmd, void *arg)
-{
-	struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
-	void __user *argp = (void __user *)arg;
-	CDBG("Enter\n");
-	CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
-	switch (cmd) {
-	case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
-		return msm_actuator_get_subdev_id(a_ctrl, argp);
-	case VIDIOC_MSM_ACTUATOR_CFG:
-		return msm_actuator_config(a_ctrl, argp);
-	default:
-		return -ENOIOCTLCMD;
-	}
-}
-
 static int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
 {
 	int rc = 0;
@@ -817,17 +676,156 @@
 	.core = &msm_actuator_subdev_core_ops,
 };
 
-static struct msm_actuator_ctrl_t msm_actuator_t = {
-	.i2c_driver = &msm_actuator_i2c_driver,
-	.pdriver = &msm_actuator_platform_driver,
-	.act_v4l2_subdev_ops = &msm_actuator_subdev_ops,
+static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int rc = 0;
+	struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+	CDBG("Enter\n");
 
-	.curr_step_pos = 0,
-	.curr_region_index = 0,
-	.actuator_mutex = &msm_actuator_mutex,
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("i2c_check_functionality failed\n");
+		goto probe_failure;
+	}
 
+	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
+	CDBG("client = %x\n", (unsigned int) client);
+	act_ctrl_t->i2c_client.client = client;
+	/* Set device type as I2C */
+	act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
+	act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
+	act_ctrl_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
+	act_ctrl_t->actuator_mutex = &msm_actuator_mutex;
+	/* Assign name for sub device */
+	snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
+		"%s", act_ctrl_t->i2c_driver->driver.name);
+
+	/* Initialize sub device */
+	v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
+		act_ctrl_t->i2c_client.client,
+		act_ctrl_t->act_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
+	act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+	act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
+	act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+	msm_sd_register(&act_ctrl_t->msm_sd);
+	CDBG("succeeded\n");
+	CDBG("Exit\n");
+
+probe_failure:
+	return rc;
+}
+
+static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	struct msm_camera_cci_client *cci_client = NULL;
+	struct msm_actuator_ctrl_t *msm_actuator_t = NULL;
+	CDBG("Enter\n");
+
+	if (!pdev->dev.of_node) {
+		pr_err("of_node NULL\n");
+		return -EINVAL;
+	}
+
+	msm_actuator_t = kzalloc(sizeof(struct msm_actuator_ctrl_t),
+		GFP_KERNEL);
+	if (!msm_actuator_t) {
+		pr_err("%s:%d failed no memory\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
+		&pdev->id);
+	CDBG("cell-index %d, rc %d\n", pdev->id, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
+		&msm_actuator_t->cci_master);
+	CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t->cci_master, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	msm_actuator_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
+	msm_actuator_t->actuator_mutex = &msm_actuator_mutex;
+	msm_actuator_t->cam_name = pdev->id;
+
+	/* Set platform device handle */
+	msm_actuator_t->pdev = pdev;
+	/* Set device type as platform device */
+	msm_actuator_t->act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+	msm_actuator_t->i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
+	msm_actuator_t->i2c_client.cci_client = kzalloc(sizeof(
+		struct msm_camera_cci_client), GFP_KERNEL);
+	if (!msm_actuator_t->i2c_client.cci_client) {
+		pr_err("failed no memory\n");
+		return -ENOMEM;
+	}
+
+	cci_client = msm_actuator_t->i2c_client.cci_client;
+	cci_client->cci_subdev = msm_cci_get_subdev();
+	v4l2_subdev_init(&msm_actuator_t->msm_sd.sd,
+		msm_actuator_t->act_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&msm_actuator_t->msm_sd.sd, msm_actuator_t);
+	msm_actuator_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+	msm_actuator_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(msm_actuator_t->msm_sd.sd.name,
+		ARRAY_SIZE(msm_actuator_t->msm_sd.sd.name), "msm_actuator");
+	media_entity_init(&msm_actuator_t->msm_sd.sd.entity, 0, NULL, 0);
+	msm_actuator_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	msm_actuator_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+	msm_sd_register(&msm_actuator_t->msm_sd);
+	CDBG("Exit\n");
+	return rc;
+}
+
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+	{"msm_actuator", (kernel_ulong_t)NULL},
+	{ }
 };
 
+static struct i2c_driver msm_actuator_i2c_driver = {
+	.id_table = msm_actuator_i2c_id,
+	.probe  = msm_actuator_i2c_probe,
+	.remove = __exit_p(msm_actuator_i2c_remove),
+	.driver = {
+		.name = "msm_actuator",
+	},
+};
+
+static const struct of_device_id msm_actuator_dt_match[] = {
+	{.compatible = "qcom,actuator", .data = NULL},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
+
+static struct platform_driver msm_actuator_platform_driver = {
+	.driver = {
+		.name = "qcom,actuator",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_actuator_dt_match,
+	},
+};
+
+static int __init msm_actuator_init_module(void)
+{
+	int32_t rc = 0;
+	CDBG("Enter\n");
+	rc = platform_driver_probe(&msm_actuator_platform_driver,
+		msm_actuator_platform_probe);
+	if (!rc)
+		return rc;
+	CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&msm_actuator_i2c_driver);
+}
+
 static struct msm_actuator msm_vcm_actuator_table = {
 	.act_type = ACTUATOR_VCM,
 	.func_tbl = {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov8825.c b/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
new file mode 100644
index 0000000..b56eb10
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
@@ -0,0 +1,167 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "msm_sensor.h"
+#define OV8825_SENSOR_NAME "ov8825"
+DEFINE_MSM_MUTEX(ov8825_mut);
+
+static struct msm_sensor_ctrl_t ov8825_s_ctrl;
+
+static struct msm_sensor_power_setting ov8825_power_setting[] = {
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VIO,
+		.config_val = 0,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VANA,
+		.config_val = 0,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VDIG,
+		.config_val = 0,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VAF,
+		.config_val = 0,
+		.delay = 15,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 15,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_CLK,
+		.seq_val = SENSOR_CAM_MCLK,
+		.config_val = 24000000,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_I2C_MUX,
+		.seq_val = 0,
+		.config_val = 0,
+		.delay = 0,
+	},
+};
+
+static struct v4l2_subdev_info ov8825_subdev_info[] = {
+	{
+		.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.fmt    = 1,
+		.order    = 0,
+	},
+};
+
+static const struct i2c_device_id ov8825_i2c_id[] = {
+	{OV8825_SENSOR_NAME, (kernel_ulong_t)&ov8825_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver ov8825_i2c_driver = {
+	.id_table = ov8825_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = OV8825_SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client ov8825_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id ov8825_dt_match[] = {
+	{.compatible = "qcom,ov8825", .data = &ov8825_s_ctrl},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, ov8825_dt_match);
+
+static struct platform_driver ov8825_platform_driver = {
+	.driver = {
+		.name = "qcom,ov8825",
+		.owner = THIS_MODULE,
+		.of_match_table = ov8825_dt_match,
+	},
+};
+
+static int32_t ov8825_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	const struct of_device_id *match;
+	match = of_match_device(ov8825_dt_match, &pdev->dev);
+	rc = msm_sensor_platform_probe(pdev, match->data);
+	return rc;
+}
+
+static int __init ov8825_init_module(void)
+{
+	int32_t rc = 0;
+	pr_info("%s:%d\n", __func__, __LINE__);
+	rc = platform_driver_probe(&ov8825_platform_driver,
+		ov8825_platform_probe);
+	if (!rc)
+		return rc;
+	pr_err("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&ov8825_i2c_driver);
+}
+
+static void __exit ov8825_exit_module(void)
+{
+	pr_info("%s:%d\n", __func__, __LINE__);
+	if (ov8825_s_ctrl.pdev) {
+		msm_sensor_free_sensor_data(&ov8825_s_ctrl);
+		platform_driver_unregister(&ov8825_platform_driver);
+	} else
+		i2c_del_driver(&ov8825_i2c_driver);
+	return;
+}
+
+static struct msm_sensor_ctrl_t ov8825_s_ctrl = {
+	.sensor_i2c_client = &ov8825_sensor_i2c_client,
+	.power_setting_array.power_setting = ov8825_power_setting,
+	.power_setting_array.size = ARRAY_SIZE(ov8825_power_setting),
+	.msm_sensor_mutex = &ov8825_mut,
+	.sensor_v4l2_subdev_info = ov8825_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov8825_subdev_info),
+};
+
+module_init(ov8825_init_module);
+module_exit(ov8825_exit_module);
+MODULE_DESCRIPTION("ov8825");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c b/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c
index 6ec1994..76ce0c0 100644
--- a/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c
+++ b/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c
@@ -19,8 +19,6 @@
 #include "mpq_stream_buffer.h"
 
 
-
-
 int mpq_streambuffer_init(
 		struct mpq_streambuffer *sbuff,
 		enum mpq_streambuffer_mode mode,
@@ -29,7 +27,8 @@
 		void *packet_buff,
 		size_t packet_buff_size)
 {
-	if ((NULL == sbuff) || (NULL == data_buffers) || (NULL == packet_buff))
+	if ((NULL == sbuff) || (NULL == data_buffers) ||
+		(NULL == packet_buff) || (data_buff_num == 0))
 		return -EINVAL;
 
 	if (data_buff_num > 1) {
@@ -41,7 +40,7 @@
 			data_buffers,
 			data_buff_num *
 			sizeof(struct mpq_streambuffer_buffer_desc));
-	} else if (data_buff_num == 1) {
+	} else {
 		if (mode != MPQ_STREAMBUFFER_BUFFER_MODE_RING)
 			return -EINVAL;
 		/* Single ring-buffer */
@@ -58,12 +57,38 @@
 }
 EXPORT_SYMBOL(mpq_streambuffer_init);
 
+void mpq_streambuffer_terminate(struct mpq_streambuffer *sbuff)
+{
+	spin_lock(&sbuff->packet_data.lock);
+	spin_lock(&sbuff->raw_data.lock);
+	sbuff->packet_data.error = -ENODEV;
+	sbuff->raw_data.error = -ENODEV;
+	spin_unlock(&sbuff->raw_data.lock);
+	spin_unlock(&sbuff->packet_data.lock);
+
+	wake_up_all(&sbuff->raw_data.queue);
+	wake_up_all(&sbuff->packet_data.queue);
+}
+EXPORT_SYMBOL(mpq_streambuffer_terminate);
 
 ssize_t mpq_streambuffer_pkt_next(
 		struct mpq_streambuffer *sbuff,
 		ssize_t idx, size_t *pktlen)
 {
-	return dvb_ringbuffer_pkt_next(&sbuff->packet_data, idx, pktlen);
+	ssize_t packet_idx;
+
+	spin_lock(&sbuff->packet_data.lock);
+
+	/* buffer was released, return no packet available */
+	if (sbuff->packet_data.error == -ENODEV) {
+		spin_unlock(&sbuff->packet_data.lock);
+		return -ENODEV;
+	}
+
+	packet_idx = dvb_ringbuffer_pkt_next(&sbuff->packet_data, idx, pktlen);
+	spin_unlock(&sbuff->packet_data.lock);
+
+	return packet_idx;
 }
 EXPORT_SYMBOL(mpq_streambuffer_pkt_next);
 
@@ -77,6 +102,14 @@
 	size_t ret;
 	size_t read_len;
 
+	spin_lock(&sbuff->packet_data.lock);
+
+	/* buffer was released, return no packet available */
+	if (sbuff->packet_data.error == -ENODEV) {
+		spin_unlock(&sbuff->packet_data.lock);
+		return -ENODEV;
+	}
+
 	/* read-out the packet header first */
 	ret = dvb_ringbuffer_pkt_read(
 				&sbuff->packet_data, idx, 0,
@@ -84,8 +117,10 @@
 				sizeof(struct mpq_streambuffer_packet_header));
 
 	/* verify length, at least packet header should exist */
-	if (ret != sizeof(struct mpq_streambuffer_packet_header))
+	if (ret != sizeof(struct mpq_streambuffer_packet_header)) {
+		spin_unlock(&sbuff->packet_data.lock);
 		return -EINVAL;
+	}
 
 	read_len = ret;
 
@@ -98,12 +133,16 @@
 				user_data,
 				packet->user_data_len);
 
-		if (ret < 0)
+		if (ret < 0) {
+			spin_unlock(&sbuff->packet_data.lock);
 			return ret;
+		}
 
 		read_len += ret;
 	}
 
+	spin_unlock(&sbuff->packet_data.lock);
+
 	return read_len;
 }
 EXPORT_SYMBOL(mpq_streambuffer_pkt_read);
@@ -120,12 +159,22 @@
 	if (NULL == sbuff)
 		return -EINVAL;
 
+	spin_lock(&sbuff->packet_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->packet_data.error == -ENODEV) {
+		spin_unlock(&sbuff->packet_data.lock);
+		return -ENODEV;
+	}
+
 	/* read-out the packet header first */
 	ret = dvb_ringbuffer_pkt_read(&sbuff->packet_data, idx,
 			0,
 			(u8 *)&packet,
 			sizeof(struct mpq_streambuffer_packet_header));
 
+	spin_unlock(&sbuff->packet_data.lock);
+
 	if (ret != sizeof(struct mpq_streambuffer_packet_header))
 		return -EINVAL;
 
@@ -138,6 +187,17 @@
 			return ret;
 	}
 
+	spin_lock(&sbuff->packet_data.lock);
+	spin_lock(&sbuff->raw_data.lock);
+
+	/* check if buffer was released */
+	if ((sbuff->packet_data.error == -ENODEV) ||
+		(sbuff->raw_data.error == -ENODEV)) {
+		spin_unlock(&sbuff->raw_data.lock);
+		spin_unlock(&sbuff->packet_data.lock);
+		return -ENODEV;
+	}
+
 	/* Move read pointer to the next linear buffer for subsequent reads */
 	if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) &&
 		(packet.raw_data_len > 0)) {
@@ -159,6 +219,9 @@
 	/* Now clear the packet from the packet header */
 	dvb_ringbuffer_pkt_dispose(&sbuff->packet_data, idx);
 
+	spin_unlock(&sbuff->raw_data.lock);
+	spin_unlock(&sbuff->packet_data.lock);
+
 	if (sbuff->cb)
 		sbuff->cb(sbuff, sbuff->cb_user_data);
 
@@ -177,12 +240,22 @@
 	if ((NULL == sbuff) || (NULL == packet))
 		return -EINVAL;
 
+	spin_lock(&sbuff->packet_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->packet_data.error == -ENODEV) {
+		spin_unlock(&sbuff->packet_data.lock);
+		return -ENODEV;
+	}
+
 	len = sizeof(struct mpq_streambuffer_packet_header) +
 		packet->user_data_len;
 
 	/* Make sure enough space available for packet header */
-	if (dvb_ringbuffer_free(&sbuff->packet_data) < len)
+	if (dvb_ringbuffer_free(&sbuff->packet_data) < len) {
+		spin_unlock(&sbuff->packet_data.lock);
 		return -ENOSPC;
+	}
 
 	/* Starting writing packet header */
 	idx = dvb_ringbuffer_pkt_start(&sbuff->packet_data, len);
@@ -202,20 +275,22 @@
 	/* Move write pointer to next linear buffer for subsequent writes */
 	if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) &&
 		(packet->raw_data_len > 0)) {
-		if (sbuff->pending_buffers_count == sbuff->buffers_num)
+		if (sbuff->pending_buffers_count == sbuff->buffers_num) {
+			spin_unlock(&sbuff->packet_data.lock);
 			return -ENOSPC;
+		}
 		DVB_RINGBUFFER_PUSH(&sbuff->raw_data,
 				sizeof(struct mpq_streambuffer_buffer_desc));
 		sbuff->pending_buffers_count++;
 	}
 
+	spin_unlock(&sbuff->packet_data.lock);
 	wake_up_all(&sbuff->packet_data.queue);
 
 	return 0;
 }
 EXPORT_SYMBOL(mpq_streambuffer_pkt_write);
 
-
 ssize_t mpq_streambuffer_data_write(
 			struct mpq_streambuffer *sbuff,
 			const u8 *buf, size_t len)
@@ -225,15 +300,27 @@
 	if ((NULL == sbuff) || (NULL == buf))
 		return -EINVAL;
 
+	spin_lock(&sbuff->raw_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return -ENODEV;
+	}
+
 	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
-		if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len))
+		if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len)) {
+			spin_unlock(&sbuff->raw_data.lock);
 			return -ENOSPC;
+		}
 		/*
 		 * Secure buffers are not permitted to be mapped into kernel
 		 * memory, and so buffer base address may be NULL
 		 */
-		if (NULL == sbuff->raw_data.data)
+		if (NULL == sbuff->raw_data.data) {
+			spin_unlock(&sbuff->raw_data.lock);
 			return -EPERM;
+		}
 		res = dvb_ringbuffer_write(&sbuff->raw_data, buf, len);
 		wake_up_all(&sbuff->raw_data.queue);
 	} else {
@@ -247,8 +334,10 @@
 		 * Secure buffers are not permitted to be mapped into kernel
 		 * memory, and so buffer base address may be NULL
 		 */
-		if (NULL == desc->base)
+		if (NULL == desc->base) {
+			spin_unlock(&sbuff->raw_data.lock);
 			return -EPERM;
+		}
 
 		if ((sbuff->pending_buffers_count == sbuff->buffers_num) ||
 			((desc->size - desc->write_ptr) < len)) {
@@ -259,6 +348,7 @@
 				sbuff->buffers_num,
 				desc->write_ptr,
 				desc->size);
+			spin_unlock(&sbuff->raw_data.lock);
 			return -ENOSPC;
 		}
 		memcpy(desc->base + desc->write_ptr, buf, len);
@@ -266,6 +356,7 @@
 		res = len;
 	}
 
+	spin_unlock(&sbuff->raw_data.lock);
 	return res;
 }
 EXPORT_SYMBOL(mpq_streambuffer_data_write);
@@ -278,9 +369,19 @@
 	if (NULL == sbuff)
 		return -EINVAL;
 
+	spin_lock(&sbuff->raw_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return -ENODEV;
+	}
+
 	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
-		if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len))
+		if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len)) {
+			spin_unlock(&sbuff->raw_data.lock);
 			return -ENOSPC;
+		}
 
 		DVB_RINGBUFFER_PUSH(&sbuff->raw_data, len);
 		wake_up_all(&sbuff->raw_data.queue);
@@ -295,11 +396,13 @@
 			MPQ_DVB_ERR_PRINT(
 				"%s: No space available!\n",
 				__func__);
+			spin_unlock(&sbuff->raw_data.lock);
 			return -ENOSPC;
 		}
 		desc->write_ptr += len;
 	}
 
+	spin_unlock(&sbuff->raw_data.lock);
 	return 0;
 }
 EXPORT_SYMBOL(mpq_streambuffer_data_write_deposit);
@@ -314,13 +417,23 @@
 	if ((NULL == sbuff) || (NULL == buf))
 		return -EINVAL;
 
+	spin_lock(&sbuff->raw_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return -ENODEV;
+	}
+
 	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
 		/*
 		 * Secure buffers are not permitted to be mapped into kernel
 		 * memory, and so buffer base address may be NULL
 		 */
-		if (NULL == sbuff->raw_data.data)
+		if (NULL == sbuff->raw_data.data) {
+			spin_unlock(&sbuff->raw_data.lock);
 			return -EPERM;
+		}
 
 		actual_len = dvb_ringbuffer_avail(&sbuff->raw_data);
 		if (actual_len < len)
@@ -340,8 +453,10 @@
 		 * Secure buffers are not permitted to be mapped into kernel
 		 * memory, and so buffer base address may be NULL
 		 */
-		if (NULL == desc->base)
+		if (NULL == desc->base) {
+			spin_unlock(&sbuff->raw_data.lock);
 			return -EPERM;
+		}
 
 		actual_len = (desc->write_ptr - desc->read_ptr);
 		if (actual_len < len)
@@ -350,6 +465,7 @@
 		desc->read_ptr += len;
 	}
 
+	spin_unlock(&sbuff->raw_data.lock);
 	return len;
 }
 EXPORT_SYMBOL(mpq_streambuffer_data_read);
@@ -364,6 +480,10 @@
 	if ((NULL == sbuff) || (NULL == buf))
 		return -EINVAL;
 
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV)
+		return -ENODEV;
+
 	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
 		/*
 		 * Secure buffers are not permitted to be mapped into kernel
@@ -397,6 +517,7 @@
 			len = actual_len;
 		if (copy_to_user(buf, desc->base + desc->read_ptr, len))
 			return -EFAULT;
+
 		desc->read_ptr += len;
 	}
 
@@ -404,7 +525,6 @@
 }
 EXPORT_SYMBOL(mpq_streambuffer_data_read_user);
 
-
 int mpq_streambuffer_data_read_dispose(
 			struct mpq_streambuffer *sbuff,
 			size_t len)
@@ -412,9 +532,19 @@
 	if (NULL == sbuff)
 		return -EINVAL;
 
+	spin_lock(&sbuff->raw_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return -ENODEV;
+	}
+
 	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
-		if (unlikely(dvb_ringbuffer_avail(&sbuff->raw_data) < len))
+		if (unlikely(dvb_ringbuffer_avail(&sbuff->raw_data) < len)) {
+			spin_unlock(&sbuff->raw_data.lock);
 			return -EINVAL;
+		}
 
 		DVB_RINGBUFFER_SKIP(&sbuff->raw_data, len);
 		wake_up_all(&sbuff->raw_data.queue);
@@ -429,6 +559,8 @@
 			desc->read_ptr += len;
 	}
 
+	spin_unlock(&sbuff->raw_data.lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mpq_streambuffer_data_read_dispose);
@@ -444,6 +576,14 @@
 	if ((NULL == sbuff) || (NULL == handle))
 		return -EINVAL;
 
+	spin_lock(&sbuff->raw_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return -ENODEV;
+	}
+
 	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
 		*handle = sbuff->buffers[0].handle;
 	} else {
@@ -455,6 +595,9 @@
 				&sbuff->raw_data.data[sbuff->raw_data.pwrite];
 		*handle = desc->handle;
 	}
+
+	spin_unlock(&sbuff->raw_data.lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mpq_streambuffer_get_buffer_handle);
@@ -484,15 +627,29 @@
 	if (NULL == sbuff)
 		return -EINVAL;
 
-	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode)
-		return dvb_ringbuffer_free(&sbuff->raw_data);
+	spin_lock(&sbuff->raw_data.lock);
 
-	if (sbuff->pending_buffers_count == sbuff->buffers_num)
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return -ENODEV;
+	}
+
+	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return dvb_ringbuffer_free(&sbuff->raw_data);
+	}
+
+	if (sbuff->pending_buffers_count == sbuff->buffers_num) {
+		spin_unlock(&sbuff->raw_data.lock);
 		return 0;
+	}
 
 	desc = (struct mpq_streambuffer_buffer_desc *)
 		&sbuff->raw_data.data[sbuff->raw_data.pwrite];
 
+	spin_unlock(&sbuff->raw_data.lock);
+
 	return desc->size - desc->write_ptr;
 }
 EXPORT_SYMBOL(mpq_streambuffer_data_free);
@@ -506,12 +663,25 @@
 	if (NULL == sbuff)
 		return -EINVAL;
 
-	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode)
-		return dvb_ringbuffer_avail(&sbuff->raw_data);
+	spin_lock(&sbuff->raw_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return -ENODEV;
+	}
+
+	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+		ssize_t avail = dvb_ringbuffer_avail(&sbuff->raw_data);
+		spin_unlock(&sbuff->raw_data.lock);
+		return avail;
+	}
 
 	desc = (struct mpq_streambuffer_buffer_desc *)
 		&sbuff->raw_data.data[sbuff->raw_data.pread];
 
+	spin_unlock(&sbuff->raw_data.lock);
+
 	return desc->write_ptr - desc->read_ptr;
 }
 EXPORT_SYMBOL(mpq_streambuffer_data_avail);
@@ -524,6 +694,14 @@
 	if (NULL == sbuff)
 		return -EINVAL;
 
+	spin_lock(&sbuff->raw_data.lock);
+
+	/* check if buffer was released */
+	if (sbuff->raw_data.error == -ENODEV) {
+		spin_unlock(&sbuff->raw_data.lock);
+		return -ENODEV;
+	}
+
 	if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
 		if (read_offset)
 			*read_offset = sbuff->raw_data.pread;
@@ -544,6 +722,8 @@
 		}
 	}
 
+	spin_unlock(&sbuff->raw_data.lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mpq_streambuffer_get_data_rw_offset);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 9be4704..83b9bb3 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -1469,7 +1469,6 @@
 			dec_buffs->buffers_size,
 			dec_buffs->is_linear);
 
-	feed_data->buffer_desc.decoder_buffers_num = dec_buffs->buffers_num;
 	if (0 == dec_buffs->buffers_num)
 		ret = mpq_dmx_init_internal_buffers(
 			feed_data, dec_buffs, client);
@@ -1515,6 +1514,8 @@
 
 	mpq_adapter_unregister_stream_if(feed_data->stream_interface);
 
+	mpq_streambuffer_terminate(video_buffer);
+
 	vfree(video_buffer->packet_data.data);
 
 	buf_num = feed_data->buffer_desc.decoder_buffers_num;
diff --git a/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h b/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h
index 3804fb2..1707c85 100644
--- a/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h
+++ b/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. 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
@@ -211,6 +211,18 @@
 		size_t packet_buff_size);
 
 /**
+ * mpq_streambuffer_terminate - Terminate stream buffer
+ *
+ * @sbuff: The buffer to terminate
+ *
+ * The function sets the the buffers error flags to ENODEV
+ * and wakeup any waiting threads on the buffer queues.
+ * Threads waiting on the buffer queues should check if
+ * error was set.
+ */
+void mpq_streambuffer_terminate(struct mpq_streambuffer *sbuff);
+
+/**
  * mpq_streambuffer_packet_next - Returns index of next available packet.
  *
  * @sbuff: The stream buffer
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 3d11400..102b9b9 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -18,7 +18,7 @@
 #include <linux/init.h>
 #include <linux/version.h>
 #include <linux/platform_device.h>
-#include <linux/android_pmem.h>
+
 #include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/time.h>
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e8096d1..2573a16 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -639,6 +639,15 @@
 	  to the fuse block. Currently this is supported only
 	  on FSM targets.
 
+config QPNP_MISC
+	tristate "QPNP Misc Peripheral"
+	depends on SPMI
+	help
+	  Say 'y' here to include support for the Qualcomm QPNP MISC
+	  peripheral. The MISC peripheral holds the USB ID interrupt
+	  and the driver provides an API to check if this interrupt
+	  is available on the current PMIC chip.
+
 config USB_HSIC_SMSC_HUB
 	tristate "Support for HSIC based MSM on-chip SMSC3503 HUB"
 	depends on USB_EHCI_MSM_HSIC
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f80f3f2..327d1ec 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -70,3 +70,4 @@
 obj-$(CONFIG_QSEECOM) += qseecom.o
 obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
 obj-$(CONFIG_TI_DRV2667) += ti_drv2667.o
+obj-$(CONFIG_QPNP_MISC) += qpnp-misc.o
diff --git a/drivers/misc/qpnp-misc.c b/drivers/misc/qpnp-misc.c
new file mode 100644
index 0000000..608be81
--- /dev/null
+++ b/drivers/misc/qpnp-misc.c
@@ -0,0 +1,167 @@
+/* Copyright (c) 2013, The Linux Foundation. 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/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/qpnp-misc.h>
+
+#define QPNP_MISC_DEV_NAME "qcom,qpnp-misc"
+
+#define REVID_REVISION2	0x1
+
+static DEFINE_MUTEX(qpnp_misc_dev_list_mutex);
+static LIST_HEAD(qpnp_misc_dev_list);
+
+/**
+ * struct qpnp_misc_dev - holds controller device specific information
+ * @list:			Doubly-linked list parameter linking to other
+ *				qpnp_misc devices.
+ * @mutex:			Mutex lock that is used to ensure mutual
+ *				exclusion between probing and accessing misc
+ *				driver information
+ * @dev:			Device pointer to the misc device
+ * @resource:			Resource pointer that holds base address
+ * @spmi:			Spmi pointer which holds spmi information
+ */
+struct qpnp_misc_dev {
+	struct list_head		list;
+	struct mutex			mutex;
+	struct device			*dev;
+	struct resource			*resource;
+	struct spmi_device		*spmi;
+};
+
+static struct of_device_id qpnp_misc_match_table[] = {
+	{ .compatible = QPNP_MISC_DEV_NAME },
+	{}
+};
+
+static u8 qpnp_read_byte(struct spmi_device *spmi, u16 addr)
+{
+	int rc;
+	u8 val;
+
+	rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, &val, 1);
+	if (rc) {
+		pr_err("SPMI read failed rc=%d\n", rc);
+		return 0;
+	}
+	return val;
+}
+
+#define REV2_IRQ_AVAILABLE_VERSION	2
+static bool __misc_irqs_available(struct qpnp_misc_dev *dev)
+{
+	u8 rev2;
+
+	rev2 = qpnp_read_byte(dev->spmi,
+		dev->resource->start + REVID_REVISION2);
+	pr_debug("rev2 0x%x\n", rev2);
+
+	if (rev2 >= REV2_IRQ_AVAILABLE_VERSION)
+		return 1;
+
+	return 0;
+}
+
+int qpnp_misc_irqs_available(struct device *consumer_dev)
+{
+	struct device_node *misc_node = NULL;
+	struct qpnp_misc_dev *mdev = NULL;
+	struct qpnp_misc_dev *mdev_found = NULL;
+
+	misc_node = of_parse_phandle(consumer_dev->of_node, "qcom,misc-ref", 0);
+	if (!misc_node) {
+		pr_debug("Could not find qcom,misc-ref property in %s\n",
+			consumer_dev->of_node->full_name);
+		return 0;
+	}
+
+	mutex_lock(&qpnp_misc_dev_list_mutex);
+	list_for_each_entry(mdev, &qpnp_misc_dev_list, list) {
+		if (mdev->dev->of_node == misc_node) {
+			mdev_found = mdev;
+			break;
+		}
+	}
+	mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+	if (!mdev_found) {
+		/* No MISC device was found. This API should only
+		 * be called by drivers which have specified the
+		 * misc phandle in their device tree node */
+		pr_err("no probed misc device found\n");
+		return -EPROBE_DEFER;
+	}
+
+	return __misc_irqs_available(mdev_found);
+}
+
+static int __devinit qpnp_misc_probe(struct spmi_device *spmi)
+{
+	struct resource *resource;
+	struct qpnp_misc_dev *mdev = ERR_PTR(-EINVAL);
+
+	resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+	if (!resource) {
+		pr_err("Unable to get spmi resource for MISC\n");
+		return -EINVAL;
+	}
+
+	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+	if (!mdev) {
+		pr_err("allocation failed\n");
+		return -ENOMEM;
+	}
+
+	mdev->spmi = spmi;
+	mdev->dev = &(spmi->dev);
+	mdev->resource = resource;
+
+	mutex_lock(&qpnp_misc_dev_list_mutex);
+	list_add_tail(&mdev->list, &qpnp_misc_dev_list);
+	mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+	pr_debug("probed successfully\n");
+	return 0;
+}
+
+static struct spmi_driver qpnp_misc_driver = {
+	.probe	= qpnp_misc_probe,
+	.driver	= {
+		.name		= QPNP_MISC_DEV_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= qpnp_misc_match_table,
+	},
+};
+
+static int __init qpnp_misc_init(void)
+{
+	return spmi_driver_register(&qpnp_misc_driver);
+}
+
+static void __exit qpnp_misc_exit(void)
+{
+	return spmi_driver_unregister(&qpnp_misc_driver);
+}
+
+module_init(qpnp_misc_init);
+module_exit(qpnp_misc_exit);
+
+MODULE_DESCRIPTION(QPNP_MISC_DEV_NAME);
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" QPNP_MISC_DEV_NAME);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 444b627..2769709 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -103,6 +103,10 @@
 	0xFFFFBBBB, 0xFFFF77FF, 0xFF7777FF, 0xEEDDBB77
 };
 
+static int disable_slots;
+/* root can write, others read */
+module_param(disable_slots, int, S_IRUGO|S_IWUSR);
+
 /* This structure keeps information per regulator */
 struct sdhci_msm_reg_data {
 	/* voltage regulator handle */
@@ -2081,6 +2085,19 @@
 
 	/* Extract platform data */
 	if (pdev->dev.of_node) {
+		ret = of_alias_get_id(pdev->dev.of_node, "sdhc");
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to get slot index %d\n",
+				ret);
+			goto pltfm_free;
+		}
+		if (disable_slots & (1 << (ret - 1))) {
+			dev_info(&pdev->dev, "%s: Slot %d disabled\n", __func__,
+				ret);
+			ret = -ENODEV;
+			goto pltfm_free;
+		}
+
 		msm_host->pdata = sdhci_msm_populate_pdata(&pdev->dev);
 		if (!msm_host->pdata) {
 			dev_err(&pdev->dev, "DT parsing error\n");
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index 0ee7f27..e954741 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -13,8 +13,6 @@
 #include <linux/delay.h>
 #include "ipa_i.h"
 
-#define IPA_HOLB_TMR_VAL 0xff
-
 static void ipa_enable_data_path(u32 clnt_hdl)
 {
 	struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
@@ -296,20 +294,6 @@
 	memcpy(&sps->desc, &ep->connect.desc, sizeof(struct sps_mem_buffer));
 	memcpy(&sps->data, &ep->connect.data, sizeof(struct sps_mem_buffer));
 
-	if (in->client == IPA_CLIENT_HSIC1_CONS ||
-			in->client == IPA_CLIENT_HSIC2_CONS ||
-			in->client == IPA_CLIENT_HSIC3_CONS ||
-			in->client == IPA_CLIENT_HSIC4_CONS) {
-		IPADBG("disable holb for ep=%d tmr=%d\n", ipa_ep_idx,
-			IPA_HOLB_TMR_VAL);
-		ipa_write_reg(ipa_ctx->mmio,
-			IPA_ENDP_INIT_HOL_BLOCK_EN_n_OFST(ipa_ep_idx),
-			0x1);
-		ipa_write_reg(ipa_ctx->mmio,
-			IPA_ENDP_INIT_HOL_BLOCK_TIMER_n_OFST(ipa_ep_idx),
-			IPA_HOLB_TMR_VAL);
-	}
-
 	IPADBG("client %d (ep: %d) connected\n", in->client, ipa_ep_idx);
 
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_hdr.c
index 0439a69..7d0bc24 100644
--- a/drivers/platform/msm/ipa/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_hdr.c
@@ -221,6 +221,8 @@
 		WARN_ON(1);
 	}
 
+	entry->ref_cnt++;
+
 	return 0;
 
 ofst_alloc_fail:
@@ -246,7 +248,7 @@
 		return -EINVAL;
 	}
 
-	if (!entry || (entry->cookie != IPA_COOKIE) || (entry->ref_cnt != 0)) {
+	if (!entry || (entry->cookie != IPA_COOKIE)) {
 		IPAERR("bad parm\n");
 		return -EINVAL;
 	}
@@ -254,6 +256,11 @@
 	IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
 			htbl->hdr_cnt, entry->offset_entry->offset);
 
+	if (--entry->ref_cnt) {
+		IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt);
+		return 0;
+	}
+
 	/* move the offset entry to appropriate free list */
 	list_move(&entry->offset_entry->link,
 		  &htbl->head_free_offset_list[entry->offset_entry->bin]);
@@ -502,8 +509,7 @@
  * ipa_get_hdr() - Lookup the specified header resource
  * @lookup:	[inout] header to lookup and its handle
  *
- * lookup the specified header resource and return handle if it exists, if
- * lookup succeeds the header entry ref cnt is increased
+ * lookup the specified header resource and return handle if it exists
  *
  * Returns:	0 on success, negative on failure
  *
@@ -522,7 +528,6 @@
 	mutex_lock(&ipa_ctx->lock);
 	entry = __ipa_find_hdr(lookup->name);
 	if (entry) {
-		entry->ref_cnt++;
 		lookup->hdl = (uint32_t) entry;
 		result = 0;
 	}
@@ -533,6 +538,34 @@
 EXPORT_SYMBOL(ipa_get_hdr);
 
 /**
+ * __ipa_release_hdr() - drop reference to header and cause
+ * deletion if reference count permits
+ * @hdr_hdl:	[in] handle of header to be released
+ *
+ * Returns:	0 on success, negative on failure
+ */
+int __ipa_release_hdr(u32 hdr_hdl)
+{
+	int result = 0;
+
+	if (__ipa_del_hdr(hdr_hdl)) {
+		IPADBG("fail to del hdr %x\n", hdr_hdl);
+		result = -EFAULT;
+		goto bail;
+	}
+
+	/* commit for put */
+	if (__ipa_commit_hdr()) {
+		IPAERR("fail to commit hdr\n");
+		result = -EFAULT;
+		goto bail;
+	}
+
+bail:
+	return result;
+}
+
+/**
  * ipa_put_hdr() - Release the specified header handle
  * @hdr_hdl:	[in] the header handle to release
  *
@@ -554,27 +587,12 @@
 		goto bail;
 	}
 
-	if (entry == NULL || entry->cookie != IPA_COOKIE ||
-			entry->ref_cnt == 0) {
+	if (entry == NULL || entry->cookie != IPA_COOKIE) {
 		IPAERR("bad params\n");
 		result = -EINVAL;
 		goto bail;
 	}
 
-	entry->ref_cnt--;
-	if (entry->ref_cnt == 0) {
-		if (__ipa_del_hdr(hdr_hdl)) {
-			IPAERR("fail to del hdr\n");
-			result = -EFAULT;
-			goto bail;
-		}
-		/* commit for put */
-		if (__ipa_commit_hdr()) {
-			IPAERR("fail to commit hdr\n");
-			result = -EFAULT;
-			goto bail;
-		}
-	}
 	result = 0;
 bail:
 	mutex_unlock(&ipa_ctx->lock);
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index d79504e..ca5740d 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -797,6 +797,7 @@
 void ipa_disable_clks(void);
 int __ipa_del_rt_rule(u32 rule_hdl);
 int __ipa_del_hdr(u32 hdr_hdl);
+int __ipa_release_hdr(u32 hdr_hdl);
 
 static inline u32 ipa_read_reg(void *base, u32 offset)
 {
diff --git a/drivers/platform/msm/ipa/ipa_ram_mmap.h b/drivers/platform/msm/ipa/ipa_ram_mmap.h
index d120f37..78093b8 100644
--- a/drivers/platform/msm/ipa/ipa_ram_mmap.h
+++ b/drivers/platform/msm/ipa/ipa_ram_mmap.h
@@ -15,22 +15,22 @@
 
 /*
  * This header defines the memory map of the IPA RAM (not all 8K is available
- * for SW use) the first 2K are set aside for NAT
+ * for SW use)
  */
 
 #define IPA_RAM_NAT_OFST    0
 #define IPA_RAM_NAT_SIZE    0
 #define IPA_RAM_HDR_OFST    (IPA_RAM_NAT_OFST + IPA_RAM_NAT_SIZE)
-#define IPA_RAM_HDR_SIZE    1288
+#define IPA_RAM_HDR_SIZE    1280
 #define IPA_RAM_V4_FLT_OFST (IPA_RAM_HDR_OFST + IPA_RAM_HDR_SIZE)
-#define IPA_RAM_V4_FLT_SIZE 1420
+#define IPA_RAM_V4_FLT_SIZE 1408
 #define IPA_RAM_V4_RT_OFST  (IPA_RAM_V4_FLT_OFST + IPA_RAM_V4_FLT_SIZE)
-#define IPA_RAM_V4_RT_SIZE  2192
+#define IPA_RAM_V4_RT_SIZE  2176
 #define IPA_RAM_V6_FLT_OFST (IPA_RAM_V4_RT_OFST + IPA_RAM_V4_RT_SIZE)
-#define IPA_RAM_V6_FLT_SIZE 1228
+#define IPA_RAM_V6_FLT_SIZE 1280
 #define IPA_RAM_V6_RT_OFST  (IPA_RAM_V6_FLT_OFST + IPA_RAM_V6_FLT_SIZE)
-#define IPA_RAM_V6_RT_SIZE  528
+#define IPA_RAM_V6_RT_SIZE  512
 #define IPA_RAM_END_OFST    (IPA_RAM_V6_RT_OFST + IPA_RAM_V6_RT_SIZE)
-#define IPA_RAM_V6_RT_SIZE_DDR 15764
+#define IPA_RAM_V6_RT_SIZE_DDR 16384
 
 #endif /* _IPA_RAM_MMAP_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index fcc5e58..1d88280 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -699,7 +699,7 @@
 	}
 
 	if (entry->hdr)
-		entry->hdr->ref_cnt--;
+		__ipa_release_hdr((u32)entry->hdr);
 	list_del(&entry->link);
 	entry->tbl->rule_cnt--;
 	IPADBG("del rt rule tbl_idx=%d rule_cnt=%d\n", entry->tbl->idx,
@@ -851,7 +851,7 @@
 			list_del(&rule->link);
 			tbl->rule_cnt--;
 			if (rule->hdr)
-				rule->hdr->ref_cnt--;
+				__ipa_release_hdr((u32)rule->hdr);
 			rule->cookie = 0;
 			kmem_cache_free(ipa_ctx->rt_rule_cache, rule);
 
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index a194c49..08cf71e 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -1518,8 +1518,8 @@
 	struct soc_params params;
 
 	if (!chip->battery_present) {
-		pr_debug("battery gone, reporting 0\n");
-		new_calculated_soc = 0;
+		pr_debug("battery gone, reporting 100\n");
+		new_calculated_soc = 100;
 		goto done_calculating;
 	}
 	calculate_soc_params(chip, raw, &params, batt_temp);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index f3b39d4a..84672d7 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -32,6 +32,7 @@
 #include <linux/uaccess.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/qpnp-misc.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/regulator/consumer.h>
 #include <linux/power_supply.h>
@@ -2395,17 +2396,30 @@
 	if (msm->ext_xceiv.otg_capability) {
 		msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
 		if (msm->pmic_id_irq > 0) {
-			ret = devm_request_irq(&pdev->dev, msm->pmic_id_irq,
-					       dwc3_pmic_id_irq,
-					       IRQF_TRIGGER_RISING |
-					       IRQF_TRIGGER_FALLING,
-					       "dwc3_msm_pmic_id", msm);
-			if (ret) {
-				dev_err(&pdev->dev, "irqreq IDINT failed\n");
+			/* check if PMIC ID IRQ is supported */
+			ret = qpnp_misc_irqs_available(&pdev->dev);
+
+			if (ret == -EPROBE_DEFER) {
+				/* qpnp hasn't probed yet; defer dwc probe */
 				goto disable_hs_ldo;
+			} else if (ret == 0) {
+				msm->pmic_id_irq = 0;
+			} else {
+				ret = devm_request_irq(&pdev->dev,
+						       msm->pmic_id_irq,
+						       dwc3_pmic_id_irq,
+						       IRQF_TRIGGER_RISING |
+						       IRQF_TRIGGER_FALLING,
+						       "dwc3_msm_pmic_id", msm);
+				if (ret) {
+					dev_err(&pdev->dev, "irqreq IDINT failed\n");
+					goto disable_hs_ldo;
+				}
+				enable_irq_wake(msm->pmic_id_irq);
 			}
-			enable_irq_wake(msm->pmic_id_irq);
-		} else {
+		}
+
+		if (msm->pmic_id_irq <= 0) {
 			/* If no PMIC ID IRQ, use ADC for ID pin detection */
 			queue_work(system_nrt_wq, &msm->init_adc_work.work);
 			device_create_file(&pdev->dev, &dev_attr_adc_enable);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 207fbf3..dd41638 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -82,6 +82,7 @@
 	u8 clk_ena;
 	u8 fs_ena;
 	u8 vsync_ena;
+	unsigned long min_mdp_clk;
 
 	u32 res_init;
 	u32 bus_hdl;
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index abef27d..7dc4f49 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -333,6 +333,9 @@
 		return -ENODEV;
 	}
 
+	debugfs_create_u32("min_mdp_clk", 0644, mdd->root,
+		(u32 *)&mdata->min_mdp_clk);
+
 	mdata->debug_data = mdd;
 
 	return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index a8eeec6..749afd8 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -520,11 +520,15 @@
 	return ret;
 }
 
-void mdss_mdp_set_clk_rate(unsigned long min_clk_rate)
+void mdss_mdp_set_clk_rate(unsigned long rate)
 {
 	struct mdss_data_type *mdata = mdss_res;
 	unsigned long clk_rate;
 	struct clk *clk = mdss_mdp_get_clk(MDSS_CLK_MDP_SRC);
+	unsigned long min_clk_rate;
+
+	min_clk_rate = max(rate, mdata->min_mdp_clk);
+
 	if (clk) {
 		mutex_lock(&mdp_clk_lock);
 		if (min_clk_rate < mdata->max_mdp_clk_rate)
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 43456ca..14c1e52 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -122,6 +122,7 @@
 	u32 flush_bits;
 
 	u32 play_cnt;
+	u32 underrun_cnt;
 
 	u16 width;
 	u16 height;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index e2c3b23..dab8674 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -244,12 +244,17 @@
 
 		rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_TIMEGEN_OFF, NULL);
 		WARN(rc, "intf %d timegen off error (%d)\n", ctl->intf_num, rc);
+
+		mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN,
+			ctl->intf_num);
 	}
 
 	mdss_mdp_video_set_vsync_handler(ctl, NULL);
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
 				   NULL, NULL);
+	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
+				   NULL, NULL);
 
 	ctx->ref_cnt--;
 	ctl->priv_data = NULL;
@@ -304,6 +309,17 @@
 	return rc;
 }
 
+static void mdss_mdp_video_underrun_intr_done(void *arg)
+{
+	struct mdss_mdp_ctl *ctl = arg;
+	if (unlikely(!ctl))
+		return;
+
+	ctl->underrun_cnt++;
+	pr_warn("display underrun detected for ctl=%d count=%d\n", ctl->num,
+			ctl->underrun_cnt);
+}
+
 static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
 {
 	struct mdss_mdp_video_ctx *ctx;
@@ -332,6 +348,8 @@
 		pr_debug("enabling timing gen for intf=%d\n", ctl->intf_num);
 
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+		mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num);
 		mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
 		wmb();
 
@@ -390,6 +408,8 @@
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
 				   mdss_mdp_video_vsync_intr_done, ctl);
+	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
+				   mdss_mdp_video_underrun_intr_done, ctl);
 
 	itp.width = pinfo->xres + pinfo->lcdc.xres_pad;
 	itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 4699e0d..7ff6414 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -81,14 +81,22 @@
 
 static int mdss_mdp_smp_reserve(struct mdss_mdp_pipe *pipe)
 {
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 	u32 num_blks = 0, reserved = 0;
 	struct mdss_mdp_plane_sizes ps;
 	int i, rc;
 
-	rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format, pipe->src.w,
-				pipe->src.h, &ps);
-	if (rc)
-		return rc;
+	if ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
+			pipe->src_fmt->is_yuv) {
+		ps.num_planes = 2;
+		ps.ystride[0] = pipe->src.w;
+		ps.ystride[1] = pipe->src.w;
+	} else {
+		rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
+				pipe->src.w, pipe->src.h, &ps);
+		if (rc)
+			return rc;
+	}
 
 	if ((ps.num_planes > 1) && (pipe->type == MDSS_MDP_PIPE_TYPE_RGB))
 		return -EINVAL;
@@ -98,7 +106,7 @@
 		num_blks = DIV_ROUND_UP(2 * ps.ystride[i],
 			mdss_res->smp_mb_size);
 
-		if (mdss_res->mdp_rev == MDSS_MDP_HW_REV_100)
+		if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
 			num_blks = roundup_pow_of_two(num_blks);
 
 		pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
@@ -124,7 +132,7 @@
 {
 	int i;
 	mutex_lock(&mdss_mdp_smp_lock);
-	for (i = 0; i < pipe->src_planes.num_planes; i++)
+	for (i = 0; i < MAX_PLANES; i++)
 		mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
 	mutex_unlock(&mdss_mdp_smp_lock);
 	return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 1c0d306..077b4e4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -35,6 +35,10 @@
 	MDP_INTR_VSYNC_INTF_1,
 	MDP_INTR_VSYNC_INTF_2,
 	MDP_INTR_VSYNC_INTF_3,
+	MDP_INTR_UNDERRUN_INTF_0,
+	MDP_INTR_UNDERRUN_INTF_1,
+	MDP_INTR_UNDERRUN_INTF_2,
+	MDP_INTR_UNDERRUN_INTF_3,
 	MDP_INTR_PING_PONG_0,
 	MDP_INTR_PING_PONG_1,
 	MDP_INTR_PING_PONG_2,
@@ -56,6 +60,9 @@
 {
 	int index = -1;
 	switch (intr_type) {
+	case MDSS_MDP_IRQ_INTF_UNDER_RUN:
+		index = MDP_INTR_UNDERRUN_INTF_0 + (intf_num - MDSS_MDP_INTF0);
+		break;
 	case MDSS_MDP_IRQ_INTF_VSYNC:
 		index = MDP_INTR_VSYNC_INTF_0 + (intf_num - MDSS_MDP_INTF0);
 		break;
@@ -128,6 +135,18 @@
 	if (isr == 0)
 		goto mdp_isr_done;
 
+	if (isr & MDSS_MDP_INTR_INTF_0_UNDERRUN)
+		mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_0);
+
+	if (isr & MDSS_MDP_INTR_INTF_1_UNDERRUN)
+		mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_1);
+
+	if (isr & MDSS_MDP_INTR_INTF_2_UNDERRUN)
+		mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_2);
+
+	if (isr & MDSS_MDP_INTR_INTF_3_UNDERRUN)
+		mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_3);
+
 	if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE)
 		mdss_mdp_intr_done(MDP_INTR_PING_PONG_0);
 
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index add65ac..2341068 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -103,8 +103,6 @@
 	return postpone_send;
 }
 
-
-
 void mhl_msc_send_work(struct work_struct *work)
 {
 	struct mhl_tx_ctrl *mhl_ctrl =
@@ -202,7 +200,6 @@
 	return 0;
 }
 
-
 int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
 			 struct msc_command_struct *req)
 {
@@ -286,8 +283,6 @@
 	return 0;
 }
 
-
-
 int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
 			 u8 sub_cmd, u8 cmd_data)
 {
@@ -315,7 +310,6 @@
 	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_PRIORITY_SEND);
 }
 
-
 int mhl_msc_read_devcap(struct mhl_tx_ctrl *mhl_ctrl, u8 offset)
 {
 	struct msc_command_struct req;
@@ -340,7 +334,6 @@
 	return ret;
 }
 
-
 static void mhl_handle_input(struct mhl_tx_ctrl *mhl_ctrl,
 			     u8 key_code, u16 input_key_code)
 {
@@ -352,8 +345,6 @@
 	input_sync(mhl_ctrl->input);
 }
 
-
-
 int mhl_rcp_recv(struct mhl_tx_ctrl *mhl_ctrl, u8 key_code)
 {
 	u8 index = key_code & 0x7f;
@@ -392,7 +383,6 @@
 	return 0;
 }
 
-
 static int mhl_rap_action(struct mhl_tx_ctrl *mhl_ctrl, u8 action_code)
 {
 	switch (action_code) {
@@ -400,7 +390,14 @@
 		mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
 		break;
 	case MHL_RAP_CONTENT_OFF:
-		mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
+		/*
+		 * instead of only disabling tmds
+		 * send power button press - CONTENT_OFF
+		 */
+		input_report_key(mhl_ctrl->input, KEY_VENDOR, 1);
+		input_sync(mhl_ctrl->input);
+		input_report_key(mhl_ctrl->input, KEY_VENDOR, 0);
+		input_sync(mhl_ctrl->input);
 		break;
 	default:
 		break;
@@ -413,9 +410,9 @@
 	u8 error_code;
 	bool tmds_en;
 
+	tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
 	switch (action_code) {
 	case MHL_RAP_POLL:
-		tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
 		if (tmds_en)
 			error_code = MHL_RAPK_NO_ERROR;
 		else
@@ -423,8 +420,12 @@
 		break;
 	case MHL_RAP_CONTENT_ON:
 	case MHL_RAP_CONTENT_OFF:
-		mhl_rap_action(mhl_ctrl, action_code);
-		error_code = MHL_RAPK_NO_ERROR;
+		if (tmds_en) {
+			mhl_rap_action(mhl_ctrl, action_code);
+			error_code = MHL_RAPK_NO_ERROR;
+		} else {
+			error_code = MHL_RAPK_UNSUPPORTED_ACTION_CODE;
+		}
 		break;
 	default:
 		error_code = MHL_RAPK_UNRECOGNIZED_ACTION_CODE;
@@ -437,7 +438,6 @@
 		error_code);
 }
 
-
 int mhl_msc_recv_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
 			 u8 sub_cmd, u8 cmd_data)
 {
diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h
index 41f7c29..2ad1ab2 100644
--- a/include/drm/kgsl_drm.h
+++ b/include/drm/kgsl_drm.h
@@ -86,7 +86,7 @@
 struct drm_kgsl_gem_create_from_ion)
 
 /* Maximum number of sub buffers per GEM object */
-#define DRM_KGSL_GEM_MAX_BUFFERS 2
+#define DRM_KGSL_GEM_MAX_BUFFERS 3
 
 /* Memory types - these define the source and caching policies
    of the GEM memory chunk */
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index a683ed4..95c4e6a 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -40,6 +40,7 @@
 	ION_CP_MFC_HEAP_ID = 12,
 	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
 	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+	ION_SYSTEM_CONTIG_HEAP_ID = 21,
 	ION_ADSP_HEAP_ID = 22,
 	ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
 	ION_SF_HEAP_ID = 24,
@@ -90,6 +91,7 @@
 
 #define ION_ADSP_HEAP_NAME	"adsp"
 #define ION_VMALLOC_HEAP_NAME	"vmalloc"
+#define ION_KMALLOC_HEAP_NAME	"kmalloc"
 #define ION_AUDIO_HEAP_NAME	"audio"
 #define ION_SF_HEAP_NAME	"sf"
 #define ION_MM_HEAP_NAME	"mm"
diff --git a/include/linux/qpnp-misc.h b/include/linux/qpnp-misc.h
new file mode 100644
index 0000000..b241e5d
--- /dev/null
+++ b/include/linux/qpnp-misc.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2013, The Linux Foundation. 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 __QPNP_MISC_H
+#define __QPNP_MISC_H
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_QPNP_MISC
+/**
+ * qpnp_misc_irqs_available - check if IRQs are available
+ *
+ * @consumer_dev: device struct
+ *
+ * This function returns true if the MISC interrupts are available
+ * based on a check in the MISC peripheral revision registers.
+ *
+ * Any consumer of this function needs to reference a MISC device phandle
+ * using the qcom,misc-ref in their device tree node.
+ */
+
+int qpnp_misc_irqs_available(struct device *consumer_dev);
+#else
+static int qpnp_misc_irq_available(struct device *consumer_dev)
+{
+	return 0;
+}
+#endif
+#endif
diff --git a/include/media/msmb_camera.h b/include/media/msmb_camera.h
index 123c86c..21a1c44 100644
--- a/include/media/msmb_camera.h
+++ b/include/media/msmb_camera.h
@@ -102,9 +102,9 @@
 	/*word 6*/
 	unsigned int notify;
 	/*word 7*/
-	unsigned int nop1;
+	unsigned int arg_value;
 	/*word 8*/
-	unsigned int nop2;
+	unsigned int ret_value;
 	/*word 9*/
 	unsigned int nop3;
 	/*word 10*/
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d3e8c6e..69318b0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2977,6 +2977,7 @@
 			return -EINVAL;
 		break;
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_P2P_CLIENT:
 		/* Only TDLS peers can be added */
 		if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
 			return -EINVAL;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 78d1749..80738ba 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -338,6 +338,7 @@
 	s32 dmic_5_6_clk_cnt;
 
 	u32 anc_slot;
+	bool anc_func;
 
 	/*track taiko interface type*/
 	u8 intf_type;
@@ -505,6 +506,56 @@
 	return 0;
 }
 
+static int taiko_get_anc_func(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = (taiko->anc_func == true ? 1 : 0);
+	return 0;
+}
+
+static int taiko_put_anc_func(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	mutex_lock(&dapm->codec->mutex);
+	taiko->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
+
+	dev_dbg(codec->dev, "%s: anc_func %x", __func__, taiko->anc_func);
+
+	if (taiko->anc_func == true) {
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
+		snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
+		snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
+		snd_soc_dapm_enable_pin(dapm, "ANC EAR");
+		snd_soc_dapm_disable_pin(dapm, "HPHR");
+		snd_soc_dapm_disable_pin(dapm, "HPHL");
+		snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
+		snd_soc_dapm_disable_pin(dapm, "EAR PA");
+		snd_soc_dapm_disable_pin(dapm, "EAR");
+	} else {
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+		snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+		snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+		snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+		snd_soc_dapm_enable_pin(dapm, "HPHR");
+		snd_soc_dapm_enable_pin(dapm, "HPHL");
+		snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
+		snd_soc_dapm_enable_pin(dapm, "EAR PA");
+		snd_soc_dapm_enable_pin(dapm, "EAR");
+	}
+	snd_soc_dapm_sync(dapm);
+	mutex_unlock(&dapm->codec->mutex);
+	return 0;
+}
+
 static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -915,6 +966,15 @@
 		SOC_ENUM_SINGLE_EXT(2, taiko_ear_pa_gain_text),
 };
 
+static const char *const taiko_anc_func_text[] = {"OFF", "ON"};
+static const struct soc_enum taiko_anc_func_enum =
+		SOC_ENUM_SINGLE_EXT(2, taiko_anc_func_text);
+
+static const char *const tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum tabla_ear_pa_gain_enum[] = {
+		SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
+};
+
 /*cut of frequency for high pass filter*/
 static const char * const cf_text[] = {
 	"MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
@@ -1054,8 +1114,10 @@
 	SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
 	SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
 
-	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, taiko_get_anc_slot,
+	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
 		taiko_put_anc_slot),
+	SOC_ENUM_EXT("ANC Function", taiko_anc_func_enum, taiko_get_anc_func,
+		taiko_put_anc_func),
 	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
 	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
 	SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
@@ -2184,101 +2246,6 @@
 	return 0;
 }
 
-static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	const char *filename;
-	const struct firmware *fw;
-	int i;
-	int ret;
-	int num_anc_slots;
-	struct anc_header *anc_head;
-	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
-	u32 anc_writes_size = 0;
-	int anc_size_remaining;
-	u32 *anc_ptr;
-	u16 reg;
-	u8 mask, val;
-
-	pr_debug("%s %d\n", __func__, event);
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-
-		filename = "wcd9320/wcd9320_anc.bin";
-
-		ret = request_firmware(&fw, filename, codec->dev);
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
-				ret);
-			return -ENODEV;
-		}
-
-		if (fw->size < sizeof(struct anc_header)) {
-			dev_err(codec->dev, "Not enough data\n");
-			release_firmware(fw);
-			return -ENOMEM;
-		}
-
-		/* First number is the number of register writes */
-		anc_head = (struct anc_header *)(fw->data);
-		anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
-		anc_size_remaining = fw->size - sizeof(struct anc_header);
-		num_anc_slots = anc_head->num_anc_slots;
-
-		if (taiko->anc_slot >= num_anc_slots) {
-			dev_err(codec->dev, "Invalid ANC slot selected\n");
-			release_firmware(fw);
-			return -EINVAL;
-		}
-
-		for (i = 0; i < num_anc_slots; i++) {
-
-			if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
-				dev_err(codec->dev, "Invalid register format\n");
-				release_firmware(fw);
-				return -EINVAL;
-			}
-			anc_writes_size = (u32)(*anc_ptr);
-			anc_size_remaining -= sizeof(u32);
-			anc_ptr += 1;
-
-			if (anc_writes_size * TAIKO_PACKED_REG_SIZE
-				> anc_size_remaining) {
-				dev_err(codec->dev, "Invalid register format\n");
-				release_firmware(fw);
-				return -ENOMEM;
-			}
-
-			if (taiko->anc_slot == i)
-				break;
-
-			anc_size_remaining -= (anc_writes_size *
-				TAIKO_PACKED_REG_SIZE);
-			anc_ptr += anc_writes_size;
-		}
-		if (i == num_anc_slots) {
-			dev_err(codec->dev, "Selected ANC slot not present\n");
-			release_firmware(fw);
-			return -ENOMEM;
-		}
-
-		for (i = 0; i < anc_writes_size; i++) {
-			TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
-				mask, val);
-			snd_soc_write(codec, reg, val);
-		}
-		release_firmware(fw);
-
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
-		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
-		break;
-	}
-	return 0;
-}
-
 static int taiko_codec_config_mad(struct snd_soc_codec *codec)
 {
 	int ret;
@@ -2780,6 +2747,106 @@
 	return 0;
 }
 
+static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	const char *filename;
+	const struct firmware *fw;
+	int i;
+	int ret;
+	int num_anc_slots;
+	struct anc_header *anc_head;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u32 anc_writes_size = 0;
+	int anc_size_remaining;
+	u32 *anc_ptr;
+	u16 reg;
+	u8 mask, val, old_val;
+
+
+	if (taiko->anc_func == 0)
+		return 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		filename = "wcd9320/wcd9320_anc.bin";
+
+		ret = request_firmware(&fw, filename, codec->dev);
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
+				ret);
+			return -ENODEV;
+		}
+
+		if (fw->size < sizeof(struct anc_header)) {
+			dev_err(codec->dev, "Not enough data\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+
+		/* First number is the number of register writes */
+		anc_head = (struct anc_header *)(fw->data);
+		anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
+		anc_size_remaining = fw->size - sizeof(struct anc_header);
+		num_anc_slots = anc_head->num_anc_slots;
+
+		if (taiko->anc_slot >= num_anc_slots) {
+			dev_err(codec->dev, "Invalid ANC slot selected\n");
+			release_firmware(fw);
+			return -EINVAL;
+		}
+		for (i = 0; i < num_anc_slots; i++) {
+			if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -EINVAL;
+			}
+			anc_writes_size = (u32)(*anc_ptr);
+			anc_size_remaining -= sizeof(u32);
+			anc_ptr += 1;
+
+			if (anc_writes_size * TAIKO_PACKED_REG_SIZE
+				> anc_size_remaining) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -ENOMEM;
+			}
+
+			if (taiko->anc_slot == i)
+				break;
+
+			anc_size_remaining -= (anc_writes_size *
+				TAIKO_PACKED_REG_SIZE);
+			anc_ptr += anc_writes_size;
+		}
+		if (i == num_anc_slots) {
+			dev_err(codec->dev, "Selected ANC slot not present\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+		for (i = 0; i < anc_writes_size; i++) {
+			TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
+				mask, val);
+			old_val = snd_soc_read(codec, reg);
+			snd_soc_write(codec, reg, (old_val & ~mask) |
+				(val & mask));
+		}
+		release_firmware(fw);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		msleep(40);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
+		msleep(20);
+		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
+		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+		break;
+	}
+	return 0;
+}
+
 static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
 			      struct snd_kcontrol *kcontrol, int event)
 {
@@ -2835,6 +2902,46 @@
 	return 0;
 }
 
+static int taiko_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = taiko_hph_pa_event(w, kcontrol, event);
+		if (w->shift == 4) {
+			ret |= taiko_codec_enable_anc(w, kcontrol, event);
+			msleep(50);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (w->shift == 4) {
+			snd_soc_update_bits(codec,
+					TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x30);
+			msleep(30);
+		}
+		ret = taiko_hph_pa_event(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (w->shift == 5) {
+			snd_soc_update_bits(codec,
+					TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
+			msleep(40);
+		}
+		if (w->shift == 5) {
+			snd_soc_update_bits(codec,
+					TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
+			ret |= taiko_codec_enable_anc(w, kcontrol, event);
+		}
+	case SND_SOC_DAPM_POST_PMD:
+		ret = taiko_hph_pa_event(w, kcontrol, event);
+		break;
+	}
+	return ret;
+}
+
 static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
 	4, 0, NULL, 0),
@@ -3022,9 +3129,10 @@
 	{"EAR_PA_MIXER", NULL, "DAC1"},
 	{"DAC1", NULL, "RX_BIAS"},
 
+	{"ANC EAR", NULL, "ANC EAR PA"},
+	{"ANC EAR PA", NULL, "EAR_PA_MIXER"},
 	{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
 	{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
-	{"ANC", NULL, "ANC1 FB MUX"},
 
 	/* Headset (RX MIX1 and RX MIX2) */
 	{"HEADPHONE", NULL, "HPHL"},
@@ -3038,18 +3146,28 @@
 	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
 	{"HPHR DAC", NULL, "RX_BIAS"},
 
-	{"ANC", NULL, "ANC1 MUX"},
-	{"ANC", NULL, "ANC2 MUX"},
+	{"ANC HEADPHONE", NULL, "ANC HPHL"},
+	{"ANC HEADPHONE", NULL, "ANC HPHR"},
+
+	{"ANC HPHL", NULL, "HPHL_PA_MIXER"},
+	{"ANC HPHR", NULL, "HPHR_PA_MIXER"},
+
 	{"ANC1 MUX", "ADC1", "ADC1"},
 	{"ANC1 MUX", "ADC2", "ADC2"},
 	{"ANC1 MUX", "ADC3", "ADC3"},
 	{"ANC1 MUX", "ADC4", "ADC4"},
+	{"ANC1 MUX", "DMIC1", "DMIC1"},
+	{"ANC1 MUX", "DMIC2", "DMIC2"},
+	{"ANC1 MUX", "DMIC3", "DMIC3"},
+	{"ANC1 MUX", "DMIC4", "DMIC4"},
+	{"ANC1 MUX", "DMIC5", "DMIC5"},
+	{"ANC1 MUX", "DMIC6", "DMIC6"},
 	{"ANC2 MUX", "ADC1", "ADC1"},
 	{"ANC2 MUX", "ADC2", "ADC2"},
 	{"ANC2 MUX", "ADC3", "ADC3"},
 	{"ANC2 MUX", "ADC4", "ADC4"},
 
-	{"ANC", NULL, "CDC_CONN"},
+	{"ANC HPHR", NULL, "CDC_CONN"},
 
 	{"DAC1", "Switch", "CLASS_H_DSM MUX"},
 	{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
@@ -3095,8 +3213,8 @@
 
 	{"RX1 CHAIN", NULL, "RX1 MIX2"},
 	{"RX2 CHAIN", NULL, "RX2 MIX2"},
-	{"RX1 CHAIN", NULL, "ANC"},
-	{"RX2 CHAIN", NULL, "ANC"},
+	{"RX1 MIX2", NULL, "ANC1 MUX"},
+	{"RX2 MIX2", NULL, "ANC2 MUX"},
 
 	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
 	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
@@ -3429,6 +3547,14 @@
 		(reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
 		return 1;
 
+	/* ANC filter registers are not cacheable */
+	if ((reg >= TAIKO_A_CDC_ANC1_IIR_B1_CTL) &&
+		(reg <= TAIKO_A_CDC_ANC1_LPF_B2_CTL))
+		return 1;
+	if ((reg >= TAIKO_A_CDC_ANC2_IIR_B1_CTL) &&
+		(reg <= TAIKO_A_CDC_ANC2_LPF_B2_CTL))
+		return 1;
+
 	/* Digital gain register is not cacheable so we have to write
 	 * the setting even it is the same
 	 */
@@ -4457,6 +4583,32 @@
 	return 0;
 }
 
+static int taiko_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = taiko_codec_enable_anc(w, kcontrol, event);
+		msleep(50);
+		snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x00);
+		msleep(40);
+		ret |= taiko_codec_enable_anc(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
+		break;
+	}
+	return ret;
+}
 
 /* Todo: Have seperate dapm widgets for I2S and Slimbus.
  * Might Need to have callbacks registered only for slimbus
@@ -4754,10 +4906,20 @@
 	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
 	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
 
-	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
-		taiko_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
+	SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
+	SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
+		taiko_codec_enable_anc_hph,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
+		taiko_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_OUTPUT("ANC EAR"),
+	SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
+		taiko_codec_enable_anc_ear,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
 
 	SND_SOC_DAPM_INPUT("AMIC2"),
@@ -5700,6 +5862,14 @@
 	(void) taiko_setup_irqs(taiko);
 
 	atomic_set(&kp_taiko_priv, (unsigned long)taiko);
+	mutex_lock(&dapm->codec->mutex);
+	snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+	snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+	snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+	snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+	snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+	snd_soc_dapm_sync(dapm);
+	mutex_unlock(&dapm->codec->mutex);
 
 	codec->ignore_pmdown_time = 1;
 	return ret;
diff --git a/sound/soc/msm/lpass-dma.c b/sound/soc/msm/lpass-dma.c
index 39a7f7f..50938df 100644
--- a/sound/soc/msm/lpass-dma.c
+++ b/sound/soc/msm/lpass-dma.c
@@ -16,7 +16,7 @@
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
-#include <linux/android_pmem.h>
+
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 4e6cbaa..e54f8b7 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -29,7 +29,7 @@
 #include <sound/pcm_params.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <sound/timer.h>
 #include <mach/qdsp6v2/q6core.h>
 #include <sound/pcm.h>
diff --git a/sound/soc/msm/msm-lowlatency-pcm-q6.c b/sound/soc/msm/msm-lowlatency-pcm-q6.c
index 6ad1410..d5281e4 100644
--- a/sound/soc/msm/msm-lowlatency-pcm-q6.c
+++ b/sound/soc/msm/msm-lowlatency-pcm-q6.c
@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <asm/dma.h>
 #include <sound/core.h>
 #include <sound/soc.h>
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 10b7e30..26bf3d9 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <asm/dma.h>
 #include <sound/core.h>
 #include <sound/soc.h>
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index e01c759..a3bcf23 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 6f1a01d..ba054bd 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -26,7 +26,7 @@
 #include <sound/control.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <sound/compress_params.h>
 #include <sound/compress_offload.h>
 #include <sound/compress_driver.h>
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index c326437..1d15c11 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -27,7 +27,7 @@
 #include <sound/control.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 
 #include "msm-pcm-q6.h"
 #include "msm-pcm-routing.h"
diff --git a/sound/soc/msm/msm7kv2-pcm.c b/sound/soc/msm/msm7kv2-pcm.c
index 2b7a438..ed23521 100644
--- a/sound/soc/msm/msm7kv2-pcm.c
+++ b/sound/soc/msm/msm7kv2-pcm.c
@@ -32,7 +32,7 @@
 #include <sound/control.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <linux/slab.h>
 #include "msm7kv2-pcm.h"
 #include <mach/qdsp5v2/audio_dev_ctl.h>
diff --git a/sound/soc/msm/msm8x60-pcm.c b/sound/soc/msm/msm8x60-pcm.c
index 7993435..f8b43cf 100644
--- a/sound/soc/msm/msm8x60-pcm.c
+++ b/sound/soc/msm/msm8x60-pcm.c
@@ -27,7 +27,7 @@
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
-#include <linux/android_pmem.h>
+
 #include <mach/qdsp6v2/audio_dev_ctl.h>
 
 #include "msm8x60-pcm.h"
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index a55700c..f15f4d1 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -25,7 +25,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
+
 #include <linux/memory_alloc.h>
 #include <linux/debugfs.h>
 #include <linux/time.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index f6e571b8..5dc5f96 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -29,7 +29,7 @@
 #include <sound/pcm_params.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <sound/timer.h>
 
 #include "msm-compr-q6-v2.h"
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index ea6f390..363fb15 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -18,7 +18,6 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
 #include <linux/of.h>
 #include <sound/core.h>
 #include <sound/soc.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
index d0d573c..a078042 100644
--- a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <asm/dma.h>
 #include <sound/core.h>
 #include <sound/soc.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index 91bb09b..e4f3f94 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 3a4a674..64f19ad 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -26,7 +26,7 @@
 #include <sound/control.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <linux/of_device.h>
 #include <sound/compress_params.h>
 #include <sound/compress_offload.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 4ca96d7..ca91fe5 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -27,7 +27,7 @@
 #include <sound/control.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 #include <linux/of_device.h>
 #include <sound/pcm_params.h>
 
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 0549671..65ac79b 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -24,7 +24,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
+
 #include <linux/memory_alloc.h>
 #include <linux/debugfs.h>
 #include <linux/time.h>