Merge "msmfb: mdss: fix the potential dead-lock in pan display"
diff --git a/Documentation/devicetree/bindings/bluetooth/bluesleep.txt b/Documentation/devicetree/bindings/bluetooth/bluesleep.txt
new file mode 100644
index 0000000..a5c5a16
--- /dev/null
+++ b/Documentation/devicetree/bindings/bluetooth/bluesleep.txt
@@ -0,0 +1,41 @@
+* Bluetooth Sleep Protocol driver
+Bluetooth controller communicates with the Bluetooth Host using HCI Transport layer.
+HCI Transport layer can be based on UART or USB serial communication protocol.
+
+Apart from the transport layer, Bluetooth Controller also supports Low Power Mode
+using various mechanisms. One of such mechanism is Out-of-Band Sleep. Also known
+as 2-wire sleep mechanism.
+
+Out-of-Band Sleep:
+It requires two GPIOs to communicate the sleep protocol between Host and Controller.
+One of them is called as Host Wake GPIO where as other is known as a External wake
+GPIO.
+Host Wake GPIO is used for awake the Host from the Sleep Mode. It is controlled by the
+Controller. It should be wakeup interruptible source on the Host.
+External Wake GPIO is used for awake the Controller from the Sleep Mode. It is controlled
+by the Host.
+
+Required Properties:
+
+  - compatible: Should be "qca,ar3002_bluesleep"
+  - host-wake-gpio: Specify GPIO for Host wake signal (Controller -> Host).
+  - ext-wake-gpio: Specify GPIO for Controller wake signal(Host -> Controller).
+  - interrupt-parent: Should be phandle for the interrupt controller
+      that services interrupts for this device.
+  - interrupts: Should contain host wake interrupt from controller.
+  - interrupt-names: indicates interrupts passed to driver
+      (via interrupts property) by name. "host_wake" is mandatory.
+
+Optional Properties:
+  None
+
+Example:
+
+	bt_sleep {
+		compatible = "qca,ar3002_bluesleep";
+		host-wake-gpio = <&msmgpio 12 0>;
+		ext-wake-gpio = <&msmgpio 13 0>;
+		interrupt-parent = <&msmgpio>;
+		interrupts = <12 0>;
+		interrupt-names = "host_wake";
+	};
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 6b95625..497471a 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -99,6 +99,9 @@
 			settings used to setup MDSS QoS for best performance.
 			The key used should be offset from "mdp_phys" register
 			defined in reg property.
+- qcom,mdss-rot-block-size:	The size of a memory block (in pixels) to be used
+				by the rotator. If this property is not specified,
+				then a default value of 128 pixels would be used.
 
 Optional subnodes:
 Child nodes representing the frame buffer virtual devices.
@@ -131,6 +134,7 @@
 		qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
 		qcom,mdss-pipe-dma-fetch-id = <10 13>;
 		qcom,mdss-smp-data = <22 4096>;
+		qcom,mdss-rot-block-size = <64>;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
 				     0x00000900 0x0000A00>;
diff --git a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
index f1f4e94..3854598 100644
--- a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
+++ b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
@@ -20,6 +20,13 @@
 - qcom,adc-bit-resolution : Bit resolution of the ADC.
 - qcom,adc-vdd-reference : Voltage reference used by the ADC.
 
+Optional properties:
+- qcom,thermal-node : If present a thermal node is created and the channel is registered as
+		part of the thermal sysfs which allows clients to use the thermal framework
+		to set temperature thresholds and receive notification when the temperature
+		crosses a set threshold, read temperature and enable/set trip types supported
+		by the thermal framework.
+
 Channel nodes
 NOTE: Atleast one Channel node is required.
 
@@ -105,7 +112,7 @@
                         qcom,adc-bit-resolution = <15>;
                         qcom,adc-vdd-reference = <1800>;
 
-			/* Channel Node */
+			/* Channel Node to be registered as part of thermal sysfs */
                         chan@b5 {
                                 label = "pa_therm1";
 				reg = <0xb5>;
@@ -116,5 +123,19 @@
                                 qcom,hw-settle-time = <0>;
                                 qcom,fast-avg-setup = <0>;
 				qcom,btm-channel-number = <0x70>;
+				qcom,thermal-node;
                         };
+
+			/* Channel Node */
+			chan@6 {
+				label = "vbat_sns";
+				reg = <6>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <1>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <3>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+				qcom,btm-channel-number = <0x78>;
+			};
 	};
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index ce6da0f..e2b6a66 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -342,6 +342,17 @@
 				qcom,hw-settle-time = <0>;
 				qcom,fast-avg-setup = <0>;
 			};
+
+			chan@c {
+				label = "ref_buf_625mv";
+				reg = <0xc>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
 		};
 
 		iadc@3600 {
@@ -678,5 +689,43 @@
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
+
+                qcom,leds@d300 {
+                        compatible = "qcom,leds-qpnp";
+                        status = "disable";
+                        reg = <0xd300 0x100>;
+                        label = "flash";
+                        pm8226_flash0: qcom,flash_0 {
+                                qcom,max-current = <1000>;
+                                qcom,default-state = "off";
+                                qcom,headroom = <0>;
+                                qcom,duration = <1280>;
+                                qcom,clamp-curr = <200>;
+                                qcom,startup-dly = <1>;
+                                qcom,safety-timer;
+                                label = "flash";
+                                linux,default-trigger =
+                                        "flash0_trigger";
+                                qcom,id = <1>;
+                                linux,name = "led:flash_0";
+                                qcom,current = <625>;
+                        };
+
+                        pm8226_flash1: qcom,flash_1 {
+                                qcom,max-current = <1000>;
+                                qcom,default-state = "off";
+                                qcom,headroom = <0>;
+                                qcom,duration = <1280>;
+                                qcom,clamp-curr = <200>;
+                                qcom,startup-dly = <1>;
+                                qcom,safety-timer;
+                                linux,default-trigger =
+                                        "flash1_trigger";
+                                label = "flash";
+                                qcom,id = <2>;
+                                linux,name = "led:flash_1";
+                                qcom,current = <625>;
+                        };
+                };
 	};
 };
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index d174157..5ccdbf3 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -830,6 +830,30 @@
 				qcom,btm-channel-number = <0x68>;
 			};
 
+			chan@8 {
+				label = "die_temp";
+				reg = <8>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <1>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+				qcom,btm-channel-number = <0x88>;
+			};
+
+			chan@6 {
+				label = "vbat_sns";
+				reg = <6>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <1>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <3>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+				qcom,btm-channel-number = <0x90>;
+			};
+
 			chan@b5 {
 				label = "pa_therm1";
 				reg = <0xb5>;
@@ -840,6 +864,7 @@
 				qcom,hw-settle-time = <2>;
 				qcom,fast-avg-setup = <0>;
 				qcom,btm-channel-number = <0x70>;
+				qcom,thermal-node;
 			};
 
 			chan@b7 {
@@ -852,6 +877,7 @@
 				qcom,hw-settle-time = <2>;
 				qcom,fast-avg-setup = <0>;
 				qcom,btm-channel-number = <0x78>;
+				qcom,thermal-node;
 			};
 
 			chan@b4 {
@@ -864,6 +890,20 @@
 				qcom,hw-settle-time = <2>;
 				qcom,fast-avg-setup = <0>;
 				qcom,btm-channel-number = <0x80>;
+				qcom,thermal-node;
+			};
+
+			chan@b3 {
+				label = "msm_therm";
+				reg = <0xb3>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <2>;
+				qcom,fast-avg-setup = <0>;
+				qcom,btm-channel-number = <0x98>;
+				qcom,thermal-node;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi
index 133dcac..b7f837f 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi
@@ -11,13 +11,33 @@
  * GNU General Public License for more details.
  */
 
+/ {
+
+	led_flash0: qcom,camera-led-flash {
+		cell-index = <0>;
+		compatible = "qcom,camera-led-flash";
+		qcom,flash-type = <1>;
+		qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+	};
+};
+
 &cci {
+
+	actuator0: qcom,actuator@6e {
+		cell-index = <3>;
+		reg = <0x6c 0x0>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+	};
+
 	qcom,camera@6f {
 		compatible = "qcom,ov8825";
 		reg = <0x6f>;
 		qcom,slave-id = <0x6c 0x300a 0x8825>;
 		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 = "ov8825";
 		cam_vdig-supply = <&pm8226_l5>;
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index ef8cb700..9c76512 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -34,6 +34,7 @@
 		qcom,mdss-dspp-off = <0x00004600>;
 		qcom,mdss-wb-off = <0x00011100 0x00013100>;
 		qcom,mdss-intf-off = <0x00000000 0x00021300>;
+		qcom,mdss-rot-block-size = <64>;
 
 		qcom,vbif-settings = <0x004 0x00000001>,
 				     <0x0D8 0x00000707>,
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index e12bb64..be831b4 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -171,6 +171,10 @@
 
 &spmi_bus {
 	qcom,pm8226@1 {
+                qcom,leds@d300 {
+                        status = "okay";
+                };
+
 		qcom,leds@d800 {
 			status = "okay";
 			qcom,wled_0 {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index cdefdd0..6bd5ea9 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -174,6 +174,10 @@
 
 &spmi_bus {
 	qcom,pm8226@1 {
+                qcom,leds@d300 {
+                        status = "okay";
+                };
+
 		qcom,leds@d800 {
 			status = "okay";
 			qcom,wled_0 {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 9fb55c9..6322b8f 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -409,6 +409,15 @@
 		gpios = <&msmgpio 40 0>, <&msmgpio 41 0>, <&msmgpio 42 0>, <&msmgpio 43 0>, <&msmgpio 44 0>;
 		qcom,has_pronto_hw;
 	};
+
+	qcom,msm-adsp-sensors {
+		compatible = "qcom,msm-adsp-sensors";
+		qcom,src-id = <11>;
+		qcom,dst-id = <604>;
+		qcom,ab = <32505856>;
+		qcom,ib = <32505856>;
+	};
+
 	qcom,wdt@f9017000 {
 		compatible = "qcom,msm-watchdog";
 		reg = <0xf9017000 0x1000>;
@@ -651,6 +660,12 @@
 		qcom,is-loadable;
 		qcom,firmware-name = "mba";
 		qcom,pil-self-auth;
+
+		/* GPIO input from mss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+
+		/* GPIO output to mss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
 	};
 
 	qcom,msm-mem-hole {
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 3fbd6fc..3612078 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -15,7 +15,7 @@
 		compatible = "arm,coresight-tmc";
 		reg = <0xfc326000 0x1000>,
 		      <0xfc37c000 0x3000>;
-		reg-names = "tmc-etr-base", "tmc-etr-bam-base";
+		reg-names = "tmc-base", "bam-base";
 
 		qcom,memory-reservation-type = "EBI1";
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
@@ -52,7 +52,7 @@
 	tmc_etf: tmc@fc325000 {
 		compatible = "arm,coresight-tmc";
 		reg = <0xfc325000 0x1000>;
-		reg-names = "tmc-etf-base";
+		reg-names = "tmc-base";
 
 		coresight-id = <3>;
 		coresight-name = "coresight-tmc-etf";
@@ -67,7 +67,7 @@
 	funnel_merg: funnel@fc323000 {
 		compatible = "arm,coresight-funnel";
 		reg = <0xfc323000 0x1000>;
-		reg-names = "funnel-merg-base";
+		reg-names = "funnel-base";
 
 		coresight-id = <4>;
 		coresight-name = "coresight-funnel-merg";
@@ -80,7 +80,7 @@
 	funnel_in0: funnel@fc321000 {
 		compatible = "arm,coresight-funnel";
 		reg = <0xfc321000 0x1000>;
-		reg-names = "funnel-in0-base";
+		reg-names = "funnel-base";
 
 		coresight-id = <5>;
 		coresight-name = "coresight-funnel-in0";
@@ -93,7 +93,7 @@
 	funnel_in1: funnel@fc322000 {
 		compatible = "arm,coresight-funnel";
 		reg = <0xfc322000 0x1000>;
-		reg-names = "funnel-in1-base";
+		reg-names = "funnel-base";
 
 		coresight-id = <6>;
 		coresight-name = "coresight-funnel-in1";
@@ -106,7 +106,7 @@
 	funnel_a7ss: funnel@fc355000 {
 		compatible = "arm,coresight-funnel";
 		reg = <0xfc355000 0x1000>;
-		reg-names = "funnel-a7ss-base";
+		reg-names = "funnel-base";
 
 		coresight-id = <7>;
 		coresight-name = "coresight-funnel-a7ss";
@@ -133,7 +133,7 @@
 	etm0: etm@fc34c000 {
 		compatible = "arm,coresight-etm";
 		reg = <0xfc34c000 0x1000>;
-		reg-names = "etm0-base";
+		reg-names = "etm-base";
 
 		coresight-id = <9>;
 		coresight-name = "coresight-etm0";
@@ -149,7 +149,7 @@
 	etm1: etm@fc34d000 {
 		compatible = "arm,coresight-etm";
 		reg = <0xfc34d000 0x1000>;
-		reg-names = "etm1-base";
+		reg-names = "etm-base";
 
 		coresight-id = <10>;
 		coresight-name = "coresight-etm1";
@@ -165,7 +165,7 @@
 	etm2: etm@fc34e000 {
 		compatible = "arm,coresight-etm";
 		reg = <0xfc34e000 0x1000>;
-		reg-names = "etm2-base";
+		reg-names = "etm-base";
 
 		coresight-id = <11>;
 		coresight-name = "coresight-etm2";
@@ -181,7 +181,7 @@
 	etm3: etm@fc34f000 {
 		compatible = "arm,coresight-etm";
 		reg = <0xfc34f000 0x1000>;
-		reg-names = "etm3-base";
+		reg-names = "etm-base";
 
 		coresight-id = <12>;
 		coresight-name = "coresight-etm3";
@@ -209,7 +209,7 @@
 	cti0: cti@fc310000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc310000 0x1000>;
-		reg-names = "cti0-base";
+		reg-names = "cti-base";
 
 		coresight-id = <14>;
 		coresight-name = "coresight-cti0";
@@ -219,7 +219,7 @@
 	cti1: cti@fc311000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc311000 0x1000>;
-		reg-names = "cti1-base";
+		reg-names = "cti-base";
 
 		coresight-id = <15>;
 		coresight-name = "coresight-cti1";
@@ -229,7 +229,7 @@
 	cti2: cti@fc312000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc312000 0x1000>;
-		reg-names = "cti2-base";
+		reg-names = "cti-base";
 
 		coresight-id = <16>;
 		coresight-name = "coresight-cti2";
@@ -239,7 +239,7 @@
 	cti3: cti@fc313000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc313000 0x1000>;
-		reg-names = "cti3-base";
+		reg-names = "cti-base";
 
 		coresight-id = <17>;
 		coresight-name = "coresight-cti3";
@@ -249,7 +249,7 @@
 	cti4: cti@fc314000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc314000 0x1000>;
-		reg-names = "cti4-base";
+		reg-names = "cti-base";
 
 		coresight-id = <18>;
 		coresight-name = "coresight-cti4";
@@ -259,7 +259,7 @@
 	cti5: cti@fc315000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc315000 0x1000>;
-		reg-names = "cti5-base";
+		reg-names = "cti-base";
 
 		coresight-id = <19>;
 		coresight-name = "coresight-cti5";
@@ -269,7 +269,7 @@
 	cti6: cti@fc316000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc316000 0x1000>;
-		reg-names = "cti6-base";
+		reg-names = "cti-base";
 
 		coresight-id = <20>;
 		coresight-name = "coresight-cti6";
@@ -279,7 +279,7 @@
 	cti7: cti@fc317000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc317000 0x1000>;
-		reg-names = "cti7-base";
+		reg-names = "cti-base";
 
 		coresight-id = <21>;
 		coresight-name = "coresight-cti7";
@@ -289,7 +289,7 @@
 	cti8: cti@fc318000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc318000 0x1000>;
-		reg-names = "cti8-base";
+		reg-names = "cti-base";
 
 		coresight-id = <22>;
 		coresight-name = "coresight-cti8";
@@ -299,7 +299,7 @@
 	cti_cpu0: cti@fc351000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc351000 0x1000>;
-		reg-names = "cti-cpu0-base";
+		reg-names = "cti-base";
 
 		coresight-id = <23>;
 		coresight-name = "coresight-cti-cpu0";
@@ -309,7 +309,7 @@
 	cti_cpu1: cti@fc352000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc352000 0x1000>;
-		reg-names = "cti-cpu1-base";
+		reg-names = "cti-base";
 
 		coresight-id = <24>;
 		coresight-name = "coresight-cti-cpu1";
@@ -319,7 +319,7 @@
 	cti_cpu2: cti@fc353000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc353000 0x1000>;
-		reg-names = "cti-cpu2-base";
+		reg-names = "cti-base";
 
 		coresight-id = <25>;
 		coresight-name = "coresight-cti-cpu2";
@@ -329,7 +329,7 @@
 	cti_cpu3: cti@fc354000 {
 		compatible = "arm,coresight-cti";
 		reg = <0xfc354000 0x1000>;
-		reg-names = "cti-cpu3-base";
+		reg-names = "cti-base";
 
 		coresight-id = <26>;
 		coresight-name = "coresight-cti-cpu3";
diff --git a/arch/arm/boot/dts/msm8610-iommu-domains.dtsi b/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
index 52a8c47..0f48517 100644
--- a/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
+++ b/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
@@ -27,7 +27,7 @@
 			qcom,virtual-addr-pool = <0x10000000 0x0FFFFFFF>;
 		};
 
-		qcom,iommu-domain3 {
+		q6_domain_ns:qcom,iommu-domain3 {
 			label = "lpass_video";
 			qcom,iommu-contexts = <&lpass_video_shared>;
 			qcom,virtual-addr-pool = <0x20000000 0x0FFFFFFF>;
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index b6a6c74..407104f 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -71,7 +71,12 @@
 
 	qcom,vidc@fdc00000 {
 		compatible = "qcom,msm-vidc";
-		hfi = "q6";
+		qcom,vidc-ns-map = <0x40000000 0x40000000>;
+		qcom,iommu-groups = <&q6_domain_ns>;
+		qcom,iommu-group-buffer-types = <0xfff>;
+		qcom,buffer-type-tz-usage-map = <0x1 0x1>,
+						<0x1fe 0x2>;
+		qcom,hfi = "q6";
 	};
 
 	usb@f9a55000 {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 0cf78bc..a10d1d6 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -299,6 +299,15 @@
 		qca,bt-reset-gpio = <&pm8941_gpios 34 0>;
 	};
 
+	bt_ar3002_sleep {
+		compatible = "qca,ar3002_bluesleep";
+		host-wake-gpio = <&msmgpio 79 0>;
+		ext-wake-gpio = <&msmgpio 51 0>;
+		interrupt-parent = <&msmgpio>;
+		interrupts = <79 2>;
+		interrupt-names = "host_wake";
+	};
+
 	sound {
 		qcom,model = "msm8974-taiko-liquid-snd-card";
 
diff --git a/arch/arm/boot/dts/msm8974-v2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-cdp.dts
index 319debe..e591dee 100644
--- a/arch/arm/boot/dts/msm8974-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-cdp.dts
@@ -32,4 +32,6 @@
 			2 &intc 0 133 0
 			3 &spmi_bus 0x0 0x0 0x9 0x0>;
 	interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+
+	qcom,misc-ref = <&pm8941_misc>;
 };
diff --git a/arch/arm/boot/dts/msm8974-v2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-fluid.dts
index 5759b56..4efad9e 100644
--- a/arch/arm/boot/dts/msm8974-v2-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-fluid.dts
@@ -20,3 +20,18 @@
 	compatible = "qcom,msm8974-fluid", "qcom,msm8974";
 	qcom,msm-id = <126 3 0x20000>;
 };
+
+&usb3 {
+	#address-cells = <0>;
+	interrupt-parent = <&usb3>;
+	interrupts = <0 1 2 3>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 131 0
+			1 &intc 0 179 0
+			2 &intc 0 133 0
+			3 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+
+	qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-liquid.dts
index 6812f60..86584f8 100644
--- a/arch/arm/boot/dts/msm8974-v2-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-liquid.dts
@@ -20,3 +20,18 @@
 	compatible = "qcom,msm8974-liquid", "qcom,msm8974";
 	qcom,msm-id = <126 9 0x20000>;
 };
+
+&usb3 {
+	#address-cells = <0>;
+	interrupt-parent = <&usb3>;
+	interrupts = <0 1 2 3>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 131 0
+			1 &intc 0 179 0
+			2 &intc 0 133 0
+			3 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+
+	qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index b29d4ca..a2e2ffa 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -20,3 +20,18 @@
 	compatible = "qcom,msm8974-mtp", "qcom,msm8974";
 	qcom,msm-id = <126 8 0x20000>;
 };
+
+&usb3 {
+	#address-cells = <0>;
+	interrupt-parent = <&usb3>;
+	interrupts = <0 1 2 3>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 131 0
+			1 &intc 0 179 0
+			2 &intc 0 133 0
+			3 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+
+	qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index da71a89..9102770 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -98,6 +98,11 @@
 		qcom,has-ocmem;
 	};
 
+	qcom,vidc {
+		compatible = "qcom,msm-vidc";
+		qcom,hfi = "q6";
+	};
+
 	qcom,wfd {
 		compatible = "qcom,msm-wfd";
 	};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index b06419d..3dbc95d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -189,6 +189,7 @@
 			qcom,dst-bam-pipe-index = <3>;
 			qcom,data-fifo-size = <0xD480>;
 			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe4 {
 			label = "hsic-ipa-in-1";
@@ -201,6 +202,7 @@
 			qcom,dst-bam-pipe-index = <4>;
 			qcom,data-fifo-size = <0xD480>;
 			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe5 {
 			label = "hsic-ipa-in-2";
@@ -213,6 +215,7 @@
 			qcom,dst-bam-pipe-index = <5>;
 			qcom,data-fifo-size = <0xD480>;
 			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe6 {
 			label = "hsic-ipa-in-3";
@@ -225,6 +228,7 @@
 			qcom,dst-bam-pipe-index = <6>;
 			qcom,data-fifo-size = <0xD480>;
 			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe7 {
 			label = "hsic-ipa-out-0";
@@ -237,6 +241,7 @@
 			qcom,src-bam-pipe-index = <7>;
 			qcom,data-fifo-size = <0xD480>;
 			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,reset-bam-on-connect;
 		};
 	};
 
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 8a7928b..10414e1 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -9,7 +9,6 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PANIC_TIMEOUT=5
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
@@ -34,7 +33,6 @@
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 # CONFIG_MSM_ONCRPCROUTER_DEBUG is not set
-# CONFIG_MSM_HW3D is not set
 # CONFIG_QSD_AUDIO is not set
 # CONFIG_SURF_FFA_GPIO_KEYPAD is not set
 CONFIG_MSM_SMCMOD=m
@@ -156,6 +154,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index db2f25d..aa3befa 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -10,7 +10,6 @@
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
@@ -33,7 +32,6 @@
 CONFIG_MSM_ONCRPCROUTER=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
-# CONFIG_MSM_HW3D is not set
 # CONFIG_QSD_AUDIO is not set
 # CONFIG_SURF_FFA_GPIO_KEYPAD is not set
 CONFIG_MSM_SMCMOD=m
@@ -155,6 +153,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 8eac20f..aea092e 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -15,7 +15,6 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -45,7 +44,6 @@
 CONFIG_MSM_IPC_ROUTER=y
 # CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
 CONFIG_MSM_RMT_STORAGE_CLIENT=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM7X27A_AUDIO=y
 CONFIG_MSM_DMA_TEST=y
 CONFIG_MSM_SLEEP_STATS_DEVICE=y
@@ -67,7 +65,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0xC800000
 CONFIG_COMPACTION=y
 CONFIG_CP_ACCESS=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -83,7 +80,6 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -249,7 +245,6 @@
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
 CONFIG_DIAG_CHAR=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
@@ -271,9 +266,6 @@
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
 CONFIG_OV5647=y
 CONFIG_AD5046_ACT=y
@@ -286,6 +278,9 @@
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
 CONFIG_OV7692=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
@@ -356,6 +351,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
 CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 27c10d0..b903a0b 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -15,7 +15,6 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -45,7 +44,6 @@
 CONFIG_MSM_IPC_ROUTER=y
 # CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
 CONFIG_MSM_RMT_STORAGE_CLIENT=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM7X27A_AUDIO=y
 CONFIG_MSM_DMA_TEST=y
 CONFIG_MSM_SLEEP_STATS_DEVICE=y
@@ -69,7 +67,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0xC800000
 CONFIG_COMPACTION=y
 CONFIG_CP_ACCESS=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -85,7 +82,6 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -251,7 +247,6 @@
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
 CONFIG_DIAG_CHAR=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
@@ -273,9 +268,6 @@
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
 CONFIG_OV5647=y
 CONFIG_AD5046_ACT=y
@@ -288,6 +280,9 @@
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
 CONFIG_OV7692=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
@@ -357,6 +352,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
 CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index e46b835..d925ab3 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -13,7 +13,6 @@
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
@@ -30,13 +29,9 @@
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG3=y
-CONFIG_MSM_SDIO_DMUX=y
-CONFIG_MSM_SDIO_CMUX=y
-CONFIG_MSM_SDIO_CTL=y
 CONFIG_MSM_ONCRPCROUTER=y
 CONFIG_MSM_RPC_WATCHDOG=y
 CONFIG_MSM_RMT_STORAGE_CLIENT=y
-# CONFIG_MSM_HW3D is not set
 # CONFIG_QSD_AUDIO is not set
 CONFIG_MSM_MEMORY_LOW_POWER_MODE=y
 CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
@@ -52,7 +47,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x1A000000
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M ip=dhcp"
@@ -64,7 +58,6 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -212,7 +205,6 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
-CONFIG_MSM_RMNET_SDIO=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 CONFIG_SLIP=y
@@ -326,7 +318,6 @@
 CONFIG_USB_G_ANDROID=y
 CONFIG_RMNET_SMD_CTL_CHANNEL="DATA40_CNTL"
 CONFIG_RMNET_SMD_DATA_CHANNEL="DATA40"
-CONFIG_RMNET_SDIO_SMD_DATA_CHANNEL=""
 CONFIG_USB_MSM_ACA=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
@@ -349,6 +340,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index 5964afb..9eea95c 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -13,7 +13,6 @@
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
@@ -30,13 +29,9 @@
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG3=y
-CONFIG_MSM_SDIO_DMUX=y
-CONFIG_MSM_SDIO_CMUX=y
-CONFIG_MSM_SDIO_CTL=y
 CONFIG_MSM_ONCRPCROUTER=y
 CONFIG_MSM_RPC_WATCHDOG=y
 CONFIG_MSM_RMT_STORAGE_CLIENT=y
-# CONFIG_MSM_HW3D is not set
 # CONFIG_QSD_AUDIO is not set
 CONFIG_MSM_MEMORY_LOW_POWER_MODE=y
 CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
@@ -53,7 +48,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x1A000000
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M ip=dhcp"
@@ -65,7 +59,6 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -213,7 +206,6 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
-CONFIG_MSM_RMNET_SDIO=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 CONFIG_SLIP=y
@@ -322,7 +314,6 @@
 CONFIG_USB_G_ANDROID=y
 CONFIG_RMNET_SMD_CTL_CHANNEL="DATA40_CNTL"
 CONFIG_RMNET_SMD_DATA_CHANNEL="DATA40"
-CONFIG_RMNET_SDIO_SMD_DATA_CHANNEL=""
 CONFIG_USB_MSM_ACA=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
@@ -345,6 +336,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 5eef05c..2a6ba73 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -23,7 +23,6 @@
 CONFIG_RD_LZMA=y
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
@@ -36,49 +35,55 @@
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8610=y
 CONFIG_ARCH_MSM8226=y
-CONFIG_SND_SOC_MSM8226=y
-CONFIG_SND_SOC_MSM8X10=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
-CONFIG_MSM_IPC_LOGGING=y
 CONFIG_MSM_BAM_DMUX=y
 CONFIG_MSM_SMP2P=y
 CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_LOGGING=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_LPASS_QDSP6V5=y
-CONFIG_MSM_PIL_PRONTO=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_MSM_PIL_VENUS=y
+CONFIG_MSM_PIL_PRONTO=y
+CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_DLOAD_MODE=y
 CONFIG_MSM_ADSP_LOADER=m
+CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_NONSECURE=y
 CONFIG_MSM_OCMEM_POWER_DISABLE=y
+CONFIG_SENSORS_ADSP=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_SCHED_MC=y
 CONFIG_ARM_ARCH_TIMER=y
-CONFIG_HOTPLUG_CPU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_USE_OF=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -180,9 +185,6 @@
 CONFIG_NET_SCH_HTB=y
 CONFIG_NET_SCH_PRIO=y
 CONFIG_NET_CLS_FW=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
-CONFIG_CMA=y
 CONFIG_BT=y
 CONFIG_BT_RFCOMM=y
 CONFIG_BT_RFCOMM_TTY=y
@@ -191,9 +193,9 @@
 CONFIG_BT_BNEP_PROTO_FILTER=y
 CONFIG_BT_HIDP=y
 CONFIG_BT_HCISMD=y
-CONFIG_MSM_BT_POWER=y
 CONFIG_CFG80211=y
 CONFIG_NL80211_TESTMODE=y
+CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_MD=y
@@ -201,18 +203,18 @@
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_KS8851=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
-CONFIG_KS8851=y
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
-CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
@@ -221,29 +223,49 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
-CONFIG_SPMI=y
-CONFIG_SPMI_MSM_PMIC_ARB=y
-CONFIG_MSM_QPNP_INT=y
-CONFIG_SLIMBUS=y
-CONFIG_SLIMBUS_MSM_NGD=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_SPI=y
-CONFIG_SPI_QUP=y
-CONFIG_SPI_SPIDEV=m
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
-CONFIG_WCD9306_CODEC=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
+CONFIG_MSM_QPNP_INT=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_QPNP_PIN=y
-CONFIG_HWMON=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_QPNP_CHARGER=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
-CONFIG_REGULATOR=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_WCD9306_CODEC=y
 CONFIG_REGULATOR_STUB=y
 CONFIG_REGULATOR_QPNP=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_MSM_CAMERA is not set
+CONFIG_OV8825=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_ISPIF=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_OV9724=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
@@ -261,6 +283,8 @@
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MSM8226=y
+CONFIG_SND_SOC_MSM8X10=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
@@ -275,25 +299,34 @@
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_TEST=m
 CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_DRV_QPNP=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_QPNP_PWM=y
-CONFIG_MSM_IOMMU=y
-CONFIG_MSM_IOMMU_PMON=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
-CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_QPNP=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_DRV_MSM is not set
-CONFIG_RTC_DRV_QPNP=y
+CONFIG_QPNP_PWM=y
+CONFIG_QPNP_POWER_ON=y
+CONFIG_MSM_IOMMU=y
+CONFIG_MSM_IOMMU_PMON=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_EVENT=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
@@ -307,66 +340,16 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_TWOFISH=y
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=y
-CONFIG_QPNP_POWER_ON=y
-CONFIG_LIBCRC32C=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_MEDIA_CAMERA_SUPPORT=y
-# CONFIG_MSM_CAMERA is not set
-CONFIG_MSM_VIDC_V4L2=y
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_SUBDEV_API=y
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_MSM_OCMEM=y
-CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
-CONFIG_MSM_OCMEM_DEBUG=y
-CONFIG_MSM_OCMEM_NONSECURE=y
-CONFIG_THERMAL=y
-CONFIG_THERMAL_TSENS8974=y
-CONFIG_THERMAL_MONITOR=y
-CONFIG_THERMAL_QPNP_ADC_TM=y
-CONFIG_MSM_RTB=y
-CONFIG_MSM_RTB_SEPARATE_CPUS=y
-CONFIG_CORESIGHT=y
-CONFIG_CORESIGHT_TMC=y
-CONFIG_CORESIGHT_TPIU=y
-CONFIG_CORESIGHT_FUNNEL=y
-CONFIG_CORESIGHT_REPLICATOR=y
-CONFIG_CORESIGHT_STM=y
-CONFIG_CORESIGHT_ETM=y
-CONFIG_CORESIGHT_EVENT=m
-CONFIG_ENABLE_DEFAULT_TRACERS=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_TZ_LOG=y
-CONFIG_MEDIA_CONTROLLER=y
-# CONFIG_MSM_CAMERA is not set
-CONFIG_OV8825=y
-CONFIG_OV9724=y
-CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_CCI=y
-CONFIG_MSM_CPP=y
-CONFIG_MSM_CSI30_HEADER=y
-CONFIG_MSM_CSIPHY=y
-CONFIG_MSM_CSID=y
-CONFIG_MSM_ISPIF=y
-CONFIG_MSMB_CAMERA=y
-CONFIG_MSMB_JPEG=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index baefac5..dda9bd3 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -21,7 +21,6 @@
 CONFIG_RD_LZMA=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PANIC_TIMEOUT=5
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 # CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
@@ -47,21 +46,15 @@
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
-CONFIG_MSM_SDIO_DMUX=y
 # CONFIG_MSM_RESET_MODEM is not set
 # CONFIG_MSM_SMD_NMEA is not set
-CONFIG_MSM_SDIO_TTY=y
 # CONFIG_MSM_SMD_QMI is not set
-CONFIG_MSM_SDIO_CMUX=y
 CONFIG_MSM_DSPS=y
-CONFIG_MSM_SDIO_CTL=y
 CONFIG_MSM_ONCRPCROUTER=y
 # CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
 # CONFIG_MSM_RPCSERVER_WATCHDOG is not set
 # CONFIG_MSM_RPCSERVER_HANDSET is not set
 CONFIG_MSM_RMT_STORAGE_CLIENT=y
-CONFIG_MSM_SDIO_SMEM=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_MODEM=y
@@ -84,7 +77,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_COMPACTION=y
 CONFIG_CP_ACCESS=y
 CONFIG_CPU_FREQ=y
@@ -96,7 +88,6 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -252,7 +243,6 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
-CONFIG_MSM_RMNET_SDIO=y
 CONFIG_SMC91X=y
 CONFIG_SMC911X=y
 CONFIG_SMSC911X=y
@@ -315,10 +305,6 @@
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
 CONFIG_IMX074=y
 CONFIG_WEBCAM_OV9726=y
@@ -328,6 +314,10 @@
 CONFIG_MSM_ACTUATOR=y
 CONFIG_MSM_GEMINI=y
 CONFIG_OV7692=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
@@ -404,7 +394,6 @@
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_SLEEP=y
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
@@ -413,6 +402,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 28d7b12..abc7460 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -21,7 +21,6 @@
 CONFIG_RD_LZMA=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PANIC_TIMEOUT=5
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -46,21 +45,15 @@
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
-CONFIG_MSM_SDIO_DMUX=y
 # CONFIG_MSM_RESET_MODEM is not set
 # CONFIG_MSM_SMD_NMEA is not set
-CONFIG_MSM_SDIO_TTY=y
 # CONFIG_MSM_SMD_QMI is not set
-CONFIG_MSM_SDIO_CMUX=y
 CONFIG_MSM_DSPS=y
-CONFIG_MSM_SDIO_CTL=y
 CONFIG_MSM_ONCRPCROUTER=y
 # CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
 # CONFIG_MSM_RPCSERVER_WATCHDOG is not set
 # CONFIG_MSM_RPCSERVER_HANDSET is not set
 CONFIG_MSM_RMT_STORAGE_CLIENT=y
-CONFIG_MSM_SDIO_SMEM=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_MODEM=y
@@ -83,7 +76,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_COMPACTION=y
 CONFIG_CP_ACCESS=y
 CONFIG_CPU_FREQ=y
@@ -95,7 +87,6 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -252,7 +243,6 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
-CONFIG_MSM_RMNET_SDIO=y
 CONFIG_SMC91X=y
 CONFIG_SMC911X=y
 CONFIG_SMSC911X=y
@@ -315,10 +305,6 @@
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
 CONFIG_IMX074=y
 CONFIG_WEBCAM_OV9726=y
@@ -328,6 +314,10 @@
 CONFIG_MSM_ACTUATOR=y
 CONFIG_MSM_GEMINI=y
 CONFIG_OV7692=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
@@ -404,7 +394,6 @@
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_SLEEP=y
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
@@ -413,6 +402,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index a8ea31d..4e6cb05 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -24,7 +24,6 @@
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -35,6 +34,7 @@
 CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_EFI_PARTITION=y
+CONFIG_IOSCHED_TEST=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8960=y
 CONFIG_ARCH_MSM8930=y
@@ -69,7 +69,6 @@
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_AVS_HW=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_LPASS_QDSP6V4=y
@@ -107,7 +106,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_CC_STACKPROTECTOR=y
 CONFIG_CP_ACCESS=y
 CONFIG_CPU_FREQ=y
@@ -119,7 +117,10 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -134,8 +135,6 @@
 CONFIG_IP_PNP_DHCP=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
@@ -355,11 +354,6 @@
 CONFIG_DVB_CORE=m
 CONFIG_USER_RC_INPUT=y
 CONFIG_IR_GPIO_CIR=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
 CONFIG_IMX074=y
 CONFIG_MT9M114=y
@@ -376,17 +370,22 @@
 CONFIG_MSM_GEMINI=y
 CONFIG_MSM_MERCURY=y
 CONFIG_MSM_CSI20_HEADER=y
-CONFIG_S5K3L1YX=y
-CONFIG_IMX091=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
+CONFIG_S5K3L1YX=y
+CONFIG_IMX091=y
 CONFIG_MSM_WFD=y
-CONFIG_RADIO_IRIS=y
-CONFIG_RADIO_IRIS_TRANSPORT=m
-# CONFIG_DVB_FE_CUSTOMISE is not set
 CONFIG_DVB_MPQ=m
 CONFIG_DVB_MPQ_DEMUX=m
 CONFIG_DVB_MPQ_VIDEO=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
+# CONFIG_DVB_FE_CUSTOMISE is not set
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
@@ -457,14 +456,13 @@
 CONFIG_MMC_BLOCK_MINORS=32
 # CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_TEST=m
+CONFIG_MMC_BLOCK_TEST=y
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
 # CONFIG_MMC_MSM_SDC2_SUPPORT is not set
 CONFIG_MMC_MSM_SDC3_SUPPORT=y
 CONFIG_MMC_MSM_SDC3_WP_SUPPORT=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_IOSCHED_TEST=y
-CONFIG_MMC_BLOCK_TEST=y
 CONFIG_LEDS_PM8XXX=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -475,6 +473,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
@@ -529,9 +528,3 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 9f10bc4..c4fffb9 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -23,7 +23,6 @@
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -34,6 +33,7 @@
 CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_EFI_PARTITION=y
+CONFIG_IOSCHED_TEST=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8960=y
 CONFIG_ARCH_MSM8930=y
@@ -68,7 +68,6 @@
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_AVS_HW=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_LPASS_QDSP6V4=y
@@ -112,7 +111,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_CC_STACKPROTECTOR=y
 CONFIG_CP_ACCESS=y
 CONFIG_CPU_FREQ=y
@@ -124,7 +122,10 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -139,8 +140,6 @@
 CONFIG_IP_PNP_DHCP=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
@@ -360,11 +359,6 @@
 CONFIG_DVB_CORE=m
 CONFIG_USER_RC_INPUT=y
 CONFIG_IR_GPIO_CIR=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA_V4L2=y
 CONFIG_IMX074=y
 CONFIG_MT9M114=y
@@ -380,17 +374,22 @@
 CONFIG_MSM_GEMINI=y
 CONFIG_MSM_MERCURY=y
 CONFIG_MSM_CSI20_HEADER=y
-CONFIG_S5K3L1YX=y
-CONFIG_IMX091=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
+CONFIG_S5K3L1YX=y
+CONFIG_IMX091=y
 CONFIG_MSM_WFD=y
-CONFIG_RADIO_IRIS=y
-CONFIG_RADIO_IRIS_TRANSPORT=m
-# CONFIG_DVB_FE_CUSTOMISE is not set
 CONFIG_DVB_MPQ=m
 CONFIG_DVB_MPQ_DEMUX=m
 CONFIG_DVB_MPQ_VIDEO=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
+# CONFIG_DVB_FE_CUSTOMISE is not set
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
@@ -460,14 +459,13 @@
 CONFIG_MMC_BLOCK_MINORS=32
 # CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_TEST=m
+CONFIG_MMC_BLOCK_TEST=y
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
 # CONFIG_MMC_MSM_SDC2_SUPPORT is not set
 CONFIG_MMC_MSM_SDC3_SUPPORT=y
 CONFIG_MMC_MSM_SDC3_WP_SUPPORT=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_IOSCHED_TEST=y
-CONFIG_MMC_BLOCK_TEST=y
 CONFIG_LEDS_PM8XXX=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -478,6 +476,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
@@ -547,9 +546,3 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index d2c97b1..c33a236 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -24,7 +24,6 @@
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -54,7 +53,6 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_IPC_ROUTER_SECURITY=y
 CONFIG_MSM_QMI_INTERFACE=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_LPASS_QDSP6V5=y
@@ -63,6 +61,7 @@
 CONFIG_MSM_PIL_PRONTO=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_MEMORY_DUMP=y
@@ -71,6 +70,7 @@
 CONFIG_MSM_OCMEM=y
 CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
 CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_SENSORS_ADSP=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_CACHE_ERP=y
@@ -80,6 +80,7 @@
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_MSM_BOOT_STATS=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -90,7 +91,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_CC_STACKPROTECTOR=y
 CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
@@ -103,7 +103,10 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -117,8 +120,6 @@
 CONFIG_IP_PNP_DHCP=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
@@ -234,13 +235,12 @@
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
 CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_QSEECOM=y
+CONFIG_QPNP_MISC=y
 CONFIG_USB_HSIC_SMSC_HUB=y
 CONFIG_TI_DRV2667=y
 CONFIG_SCSI=y
@@ -293,8 +293,6 @@
 CONFIG_SPMI=y
 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
@@ -325,14 +323,14 @@
 # CONFIG_MSM_CAMERA is not set
 CONFIG_MT9M114=y
 CONFIG_OV2720=y
+CONFIG_IMX135=y
 CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_CCI=y
 CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
 CONFIG_MSM_CSI30_HEADER=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
 CONFIG_MSM_ISPIF=y
-CONFIG_IMX135=y
 CONFIG_S5K3L1YX=y
 CONFIG_MSMB_CAMERA=y
 CONFIG_MSMB_JPEG=y
@@ -402,8 +400,8 @@
 CONFIG_MMC_BLOCK_TEST=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_MSM=y
 CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
@@ -416,6 +414,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
@@ -427,6 +426,7 @@
 CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_REVID=y
 CONFIG_QPNP_COINCELL=y
 CONFIG_MSM_IOMMU=y
 CONFIG_MOBICORE_SUPPORT=m
@@ -465,17 +465,10 @@
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCEDEV=y
-CONFIG_CRC_CCITT=y
-CONFIG_MSM_EVENT_TIMER=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index c9d6112..1cda524 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -23,7 +23,6 @@
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -53,7 +52,6 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_IPC_ROUTER_SECURITY=y
 CONFIG_MSM_QMI_INTERFACE=y
-# CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_LPASS_QDSP6V5=y
@@ -62,6 +60,7 @@
 CONFIG_MSM_PIL_PRONTO=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_MEMORY_DUMP=y
@@ -70,6 +69,7 @@
 CONFIG_MSM_OCMEM=y
 CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
 CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_SENSORS_ADSP=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_CACHE_ERP=y
@@ -84,6 +84,7 @@
 CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_MSM_BOOT_STATS=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -94,7 +95,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_CC_STACKPROTECTOR=y
 CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
@@ -107,7 +107,10 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -121,8 +124,6 @@
 CONFIG_IP_PNP_DHCP=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
@@ -238,14 +239,13 @@
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
 CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_TSPP=m
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_QSEECOM=y
+CONFIG_QPNP_MISC=y
 CONFIG_USB_HSIC_SMSC_HUB=y
 CONFIG_TI_DRV2667=y
 CONFIG_SCSI=y
@@ -298,8 +298,6 @@
 CONFIG_SPMI=y
 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
@@ -331,15 +329,15 @@
 # CONFIG_MSM_CAMERA is not set
 CONFIG_MT9M114=y
 CONFIG_OV2720=y
+CONFIG_IMX135=y
 CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_CCI=y
 CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
 CONFIG_MSM_CSI30_HEADER=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
 CONFIG_MSM_ISPIF=y
 CONFIG_S5K3L1YX=y
-CONFIG_IMX135=y
 CONFIG_MSMB_CAMERA=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
@@ -410,8 +408,8 @@
 CONFIG_MMC_BLOCK_TEST=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_MSM=y
 CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
@@ -424,6 +422,7 @@
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
 CONFIG_ANDROID_LOGGER=y
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
@@ -435,6 +434,7 @@
 CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_REVID=y
 CONFIG_QPNP_COINCELL=y
 CONFIG_MSM_IOMMU=y
 CONFIG_MSM_IOMMU_PMON=y
@@ -490,17 +490,10 @@
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCEDEV=y
-CONFIG_CRC_CCITT=y
-CONFIG_MSM_EVENT_TIMER=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 9ab1cdd..0fb8538 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -62,7 +62,6 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -185,7 +184,6 @@
 CONFIG_SERIO_LIBPS2=y
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index c2fb1487..8d6bc81 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -34,7 +34,6 @@
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM9625=y
 # CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
@@ -52,15 +51,18 @@
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
 CONFIG_MSM_DLOAD_MODE=y
 CONFIG_MSM_ADSP_LOADER=m
+CONFIG_MSM_RTB=y
+CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_MSM_BOOT_STATS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_ARM_ARCH_TIMER=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -71,6 +73,7 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -161,11 +164,18 @@
 CONFIG_MTD_BLOCK=y
 # CONFIG_MTD_MSM_NAND is not set
 CONFIG_MTD_MSM_QPIC_NAND=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_ANDROID_PMEM is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
@@ -174,8 +184,8 @@
 CONFIG_KS8851=y
 # CONFIG_NET_VENDOR_MICROCHIP is not set
 # CONFIG_MSM_RMNET is not set
-# CONFIG_MSM_RMNET_BAM is not set
 CONFIG_MSM_RMNET_WWAN=y
+CONFIG_ECM_IPA=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
@@ -190,9 +200,8 @@
 CONFIG_INPUT_GPIO=m
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HS=y
-CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_SERIAL_MSM_HSL=y
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
@@ -222,18 +231,35 @@
 CONFIG_ION_MSM=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
-CONFIG_FB_MSM_QPIC=y
 CONFIG_FB_MSM_QPIC_PANEL_DETECT=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_MDM9625=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_CI13XXX_MSM=y
 CONFIG_USB_G_ANDROID=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
@@ -253,7 +279,6 @@
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_IPA=y
-CONFIG_ECM_IPA=y
 CONFIG_CORESIGHT=y
 CONFIG_CORESIGHT_TMC=y
 CONFIG_CORESIGHT_TPIU=y
@@ -262,10 +287,10 @@
 CONFIG_CORESIGHT_STM=y
 CONFIG_CORESIGHT_ETM=y
 CONFIG_CORESIGHT_EVENT=m
+CONFIG_EXT3_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_YAFFS_FS=y
-CONFIG_EXT3_FS=y
 CONFIG_YAFFS_DISABLE_TAGS_ECC=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -298,37 +323,3 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_EHSET=y
-CONFIG_USB_EHCI_MSM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-CONFIG_USB_STORAGE_ONETOUCH=y
-CONFIG_USB_STORAGE_KARMA=y
-CONFIG_USB_STORAGE_CYPRESS_ATACB=y
-CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_MSM_RTB=y
-CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 828eaa9..9e9bba9 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -34,7 +34,6 @@
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM9625=y
 # CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
@@ -52,15 +51,18 @@
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
 CONFIG_MSM_DLOAD_MODE=y
 CONFIG_MSM_ADSP_LOADER=m
+CONFIG_MSM_RTB=y
+CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_MSM_BOOT_STATS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_ARM_ARCH_TIMER=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -71,6 +73,7 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -161,11 +164,18 @@
 CONFIG_MTD_BLOCK=y
 # CONFIG_MTD_MSM_NAND is not set
 CONFIG_MTD_MSM_QPIC_NAND=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_ANDROID_PMEM is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
@@ -174,8 +184,8 @@
 CONFIG_KS8851=y
 # CONFIG_NET_VENDOR_MICROCHIP is not set
 # CONFIG_MSM_RMNET is not set
-# CONFIG_MSM_RMNET_BAM is not set
 CONFIG_MSM_RMNET_WWAN=y
+CONFIG_ECM_IPA=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
@@ -190,10 +200,9 @@
 CONFIG_INPUT_GPIO=m
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
-CONFIG_SERIAL_MSM_HS=y
-CONFIG_MSM_UARTDM_Core_v14=y
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
@@ -223,18 +232,35 @@
 CONFIG_ION_MSM=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
-CONFIG_FB_MSM_QPIC=y
 CONFIG_FB_MSM_QPIC_PANEL_DETECT=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_MDM9625=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_CI13XXX_MSM=y
 CONFIG_USB_G_ANDROID=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
@@ -254,7 +280,6 @@
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_IPA=y
-CONFIG_ECM_IPA=y
 CONFIG_CORESIGHT=y
 CONFIG_CORESIGHT_TMC=y
 CONFIG_CORESIGHT_TPIU=y
@@ -263,10 +288,10 @@
 CONFIG_CORESIGHT_STM=y
 CONFIG_CORESIGHT_ETM=y
 CONFIG_CORESIGHT_EVENT=m
+CONFIG_EXT3_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_YAFFS_FS=y
-CONFIG_EXT3_FS=y
 CONFIG_YAFFS_DISABLE_TAGS_ECC=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -299,37 +324,3 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_EHSET=y
-CONFIG_USB_EHCI_MSM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-CONFIG_USB_STORAGE_ONETOUCH=y
-CONFIG_USB_STORAGE_KARMA=y
-CONFIG_USB_STORAGE_CYPRESS_ATACB=y
-CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_MSM_RTB=y
-CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 18b1c5a..618668f 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -281,7 +281,6 @@
 	select MSM_RPM_STATS_LOG
 	select QMI_ENCDEC
 	select DONT_MAP_HOLE_AFTER_MEMBANK0
-	select SENSORS_ADSP
 	select MSM_ULTRASOUND_B
 	select MSM_LPM_TEST
 	select MSM_RPM_LOG
@@ -2642,6 +2641,8 @@
 
 config SENSORS_ADSP
 	bool "Enable Sensors Driver Support for ADSP"
+	depends on (ARCH_MSM8226 || ARCH_MSM8974)
+	default y
 	help
 	  Add support for sensors ADSP driver.
 	  This driver is used for exercising different sensors use cases,
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 48abd35..42bde8f 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1887,7 +1887,7 @@
 
 static struct gpiomux_setting mdm2ap_status_gpio_run_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
 
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 1aa7508..bf8f895 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -243,25 +243,25 @@
 
 static struct gpiomux_setting ap2mdm_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_4MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting mdm2ap_status_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
 
 static struct gpiomux_setting mdm2ap_errfatal_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_16MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_4MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 930f9e3..a645e9c 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3036,6 +3036,8 @@
 	CLK_LOOKUP("mem_clk",	bimc_msmbus_clk.c,	"msm_bimc"),
 	CLK_LOOKUP("mem_a_clk",	bimc_msmbus_a_clk.c,	"msm_bimc"),
 	CLK_LOOKUP("mem_clk",	bimc_acpu_a_clk.c,	""),
+	CLK_LOOKUP("bus_clk",	mmss_s0_axi_clk.c,	"msm_mmss_noc"),
+	CLK_LOOKUP("bus_a_clk",	mmss_s0_axi_clk.c,	"msm_mmss_noc"),
 
 	/* CoreSight clocks */
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc326000.tmc"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e040d7f..e6874b7 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -707,6 +707,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),
 	.base = &virt_bases[GCC_BASE],
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index b7707d7..656c3f4 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -3154,6 +3154,7 @@
 
 static struct resource coresight_funnel_resources[] = {
 	{
+		.name  = "funnel-base",
 		.start = CORESIGHT_FUNNEL_PHYS_BASE,
 		.end   = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
@@ -3186,6 +3187,7 @@
 
 static struct resource coresight_etm2_resources[] = {
 	{
+		.name  = "etm-base",
 		.start = CORESIGHT_ETM2_PHYS_BASE,
 		.end   = CORESIGHT_ETM2_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
@@ -3218,6 +3220,7 @@
 
 static struct resource coresight_etm3_resources[] = {
 	{
+		.name  = "etm-base",
 		.start = CORESIGHT_ETM3_PHYS_BASE,
 		.end   = CORESIGHT_ETM3_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 24b579f..d4c33e3 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -4104,6 +4104,7 @@
 
 static struct resource coresight_tpiu_resources[] = {
 	{
+		.name  = "tpiu-base",
 		.start = CORESIGHT_TPIU_PHYS_BASE,
 		.end   = CORESIGHT_TPIU_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
@@ -4129,6 +4130,7 @@
 
 static struct resource coresight_etb_resources[] = {
 	{
+		.name  = "etb-base",
 		.start = CORESIGHT_ETB_PHYS_BASE,
 		.end   = CORESIGHT_ETB_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
@@ -4155,6 +4157,7 @@
 
 static struct resource coresight_funnel_resources[] = {
 	{
+		.name  = "funnel-base",
 		.start = CORESIGHT_FUNNEL_PHYS_BASE,
 		.end   = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
@@ -4187,11 +4190,13 @@
 
 static struct resource coresight_stm_resources[] = {
 	{
+		.name  = "stm-base",
 		.start = CORESIGHT_STM_PHYS_BASE,
 		.end   = CORESIGHT_STM_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.name  = "stm-data-base",
 		.start = CORESIGHT_STM_CHANNEL_PHYS_BASE,
 		.end   = CORESIGHT_STM_CHANNEL_PHYS_BASE + SZ_1M + SZ_512K - 1,
 		.flags = IORESOURCE_MEM,
@@ -4224,6 +4229,7 @@
 
 static struct resource coresight_etm0_resources[] = {
 	{
+		.name  = "etm-base",
 		.start = CORESIGHT_ETM0_PHYS_BASE,
 		.end   = CORESIGHT_ETM0_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
@@ -4256,6 +4262,7 @@
 
 static struct resource coresight_etm1_resources[] = {
 	{
+		.name  = "etm-base",
 		.start = CORESIGHT_ETM1_PHYS_BASE,
 		.end   = CORESIGHT_ETM1_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index d908a65..fec734a 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -76,6 +76,8 @@
 
 #if defined(CONFIG_MSM_IOMMU)
 
+extern void msm_iommu_set_client_name(struct iommu_domain *domain,
+				      char const *name);
 extern struct iommu_domain *msm_get_iommu_domain(int domain_num);
 extern int msm_find_domain_no(const struct iommu_domain *domain);
 
@@ -121,6 +123,11 @@
 extern int msm_register_domain(struct msm_iova_layout *layout);
 
 #else
+static inline void msm_iommu_set_client_name(struct iommu_domain *domain,
+					     char const *name)
+{
+}
+
 static inline struct iommu_domain
 	*msm_get_iommu_domain(int subsys_id) { return NULL; }
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iommu_priv.h b/arch/arm/mach-msm/include/mach/msm_iommu_priv.h
new file mode 100644
index 0000000..a2f4836
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iommu_priv.h
@@ -0,0 +1,41 @@
+/* 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 MSM_IOMMU_PRIV_H
+#define MSM_IOMMU_PRIV_H
+
+/**
+ * struct msm_iommu_pt - Container for first level page table and its
+ * attributes.
+ * fl_table: Pointer to the first level page table.
+ * redirect: Set to 1 if L2 redirect for page tables are enabled, 0 otherwise.
+ */
+struct msm_iommu_pt {
+	unsigned long *fl_table;
+	int redirect;
+};
+
+/**
+ * struct msm_iommu_priv - Container for page table attributes and other
+ * private iommu domain information.
+ * attributes.
+ * pt: Page table attribute structure
+ * list_attached: List of devices (contexts) attached to this domain.
+ * client_name: Name of the domain client.
+ */
+struct msm_iommu_priv {
+	struct msm_iommu_pt pt;
+	struct list_head list_attached;
+	const char *client_name;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 5228abc..a837ca1 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -25,6 +25,7 @@
 #include <asm/page.h>
 #include <mach/iommu.h>
 #include <mach/iommu_domains.h>
+#include <mach/msm_iommu_priv.h>
 #include <mach/socinfo.h>
 #include <mach/msm_subsystem_map.h>
 
@@ -40,6 +41,12 @@
 DEFINE_MUTEX(domain_mutex);
 static atomic_t domain_nums = ATOMIC_INIT(-1);
 
+void msm_iommu_set_client_name(struct iommu_domain *domain, char const *name)
+{
+	struct msm_iommu_priv *priv = domain->priv;
+	priv->client_name = name;
+}
+
 int msm_use_iommu()
 {
 	return iommu_present(&platform_bus_type);
@@ -431,6 +438,10 @@
 	data->npools = layout->npartitions;
 	data->domain_num = atomic_inc_return(&domain_nums);
 	data->domain = iommu_domain_alloc(bus, layout->domain_flags);
+	if (!data->domain)
+		goto out;
+
+	msm_iommu_set_client_name(data->domain, layout->client_name);
 
 	add_domain(data);
 
@@ -479,7 +490,8 @@
 }
 
 static int create_and_add_domain(struct iommu_group *group,
-				 const struct device_node *node)
+				 struct device_node const *node,
+				 char const *name)
 {
 	unsigned int ret_val = 0;
 	unsigned int i, j;
@@ -539,6 +551,7 @@
 		part[0].size = 0xFFFFFFFF;
 	}
 
+	l.client_name = name;
 	l.partitions = part;
 
 	secure_domain = of_property_read_bool(node, "qcom,secure-domain");
@@ -594,7 +607,7 @@
 			ret_val = -EINVAL;
 			goto free_group;
 		}
-		ret_val = create_and_add_domain(group, node);
+		ret_val = create_and_add_domain(group, node, name);
 		if (ret_val) {
 			ret_val = -EINVAL;
 			goto free_group;
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index a50a37d..cafcdd2 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -48,7 +48,7 @@
 #define IPC_ROUTER_XPRT_EVENT_CLOSE 3
 
 #define IPC_ROUTER_INFINITY -1
-#define DEFAULT_RCV_TIMEO IPC_ROUTER_INFINITY
+#define DEFAULT_RCV_TIMEO 0
 
 #define ALIGN_SIZE(x) ((4 - ((x) & 3)) & 3)
 
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 16b60a1..f40bd5d 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -414,7 +414,7 @@
 		}
 
 		if (timeout == 0)
-			return -ETIMEDOUT;
+			return 0;
 		lock_sock(sk);
 		mutex_lock(&port_ptr->port_rx_q_lock);
 	}
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 9f06cf6..c8d6d5a 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -161,9 +161,11 @@
 		 */
 		pr_debug("%s: Pulling AP2MDM_KPDPWR gpio high\n", __func__);
 		gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
+		gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
 		msleep(1000);
 		gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
-	}
+	} else
+		gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
 
 	if (!GPIO_IS_VALID(mdm_drv->mdm2ap_pblrdy))
 		goto start_mdm_peripheral;
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 03d158e..de46be8 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -649,7 +649,7 @@
 		}
 	}
 
-	gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
+	gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 0);
 	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);
 
 	if (GPIO_IS_VALID(mdm_drv->ap2mdm_wakeup_gpio))
diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c
index 1589623..f70022e 100644
--- a/arch/arm/mach-msm/msm_rq_stats.c
+++ b/arch/arm/mach-msm/msm_rq_stats.c
@@ -213,7 +213,9 @@
 	switch (val) {
 	case PM_POST_HIBERNATION:
 	case PM_POST_SUSPEND:
+	case PM_POST_RESTORE:
 		rq_info.hotplug_disabled = 0;
+		break;
 	case PM_HIBERNATION_PREPARE:
 	case PM_SUSPEND_PREPARE:
 		rq_info.hotplug_disabled = 1;
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 34d336e..88de98b 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -24,7 +24,7 @@
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o
-obj-$(CONFIG_MSM_QDSP6V2_CODECS)  += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS)  += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
 obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
 obj-$(CONFIG_MSM_ULTRASOUND_B) += ultrasound/version_b/
diff --git a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
index 7472b46..e74fdf9 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
+++ b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -56,9 +56,6 @@
 			goto fail;
 		}
 
-		/* Query the DSP to check if resources are available */
-		msleep(Q6_PIL_GET_DELAY_MS);
-
 		/* Set the state of the ADSP in APR driver */
 		apr_set_q6_state(APR_SUBSYS_LOADED);
 	} else if (adsp_state == APR_SUBSYS_LOADED) {
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 57c85e1..1f0fa85 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -278,6 +278,7 @@
 
 	/* 8974 IDs */
 	[126] = MSM_CPU_8974,
+	[184] = MSM_CPU_8974,
 
 	/* 8625 IDs */
 	[127] = MSM_CPU_8625,
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index b6d90d4..2557983 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -5,7 +5,7 @@
  *  power management protocol extension to H4 to support AR300x Bluetooth Chip.
  *
  *  Copyright (c) 2009-2010 Atheros Communications Inc.
- *  Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
  *
  *  Acknowledgements:
  *  This file is based on hci_h4.c, which was written
@@ -38,7 +38,7 @@
 #include <linux/skbuff.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-
+#include <linux/of_gpio.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
@@ -52,6 +52,13 @@
 /*
  * Global variables
  */
+
+/** Device table */
+static struct of_device_id bluesleep_match_table[] = {
+	{ .compatible = "qca,ar3002_bluesleep" },
+	{}
+};
+
 /** Global state flags */
 static unsigned long flags;
 
@@ -436,10 +443,59 @@
 	.flush = ath_flush,
 };
 
-static int __init bluesleep_probe(struct platform_device *pdev)
+
+static int bluesleep_populate_dt_pinfo(struct platform_device *pdev)
+{
+	BT_DBG("");
+
+	if (!bsi)
+		return -ENOMEM;
+
+	bsi->host_wake = of_get_named_gpio(pdev->dev.of_node,
+					 "host-wake-gpio", 0);
+	if (bsi->host_wake < 0) {
+		BT_ERR("couldn't find host_wake gpio\n");
+		return -ENODEV;
+	}
+
+	bsi->ext_wake = of_get_named_gpio(pdev->dev.of_node,
+					 "ext-wake-gpio", 0);
+	if (bsi->ext_wake < 0) {
+		BT_ERR("couldn't find ext_wake gpio\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bluesleep_populate_pinfo(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	BT_DBG("");
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IO,
+				"gpio_host_wake");
+	if (!res) {
+		BT_ERR("couldn't find host_wake gpio\n");
+		return -ENODEV;
+	}
+	bsi->host_wake = res->start;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IO,
+				"gpio_ext_wake");
+	if (!res) {
+		BT_ERR("couldn't find ext_wake gpio\n");
+		return -ENODEV;
+	}
+	bsi->ext_wake = res->start;
+
+	return 0;
+}
+
+static int __devinit bluesleep_probe(struct platform_device *pdev)
 {
 	int ret;
-	struct resource *res;
 
 	BT_DBG("");
 
@@ -449,23 +505,22 @@
 		goto failed;
 	}
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_IO,
-						"gpio_host_wake");
-	if (!res) {
-		BT_ERR("couldn't find host_wake gpio\n");
-		ret = -ENODEV;
-		goto free_bsi;
+	if (pdev->dev.of_node) {
+		ret = bluesleep_populate_dt_pinfo(pdev);
+		if (ret < 0) {
+			BT_ERR("Failed to populate device tree info");
+			goto free_bsi;
+		}
+	} else {
+		ret = bluesleep_populate_pinfo(pdev);
+		if (ret < 0) {
+			BT_ERR("Failed to populate device info");
+			goto free_bsi;
+		}
 	}
-	bsi->host_wake = res->start;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_IO,
-						"gpio_ext_wake");
-	if (!res) {
-		BT_ERR("couldn't find ext_wake gpio\n");
-		ret = -ENODEV;
-		goto free_bsi;
-	}
-	bsi->ext_wake = res->start;
+	BT_DBG("host_wake_gpio: %d ext_wake_gpio: %d",
+				bsi->host_wake, bsi->ext_wake);
 
 	bsi->host_wake_irq = platform_get_irq_byname(pdev, "host_wake");
 	if (bsi->host_wake_irq < 0) {
@@ -492,10 +547,12 @@
 }
 
 static struct platform_driver bluesleep_driver = {
+	.probe = bluesleep_probe,
 	.remove = bluesleep_remove,
 	.driver = {
 		.name = "bluesleep",
 		.owner = THIS_MODULE,
+		.of_match_table = bluesleep_match_table,
 	},
 };
 
@@ -511,9 +568,13 @@
 		BT_ERR("HCIATH3K protocol registration failed");
 		return ret;
 	}
-	ret = platform_driver_probe(&bluesleep_driver, bluesleep_probe);
-	if (ret)
+
+	ret = platform_driver_register(&bluesleep_driver);
+	if (ret) {
+		BT_ERR("Failed to register bluesleep driver");
 		return ret;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 071dd69..9e36e1e 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -314,6 +314,9 @@
 	diag_send_event_mask_update(smd_info->ch, diag_event_num_bytes);
 	diag_send_feature_mask_update(smd_info->ch, smd_info->peripheral);
 
+	if (smd_info->notify_context == SMD_EVENT_OPEN)
+		diag_send_diag_mode_update_by_smd(smd_info, MODE_REALTIME);
+
 	smd_info->notify_context = 0;
 }
 
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9d9df2a..555ffa0 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -20,6 +20,7 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/sched.h>
+#include <linux/wakelock.h>
 #include <mach/msm_smd.h>
 #include <asm/atomic.h>
 #include <asm/mach-types.h>
@@ -76,6 +77,9 @@
 #define DIAG_STATUS_OPEN (0x00010000)	/* DCI channel open status mask   */
 #define DIAG_STATUS_CLOSED (0x00020000)	/* DCI channel closed status mask */
 
+#define MODE_REALTIME 1
+#define MODE_NONREALTIME 0
+
 #define NUM_SMD_DATA_CHANNELS 3
 #define NUM_SMD_CONTROL_CHANNELS 3
 #define NUM_SMD_DCI_CHANNELS 1
@@ -143,6 +147,14 @@
 	int pid;
 };
 
+struct diag_nrt_wake_lock {
+	int enabled;
+	int ref_count;
+	int copy_count;
+	struct wake_lock read_lock;
+	spinlock_t read_spinlock;
+};
+
 /* This structure is defined in USB header file */
 #ifndef CONFIG_DIAG_OVER_USB
 struct diag_request {
@@ -173,6 +185,8 @@
 	struct diag_request *write_ptr_1;
 	struct diag_request *write_ptr_2;
 
+	struct diag_nrt_wake_lock nrt_lock;
+
 	struct work_struct diag_read_smd_work;
 	struct work_struct diag_notify_update_smd_work;
 	int notify_context;
@@ -239,6 +253,7 @@
 	struct diag_ctrl_msg_mask *msg_mask;
 	struct diag_ctrl_feature_mask *feature_mask;
 	/* State for diag forwarding */
+	int real_time_mode;
 	struct diag_smd_info smd_data[NUM_SMD_DATA_CHANNELS];
 	struct diag_smd_info smd_cntl[NUM_SMD_CONTROL_CHANNELS];
 	struct diag_smd_info smd_dci[NUM_SMD_DCI_CHANNELS];
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 65fc89f..fb8efe4 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -20,6 +20,7 @@
 #include <linux/diagchar.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/ratelimit.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <mach/usbdiag.h>
 #endif
@@ -278,10 +279,11 @@
 	/* If the SD logging process exits, change logging to USB mode */
 	if (driver->logging_process_id == current->tgid) {
 		driver->logging_mode = USB_MODE;
+		diag_send_diag_mode_update(MODE_REALTIME);
 		diagfwd_connect();
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 		diag_clear_hsic_tbl();
-		diagfwd_cancel_hsic();
+		diagfwd_cancel_hsic(REOPEN_HSIC);
 		diagfwd_connect_bridge(0);
 #endif
 	}
@@ -707,6 +709,11 @@
 		diag_clear_hsic_tbl();
 	} else if (old_mode == NO_LOGGING_MODE && new_mode
 					== MEMORY_DEVICE_MODE) {
+		int i;
+		for (i = 0; i < MAX_HSIC_CH; i++)
+			if (diag_hsic[i].hsic_inited)
+				diag_hsic[i].hsic_data_requested =
+					driver->real_time_mode ? 1 : 0;
 		diagfwd_connect_bridge(0);
 	} else if (old_mode == USB_MODE && new_mode
 					 == NO_LOGGING_MODE) {
@@ -716,12 +723,15 @@
 		diagfwd_connect_bridge(0);
 	} else if (old_mode == USB_MODE && new_mode
 					== MEMORY_DEVICE_MODE) {
-		diagfwd_cancel_hsic();
+		if (driver->real_time_mode)
+			diagfwd_cancel_hsic(REOPEN_HSIC);
+		else
+			diagfwd_cancel_hsic(DONT_REOPEN_HSIC);
 		diagfwd_connect_bridge(0);
 	} else if (old_mode == MEMORY_DEVICE_MODE && new_mode
 					== USB_MODE) {
 		diag_clear_hsic_tbl();
-		diagfwd_cancel_hsic();
+		diagfwd_cancel_hsic(REOPEN_HSIC);
 		diagfwd_connect_bridge(0);
 	}
 }
@@ -770,12 +780,25 @@
 int diag_switch_logging(unsigned long ioarg)
 {
 	int i, temp, success = -EINVAL, status;
+	int temp_realtime_mode = driver->real_time_mode;
+
 	mutex_lock(&driver->diagchar_mutex);
 	temp = driver->logging_mode;
 	driver->logging_mode = (int)ioarg;
+
+	if (driver->logging_mode == MEMORY_DEVICE_MODE_NRT) {
+		diag_send_diag_mode_update(MODE_NONREALTIME);
+		driver->logging_mode = MEMORY_DEVICE_MODE;
+	} else {
+		diag_send_diag_mode_update(MODE_REALTIME);
+	}
+
 	if (temp == driver->logging_mode) {
 		mutex_unlock(&driver->diagchar_mutex);
-		pr_err("diag: forbidden logging change requested\n");
+		if (driver->logging_mode != MEMORY_DEVICE_MODE ||
+			temp_realtime_mode)
+			pr_info_ratelimited("diag: Already in logging mode change requested, mode: %d\n",
+					driver->logging_mode);
 		return 0;
 	}
 
@@ -1097,6 +1120,7 @@
 	int num_data = 0, data_type;
 	int remote_token;
 	int exit_stat;
+	int clear_read_wakelock;
 
 	for (i = 0; i < driver->num_clients; i++)
 		if (driver->client_map[i].pid == current->tgid)
@@ -1111,6 +1135,7 @@
 				  driver->data_ready[index]);
 	mutex_lock(&driver->diagchar_mutex);
 
+	clear_read_wakelock = 0;
 	if ((driver->data_ready[index] & USER_SPACE_DATA_TYPE) && (driver->
 					logging_mode == MEMORY_DEVICE_MODE)) {
 		remote_token = 0;
@@ -1172,6 +1197,10 @@
 				COPY_USER_SPACE_OR_EXIT(buf+ret,
 					*(data->buf_in_1),
 					data->write_ptr_1->length);
+				if (!driver->real_time_mode) {
+					process_lock_on_copy(&data->nrt_lock);
+					clear_read_wakelock++;
+				}
 				data->in_busy_1 = 0;
 			}
 			if (data->in_busy_2 == 1) {
@@ -1183,6 +1212,10 @@
 				COPY_USER_SPACE_OR_EXIT(buf+ret,
 					*(data->buf_in_2),
 					data->write_ptr_2->length);
+				if (!driver->real_time_mode) {
+					process_lock_on_copy(&data->nrt_lock);
+					clear_read_wakelock++;
+				}
 				data->in_busy_2 = 0;
 			}
 		}
@@ -1308,6 +1341,11 @@
 		goto exit;
 	}
 exit:
+	if (clear_read_wakelock) {
+		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++)
+			process_lock_on_copy_complete(
+				&driver->smd_data[i].nrt_lock);
+	}
 	mutex_unlock(&driver->diagchar_mutex);
 	return ret;
 }
@@ -1405,9 +1443,19 @@
 #endif
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 		/* send masks to All 9k */
-		if ((remote_proc >= MDM) && (remote_proc <= MDM4)) {
+		if ((remote_proc >= MDM) && (remote_proc <= MDM4) &&
+							(payload_size > 0)) {
 			index = remote_proc - MDM;
-			if (diag_hsic[index].hsic_ch && (payload_size > 0)) {
+			/*
+			 * If hsic data is being requested for this remote
+			 * processor and its hsic in not open
+			 */
+			if (!diag_hsic[index].hsic_device_opened) {
+				diag_hsic[index].hsic_data_requested = 1;
+				connect_bridge(0, index);
+			}
+
+			if (diag_hsic[index].hsic_ch) {
 				/* wait sending mask updates
 				 * if HSIC ch not ready */
 				if (diag_hsic[index].in_busy_hsic_write)
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 79a73f3..bb74370 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -227,6 +227,93 @@
 	}
 }
 
+void process_lock_enabling(struct diag_nrt_wake_lock *lock, int real_time)
+{
+	unsigned long read_lock_flags;
+
+	spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+	if (real_time)
+		lock->enabled = 0;
+	else
+		lock->enabled = 1;
+	lock->ref_count = 0;
+	lock->copy_count = 0;
+	wake_unlock(&lock->read_lock);
+	spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
+void process_lock_on_notify(struct diag_nrt_wake_lock *lock)
+{
+	unsigned long read_lock_flags;
+
+	spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+	/*
+	 * Do not work with ref_count here in case
+	 * of spurious interrupt
+	 */
+	if (lock->enabled)
+		wake_lock(&lock->read_lock);
+	spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
+void process_lock_on_read(struct diag_nrt_wake_lock *lock, int pkt_len)
+{
+	unsigned long read_lock_flags;
+
+	spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+	if (lock->enabled) {
+		if (pkt_len > 0) {
+			/*
+			 * We have an data that is read that
+			 * needs to be processed, make sure the
+			 * processor does not go to sleep
+			 */
+			lock->ref_count++;
+			if (!wake_lock_active(&lock->read_lock))
+				wake_lock(&lock->read_lock);
+		} else {
+			/*
+			 * There was no data associated with the
+			 * read from the smd, unlock the wake lock
+			 * if it is not needed.
+			 */
+			if (lock->ref_count < 1) {
+				if (wake_lock_active(&lock->read_lock))
+					wake_unlock(&lock->read_lock);
+				lock->ref_count = 0;
+				lock->copy_count = 0;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
+void process_lock_on_copy(struct diag_nrt_wake_lock *lock)
+{
+	unsigned long read_lock_flags;
+
+	spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+	if (lock->enabled)
+		lock->copy_count++;
+	spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
+void process_lock_on_copy_complete(struct diag_nrt_wake_lock *lock)
+{
+	unsigned long read_lock_flags;
+
+	spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+	if (lock->enabled) {
+		lock->ref_count -= lock->copy_count;
+		if (lock->ref_count < 1) {
+			wake_unlock(&lock->read_lock);
+			lock->ref_count = 0;
+		}
+		lock->copy_count = 0;
+	}
+	spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
 /* Process the data read from the smd data channel */
 int diag_process_smd_read_data(struct diag_smd_info *smd_info, void *buf,
 								int total_recd)
@@ -324,6 +411,8 @@
 			smd_read(smd_info->ch, temp_buf, r);
 			temp_buf += r;
 		}
+		if (!driver->real_time_mode && smd_info->type == SMD_DATA_TYPE)
+			process_lock_on_read(&smd_info->nrt_lock, pkt_len);
 
 		if (total_recd > 0) {
 			if (!buf) {
@@ -1321,6 +1410,9 @@
 			diag_dci_notify_client(smd_info->peripheral_mask,
 							DIAG_STATUS_OPEN);
 		}
+	} else if (event == SMD_EVENT_DATA && !driver->real_time_mode &&
+					smd_info->type == SMD_DATA_TYPE) {
+		process_lock_on_notify(&smd_info->nrt_lock);
 	}
 
 	wake_up(&driver->smd_wait_q);
@@ -1413,6 +1505,9 @@
 
 void diag_smd_destructor(struct diag_smd_info *smd_info)
 {
+	if (smd_info->type == SMD_DATA_TYPE)
+		wake_lock_destroy(&smd_info->nrt_lock.read_lock);
+
 	if (smd_info->ch)
 		smd_close(smd_info->ch);
 
@@ -1524,6 +1619,30 @@
 		goto err;
 	}
 
+	smd_info->nrt_lock.enabled = 0;
+	smd_info->nrt_lock.ref_count = 0;
+	smd_info->nrt_lock.copy_count = 0;
+	if (type == SMD_DATA_TYPE) {
+		spin_lock_init(&smd_info->nrt_lock.read_spinlock);
+
+		switch (peripheral) {
+		case MODEM_DATA:
+			wake_lock_init(&smd_info->nrt_lock.read_lock,
+				WAKE_LOCK_SUSPEND, "diag_nrt_modem_read");
+			break;
+		case LPASS_DATA:
+			wake_lock_init(&smd_info->nrt_lock.read_lock,
+				WAKE_LOCK_SUSPEND, "diag_nrt_lpass_read");
+			break;
+		case WCNSS_DATA:
+			wake_lock_init(&smd_info->nrt_lock.read_lock,
+				WAKE_LOCK_SUSPEND, "diag_nrt_wcnss_read");
+			break;
+		default:
+			break;
+		}
+	}
+
 	return 1;
 err:
 	kfree(smd_info->buf_in_1);
@@ -1544,6 +1663,7 @@
 	diag_debug_buf_idx = 0;
 	driver->read_len_legacy = 0;
 	driver->use_device_tree = has_device_tree();
+	driver->real_time_mode = 1;
 	mutex_init(&driver->diag_hdlc_mutex);
 	mutex_init(&driver->diag_cntl_mutex);
 
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index afbe4be..8cf15de 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -23,6 +23,11 @@
 void diagfwd_exit(void);
 void diag_process_hdlc(void *data, unsigned len);
 void diag_smd_send_req(struct diag_smd_info *smd_info);
+void process_lock_enabling(struct diag_nrt_wake_lock *lock, int real_time);
+void process_lock_on_notify(struct diag_nrt_wake_lock *lock);
+void process_lock_on_read(struct diag_nrt_wake_lock *lock, int pkt_len);
+void process_lock_on_copy(struct diag_nrt_wake_lock *lock);
+void process_lock_on_copy_complete(struct diag_nrt_wake_lock *lock);
 void diag_usb_legacy_notifier(void *, unsigned, struct diag_request *);
 long diagchar_ioctl(struct file *, unsigned int, unsigned long);
 int diag_device_write(void *, int, struct diag_request *);
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
index b934805..475f5ba 100644
--- a/drivers/char/diag/diagfwd_bridge.c
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -65,7 +65,9 @@
 		driver->in_busy_smux = 0;
 		diagfwd_connect_smux();
 	} else {
-		if (diag_hsic[index].hsic_device_enabled) {
+		if (diag_hsic[index].hsic_device_enabled &&
+			(driver->logging_mode != MEMORY_DEVICE_MODE ||
+			diag_hsic[index].hsic_data_requested)) {
 			diag_hsic[index].in_busy_hsic_read_on_device = 0;
 			diag_hsic[index].in_busy_hsic_write = 0;
 			/* If the HSIC (diag_bridge) platform
@@ -126,20 +128,24 @@
 				usb_diag_free_req(diag_bridge[i].ch);
 			}
 
-			if (i == SMUX && driver->diag_smux_enabled &&
+			if (i == SMUX) {
+				if (driver->diag_smux_enabled &&
 					driver->logging_mode == USB_MODE) {
-				driver->in_busy_smux = 1;
-				driver->lcid = LCID_INVALID;
-				driver->smux_connected = 0;
-				/* Turn off communication over usb and smux */
-				msm_smux_close(LCID_VALID);
+					driver->in_busy_smux = 1;
+					driver->lcid = LCID_INVALID;
+					driver->smux_connected = 0;
+					/*
+					 * Turn off communication over usb
+					 * and smux
+					 */
+					msm_smux_close(LCID_VALID);
+				}
 			}  else {
 				if (diag_hsic[i].hsic_device_enabled &&
-				     driver->logging_mode !=
-							MEMORY_DEVICE_MODE) {
+				     (driver->logging_mode != MEMORY_DEVICE_MODE
+				     || !diag_hsic[i].hsic_data_requested)) {
 					diag_hsic[i].
-						in_busy_hsic_read_on_device
-						= 1;
+						in_busy_hsic_read_on_device = 1;
 					diag_hsic[i].in_busy_hsic_write = 1;
 					/* Turn off communication over usb
 					 * and HSIC */
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 7e58249..4ddd78a 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.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
@@ -14,6 +14,7 @@
 #include <linux/diagchar.h>
 #include <linux/platform_device.h>
 #include <linux/kmemleak.h>
+#include <linux/delay.h>
 #include "diagchar.h"
 #include "diagfwd.h"
 #include "diagfwd_cntl.h"
@@ -131,6 +132,83 @@
 	return flag;
 }
 
+void diag_send_diag_mode_update(int real_time)
+{
+	int i;
+
+	for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
+		diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
+							real_time);
+}
+
+void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info,
+							int real_time)
+{
+	struct diag_ctrl_msg_diagmode diagmode;
+	char buf[sizeof(struct diag_ctrl_msg_diagmode)];
+	int msg_size = sizeof(struct diag_ctrl_msg_diagmode);
+	int wr_size = -ENOMEM, retry_count = 0, timer;
+
+	/* For now only allow the modem to receive the message */
+	if (!smd_info || smd_info->type != SMD_CNTL_TYPE ||
+		(smd_info->peripheral != MODEM_DATA))
+		return;
+
+	mutex_lock(&driver->diag_cntl_mutex);
+	diagmode.ctrl_pkt_id = DIAG_CTRL_MSG_DIAGMODE;
+	diagmode.ctrl_pkt_data_len = 36;
+	diagmode.version = 1;
+	diagmode.sleep_vote = real_time ? 1 : 0;
+	/*
+	 * 0 - Disables real-time logging (to prevent
+	 *     frequent APPS wake-ups, etc.).
+	 * 1 - Enable real-time logging
+	 */
+	diagmode.real_time = real_time;
+	diagmode.use_nrt_values = 0;
+	diagmode.commit_threshold = 0;
+	diagmode.sleep_threshold = 0;
+	diagmode.sleep_time = 0;
+	diagmode.drain_timer_val = 0;
+	diagmode.event_stale_timer_val = 0;
+
+	memcpy(buf, &diagmode, msg_size);
+
+	if (smd_info->ch) {
+		while (retry_count < 3) {
+			wr_size = smd_write(smd_info->ch, buf, msg_size);
+			if (wr_size == -ENOMEM) {
+				/*
+				 * The smd channel is full. Delay while
+				 * smd processes existing data and smd
+				 * has memory become available. The delay
+				 * of 2000 was determined empirically as
+				 * best value to use.
+				 */
+				retry_count++;
+				for (timer = 0; timer < 5; timer++)
+					udelay(2000);
+			} else {
+				struct diag_smd_info *data =
+				&driver->smd_data[smd_info->peripheral];
+				driver->real_time_mode = real_time;
+				process_lock_enabling(&data->nrt_lock,
+								real_time);
+				break;
+			}
+		}
+		if (wr_size != msg_size)
+			pr_err("diag: proc %d fail feature update %d, tried %d",
+				smd_info->peripheral,
+				wr_size, msg_size);
+	} else {
+		pr_err("diag: ch invalid, feature update on proc %d\n",
+				smd_info->peripheral);
+	}
+
+	mutex_unlock(&driver->diag_cntl_mutex);
+}
+
 static int diag_smd_cntl_probe(struct platform_device *pdev)
 {
 	int r = 0;
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index c28b06d..7cd1866 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -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
@@ -84,11 +84,28 @@
 	/* Copy feature mask here */
 } __packed;
 
+struct diag_ctrl_msg_diagmode {
+	uint32_t ctrl_pkt_id;
+	uint32_t ctrl_pkt_data_len;
+	uint32_t version;
+	uint32_t sleep_vote;
+	uint32_t real_time;
+	uint32_t use_nrt_values;
+	uint32_t commit_threshold;
+	uint32_t sleep_threshold;
+	uint32_t sleep_time;
+	uint32_t drain_timer_val;
+	uint32_t event_stale_timer_val;
+} __packed;
+
 void diagfwd_cntl_init(void);
 void diagfwd_cntl_exit(void);
 void diag_read_smd_cntl_work_fn(struct work_struct *);
 void diag_clean_reg_fn(struct work_struct *work);
 int diag_process_smd_cntl_read_data(struct diag_smd_info *smd_info, void *buf,
 								int total_recd);
+void diag_send_diag_mode_update(int real_time);
+void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info,
+							int real_time);
 
 #endif
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 616c498..fa46aab 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -227,8 +227,12 @@
 	if (diag_hsic[index].in_busy_hsic_write)
 		return -EBUSY;
 
-	/* Don't allow suspend if in MEMORY_DEVICE_MODE */
-	if (driver->logging_mode == MEMORY_DEVICE_MODE)
+	/*
+	 * Don't allow suspend if in MEMORY_DEVICE_MODE and if there
+	 * has been hsic data requested
+	 */
+	if (driver->logging_mode == MEMORY_DEVICE_MODE &&
+				diag_hsic[index].hsic_ch)
 		return -EBUSY;
 
 	diag_hsic[index].hsic_suspend = 1;
@@ -288,7 +292,7 @@
 }
 
 /* diagfwd_cancel_hsic is called to cancel outstanding read/writes */
-int diagfwd_cancel_hsic(void)
+int diagfwd_cancel_hsic(int reopen)
 {
 	int err, i;
 
@@ -302,17 +306,24 @@
 				diag_hsic[i].hsic_ch = 0;
 				diag_hsic[i].hsic_device_opened = 0;
 				diag_bridge_close(i);
-				hsic_diag_bridge_ops[i].ctxt = (void *)(i);
-				err = diag_bridge_open(i,
-						   &hsic_diag_bridge_ops[i]);
-				if (err) {
-					pr_err("diag: HSIC %d channel open error: %d\n",
-						 i, err);
+				if (reopen) {
+					hsic_diag_bridge_ops[i].ctxt =
+								(void *)(i);
+					err = diag_bridge_open(i,
+						&hsic_diag_bridge_ops[i]);
+					if (err) {
+						pr_err("diag: HSIC %d channel open error: %d\n",
+							 i, err);
+					} else {
+						pr_debug("diag: opened HSIC channel: %d\n",
+							i);
+						diag_hsic[i].
+							hsic_device_opened = 1;
+						diag_hsic[i].hsic_ch = 1;
+					}
+					diag_hsic[i].hsic_data_requested = 1;
 				} else {
-					pr_debug("diag: opened HSIC channel: %d\n",
-						i);
-					diag_hsic[i].hsic_device_opened = 1;
-					diag_hsic[i].hsic_ch = 1;
+					diag_hsic[i].hsic_data_requested = 0;
 				}
 			}
 		}
@@ -428,15 +439,20 @@
 		diagmem_hsic_init(pdev->id);
 		INIT_WORK(&(diag_hsic[pdev->id].diag_read_hsic_work),
 			    diag_read_hsic_work_fn);
+		diag_hsic[pdev->id].hsic_data_requested =
+			(driver->logging_mode == MEMORY_DEVICE_MODE) ? 0 : 1;
 		diag_hsic[pdev->id].hsic_inited = 1;
 	}
 	/*
 	 * The probe function was called after the usb was connected
-	 * on the legacy channel OR ODL is turned on. Communication over usb
-	 * mdm and HSIC needs to be turned on.
+	 * on the legacy channel OR ODL is turned on and hsic data is
+	 * requested. Communication over usb mdm and HSIC needs to be
+	 * turned on.
 	 */
-	if (diag_bridge[pdev->id].usb_connected || (driver->logging_mode ==
-						   MEMORY_DEVICE_MODE)) {
+	if ((diag_bridge[pdev->id].usb_connected &&
+		(driver->logging_mode != MEMORY_DEVICE_MODE)) ||
+		((driver->logging_mode == MEMORY_DEVICE_MODE) &&
+		diag_hsic[pdev->id].hsic_data_requested)) {
 		if (diag_hsic[pdev->id].hsic_device_opened) {
 			/* should not happen. close it before re-opening */
 			pr_warn("diag: HSIC channel already opened in probe\n");
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index d171efa..64556f2 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -19,8 +19,10 @@
 #define N_MDM_READ	1
 #define NUM_HSIC_BUF_TBL_ENTRIES N_MDM_WRITE
 #define MAX_HSIC_CH	4
+#define REOPEN_HSIC 1
+#define DONT_REOPEN_HSIC 0
 int diagfwd_write_complete_hsic(struct diag_request *, int index);
-int diagfwd_cancel_hsic(void);
+int diagfwd_cancel_hsic(int reopen);
 void diag_read_usb_hsic_work_fn(struct work_struct *work);
 void diag_usb_read_complete_hsic_fn(struct work_struct *w);
 extern struct diag_bridge_ops hsic_diag_bridge_ops[MAX_HSIC_CH];
@@ -37,6 +39,7 @@
 	int hsic_device_enabled;
 	int hsic_device_opened;
 	int hsic_suspend;
+	int hsic_data_requested;
 	int in_busy_hsic_read_on_device;
 	int in_busy_hsic_write;
 	struct work_struct diag_read_hsic_work;
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 4774c76..988d1c9 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -158,7 +158,7 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr-base");
 	if (!res)
 		return -ENODEV;
 
diff --git a/drivers/coresight/coresight-cti.c b/drivers/coresight/coresight-cti.c
index e077edf..6a8d412 100644
--- a/drivers/coresight/coresight-cti.c
+++ b/drivers/coresight/coresight-cti.c
@@ -402,7 +402,7 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cti-base");
 	if (!res)
 		return -ENODEV;
 
diff --git a/drivers/coresight/coresight-etb.c b/drivers/coresight/coresight-etb.c
index d52ab28..31f85dc 100644
--- a/drivers/coresight/coresight-etb.c
+++ b/drivers/coresight/coresight-etb.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
@@ -375,7 +375,7 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "etb-base");
 	if (!res)
 		return -ENODEV;
 
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 1033233..2777769 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -2090,7 +2090,7 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "etm-base");
 	if (!res)
 		return -ENODEV;
 	reg_size = resource_size(res);
diff --git a/drivers/coresight/coresight-funnel.c b/drivers/coresight/coresight-funnel.c
index 7f39a3e..625f481 100644
--- a/drivers/coresight/coresight-funnel.c
+++ b/drivers/coresight/coresight-funnel.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
@@ -187,7 +187,7 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "funnel-base");
 	if (!res)
 		return -ENODEV;
 
diff --git a/drivers/coresight/coresight-replicator.c b/drivers/coresight/coresight-replicator.c
index fe37e5e..d4afa42 100644
--- a/drivers/coresight/coresight-replicator.c
+++ b/drivers/coresight/coresight-replicator.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
@@ -139,7 +139,8 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "replicator-base");
 	if (!res)
 		return -ENODEV;
 
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 1db499b..87cf63a 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -806,7 +806,7 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "stm-base");
 	if (!res)
 		return -ENODEV;
 
@@ -814,7 +814,8 @@
 	if (!drvdata->base)
 		return -ENOMEM;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "stm-data-base");
 	if (!res)
 		return -ENODEV;
 
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 86276b7..4a9a97a 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1090,7 +1090,7 @@
 		return -ENOMEM;
 	drvdata->bamdata = bamdata;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bam-base");
 	if (!res)
 		return -ENODEV;
 
@@ -1147,7 +1147,7 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tmc-base");
 	if (!res)
 		return -ENODEV;
 	reg_size = resource_size(res);
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index 73800dd..7ea71d3 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -710,7 +710,7 @@
 	drvdata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpiu-base");
 	if (!res)
 		return -ENODEV;
 
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 583add9..1134f90 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -2735,6 +2735,7 @@
 		pr_warn("Unable to get CE core src clk, set to NULL\n");
 		pce_dev->ce_core_src_clk = NULL;
 	}
+	pce_dev->ce_core_src_clk = ce_core_src_clk;
 
 	/* Get CE core clk */
 	ce_core_clk = clk_get(pce_dev->pdev, "core_clk");
@@ -2772,43 +2773,86 @@
 	}
 	pce_dev->ce_bus_clk = ce_bus_clk;
 
+err_clk:
+	if (rc)
+		pr_err("Unable to init CE clks, rc = %d\n", rc);
+	return rc;
+}
+
+static void __qce_deinit_clk(struct qce_device *pce_dev)
+{
+	if (pce_dev->ce_clk  != NULL) {
+		clk_put(pce_dev->ce_clk);
+		pce_dev->ce_clk  = NULL;
+	}
+	if (pce_dev->ce_core_clk != NULL) {
+		clk_put(pce_dev->ce_core_clk);
+		pce_dev->ce_core_clk = NULL;
+	}
+	if (pce_dev->ce_bus_clk != NULL) {
+		clk_put(pce_dev->ce_bus_clk);
+		pce_dev->ce_bus_clk = NULL;
+	}
+	if (pce_dev->ce_core_src_clk != NULL) {
+		clk_put(pce_dev->ce_core_src_clk);
+		pce_dev->ce_core_src_clk = NULL;
+	}
+}
+
+static int __qce_enable_clk(void *handle)
+{
+	struct qce_device *pce_dev = (struct qce_device *) handle;
+	int rc = 0;
+
 	/* Enable CE core clk */
 	rc = clk_prepare_enable(pce_dev->ce_core_clk);
 	if (rc) {
 		pr_err("Unable to enable/prepare CE core clk\n");
-		if (pce_dev->ce_core_src_clk != NULL)
-			clk_put(pce_dev->ce_core_src_clk);
-		clk_put(pce_dev->ce_core_clk);
-		clk_put(pce_dev->ce_clk);
-		goto err_clk;
-	} else {
-		/* Enable CE clk */
-		rc = clk_prepare_enable(pce_dev->ce_clk);
-		if (rc) {
-			pr_err("Unable to enable/prepare CE iface clk\n");
-			clk_disable_unprepare(pce_dev->ce_core_clk);
-			if (pce_dev->ce_core_src_clk != NULL)
-				clk_put(pce_dev->ce_core_src_clk);
-			clk_put(pce_dev->ce_core_clk);
-			clk_put(pce_dev->ce_clk);
-			goto err_clk;
-		}
-		/* Enable AXI clk */
-		rc = clk_prepare_enable(pce_dev->ce_bus_clk);
+		return rc;
+	}
+	/* Enable CE clk */
+	rc = clk_prepare_enable(pce_dev->ce_clk);
+	if (rc) {
+		pr_err("Unable to enable/prepare CE iface clk\n");
+		clk_disable_unprepare(pce_dev->ce_core_clk);
+	return rc;
+	}
+	/* Enable AXI clk */
+	rc = clk_prepare_enable(pce_dev->ce_bus_clk);
+	if (rc) {
+		pr_err("Unable to enable/prepare CE BUS clk\n");
+		clk_disable_unprepare(pce_dev->ce_clk);
+		clk_disable_unprepare(pce_dev->ce_core_clk);
+		return rc;
+	}
+	/* Enable CORE SRC (INTERFACE)  clk */
+	if (pce_dev->ce_core_src_clk != NULL) {
+		rc = clk_prepare_enable(pce_dev->ce_core_src_clk);
 		if (rc) {
 			pr_err("Unable to enable/prepare CE BUS clk\n");
+			clk_disable_unprepare(pce_dev->ce_clk);
 			clk_disable_unprepare(pce_dev->ce_core_clk);
-			if (pce_dev->ce_core_src_clk != NULL)
-				clk_put(pce_dev->ce_core_src_clk);
-			clk_put(pce_dev->ce_core_clk);
-			clk_put(pce_dev->ce_clk);
-			clk_put(pce_dev->ce_bus_clk);
-			goto err_clk;
+			clk_disable_unprepare(pce_dev->ce_bus_clk);
+			return rc;
 		}
 	}
-err_clk:
-	if (rc)
-		pr_err("Unable to init CE clks, rc = %d\n", rc);
+	return rc;
+}
+
+static int __qce_disable_clk(void *handle)
+{
+	struct qce_device *pce_dev = (struct qce_device *) handle;
+	int rc = 0;
+
+	if (pce_dev->ce_clk != NULL)
+		clk_disable_unprepare(pce_dev->ce_clk);
+	if (pce_dev->ce_core_src_clk != NULL)
+		clk_disable_unprepare(pce_dev->ce_core_src_clk);
+	if (pce_dev->ce_core_clk != NULL)
+		clk_disable_unprepare(pce_dev->ce_core_clk);
+	if (pce_dev->ce_bus_clk != NULL)
+		clk_disable_unprepare(pce_dev->ce_bus_clk);
+
 	return rc;
 }
 
@@ -2848,8 +2892,13 @@
 	if (*rc)
 		goto err_mem;
 
+	*rc = __qce_enable_clk(pce_dev);
+	if (*rc)
+		goto err;
+
 	if (_probe_ce_engine(pce_dev)) {
 		*rc = -ENXIO;
+		__qce_disable_clk(pce_dev);
 		goto err;
 	}
 	*rc = 0;
@@ -2858,13 +2907,8 @@
 
 	return pce_dev;
 err:
-	clk_disable_unprepare(pce_dev->ce_clk);
-	clk_disable_unprepare(pce_dev->ce_core_clk);
+	__qce_deinit_clk(pce_dev);
 
-	if (pce_dev->ce_core_src_clk != NULL)
-		clk_put(pce_dev->ce_core_src_clk);
-	clk_put(pce_dev->ce_clk);
-	clk_put(pce_dev->ce_core_clk);
 err_mem:
 	if (pce_dev->coh_vmem)
 		dma_free_coherent(pce_dev->pdev, pce_dev->memsize,
@@ -2894,14 +2938,8 @@
 		dma_free_coherent(pce_dev->pdev, pce_dev->memsize,
 				pce_dev->coh_vmem, pce_dev->coh_pmem);
 
-	clk_disable_unprepare(pce_dev->ce_clk);
-	clk_disable_unprepare(pce_dev->ce_core_clk);
-	clk_disable_unprepare(pce_dev->ce_bus_clk);
-	if (pce_dev->ce_core_src_clk != NULL)
-		clk_put(pce_dev->ce_core_src_clk);
-	clk_put(pce_dev->ce_clk);
-	clk_put(pce_dev->ce_core_clk);
-	clk_put(pce_dev->ce_bus_clk);
+	__qce_disable_clk(pce_dev);
+	__qce_deinit_clk(pce_dev);
 
 	qce_sps_exit(pce_dev);
 	kfree(handle);
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 9ab2343..9128177 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1248,14 +1248,12 @@
 	mutex_lock(&buffer->lock);
 	/* now map it to userspace */
 	ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma);
+	mutex_unlock(&buffer->lock);
 
 	if (ret) {
-		mutex_unlock(&buffer->lock);
 		pr_err("%s: failure mapping buffer to userspace\n",
 		       __func__);
 	} else {
-		mutex_unlock(&buffer->lock);
-
 		vma->vm_ops = &ion_vm_ops;
 		/*
 		 * move the buffer into the vm_private_data so we can access it
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 3000252..8a5e5c9 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -614,6 +614,11 @@
 			int i;
 			pgprot_t pgprot;
 
+			if (!pages) {
+				mutex_unlock(&cp_heap->lock);
+				return ERR_PTR(-ENOMEM);
+			}
+
 			if (ION_IS_CACHED(buffer->flags))
 				pgprot = PAGE_KERNEL;
 			else
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index ba48b50..9ab6b85 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -330,6 +330,14 @@
 	data->mapped_size = iova_length;
 	extra = iova_length - buffer->size;
 
+	/* Use the biggest alignment to allow bigger IOMMU mappings.
+	 * Use the first entry since the first entry will always be the
+	 * biggest entry. To take advantage of bigger mapping sizes both the
+	 * VA and PA addresses have to be aligned to the biggest size.
+	 */
+	if (buffer->sg_table->sgl->length > align)
+		align = buffer->sg_table->sgl->length;
+
 	ret = msm_allocate_iova_address(domain_num, partition_num,
 						data->mapped_size, align,
 						&data->iova_addr);
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 7ca2cd2..7046709 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -271,6 +271,14 @@
 	data->mapped_size = iova_length;
 	extra = iova_length - buffer->size;
 
+	/* Use the biggest alignment to allow bigger IOMMU mappings.
+	 * Use the first entry since the first entry will always be the
+	 * biggest entry. To take advantage of bigger mapping sizes both the
+	 * VA and PA addresses have to be aligned to the biggest size.
+	 */
+	if (table->sgl->length > align)
+		align = table->sgl->length;
+
 	ret = msm_allocate_iova_address(domain_num, partition_num,
 						data->mapped_size, align,
 						&data->iova_addr);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 9f4d791..de1048e 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1225,10 +1225,10 @@
 	return 0;
 }
 
-static int adreno_start(struct kgsl_device *device, unsigned int init_ram)
+static int adreno_init(struct kgsl_device *device)
 {
-	int status = -EINVAL;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
 	if (KGSL_STATE_DUMP_AND_FT != device->state)
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
@@ -1254,10 +1254,9 @@
 	if (adreno_dev->gpurev == ADRENO_REV_UNKNOWN) {
 		KGSL_DRV_ERR(device, "Unknown chip ID %x\n",
 			adreno_dev->chip_id);
-		goto error_clk_off;
+		BUG_ON(1);
 	}
 
-
 	/*
 	 * Check if firmware supports the sync lock PM4 packets needed
 	 * for IOMMUv1
@@ -1269,19 +1268,7 @@
 		adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver))
 		device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;
 
-	/* Set up the MMU */
-	if (adreno_is_a2xx(adreno_dev)) {
-		/*
-		 * the MH_CLNT_INTF_CTRL_CONFIG registers aren't present
-		 * on older gpus
-		 */
-		if (adreno_is_a20x(adreno_dev)) {
-			device->mh.mh_intf_cfg1 = 0;
-			device->mh.mh_intf_cfg2 = 0;
-		}
-
-		kgsl_mh_start(device);
-	}
+	rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
 
 	/* Assign correct RBBM status register to hang detect regs
 	 */
@@ -1297,6 +1284,37 @@
 		ft_detect_regs[11] = A3XX_RBBM_PERFCTR_SP_5_HI;
 	}
 
+	/* Power down the device */
+	kgsl_pwrctrl_disable(device);
+
+	return 0;
+}
+
+static int adreno_start(struct kgsl_device *device)
+{
+	int status = -EINVAL;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+	if (KGSL_STATE_DUMP_AND_FT != device->state)
+		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+
+	/* Power up the device */
+	kgsl_pwrctrl_enable(device);
+
+	/* Set up a2xx special case */
+	if (adreno_is_a2xx(adreno_dev)) {
+		/*
+		 * the MH_CLNT_INTF_CTRL_CONFIG registers aren't present
+		 * on older gpus
+		 */
+		if (adreno_is_a20x(adreno_dev)) {
+			device->mh.mh_intf_cfg1 = 0;
+			device->mh.mh_intf_cfg2 = 0;
+		}
+
+		kgsl_mh_start(device);
+	}
+
 	status = kgsl_mmu_start(device);
 	if (status)
 		goto error_clk_off;
@@ -1313,7 +1331,7 @@
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
 	device->ftbl->irqctrl(device, 1);
 
-	status = adreno_ringbuffer_start(&adreno_dev->ringbuffer, init_ram);
+	status = adreno_ringbuffer_start(&adreno_dev->ringbuffer);
 	if (status)
 		goto error_irq_off;
 
@@ -1712,7 +1730,12 @@
 		return 1;
 	}
 
-	if (adreno_start(device, true)) {
+	if (adreno_init(device)) {
+		KGSL_FT_ERR(device, "Device init failed\n");
+		return 1;
+	}
+
+	if (adreno_start(device)) {
 		KGSL_FT_ERR(device, "Device start failed\n");
 		return 1;
 	}
@@ -3270,6 +3293,7 @@
 	.idle = adreno_idle,
 	.isidle = adreno_isidle,
 	.suspend_context = adreno_suspend_context,
+	.init = adreno_init,
 	.start = adreno_start,
 	.stop = adreno_stop,
 	.getproperty = adreno_getproperty,
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 29d689b..5396196 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -702,7 +702,7 @@
 		" %08X\n", r1, r2, r3);
 
 	KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ",
-		kgsl_mmu_get_ptsize());
+		kgsl_mmu_get_ptsize(&device->mmu));
 
 	kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1);
 	KGSL_LOG_DUMP(device, "        TRAN_ERROR = %08X\n", r1);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 4333f2f..b746671 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -319,7 +319,7 @@
 	return 0;
 }
 
-int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram)
+int adreno_ringbuffer_start(struct adreno_ringbuffer *rb)
 {
 	int status;
 	/*cp_rb_cntl_u cp_rb_cntl; */
@@ -331,9 +331,6 @@
 	if (rb->flags & KGSL_FLAGS_STARTED)
 		return 0;
 
-	if (init_ram)
-		rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
-
 	kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
 			   sizeof(struct kgsl_rbmemptrs));
 
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index fa03c05..e563ec7 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -97,8 +97,7 @@
 
 int adreno_ringbuffer_init(struct kgsl_device *device);
 
-int adreno_ringbuffer_start(struct adreno_ringbuffer *rb,
-				unsigned int init_ram);
+int adreno_ringbuffer_start(struct adreno_ringbuffer *rb);
 
 void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb);
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2b0d5d9..af25a3f 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -671,9 +671,10 @@
 	if (kgsl_mmu_enabled())
 	{
 		unsigned long pt_name;
+		struct kgsl_mmu *mmu = &cur_dev_priv->device->mmu;
 
 		pt_name = task_tgid_nr(current);
-		private->pagetable = kgsl_mmu_getpagetable(pt_name);
+		private->pagetable = kgsl_mmu_getpagetable(mmu, pt_name);
 		if (private->pagetable == NULL) {
 			kfree(private);
 			private = NULL;
@@ -821,12 +822,14 @@
 		kgsl_sharedmem_set(&device->memstore, 0, 0,
 				device->memstore.size);
 
-		result = device->ftbl->start(device, true);
-
-		if (result) {
-			mutex_unlock(&device->mutex);
+		result = device->ftbl->init(device);
+		if (result)
 			goto err_freedevpriv;
-		}
+
+		result = device->ftbl->start(device);
+		if (result)
+			goto err_freedevpriv;
+
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
 	}
 	device->open_count++;
@@ -856,8 +859,8 @@
 		result = device->ftbl->stop(device);
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
 	}
-	mutex_unlock(&device->mutex);
 err_freedevpriv:
+	mutex_unlock(&device->mutex);
 	filep->private_data = NULL;
 	kfree(dev_priv);
 err_pmruntime:
@@ -872,7 +875,7 @@
 {
 	struct rb_node *node = private->mem_rb.rb_node;
 
-	if (!kgsl_mmu_gpuaddr_in_range(gpuaddr))
+	if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
 		return NULL;
 
 	while (node != NULL) {
@@ -925,7 +928,7 @@
 
 	struct rb_node *node = private->mem_rb.rb_node;
 
-	if (!kgsl_mmu_gpuaddr_in_range(gpuaddr))
+	if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
 		return 0;
 
 	/* don't overflow */
@@ -1193,7 +1196,9 @@
 	}
 
 	for (i = 0; i < param->numibs; i++) {
-		if (!kgsl_mmu_gpuaddr_in_range(ibdesc[i].gpuaddr)) {
+		struct kgsl_pagetable *pt = dev_priv->process_priv->pagetable;
+
+		if (!kgsl_mmu_gpuaddr_in_range(pt, ibdesc[i].gpuaddr)) {
 			result = -ERANGE;
 			KGSL_DRV_ERR(dev_priv->device,
 				     "invalid ib base GPU virtual addr %x\n",
@@ -1767,13 +1772,6 @@
 	return -ENOMEM;
 }
 
-static inline int
-can_use_cpu_map(void)
-{
-	return (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU
-		&& kgsl_mmu_is_perprocess());
-}
-
 static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
 				     unsigned int cmd, void *data)
 {
@@ -1805,7 +1803,7 @@
 			| KGSL_MEMFLAGS_USE_CPU_MAP;
 
 	entry->memdesc.flags = param->flags;
-	if (!can_use_cpu_map())
+	if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu))
 		entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
 
 	switch (memtype) {
@@ -2092,7 +2090,7 @@
 	struct kgsl_mem_entry *entry = NULL;
 	int result;
 
-	if (!can_use_cpu_map())
+	if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu))
 		param->flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
 
 	result = _gpumem_alloc(dev_priv, &entry, param->size, param->flags);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index aca5660..37b5730 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -73,7 +73,8 @@
 	int (*idle) (struct kgsl_device *device);
 	unsigned int (*isidle) (struct kgsl_device *device);
 	int (*suspend_context) (struct kgsl_device *device);
-	int (*start) (struct kgsl_device *device, unsigned int init_ram);
+	int (*init) (struct kgsl_device *device);
+	int (*start) (struct kgsl_device *device);
 	int (*stop) (struct kgsl_device *device);
 	int (*getproperty) (struct kgsl_device *device,
 		enum kgsl_property_type type, void *value,
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index cb206ac..5cc0dff 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -19,6 +19,7 @@
 
 #include "kgsl.h"
 #include "kgsl_mmu.h"
+#include "kgsl_gpummu.h"
 #include "kgsl_device.h"
 #include "kgsl_sharedmem.h"
 #include "kgsl_trace.h"
@@ -364,10 +365,9 @@
 	return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
 }
 
-void kgsl_gpummu_destroy_pagetable(void *mmu_specific_pt)
+void kgsl_gpummu_destroy_pagetable(struct kgsl_pagetable *pt)
 {
-	struct kgsl_gpummu_pt *gpummu_pt = (struct kgsl_gpummu_pt *)
-						mmu_specific_pt;
+	struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
 	kgsl_ptpool_free((struct kgsl_ptpool *)kgsl_driver.ptpool,
 				gpummu_pt->base.hostptr);
 
@@ -528,6 +528,11 @@
 	 */
 	int status = 0;
 
+	mmu->pt_base = KGSL_PAGETABLE_BASE;
+	mmu->pt_size = CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
+	mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT;
+	mmu->use_cpu_map = false;
+
 	/* sub-client MMU lookups require address translation */
 	if ((mmu->config & ~0x1) > 0) {
 		/*make sure virtual address range is a multiple of 64Kb */
@@ -584,7 +589,7 @@
 
 	if (mmu->defaultpagetable == NULL)
 		mmu->defaultpagetable =
-			kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+			kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT);
 
 	/* Return error if the default pagetable doesn't exist */
 	if (mmu->defaultpagetable == NULL)
@@ -604,14 +609,14 @@
 }
 
 static int
-kgsl_gpummu_unmap(void *mmu_specific_pt,
+kgsl_gpummu_unmap(struct kgsl_pagetable *pt,
 		struct kgsl_memdesc *memdesc,
 		unsigned int *tlb_flags)
 {
 	unsigned int numpages;
 	unsigned int pte, ptefirst, ptelast, superpte;
 	unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen);
-	struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt;
+	struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
 
 	/* All GPU addresses as assigned are page aligned, but some
 	   functions purturb the gpuaddr with an offset, so apply the
@@ -653,13 +658,13 @@
 GSL_TLBFLUSH_FILTER_ISDIRTY((_p) / GSL_PT_SUPER_PTE))
 
 static int
-kgsl_gpummu_map(void *mmu_specific_pt,
+kgsl_gpummu_map(struct kgsl_pagetable *pt,
 		struct kgsl_memdesc *memdesc,
 		unsigned int protflags,
 		unsigned int *tlb_flags)
 {
 	unsigned int pte;
-	struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt;
+	struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
 	struct scatterlist *s;
 	int flushtlb = 0;
 	int i;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index e3cea88..f327c04 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -21,6 +21,7 @@
 #include <mach/socinfo.h>
 #include <mach/msm_iomap.h>
 #include <mach/board.h>
+#include <mach/iommu_domains.h>
 #include <stddef.h>
 
 #include "kgsl.h"
@@ -603,9 +604,9 @@
  *
  * Return - void
  */
-static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt)
+static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt)
 {
-	struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
+	struct kgsl_iommu_pt *iommu_pt = pt->priv;
 	if (iommu_pt->domain)
 		iommu_domain_free(iommu_pt->domain);
 	kfree(iommu_pt);
@@ -620,8 +621,20 @@
  */
 void *kgsl_iommu_create_pagetable(void)
 {
+	int domain_num;
 	struct kgsl_iommu_pt *iommu_pt;
 
+	struct msm_iova_partition kgsl_partition = {
+		.start = 0,
+		.size = 0xFFFFFFFF,
+	};
+	struct msm_iova_layout kgsl_layout = {
+		.partitions = &kgsl_partition,
+		.npartitions = 1,
+		.client_name = "kgsl",
+		.domain_flags = 0,
+	};
+
 	iommu_pt = kzalloc(sizeof(struct kgsl_iommu_pt), GFP_KERNEL);
 	if (!iommu_pt) {
 		KGSL_CORE_ERR("kzalloc(%d) failed\n",
@@ -630,18 +643,17 @@
 	}
 	/* L2 redirect is not stable on IOMMU v1 */
 	if (msm_soc_version_supports_iommu_v0())
-		iommu_pt->domain = iommu_domain_alloc(&platform_bus_type,
-					MSM_IOMMU_DOMAIN_PT_CACHEABLE);
-	else
-		iommu_pt->domain = iommu_domain_alloc(&platform_bus_type,
-					0);
-	if (!iommu_pt->domain) {
+		kgsl_layout.domain_flags = MSM_IOMMU_DOMAIN_PT_CACHEABLE;
+
+	domain_num = msm_register_domain(&kgsl_layout);
+	if (domain_num >= 0) {
+		iommu_pt->domain = msm_get_iommu_domain(domain_num);
+		iommu_set_fault_handler(iommu_pt->domain,
+			kgsl_iommu_fault_handler, NULL);
+	} else {
 		KGSL_CORE_ERR("Failed to create iommu domain\n");
 		kfree(iommu_pt);
 		return NULL;
-	} else {
-		iommu_set_fault_handler(iommu_pt->domain,
-			kgsl_iommu_fault_handler, NULL);
 	}
 
 	return iommu_pt;
@@ -817,7 +829,7 @@
 
 	if (KGSL_DEVICE_3D0 != mmu->device->id ||
 		!msm_soc_version_supports_iommu_v0() ||
-		!kgsl_mmu_is_perprocess() ||
+		!kgsl_mmu_is_perprocess(mmu) ||
 		iommu->sync_lock_vars)
 		return 0;
 
@@ -858,7 +870,7 @@
 	uint32_t page_offset = 0;
 
 	if (!msm_soc_version_supports_iommu_v0() ||
-		!kgsl_mmu_is_perprocess())
+		!kgsl_mmu_is_perprocess(mmu))
 		return status;
 
 	/*
@@ -1256,6 +1268,32 @@
 	if (status)
 		goto done;
 
+	/* We presently do not support per-process for IOMMU-v1 */
+	mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT &&
+				msm_soc_version_supports_iommu_v0();
+
+	/*
+	 * For IOMMU per-process pagetables, the allocatable range
+	 * and the kernel global range must both be outside
+	 * the userspace address range. There is a 1Mb gap
+	 * between these address ranges to make overrun
+	 * detection easier.
+	 * For the shared pagetable case use 2GB and because
+	 * mirroring the CPU address space is not possible and
+	 * we're better off with extra room.
+	 */
+	if (mmu->pt_per_process) {
+		mmu->pt_base = PAGE_OFFSET;
+		mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE
+				- kgsl_mmu_get_base_addr(mmu) - SZ_1M;
+		mmu->use_cpu_map = true;
+	} else {
+		mmu->pt_base = KGSL_PAGETABLE_BASE;
+		mmu->pt_size = SZ_2G;
+		mmu->use_cpu_map = false;
+	}
+
+
 	iommu->iommu_reg_list = kgsl_iommuv0_reg;
 	iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V0;
 
@@ -1309,7 +1347,8 @@
 	 * switching on the 3D side for which a separate table is allocated */
 	if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v0()) {
 		mmu->priv_bank_table =
-			kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME);
+			kgsl_mmu_getpagetable(mmu,
+					KGSL_MMU_PRIV_BANK_TABLE_NAME);
 		if (mmu->priv_bank_table == NULL) {
 			status = -ENOMEM;
 			goto err;
@@ -1318,7 +1357,7 @@
 		if (status)
 			goto err;
 	}
-	mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+	mmu->defaultpagetable = kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT);
 	/* Return error if the default pagetable doesn't exist */
 	if (mmu->defaultpagetable == NULL) {
 		status = -ENOMEM;
@@ -1522,13 +1561,13 @@
 }
 
 static int
-kgsl_iommu_unmap(void *mmu_specific_pt,
+kgsl_iommu_unmap(struct kgsl_pagetable *pt,
 		struct kgsl_memdesc *memdesc,
 		unsigned int *tlb_flags)
 {
 	int ret;
 	unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen);
-	struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
+	struct kgsl_iommu_pt *iommu_pt = pt->priv;
 
 	/* All GPU addresses as assigned are page aligned, but some
 	   functions purturb the gpuaddr with an offset, so apply the
@@ -1549,20 +1588,20 @@
 	 * Flushing only required if per process pagetables are used. With
 	 * global case, flushing will happen inside iommu_map function
 	 */
-	if (!ret && kgsl_mmu_is_perprocess())
+	if (!ret && kgsl_mmu_is_perprocess(pt->mmu))
 		*tlb_flags = UINT_MAX;
 	return 0;
 }
 
 static int
-kgsl_iommu_map(void *mmu_specific_pt,
+kgsl_iommu_map(struct kgsl_pagetable *pt,
 			struct kgsl_memdesc *memdesc,
 			unsigned int protflags,
 			unsigned int *tlb_flags)
 {
 	int ret;
 	unsigned int iommu_virt_addr;
-	struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
+	struct kgsl_iommu_pt *iommu_pt = pt->priv;
 	int size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
 
 	BUG_ON(NULL == iommu_pt);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index ccaceb3..4e95373 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -23,6 +23,7 @@
 
 #include "kgsl.h"
 #include "kgsl_mmu.h"
+#include "kgsl_gpummu.h"
 #include "kgsl_device.h"
 #include "kgsl_sharedmem.h"
 #include "adreno.h"
@@ -103,7 +104,7 @@
 	if (pagetable->pool)
 		gen_pool_destroy(pagetable->pool);
 
-	pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv);
+	pagetable->pt_ops->mmu_destroy_pagetable(pagetable);
 
 	kfree(pagetable);
 }
@@ -193,7 +194,7 @@
 
 	if (pt) {
 		ret += snprintf(buf, PAGE_SIZE, "0x%x\n",
-			kgsl_mmu_get_ptsize());
+			kgsl_mmu_get_ptsize(pt->mmu));
 	}
 
 	kgsl_put_pagetable(pt);
@@ -444,7 +445,8 @@
 }
 EXPORT_SYMBOL(kgsl_mh_intrcallback);
 
-static struct kgsl_pagetable *kgsl_mmu_createpagetableobject(
+static struct kgsl_pagetable *
+kgsl_mmu_createpagetableobject(struct kgsl_mmu *mmu,
 				unsigned int name)
 {
 	int status = 0;
@@ -463,8 +465,8 @@
 
 	spin_lock_init(&pagetable->lock);
 
-	ptsize = kgsl_mmu_get_ptsize();
-
+	ptsize = kgsl_mmu_get_ptsize(mmu);
+	pagetable->mmu = mmu;
 	pagetable->name = name;
 	pagetable->max_entries = KGSL_PAGETABLE_ENTRIES(ptsize);
 	pagetable->fault_addr = 0xFFFFFFFF;
@@ -497,7 +499,7 @@
 		goto err_kgsl_pool;
 	}
 
-	if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(),
+	if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(mmu),
 				ptsize, -1)) {
 		KGSL_CORE_ERR("gen_pool_add failed\n");
 		goto err_pool;
@@ -526,7 +528,7 @@
 	return pagetable;
 
 err_mmu_create:
-	pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv);
+	pagetable->pt_ops->mmu_destroy_pagetable(pagetable);
 err_pool:
 	gen_pool_destroy(pagetable->pool);
 err_kgsl_pool:
@@ -538,20 +540,21 @@
 	return NULL;
 }
 
-struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name)
+struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *mmu,
+						unsigned long name)
 {
 	struct kgsl_pagetable *pt;
 
 	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
 		return (void *)(-1);
 
-	if (!kgsl_mmu_is_perprocess())
+	if (!kgsl_mmu_is_perprocess(mmu))
 		name = KGSL_MMU_GLOBAL_PT;
 
 	pt = kgsl_get_pagetable(name);
 
 	if (pt == NULL)
-		pt = kgsl_mmu_createpagetableobject(name);
+		pt = kgsl_mmu_createpagetableobject(mmu, name);
 
 	return pt;
 }
@@ -688,7 +691,7 @@
 
 	if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
 		spin_lock(&pagetable->lock);
-	ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags,
+	ret = pagetable->pt_ops->mmu_map(pagetable, memdesc, protflags,
 						&pagetable->tlb_flags);
 	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
 		spin_lock(&pagetable->lock);
@@ -741,7 +744,7 @@
 
 	if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
 		spin_lock(&pagetable->lock);
-	pagetable->pt_ops->mmu_unmap(pagetable->priv, memdesc,
+	pagetable->pt_ops->mmu_unmap(pagetable, memdesc,
 					&pagetable->tlb_flags);
 
 	/* If buffer is unmapped 0 fault addr */
@@ -894,15 +897,16 @@
 }
 EXPORT_SYMBOL(kgsl_mmu_set_mmutype);
 
-int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr)
+int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr)
 {
 	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
 		return 1;
-	if (gpuaddr >= kgsl_mmu_get_base_addr() &&
-		gpuaddr < kgsl_mmu_get_base_addr() + kgsl_mmu_get_ptsize())
+	if (gpuaddr >= kgsl_mmu_get_base_addr(pt->mmu) &&
+		gpuaddr < kgsl_mmu_get_base_addr(pt->mmu) +
+		kgsl_mmu_get_ptsize(pt->mmu))
 		return 1;
 	if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU
-		&& kgsl_mmu_is_perprocess())
+		&& kgsl_mmu_is_perprocess(pt->mmu))
 		return (gpuaddr > 0 && gpuaddr < TASK_SIZE);
 	return 0;
 }
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 2d48e86..d7d9516 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -24,6 +24,13 @@
 
 #define KGSL_MMU_ALIGN_MASK     (~((1 << PAGE_SHIFT) - 1))
 
+/* defconfig option for disabling per process pagetables */
+#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
+#define KGSL_MMU_USE_PER_PROCESS_PT true
+#else
+#define KGSL_MMU_USE_PER_PROCESS_PT false
+#endif
+
 /* Identifier for the global page table */
 /* Per process page tables will probably pass in the thread group
    as an identifier */
@@ -116,6 +123,7 @@
 	unsigned int tlb_flags;
 	unsigned int fault_addr;
 	void *priv;
+	struct kgsl_mmu *mmu;
 };
 
 struct kgsl_mmu;
@@ -160,15 +168,15 @@
 };
 
 struct kgsl_mmu_pt_ops {
-	int (*mmu_map) (void *mmu_pt,
+	int (*mmu_map) (struct kgsl_pagetable *pt,
 			struct kgsl_memdesc *memdesc,
 			unsigned int protflags,
 			unsigned int *tlb_flags);
-	int (*mmu_unmap) (void *mmu_pt,
+	int (*mmu_unmap) (struct kgsl_pagetable *pt,
 			struct kgsl_memdesc *memdesc,
 			unsigned int *tlb_flags);
 	void *(*mmu_create_pagetable) (void);
-	void (*mmu_destroy_pagetable) (void *pt);
+	void (*mmu_destroy_pagetable) (struct kgsl_pagetable *);
 };
 
 #define KGSL_MMU_FLAGS_IOMMU_SYNC BIT(31)
@@ -187,14 +195,19 @@
 	const struct kgsl_mmu_ops *mmu_ops;
 	void *priv;
 	int fault;
+	unsigned long pt_base;
+	unsigned long pt_size;
+	bool pt_per_process;
+	bool use_cpu_map;
 };
 
-#include "kgsl_gpummu.h"
-
 extern struct kgsl_mmu_ops iommu_ops;
 extern struct kgsl_mmu_pt_ops iommu_pt_ops;
+extern struct kgsl_mmu_ops gpummu_ops;
+extern struct kgsl_mmu_pt_ops gpummu_pt_ops;
 
-struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name);
+struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *,
+						unsigned long name);
 void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable);
 void kgsl_mh_start(struct kgsl_device *device);
 void kgsl_mh_intrcallback(struct kgsl_device *device);
@@ -221,7 +234,7 @@
 int kgsl_mmu_enabled(void);
 void kgsl_mmu_set_mmutype(char *mmutype);
 enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
-int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr);
+int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr);
 
 /*
  * Static inline functions of MMU that simply call the SMMU specific
@@ -335,75 +348,51 @@
 /*
  * kgsl_mmu_is_perprocess() - Runtime check for per-process
  * pagetables.
+ * @mmu: the mmu
  *
- * Returns non-zero if per-process pagetables are enabled,
- * 0 if not.
+ * Returns true if per-process pagetables are enabled,
+ * false if not.
  */
-#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
-static inline int kgsl_mmu_is_perprocess(void)
+static inline int kgsl_mmu_is_perprocess(struct kgsl_mmu *mmu)
 {
+	return mmu->pt_per_process;
+}
 
-	/* We presently do not support per-process for IOMMU-v1 */
-	return (kgsl_mmu_get_mmutype() != KGSL_MMU_TYPE_IOMMU)
-		|| msm_soc_version_supports_iommu_v0();
-}
-#else
-static inline int kgsl_mmu_is_perprocess(void)
+/*
+ * kgsl_mmu_use_cpu_map() - Runtime check for matching the CPU
+ * address space on the GPU.
+ * @mmu: the mmu
+ *
+ * Returns true if supported false if not.
+ */
+static inline int kgsl_mmu_use_cpu_map(struct kgsl_mmu *mmu)
 {
-	return 0;
+	return mmu->pt_per_process;
 }
-#endif
 
 /*
  * kgsl_mmu_base_addr() - Get gpu virtual address base.
+ * @mmu: the mmu
  *
  * Returns the start address of the allocatable gpu
  * virtual address space. Other mappings that mirror
  * the CPU address space are possible outside this range.
  */
-static inline unsigned int kgsl_mmu_get_base_addr(void)
+static inline unsigned int kgsl_mmu_get_base_addr(struct kgsl_mmu *mmu)
 {
-	if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype()
-		|| !kgsl_mmu_is_perprocess())
-		return KGSL_PAGETABLE_BASE;
-	/*
-	 * This is the start of the kernel address
-	 * space, so allocations from this range will
-	 * never conflict with userpace addresses
-	 */
-	return PAGE_OFFSET;
+	return mmu->pt_base;
 }
 
 /*
  * kgsl_mmu_get_ptsize() - Get gpu pagetable size
+ * @mmu: the mmu
  *
  * Returns the usable size of the gpu allocatable
  * address space.
  */
-static inline unsigned int kgsl_mmu_get_ptsize(void)
+static inline unsigned int kgsl_mmu_get_ptsize(struct kgsl_mmu *mmu)
 {
-	/*
-	 * For IOMMU per-process pagetables, the allocatable range
-	 * and the kernel global range must both be outside
-	 * the userspace address range. There is a 1Mb gap
-	 * between these address ranges to make overrun
-	 * detection easier.
-	 * For the shared pagetable case use 2GB and because
-	 * mirroring the CPU address space is not possible and
-	 * we're better off with extra room.
-	 */
-	enum kgsl_mmutype mmu_type = kgsl_mmu_get_mmutype();
-
-	if (KGSL_MMU_TYPE_GPU == mmu_type)
-		return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
-	else if (KGSL_MMU_TYPE_IOMMU == mmu_type) {
-		if (kgsl_mmu_is_perprocess())
-			return KGSL_IOMMU_GLOBAL_MEM_BASE
-				- kgsl_mmu_get_base_addr() - SZ_1M;
-		else
-			return SZ_2G;
-	}
-	return 0;
+	return mmu->pt_size;
 }
 
 static inline int kgsl_mmu_sync_lock(struct kgsl_mmu *mmu,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index c716731..2f8d93e 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1289,7 +1289,7 @@
 	kgsl_pwrctrl_request_state(device, KGSL_STATE_ACTIVE);
 	switch (device->state) {
 	case KGSL_STATE_SLUMBER:
-		status = device->ftbl->start(device, 0);
+		status = device->ftbl->start(device);
 		if (status) {
 			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
 			KGSL_DRV_ERR(device, "start failed %d\n", status);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index f0410d6..b78c6fe 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -93,7 +93,8 @@
 #define Z180_CMDWINDOW_TARGET_SHIFT		0
 #define Z180_CMDWINDOW_ADDR_SHIFT		8
 
-static int z180_start(struct kgsl_device *device, unsigned int init_ram);
+static int z180_init(struct kgsl_device *device);
+static int z180_start(struct kgsl_device *device);
 static int z180_stop(struct kgsl_device *device);
 static int z180_wait(struct kgsl_device *device,
 				struct kgsl_context *context,
@@ -319,16 +320,11 @@
 	*p++ = ADDR_VGV3_LAST << 24;
 }
 
-static void z180_cmdstream_start(struct kgsl_device *device, int init_ram)
+static void z180_cmdstream_start(struct kgsl_device *device)
 {
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 	unsigned int cmd = VGV3_NEXTCMD_JUMP << VGV3_NEXTCMD_NEXTCMD_FSHIFT;
 
-	if (init_ram) {
-		z180_dev->timestamp = 0;
-		z180_dev->current_timestamp = 0;
-	}
-
 	addmarker(&z180_dev->ringbuffer, 0);
 
 	z180_cmdwindow_write(device, ADDR_VGV3_MODE, 4);
@@ -552,7 +548,17 @@
 	return 0;
 }
 
-static int z180_start(struct kgsl_device *device, unsigned int init_ram)
+static int z180_init(struct kgsl_device *device)
+{
+	struct z180_device *z180_dev = Z180_DEVICE(device);
+
+	z180_dev->timestamp = 0;
+	z180_dev->current_timestamp = 0;
+
+	return 0;
+}
+
+static int z180_start(struct kgsl_device *device)
 {
 	int status = 0;
 
@@ -569,7 +575,7 @@
 	if (status)
 		goto error_clk_off;
 
-	z180_cmdstream_start(device, init_ram);
+	z180_cmdstream_start(device);
 
 	mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
@@ -919,6 +925,7 @@
 	.idle = z180_idle,
 	.isidle = z180_isidle,
 	.suspend_context = z180_suspend_context,
+	.init = z180_init,
 	.start = z180_start,
 	.stop = z180_stop,
 	.getproperty = z180_getproperty,
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index ecd4bbb..60c2da3 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.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
@@ -212,7 +212,7 @@
 	bool descending = 1;
 	uint32_t i = 0;
 
-	if ((pts == NULL) || (output == NULL))
+	if (pts == NULL)
 		return -EINVAL;
 
 	/* Check if table is descending or ascending */
@@ -258,7 +258,7 @@
 	bool descending = 1;
 	uint32_t i = 0;
 
-	if ((pts == NULL) || (output == NULL))
+	if (pts == NULL)
 		return -EINVAL;
 
 	/* Check if table is descending or ascending */
@@ -367,7 +367,42 @@
 }
 EXPORT_SYMBOL_GPL(qpnp_adc_scale_pmic_therm);
 
-/* Scales the ADC code to 0.001 degrees C using the map
+int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+		struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold)
+{
+	struct qpnp_vadc_linear_graph btm_param;
+	int64_t low_output = 0, high_output = 0;
+	int rc = 0;
+
+	rc = qpnp_get_vadc_gain_and_offset(&btm_param, CALIB_ABSOLUTE);
+	if (rc < 0) {
+		pr_err("Could not acquire gain and offset\n");
+		return rc;
+	}
+
+	/* Convert to Kelvin and account for voltage to be written as 2mV/K */
+	low_output = (param->low_temp + KELVINMIL_DEGMIL) * 2;
+	/* Convert to voltage threshold */
+	low_output *= btm_param.dy;
+	do_div(low_output, btm_param.adc_vref);
+	low_output += btm_param.adc_gnd;
+
+	/* Convert to Kelvin and account for voltage to be written as 2mV/K */
+	high_output = (param->high_temp + KELVINMIL_DEGMIL) * 2;
+	/* Convert to voltage threshold */
+	high_output *= btm_param.dy;
+	do_div(high_output, btm_param.adc_vref);
+	high_output += btm_param.adc_gnd;
+
+	*low_threshold = low_output;
+	*high_threshold = high_output;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_millidegc_pmic_voltage_thr);
+
+/* Scales the ADC code to degC using the mapping
  * table for the XO thermistor.
  */
 int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
@@ -577,7 +612,7 @@
 }
 EXPORT_SYMBOL_GPL(qpnp_adc_scale_default);
 
-int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_usbid_param *param,
+int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
 	struct qpnp_vadc_linear_graph usb_param;
@@ -592,46 +627,81 @@
 	do_div(*high_threshold, usb_param.adc_vref);
 	*high_threshold += usb_param.adc_gnd;
 
+	pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
+				param->low_thr);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(qpnp_adc_usb_scaler);
 
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold)
+{
+	struct qpnp_vadc_linear_graph vbatt_param;
+
+	qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
+
+	*low_threshold = param->low_thr * vbatt_param.dy;
+	do_div(*low_threshold, vbatt_param.adc_vref);
+	*low_threshold += vbatt_param.adc_gnd;
+
+	*high_threshold = param->high_thr * vbatt_param.dy;
+	do_div(*high_threshold, vbatt_param.adc_vref);
+	*high_threshold += vbatt_param.adc_gnd;
+
+	pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
+				param->low_thr);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_vbatt_rscaler);
+
 int32_t qpnp_adc_btm_scaler(struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
 	struct qpnp_vadc_linear_graph btm_param;
-	int64_t *low_output = 0, *high_output = 0;
+	int64_t low_output = 0, high_output = 0;
 	int rc = 0;
 
 	qpnp_get_vadc_gain_and_offset(&btm_param, CALIB_RATIOMETRIC);
 
-	rc = qpnp_adc_map_temp_voltage(
+	pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
+				param->low_temp);
+	rc = qpnp_adc_map_voltage_temp(
 		adcmap_btm_threshold,
 		ARRAY_SIZE(adcmap_btm_threshold),
 		(param->low_temp),
-		low_output);
-	if (rc)
+		&low_output);
+	if (rc) {
+		pr_debug("low_temp mapping failed with %d\n", rc);
 		return rc;
+	}
 
-	*low_output *= btm_param.dy;
-	do_div(*low_output, btm_param.adc_vref);
-	*low_output += btm_param.adc_gnd;
+	pr_debug("low_output:%lld\n", low_output);
+	low_output *= btm_param.dy;
+	do_div(low_output, btm_param.adc_vref);
+	low_output += btm_param.adc_gnd;
 
-	rc = qpnp_adc_map_temp_voltage(
+	rc = qpnp_adc_map_voltage_temp(
 		adcmap_btm_threshold,
 		ARRAY_SIZE(adcmap_btm_threshold),
 		(param->high_temp),
-		high_output);
-	if (rc)
+		&high_output);
+	if (rc) {
+		pr_debug("high temp mapping failed with %d\n", rc);
 		return rc;
+	}
 
-	*high_output *= btm_param.dy;
-	do_div(*high_output, btm_param.adc_vref);
-	*high_output += btm_param.adc_gnd;
+	pr_debug("high_output:%lld\n", high_output);
+	high_output *= btm_param.dy;
+	do_div(high_output, btm_param.adc_vref);
+	high_output += btm_param.adc_gnd;
 
-	low_threshold = (uint32_t *) low_output;
-	high_threshold = (uint32_t *) high_output;
+	/* btm low temperature correspondes to high voltage threshold */
+	*low_threshold = high_output;
+	/* btm high temperature correspondes to low voltage threshold */
+	*high_threshold = low_output;
 
+	pr_debug("high_volt:%d, low_volt:%d\n", *high_threshold,
+				*low_threshold);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(qpnp_adc_btm_scaler);
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index 6bf0220..de35f9a 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -29,6 +29,7 @@
 
 #include <mach/iommu_perfmon.h>
 #include <mach/iommu_hw-v0.h>
+#include <mach/msm_iommu_priv.h>
 #include <mach/iommu.h>
 #include <mach/msm_smsm.h>
 
@@ -131,12 +132,6 @@
 	return msm_iommu_remote_lock.lock;
 }
 
-struct msm_priv {
-	unsigned long *pgtable;
-	int redirect;
-	struct list_head list_attached;
-};
-
 static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
 {
 	int ret;
@@ -198,7 +193,7 @@
 
 static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
 {
-	struct msm_priv *priv = domain->priv;
+	struct msm_iommu_priv *priv = domain->priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret = 0;
@@ -235,7 +230,7 @@
 
 static int __flush_iotlb(struct iommu_domain *domain)
 {
-	struct msm_priv *priv = domain->priv;
+	struct msm_iommu_priv *priv = domain->priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret = 0;
@@ -396,26 +391,27 @@
 
 static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
 {
-	struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	struct msm_iommu_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 
 	if (!priv)
 		goto fail_nomem;
 
 	INIT_LIST_HEAD(&priv->list_attached);
-	priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
+	priv->pt.fl_table = (unsigned long *)__get_free_pages(GFP_KERNEL,
 							  get_order(SZ_16K));
 
-	if (!priv->pgtable)
+	if (!priv->pt.fl_table)
 		goto fail_nomem;
 
 #ifdef CONFIG_IOMMU_PGTABLES_L2
-	priv->redirect = flags & MSM_IOMMU_DOMAIN_PT_CACHEABLE;
+	priv->pt.redirect = flags & MSM_IOMMU_DOMAIN_PT_CACHEABLE;
 #endif
 
-	memset(priv->pgtable, 0, SZ_16K);
+	memset(priv->pt.fl_table, 0, SZ_16K);
 	domain->priv = priv;
 
-	clean_pte(priv->pgtable, priv->pgtable + NUM_FL_PTE, priv->redirect);
+	clean_pte(priv->pt.fl_table, priv->pt.fl_table + NUM_FL_PTE,
+		  priv->pt.redirect);
 
 	return 0;
 
@@ -426,7 +422,7 @@
 
 static void msm_iommu_domain_destroy(struct iommu_domain *domain)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	unsigned long *fl_table;
 	int i;
 
@@ -435,15 +431,15 @@
 	domain->priv = NULL;
 
 	if (priv) {
-		fl_table = priv->pgtable;
+		fl_table = priv->pt.fl_table;
 
 		for (i = 0; i < NUM_FL_PTE; i++)
 			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
 				free_page((unsigned long) __va(((fl_table[i]) &
 								FL_BASE_MASK)));
 
-		free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
-		priv->pgtable = NULL;
+		free_pages((unsigned long)priv->pt.fl_table, get_order(SZ_16K));
+		priv->pt.fl_table = NULL;
 	}
 
 	kfree(priv);
@@ -452,7 +448,7 @@
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	struct msm_iommu_ctx_drvdata *tmp_drvdata;
@@ -497,7 +493,7 @@
 
 	__program_context(iommu_drvdata->base, iommu_drvdata->glb_base,
 			  ctx_drvdata->num, iommu_drvdata->ncb,
-			  __pa(priv->pgtable), priv->redirect,
+			  __pa(priv->pt.fl_table), priv->pt.redirect,
 			  iommu_drvdata->ttbr_split);
 
 	__disable_clocks(iommu_drvdata);
@@ -517,7 +513,7 @@
 static void msm_iommu_detach_dev(struct iommu_domain *domain,
 				 struct device *dev)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret;
@@ -605,7 +601,7 @@
 	return pgprot;
 }
 
-static unsigned long *make_second_level(struct msm_priv *priv,
+static unsigned long *make_second_level(struct msm_iommu_priv *priv,
 					unsigned long *fl_pte)
 {
 	unsigned long *sl;
@@ -617,12 +613,12 @@
 		goto fail;
 	}
 	memset(sl, 0, SZ_4K);
-	clean_pte(sl, sl + NUM_SL_PTE, priv->redirect);
+	clean_pte(sl, sl + NUM_SL_PTE, priv->pt.redirect);
 
 	*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | \
 			FL_TYPE_TABLE);
 
-	clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+	clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
 fail:
 	return sl;
 }
@@ -694,7 +690,7 @@
 static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
 			 phys_addr_t pa, size_t len, int prot)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	unsigned long *fl_table;
 	unsigned long *fl_pte;
 	unsigned long fl_offset;
@@ -712,7 +708,7 @@
 		goto fail;
 	}
 
-	fl_table = priv->pgtable;
+	fl_table = priv->pt.fl_table;
 
 	if (len != SZ_16M && len != SZ_1M &&
 	    len != SZ_64K && len != SZ_4K) {
@@ -741,14 +737,14 @@
 		ret = fl_16m(fl_pte, pa, pgprot);
 		if (ret)
 			goto fail;
-		clean_pte(fl_pte, fl_pte + 16, priv->redirect);
+		clean_pte(fl_pte, fl_pte + 16, priv->pt.redirect);
 	}
 
 	if (len == SZ_1M) {
 		ret = fl_1m(fl_pte, pa, pgprot);
 		if (ret)
 			goto fail;
-		clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+		clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
 	}
 
 	/* Need a 2nd level table */
@@ -776,14 +772,14 @@
 		if (ret)
 			goto fail;
 
-		clean_pte(sl_pte, sl_pte + 1, priv->redirect);
+		clean_pte(sl_pte, sl_pte + 1, priv->pt.redirect);
 	}
 
 	if (len == SZ_64K) {
 		ret = sl_64k(sl_pte, pa, pgprot);
 		if (ret)
 			goto fail;
-		clean_pte(sl_pte, sl_pte + 16, priv->redirect);
+		clean_pte(sl_pte, sl_pte + 16, priv->pt.redirect);
 	}
 
 	ret = __flush_iotlb_va(domain, va);
@@ -795,7 +791,7 @@
 static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
 			    size_t len)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	unsigned long *fl_table;
 	unsigned long *fl_pte;
 	unsigned long fl_offset;
@@ -811,7 +807,7 @@
 	if (!priv)
 		goto fail;
 
-	fl_table = priv->pgtable;
+	fl_table = priv->pt.fl_table;
 
 	if (len != SZ_16M && len != SZ_1M &&
 	    len != SZ_64K && len != SZ_4K) {
@@ -837,13 +833,13 @@
 		for (i = 0; i < 16; i++)
 			*(fl_pte+i) = 0;
 
-		clean_pte(fl_pte, fl_pte + 16, priv->redirect);
+		clean_pte(fl_pte, fl_pte + 16, priv->pt.redirect);
 	}
 
 	if (len == SZ_1M) {
 		*fl_pte = 0;
 
-		clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+		clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
 	}
 
 	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
@@ -854,13 +850,13 @@
 		for (i = 0; i < 16; i++)
 			*(sl_pte+i) = 0;
 
-		clean_pte(sl_pte, sl_pte + 16, priv->redirect);
+		clean_pte(sl_pte, sl_pte + 16, priv->pt.redirect);
 	}
 
 	if (len == SZ_4K) {
 		*sl_pte = 0;
 
-		clean_pte(sl_pte, sl_pte + 1, priv->redirect);
+		clean_pte(sl_pte, sl_pte + 1, priv->pt.redirect);
 	}
 
 	if (len == SZ_4K || len == SZ_64K) {
@@ -873,7 +869,7 @@
 			free_page((unsigned long)sl_table);
 			*fl_pte = 0;
 
-			clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+			clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
 		}
 	}
 
@@ -969,7 +965,7 @@
 	unsigned long sl_offset, sl_start;
 	unsigned int chunk_size, chunk_offset = 0;
 	int ret = 0;
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	unsigned int pgprot4k, pgprot64k, pgprot1m, pgprot16m;
 
 	mutex_lock(&msm_iommu_lock);
@@ -977,7 +973,7 @@
 	BUG_ON(len & (SZ_4K - 1));
 
 	priv = domain->priv;
-	fl_table = priv->pgtable;
+	fl_table = priv->pt.fl_table;
 
 	pgprot4k = __get_pgprot(prot, SZ_4K);
 	pgprot64k = __get_pgprot(prot, SZ_64K);
@@ -1013,13 +1009,15 @@
 				ret = fl_16m(fl_pte, pa, pgprot16m);
 				if (ret)
 					goto fail;
-				clean_pte(fl_pte, fl_pte + 16, priv->redirect);
+				clean_pte(fl_pte, fl_pte + 16,
+					  priv->pt.redirect);
 				fl_pte += 16;
 			} else if (chunk_size == SZ_1M) {
 				ret = fl_1m(fl_pte, pa, pgprot1m);
 				if (ret)
 					goto fail;
-				clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+				clean_pte(fl_pte, fl_pte + 1,
+					  priv->pt.redirect);
 				fl_pte++;
 			}
 
@@ -1101,7 +1099,7 @@
 		}
 
 		clean_pte(sl_table + sl_start, sl_table + sl_offset,
-				priv->redirect);
+				priv->pt.redirect);
 
 		fl_pte++;
 		sl_offset = 0;
@@ -1123,14 +1121,14 @@
 	unsigned long *sl_table;
 	unsigned long sl_start, sl_end;
 	int used, i;
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 
 	mutex_lock(&msm_iommu_lock);
 
 	BUG_ON(len & (SZ_4K - 1));
 
 	priv = domain->priv;
-	fl_table = priv->pgtable;
+	fl_table = priv->pt.fl_table;
 
 	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
 	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
@@ -1146,7 +1144,7 @@
 
 			memset(sl_table + sl_start, 0, (sl_end - sl_start) * 4);
 			clean_pte(sl_table + sl_start, sl_table + sl_end,
-					priv->redirect);
+					priv->pt.redirect);
 
 			offset += (sl_end - sl_start) * SZ_4K;
 			va += (sl_end - sl_start) * SZ_4K;
@@ -1171,13 +1169,14 @@
 				free_page((unsigned long)sl_table);
 				*fl_pte = 0;
 
-				clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+				clean_pte(fl_pte, fl_pte + 1,
+					  priv->pt.redirect);
 			}
 
 			sl_start = 0;
 		} else {
 			*fl_pte = 0;
-			clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+			clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
 			va += SZ_1M;
 			offset += SZ_1M;
 			sl_start = 0;
@@ -1193,7 +1192,7 @@
 static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 					  unsigned long va)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	unsigned int par;
@@ -1339,8 +1338,8 @@
 
 static phys_addr_t msm_iommu_get_pt_base_addr(struct iommu_domain *domain)
 {
-	struct msm_priv *priv = domain->priv;
-	return __pa(priv->pgtable);
+	struct msm_iommu_priv *priv = domain->priv;
+	return __pa(priv->pt.fl_table);
 }
 
 static struct iommu_ops msm_iommu_ops = {
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 24d2854..f552474 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -30,6 +30,7 @@
 
 #include <mach/iommu_hw-v1.h>
 #include <mach/iommu.h>
+#include <mach/msm_iommu_priv.h>
 #include <mach/iommu_perfmon.h>
 #include "msm_iommu_pagetable.h"
 
@@ -38,11 +39,6 @@
 
 static DEFINE_MUTEX(msm_iommu_lock);
 
-struct msm_priv {
-	struct iommu_pt pt;
-	struct list_head list_attached;
-};
-
 static int __enable_regulators(struct msm_iommu_drvdata *drvdata)
 {
 	int ret = regulator_enable(drvdata->gdsc);
@@ -198,7 +194,7 @@
 
 static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
 {
-	struct msm_priv *priv = domain->priv;
+	struct msm_iommu_priv *priv = domain->priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret = 0;
@@ -226,7 +222,7 @@
 
 static int __flush_iotlb(struct iommu_domain *domain)
 {
-	struct msm_priv *priv = domain->priv;
+	struct msm_iommu_priv *priv = domain->priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret = 0;
@@ -335,7 +331,7 @@
 
 static void msm_iommu_assign_ASID(const struct msm_iommu_drvdata *iommu_drvdata,
 				  struct msm_iommu_ctx_drvdata *curr_ctx,
-				  struct msm_priv *priv)
+				  struct msm_iommu_priv *priv)
 {
 	unsigned int found = 0;
 	void __iomem *base = iommu_drvdata->base;
@@ -374,7 +370,7 @@
 
 static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
 			      struct msm_iommu_ctx_drvdata *ctx_drvdata,
-			      struct msm_priv *priv, bool is_secure)
+			      struct msm_iommu_priv *priv, bool is_secure)
 {
 	unsigned int prrr, nmrr;
 	unsigned int pn;
@@ -469,7 +465,7 @@
 
 static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -493,7 +489,7 @@
 
 static void msm_iommu_domain_destroy(struct iommu_domain *domain)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 
 	mutex_lock(&msm_iommu_lock);
 	priv = domain->priv;
@@ -508,7 +504,7 @@
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	struct msm_iommu_ctx_drvdata *tmp_drvdata;
@@ -596,7 +592,7 @@
 static void msm_iommu_detach_dev(struct iommu_domain *domain,
 				 struct device *dev)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret;
@@ -649,7 +645,7 @@
 static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
 			 phys_addr_t pa, size_t len, int prot)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	int ret = 0;
 
 	mutex_lock(&msm_iommu_lock);
@@ -673,7 +669,7 @@
 static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
 			    size_t len)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	int ret = -ENODEV;
 
 	mutex_lock(&msm_iommu_lock);
@@ -700,7 +696,7 @@
 			       int prot)
 {
 	int ret;
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 
 	mutex_lock(&msm_iommu_lock);
 
@@ -724,7 +720,7 @@
 static int msm_iommu_unmap_range(struct iommu_domain *domain, unsigned int va,
 				 unsigned int len)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 
 	mutex_lock(&msm_iommu_lock);
 
@@ -739,7 +735,7 @@
 static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 					  unsigned long va)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	unsigned int par;
@@ -876,7 +872,7 @@
 
 static phys_addr_t msm_iommu_get_pt_base_addr(struct iommu_domain *domain)
 {
-	struct msm_priv *priv = domain->priv;
+	struct msm_iommu_priv *priv = domain->priv;
 	return __pa(priv->pt.fl_table);
 }
 
diff --git a/drivers/iommu/msm_iommu_pagetable.c b/drivers/iommu/msm_iommu_pagetable.c
index b32bd26..b62bb76 100644
--- a/drivers/iommu/msm_iommu_pagetable.c
+++ b/drivers/iommu/msm_iommu_pagetable.c
@@ -20,6 +20,7 @@
 #include <asm/cacheflush.h>
 
 #include <mach/iommu.h>
+#include <mach/msm_iommu_priv.h>
 #include "msm_iommu_pagetable.h"
 
 /* Sharability attributes of MSM IOMMU mappings */
@@ -41,7 +42,7 @@
 		dmac_flush_range(start, end);
 }
 
-int msm_iommu_pagetable_alloc(struct iommu_pt *pt)
+int msm_iommu_pagetable_alloc(struct msm_iommu_pt *pt)
 {
 	pt->fl_table = (unsigned long *)__get_free_pages(GFP_KERNEL,
 							  get_order(SZ_16K));
@@ -54,7 +55,7 @@
 	return 0;
 }
 
-void msm_iommu_pagetable_free(struct iommu_pt *pt)
+void msm_iommu_pagetable_free(struct msm_iommu_pt *pt)
 {
 	unsigned long *fl_table;
 	int i;
@@ -110,7 +111,7 @@
 	return pgprot;
 }
 
-static unsigned long *make_second_level(struct iommu_pt *pt,
+static unsigned long *make_second_level(struct msm_iommu_pt *pt,
 					unsigned long *fl_pte)
 {
 	unsigned long *sl;
@@ -194,7 +195,7 @@
 	return ret;
 }
 
-int msm_iommu_pagetable_map(struct iommu_pt *pt, unsigned long va,
+int msm_iommu_pagetable_map(struct msm_iommu_pt *pt, unsigned long va,
 			phys_addr_t pa, size_t len, int prot)
 {
 	unsigned long *fl_pte;
@@ -279,7 +280,7 @@
 	return ret;
 }
 
-size_t msm_iommu_pagetable_unmap(struct iommu_pt *pt, unsigned long va,
+size_t msm_iommu_pagetable_unmap(struct msm_iommu_pt *pt, unsigned long va,
 				size_t len)
 {
 	unsigned long *fl_pte;
@@ -370,6 +371,55 @@
 	return pa;
 }
 
+static int check_range(unsigned long *fl_table, unsigned int va,
+				 unsigned int len)
+{
+	unsigned int offset = 0;
+	unsigned long *fl_pte;
+	unsigned long fl_offset;
+	unsigned long *sl_table;
+	unsigned long sl_start, sl_end;
+	int i;
+
+	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
+	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
+
+	while (offset < len) {
+		if (*fl_pte & FL_TYPE_TABLE) {
+			sl_start = SL_OFFSET(va);
+			sl_table =  __va(((*fl_pte) & FL_BASE_MASK));
+			sl_end = ((len - offset) / SZ_4K) + sl_start;
+
+			if (sl_end > NUM_SL_PTE)
+				sl_end = NUM_SL_PTE;
+
+			for (i = sl_start; i < sl_end; i++) {
+				if (sl_table[i] != 0) {
+					pr_err("%08x - %08x already mapped\n",
+						va, va + SZ_4K);
+					return -EBUSY;
+				}
+				offset += SZ_4K;
+				va += SZ_4K;
+			}
+
+
+			sl_start = 0;
+		} else {
+			if (*fl_pte != 0) {
+				pr_err("%08x - %08x already mapped\n",
+				       va, va + SZ_1M);
+				return -EBUSY;
+			}
+			va += SZ_1M;
+			offset += SZ_1M;
+			sl_start = 0;
+		}
+		fl_pte++;
+	}
+	return 0;
+}
+
 static inline int is_fully_aligned(unsigned int va, phys_addr_t pa, size_t len,
 				   int align)
 {
@@ -377,7 +427,7 @@
 		&& (len >= align);
 }
 
-int msm_iommu_pagetable_map_range(struct iommu_pt *pt, unsigned int va,
+int msm_iommu_pagetable_map_range(struct msm_iommu_pt *pt, unsigned int va,
 		       struct scatterlist *sg, unsigned int len, int prot)
 {
 	phys_addr_t pa;
@@ -405,6 +455,10 @@
 	fl_pte = pt->fl_table + fl_offset;	/* int pointers, 4 bytes */
 	pa = get_phys_addr(sg);
 
+	ret = check_range(pt->fl_table, va, len);
+	if (ret)
+		goto fail;
+
 	while (offset < len) {
 		chunk_size = SZ_4K;
 
@@ -518,7 +572,7 @@
 	return ret;
 }
 
-void msm_iommu_pagetable_unmap_range(struct iommu_pt *pt, unsigned int va,
+void msm_iommu_pagetable_unmap_range(struct msm_iommu_pt *pt, unsigned int va,
 				 unsigned int len)
 {
 	unsigned int offset = 0;
diff --git a/drivers/iommu/msm_iommu_pagetable.h b/drivers/iommu/msm_iommu_pagetable.h
index 3266681..7513aa5 100644
--- a/drivers/iommu/msm_iommu_pagetable.h
+++ b/drivers/iommu/msm_iommu_pagetable.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
@@ -71,20 +71,17 @@
 #define RCP15_PRRR(reg)   MRC(reg, p15, 0, c10, c2, 0)
 #define RCP15_NMRR(reg)   MRC(reg, p15, 0, c10, c2, 1)
 
-struct iommu_pt {
-	unsigned long *fl_table;
-	int redirect;
-};
+struct iommu_pt;
 
 void msm_iommu_pagetable_init(void);
-int msm_iommu_pagetable_alloc(struct iommu_pt *pt);
-void msm_iommu_pagetable_free(struct iommu_pt *pt);
-int msm_iommu_pagetable_map(struct iommu_pt *pt, unsigned long va,
+int msm_iommu_pagetable_alloc(struct msm_iommu_pt *pt);
+void msm_iommu_pagetable_free(struct msm_iommu_pt *pt);
+int msm_iommu_pagetable_map(struct msm_iommu_pt *pt, unsigned long va,
 			phys_addr_t pa, size_t len, int prot);
-size_t msm_iommu_pagetable_unmap(struct iommu_pt *pt, unsigned long va,
+size_t msm_iommu_pagetable_unmap(struct msm_iommu_pt *pt, unsigned long va,
 				size_t len);
-int msm_iommu_pagetable_map_range(struct iommu_pt *pt, unsigned int va,
+int msm_iommu_pagetable_map_range(struct msm_iommu_pt *pt, unsigned int va,
 			struct scatterlist *sg, unsigned int len, int prot);
-void msm_iommu_pagetable_unmap_range(struct iommu_pt *pt, unsigned int va,
+void msm_iommu_pagetable_unmap_range(struct msm_iommu_pt *pt, unsigned int va,
 				unsigned int len);
 #endif
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 44146a4..5ca6fd9 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -31,6 +31,7 @@
 
 #include <mach/iommu_perfmon.h>
 #include <mach/iommu_hw-v1.h>
+#include <mach/msm_iommu_priv.h>
 #include <mach/iommu.h>
 #include <mach/scm.h>
 
@@ -45,10 +46,6 @@
 
 static DEFINE_MUTEX(msm_iommu_lock);
 
-struct msm_priv {
-	struct list_head list_attached;
-};
-
 struct msm_scm_paddr_list {
 	unsigned int list;
 	unsigned int list_size;
@@ -298,7 +295,7 @@
 
 static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -311,7 +308,7 @@
 
 static void msm_iommu_domain_destroy(struct iommu_domain *domain)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 
 	mutex_lock(&msm_iommu_lock);
 	priv = domain->priv;
@@ -323,7 +320,7 @@
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-	struct msm_priv *priv;
+	struct msm_iommu_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	struct msm_iommu_ctx_drvdata *tmp_drvdata;
@@ -424,7 +421,7 @@
 			struct msm_iommu_drvdata **iommu_drvdata,
 			struct msm_iommu_ctx_drvdata **ctx_drvdata)
 {
-	struct msm_priv *priv = domain->priv;
+	struct msm_iommu_priv *priv = domain->priv;
 	struct msm_iommu_ctx_drvdata *ctx;
 
 	list_for_each_entry(ctx, &priv->list_attached, attached_elm) {
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 40e09b6..addd235 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -34,6 +34,17 @@
 		HFI_H264_PROFILE_CONSTRAINED_HIGH,
 };
 
+static int entropy_mode[] = {
+	[ilog2(HAL_H264_ENTROPY_CAVLC)] = HFI_H264_ENTROPY_CAVLC,
+	[ilog2(HAL_H264_ENTROPY_CABAC)] = HFI_H264_ENTROPY_CABAC,
+};
+
+static int cabac_model[] = {
+	[ilog2(HAL_H264_CABAC_MODEL_0)] = HFI_H264_CABAC_MODEL_0,
+	[ilog2(HAL_H264_CABAC_MODEL_1)] = HFI_H264_CABAC_MODEL_1,
+	[ilog2(HAL_H264_CABAC_MODEL_2)] = HFI_H264_CABAC_MODEL_2,
+};
+
 static inline int hal_to_hfi_type(int property, int hal_type)
 {
 	if (hal_type && (roundup_pow_of_two(hal_type) != hal_type)) {
@@ -49,6 +60,12 @@
 	case HAL_PARAM_PROFILE_LEVEL_CURRENT:
 		return (hal_type >= ARRAY_SIZE(profile_table)) ?
 			-ENOTSUPP : profile_table[hal_type];
+	case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
+		return (hal_type >= ARRAY_SIZE(entropy_mode)) ?
+			-ENOTSUPP : entropy_mode[hal_type];
+	case HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL:
+		return (hal_type >= ARRAY_SIZE(cabac_model)) ?
+			-ENOTSUPP : cabac_model[hal_type];
 	default:
 		return -ENOTSUPP;
 	}
@@ -918,35 +935,13 @@
 			HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
 		hfi = (struct hfi_h264_entropy_control *)
 			&pkt->rg_property_data[1];
-		switch (prop->entropy_mode) {
-		case HAL_H264_ENTROPY_CAVLC:
-			hfi->cabac_model = HFI_H264_ENTROPY_CAVLC;
-			break;
-		case HAL_H264_ENTROPY_CABAC:
-			hfi->cabac_model = HFI_H264_ENTROPY_CABAC;
-			switch (prop->cabac_model) {
-			case HAL_H264_CABAC_MODEL_0:
-				hfi->cabac_model = HFI_H264_CABAC_MODEL_0;
-				break;
-			case HAL_H264_CABAC_MODEL_1:
-				hfi->cabac_model = HFI_H264_CABAC_MODEL_1;
-				break;
-			case HAL_H264_CABAC_MODEL_2:
-				hfi->cabac_model = HFI_H264_CABAC_MODEL_2;
-				break;
-			default:
-				dprintk(VIDC_ERR,
-					"Invalid cabac model 0x%x",
-					prop->entropy_mode);
-				break;
-			}
-		break;
-		default:
-			dprintk(VIDC_ERR,
-				"Invalid entropy selected: 0x%x",
-				prop->cabac_model);
-			break;
-		}
+		hfi->entropy_mode = hal_to_hfi_type(
+		   HAL_PARAM_VENC_H264_ENTROPY_CONTROL,
+		   prop->entropy_mode);
+		if (hfi->entropy_mode == HAL_H264_ENTROPY_CABAC)
+			hfi->cabac_model = hal_to_hfi_type(
+			   HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,
+			   prop->cabac_model);
 		pkt->size += sizeof(u32) + sizeof(
 			struct hfi_h264_entropy_control);
 		break;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 8f8e723..2ca5008 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -241,7 +241,7 @@
 static u32 get_frame_size_compressed(int plane,
 					u32 height, u32 width)
 {
-	return (MAX_SUPPORTED_WIDTH * MAX_SUPPORTED_HEIGHT * 3/2)/2;
+	return (width * height * 3/2)/2;
 }
 
 struct msm_vidc_format vdec_formats[] = {
@@ -302,6 +302,14 @@
 		.type = OUTPUT_PORT,
 	},
 	{
+		.name = "HEVC",
+		.description = "HEVC compressed format",
+		.fourcc = V4L2_PIX_FMT_HEVC,
+		.num_planes = 1,
+		.get_frame_size = get_frame_size_compressed,
+		.type = OUTPUT_PORT,
+	},
+	{
 		.name = "VP8",
 		.description = "VP8 compressed format",
 		.fourcc = V4L2_PIX_FMT_VP8,
@@ -630,8 +638,8 @@
 			for (i = 0; i < fmt->num_planes; ++i) {
 				f->fmt.pix_mp.plane_fmt[i].sizeimage =
 					fmt->get_frame_size(i,
-						f->fmt.pix_mp.height,
-						f->fmt.pix_mp.width);
+						inst->capability.height.max,
+						inst->capability.width.max);
 				inst->bufq[OUTPUT_PORT].
 					vb2_bufq.plane_sizes[i] =
 					f->fmt.pix_mp.plane_fmt[i].sizeimage;
@@ -767,8 +775,8 @@
 			for (i = 0; i < fmt->num_planes; ++i) {
 				f->fmt.pix_mp.plane_fmt[i].sizeimage =
 					fmt->get_frame_size(i,
-						f->fmt.pix_mp.height,
-						f->fmt.pix_mp.width);
+						inst->capability.height.max,
+						inst->capability.width.max);
 			}
 		} else {
 			buff_req_buffer =
@@ -827,8 +835,8 @@
 		frame_sz.height = inst->prop.height;
 		msm_comm_try_set_prop(inst, HAL_PARAM_FRAME_SIZE, &frame_sz);
 		f->fmt.pix_mp.plane_fmt[0].sizeimage =
-			fmt->get_frame_size(0, f->fmt.pix_mp.height,
-					f->fmt.pix_mp.width);
+			fmt->get_frame_size(0, inst->capability.height.max,
+					inst->capability.width.max);
 		f->fmt.pix_mp.num_planes = fmt->num_planes;
 		for (i = 0; i < fmt->num_planes; ++i) {
 			inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[i] =
@@ -921,7 +929,8 @@
 			*num_buffers = MIN_NUM_OUTPUT_BUFFERS;
 		for (i = 0; i < *num_planes; i++) {
 			sizes[i] = inst->fmts[OUTPUT_PORT]->get_frame_size(
-					i, inst->prop.height, inst->prop.width);
+					i, inst->capability.height.max,
+					inst->capability.width.max);
 		}
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 9aa8175..bf29a95 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1040,6 +1040,26 @@
 		default:
 			goto unknown_value;
 		}
+	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+		switch (value) {
+		case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
+			return HAL_H264_ENTROPY_CAVLC;
+		case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
+			return HAL_H264_ENTROPY_CABAC;
+		default:
+			goto unknown_value;
+		}
+	case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
+		switch (value) {
+		case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0:
+			return HAL_H264_CABAC_MODEL_0;
+		case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1:
+			return HAL_H264_CABAC_MODEL_1;
+		case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_2:
+			return HAL_H264_CABAC_MODEL_2;
+		default:
+			goto unknown_value;
+		}
 	case V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL:
 		switch (value) {
 		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0:
@@ -1241,8 +1261,11 @@
 
 		property_id =
 			HAL_PARAM_VENC_H264_ENTROPY_CONTROL;
-		h264_entropy_control.entropy_mode = ctrl->val;
-		h264_entropy_control.cabac_model = temp_ctrl->val;
+		h264_entropy_control.entropy_mode = venc_v4l2_to_hal(
+			V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, ctrl->val);
+		h264_entropy_control.cabac_model = venc_v4l2_to_hal(
+			V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL,
+			temp_ctrl->val);
 		pdata = &h264_entropy_control;
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
@@ -1250,8 +1273,11 @@
 
 		property_id =
 			HAL_PARAM_VENC_H264_ENTROPY_CONTROL;
-		h264_entropy_control.cabac_model = ctrl->val;
-		h264_entropy_control.entropy_mode = temp_ctrl->val;
+		h264_entropy_control.cabac_model = venc_v4l2_to_hal(
+			V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, ctrl->val);
+		h264_entropy_control.entropy_mode = venc_v4l2_to_hal(
+			V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL,
+			temp_ctrl->val);
 		pdata = &h264_entropy_control;
 		break;
 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 4346a4e..30530d4 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -142,9 +142,10 @@
 	}
 	mutex_lock(&vidc_driver->lock);
 	list_for_each_entry(core, &vidc_driver->cores, list) {
-		if (core && core->id == core_id)
+		if (core && core->id == core_id) {
 			found = 1;
 			break;
+		}
 	}
 	mutex_unlock(&vidc_driver->lock);
 	if (found)
@@ -366,22 +367,27 @@
 	}
 }
 
+static void queue_v4l2_event(struct msm_vidc_inst *inst, int event_type)
+{
+	struct v4l2_event event = {.id = 0, .type = event_type};
+	v4l2_event_queue_fh(&inst->event_handler, &event);
+	wake_up(&inst->kernel_event_queue);
+}
+
 static void handle_event_change(enum command_response cmd, void *data)
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct v4l2_event dqevent;
 	struct v4l2_control control = {0};
 	struct msm_vidc_cb_event *event_notify;
+	int event = 0;
 	int rc = 0;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
-		dqevent.id = 0;
 		event_notify = (struct msm_vidc_cb_event *) response->data;
 		switch (event_notify->hal_event_type) {
 		case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
-			dqevent.type =
-				V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
+			event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
 			control.id =
 				V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
 			rc = v4l2_g_ctrl(&inst->ctrl_handler, &control);
@@ -389,24 +395,24 @@
 				dprintk(VIDC_WARN,
 					"Failed to get Smooth streamng flag\n");
 			if (!rc && control.value == true)
-				dqevent.type =
-					V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
+				event = V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
 			break;
 		case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
-			dqevent.type =
-				V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
+			event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
 			break;
 		default:
 			break;
 		}
+
 		inst->reconfig_height = event_notify->height;
 		inst->reconfig_width = event_notify->width;
 		inst->in_reconfig = true;
+
 		rc = msm_vidc_check_session_supported(inst);
 		if (!rc) {
-			v4l2_event_queue_fh(&inst->event_handler, &dqevent);
-			wake_up(&inst->kernel_event_queue);
+			queue_v4l2_event(inst, event);
 		}
+
 		return;
 	} else {
 		dprintk(VIDC_ERR,
@@ -496,13 +502,9 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct v4l2_event dqevent;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
-		dqevent.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
-		dqevent.id = 0;
-		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
-		wake_up(&inst->kernel_event_queue);
+		queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
 	} else {
 		dprintk(VIDC_ERR, "Failed to get valid response for flush\n");
 	}
@@ -512,7 +514,6 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst = NULL;
-	struct v4l2_event dqevent;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
 		if (inst) {
@@ -521,10 +522,7 @@
 			mutex_lock(&inst->sync_lock);
 			inst->state = MSM_VIDC_CORE_INVALID;
 			mutex_unlock(&inst->sync_lock);
-			dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
-			dqevent.id = 0;
-			v4l2_event_queue_fh(&inst->event_handler, &dqevent);
-			wake_up(&inst->kernel_event_queue);
+			queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
 		}
 	} else {
 		dprintk(VIDC_ERR,
@@ -536,7 +534,6 @@
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst = NULL ;
 	struct msm_vidc_core *core = NULL;
-	struct v4l2_event dqevent;
 	if (response) {
 		core = get_vidc_core(response->device_id);
 		dprintk(VIDC_WARN, "SYS_ERROR received for core %p\n", core);
@@ -544,18 +541,14 @@
 			mutex_lock(&core->lock);
 			core->state = VIDC_CORE_INVALID;
 			mutex_unlock(&core->lock);
-			dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
-			dqevent.id = 0;
 			list_for_each_entry(inst, &core->instances,
 					list) {
-				v4l2_event_queue_fh(&inst->event_handler,
-						&dqevent);
-
 				mutex_lock(&inst->lock);
 				inst->state = MSM_VIDC_CORE_INVALID;
 				mutex_unlock(&inst->lock);
 
-				wake_up(&inst->kernel_event_queue);
+				queue_v4l2_event(inst,
+						V4L2_EVENT_MSM_VIDC_SYS_ERROR);
 			}
 		} else {
 			dprintk(VIDC_ERR,
@@ -572,7 +565,6 @@
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
 	struct msm_vidc_core *core = NULL;
-	struct v4l2_event dqevent;
 	dprintk(VIDC_ERR, "Venus Subsystem crashed\n");
 	core = get_vidc_core(response->device_id);
 	if (!core) {
@@ -583,11 +575,9 @@
 	mutex_lock(&core->lock);
 	core->state = VIDC_CORE_INVALID;
 	mutex_unlock(&core->lock);
-	dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
-	dqevent.id = 0;
 	list_for_each_entry(inst, &core->instances, list) {
 		if (inst) {
-			v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+			queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
 			mutex_lock(&inst->lock);
 			inst->state = MSM_VIDC_CORE_INVALID;
 			inst->session = NULL;
@@ -600,15 +590,11 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct v4l2_event dqevent;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
-		dqevent.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
-		dqevent.id = 0;
-		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+		queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_CLOSE_DONE);
 		inst->session = NULL;
-		wake_up(&inst->kernel_event_queue);
 		show_stats(inst);
 	} else {
 		dprintk(VIDC_ERR,
@@ -1212,6 +1198,10 @@
 		  HAL_VIDEO_CODEC_SPARK
 		  HAL_VIDEO_CODEC_VP6
 		  HAL_VIDEO_CODEC_VP7*/
+	case V4L2_PIX_FMT_HEVC:
+		codec = HAL_VIDEO_CODEC_HEVC;
+		break;
+
 	default:
 		dprintk(VIDC_ERR, "Wrong codec: %d\n", fourcc);
 		codec = HAL_UNUSED_CODEC;
@@ -2144,7 +2134,6 @@
 
 static void msm_comm_flush_in_invalid_state(struct msm_vidc_inst *inst)
 {
-	struct v4l2_event dqevent = {0};
 	struct list_head *ptr, *next;
 	struct vb2_buffer *vb;
 	if (!list_empty(&inst->bufq[CAPTURE_PORT].
@@ -2181,9 +2170,7 @@
 			}
 		}
 	}
-	dqevent.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
-	dqevent.id = 0;
-	v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+	queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
 	return;
 }
 int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index 5948c7c..3208df9 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -210,8 +210,7 @@
 		"Output" : "Capture");
 		for (j = 0; j < inst->fmts[i]->num_planes; j++)
 			write_str(&dbg_buf, "size for plane %d: %u\n", j,
-			inst->fmts[i]->get_frame_size(j,
-			inst->prop.height, inst->prop.width));
+			inst->bufq[i].vb2_bufq.plane_sizes[j]);
 	}
 	write_str(&dbg_buf, "-------------------------------\n");
 	for (i = SESSION_MSG_START; i < SESSION_MSG_END; i++) {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 5ad0bb5..e20348d 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -165,6 +165,7 @@
 	HAL_PARAM_VENC_LOW_LATENCY,
 	HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER,
 	HAL_PARAM_VDEC_SYNC_FRAME_DECODE,
+	HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,
 };
 
 enum hal_domain {
@@ -189,6 +190,7 @@
 	HAL_VIDEO_CODEC_VP6      = 0x00000400,
 	HAL_VIDEO_CODEC_VP7      = 0x00000800,
 	HAL_VIDEO_CODEC_VP8      = 0x00001000,
+	HAL_VIDEO_CODEC_HEVC     = 0x00010000,
 	HAL_UNUSED_CODEC = 0x10000000,
 };
 
@@ -533,15 +535,15 @@
 };
 */
 enum hal_h264_entropy {
-	HAL_H264_ENTROPY_CAVLC,
-	HAL_H264_ENTROPY_CABAC,
+	HAL_H264_ENTROPY_CAVLC = 1,
+	HAL_H264_ENTROPY_CABAC = 2,
 	HAL_UNUSED_ENTROPY = 0x10000000,
 };
 
 enum hal_h264_cabac_model {
-	HAL_H264_CABAC_MODEL_0,
-	HAL_H264_CABAC_MODEL_1,
-	HAL_H264_CABAC_MODEL_2,
+	HAL_H264_CABAC_MODEL_0 = 1,
+	HAL_H264_CABAC_MODEL_1 = 2,
+	HAL_H264_CABAC_MODEL_2 = 4,
 	HAL_UNUSED_CABAC = 0x10000000,
 };
 
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 01c5e0b..baf7bc4 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -76,9 +76,10 @@
 #define HFI_VIDEO_CODEC_MPEG4				0x00000020
 #define HFI_VIDEO_CODEC_DIVX_311			0x00000040
 #define HFI_VIDEO_CODEC_DIVX				0x00000080
-#define HFI_VIDEO_CODEC_VC1					0x00000100
+#define HFI_VIDEO_CODEC_VC1				0x00000100
 #define HFI_VIDEO_CODEC_SPARK				0x00000200
-#define HFI_VIDEO_CODEC_VP8					0x00001000
+#define HFI_VIDEO_CODEC_VP8				0x00001000
+#define HFI_VIDEO_CODEC_HEVC				0x00010000
 
 #define HFI_H264_PROFILE_BASELINE			0x00000001
 #define HFI_H264_PROFILE_MAIN				0x00000002
diff --git a/drivers/media/platform/msm/wfd/enc-subdev.h b/drivers/media/platform/msm/wfd/enc-subdev.h
index 8bfb884..a1469cd 100644
--- a/drivers/media/platform/msm/wfd/enc-subdev.h
+++ b/drivers/media/platform/msm/wfd/enc-subdev.h
@@ -25,6 +25,10 @@
 	VENC_MODE_VFR,
 };
 
+enum venc_event {
+	VENC_EVENT_HARDWARE_ERROR,
+};
+
 struct mem_region {
 	struct list_head list;
 	u8 *kvaddr;
@@ -64,6 +68,7 @@
 			struct vb2_buffer *buf);
 	void (*ip_buffer_done)(void *cookie, u32 status,
 			struct mem_region *mregion);
+	void (*on_event)(void *cookie, enum venc_event e);
 };
 
 static inline bool mem_region_equals(struct mem_region *a,
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 40362f0..9ebf763 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -48,6 +48,12 @@
 	bool secure;
 };
 
+static const int subscribed_events[] = {
+	V4L2_EVENT_MSM_VIDC_CLOSE_DONE,
+	V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
+	V4L2_EVENT_MSM_VIDC_SYS_ERROR,
+};
+
 int venc_load_fw(struct v4l2_subdev *sd)
 {
 	/*No need to explicitly load the fw */
@@ -134,13 +140,21 @@
 			bool bail_out = false;
 
 			msm_vidc_dqevent(inst->vidc_context, &event);
-			if (event.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE) {
+
+			switch (event.type) {
+			case V4L2_EVENT_MSM_VIDC_CLOSE_DONE:
 				WFD_MSG_DBG("enc callback thread shutting " \
 						"down normally\n");
 				bail_out = true;
-			} else {
-				WFD_MSG_ERR("Got unknown event %d, ignoring\n",
-						event.id);
+				break;
+			case V4L2_EVENT_MSM_VIDC_SYS_ERROR:
+				inst->vmops.on_event(inst->vmops.cbdata,
+						VENC_EVENT_HARDWARE_ERROR);
+				bail_out = true;
+				break;
+			default:
+				WFD_MSG_INFO("Got unknown event %d, ignoring\n",
+						event.type);
 			}
 
 			complete_all(&inst->cmd_complete);
@@ -251,11 +265,43 @@
 	return msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
 }
 
+static int subscribe_events(struct venc_inst *inst)
+{
+	struct v4l2_event_subscription event = {0};
+	int c = 0, rc = 0;
+
+	for (c = 0; c < ARRAY_SIZE(subscribed_events); c++) {
+		event.type = subscribed_events[c];
+		rc = msm_vidc_subscribe_event(inst->vidc_context, &event);
+		if (rc) {
+			WFD_MSG_ERR("Failed to subscribe to event 0x%x\n",
+					subscribed_events[c]);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static void unsubscribe_events(struct venc_inst *inst)
+{
+	struct v4l2_event_subscription event = {0};
+	int c = 0, rc = 0;
+	for (c = 0; c < ARRAY_SIZE(subscribed_events); c++) {
+		event.type = subscribed_events[c];
+		rc = msm_vidc_unsubscribe_event(inst->vidc_context, &event);
+		if (rc) {
+			/* Just log and ignore failiures */
+			WFD_MSG_WARN("Failed to unsubscribe to event 0x%x\n",
+					subscribed_events[c]);
+		}
+	}
+}
+
 static long venc_open(struct v4l2_subdev *sd, void *arg)
 {
 	struct venc_inst *inst = NULL;
 	struct venc_msg_ops *vmops = arg;
-	struct v4l2_event_subscription event = {0};
 	int rc = 0;
 
 	if (!vmops) {
@@ -289,17 +335,9 @@
 		goto vidc_open_fail;
 	}
 
-	event.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
-	rc = msm_vidc_subscribe_event(inst->vidc_context, &event);
+	rc = subscribe_events(inst);
 	if (rc) {
-		WFD_MSG_ERR("Failed to subscribe to CLOSE_DONE event\n");
-		goto vidc_subscribe_fail;
-	}
-
-	event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
-	rc = msm_vidc_subscribe_event(inst->vidc_context, &event);
-	if (rc) {
-		WFD_MSG_ERR("Failed to subscribe to FLUSH_DONE event\n");
+		WFD_MSG_ERR("Failed to subscribe to events\n");
 		goto vidc_subscribe_fail;
 	}
 
@@ -317,11 +355,7 @@
 	vmops->cookie = inst;
 	return 0;
 vidc_kthread_create_fail:
-	event.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
-	msm_vidc_unsubscribe_event(inst->vidc_context, &event);
-
-	event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
-	msm_vidc_unsubscribe_event(inst->vidc_context, &event);
+	unsubscribe_events(inst);
 vidc_subscribe_fail:
 	msm_vidc_close(inst->vidc_context);
 vidc_open_fail:
@@ -333,7 +367,6 @@
 static long venc_close(struct v4l2_subdev *sd, void *arg)
 {
 	struct venc_inst *inst = NULL;
-	struct v4l2_event_subscription event = {0};
 	struct v4l2_encoder_cmd enc_cmd = {0};
 	int rc = 0;
 
@@ -352,15 +385,7 @@
 	if (inst->callback_thread && inst->callback_thread_running)
 		kthread_stop(inst->callback_thread);
 
-	event.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
-	rc = msm_vidc_unsubscribe_event(inst->vidc_context, &event);
-	if (rc)
-		WFD_MSG_WARN("Failed to unsubscribe close event\n");
-
-	event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
-	rc = msm_vidc_unsubscribe_event(inst->vidc_context, &event);
-	if (rc)
-		WFD_MSG_WARN("Failed to unsubscribe flush event\n");
+	unsubscribe_events(inst);
 
 	rc = msm_vidc_close(inst->vidc_context);
 	if (rc)
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 102b9b9..72b02bb 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -25,8 +25,9 @@
 #include <mach/board.h>
 
 #include <media/v4l2-dev.h>
-#include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
 #include <media/v4l2-subdev.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-msm-mem.h>
@@ -42,6 +43,7 @@
 #define DEFAULT_WFD_WIDTH 1280
 #define DEFAULT_WFD_HEIGHT 720
 #define VENC_INPUT_BUFFERS 4
+#define MAX_EVENTS 16
 
 struct wfd_device {
 	struct mutex dev_lock;
@@ -92,12 +94,18 @@
 	struct list_head input_mem_list;
 	struct wfd_stats stats;
 	struct completion stop_mdp_thread;
+	struct v4l2_fh event_handler;
 };
 
 struct wfd_vid_buffer {
 	struct vb2_buffer    vidbuf;
 };
 
+static inline struct wfd_inst *file_to_inst(struct file *filp)
+{
+	return container_of(filp->private_data, struct wfd_inst, event_handler);
+}
+
 static int wfd_vidbuf_queue_setup(struct vb2_queue *q,
 				   const struct v4l2_format *fmt,
 				   unsigned int *num_buffers,
@@ -105,7 +113,7 @@
 				   unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct file *priv_data = (struct file *)(q->drv_priv);
-	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct wfd_inst *inst = file_to_inst(priv_data);
 	unsigned long flags;
 	int i;
 
@@ -124,10 +132,11 @@
 	return 0;
 }
 
-void wfd_vidbuf_wait_prepare(struct vb2_queue *q)
+static void wfd_vidbuf_wait_prepare(struct vb2_queue *q)
 {
 }
-void wfd_vidbuf_wait_finish(struct vb2_queue *q)
+
+static void wfd_vidbuf_wait_finish(struct vb2_queue *q)
 {
 }
 
@@ -236,7 +245,8 @@
 			ION_IOC_INV_CACHES);
 
 }
-int wfd_allocate_input_buffers(struct wfd_device *wfd_dev,
+
+static int wfd_allocate_input_buffers(struct wfd_device *wfd_dev,
 			struct wfd_inst *inst)
 {
 	int i;
@@ -389,7 +399,8 @@
 recon_alloc_fail:
 	return rc;
 }
-void wfd_free_input_buffers(struct wfd_device *wfd_dev,
+
+static void wfd_free_input_buffers(struct wfd_device *wfd_dev,
 			struct wfd_inst *inst)
 {
 	struct list_head *ptr, *next;
@@ -450,7 +461,7 @@
 		WFD_MSG_ERR("Failed to free recon buffers\n");
 }
 
-struct mem_info *wfd_get_mem_info(struct wfd_inst *inst,
+static struct mem_info *wfd_get_mem_info(struct wfd_inst *inst,
 			unsigned long userptr)
 {
 	struct mem_info_entry *temp;
@@ -468,7 +479,8 @@
 	spin_unlock_irqrestore(&inst->inst_lock, flags);
 	return ret;
 }
-void wfd_put_mem_info(struct wfd_inst *inst,
+
+static void wfd_put_mem_info(struct wfd_inst *inst,
 			struct mem_info *minfo)
 {
 	struct list_head *ptr, *next;
@@ -497,12 +509,13 @@
 	}
 	wfd_put_mem_info(inst, minfo);
 }
-int wfd_vidbuf_buf_init(struct vb2_buffer *vb)
+
+static int wfd_vidbuf_buf_init(struct vb2_buffer *vb)
 {
 	int rc = 0;
 	struct vb2_queue *q = vb->vb2_queue;
 	struct file *priv_data = (struct file *)(q->drv_priv);
-	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct wfd_inst *inst = file_to_inst(priv_data);
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(priv_data);
 	struct mem_info *minfo = vb2_plane_cookie(vb, 0);
@@ -532,24 +545,24 @@
 	return rc;
 }
 
-int wfd_vidbuf_buf_prepare(struct vb2_buffer *vb)
+static int wfd_vidbuf_buf_prepare(struct vb2_buffer *vb)
 {
 	return 0;
 }
 
-int wfd_vidbuf_buf_finish(struct vb2_buffer *vb)
+static int wfd_vidbuf_buf_finish(struct vb2_buffer *vb)
 {
 	return 0;
 }
 
-void wfd_vidbuf_buf_cleanup(struct vb2_buffer *vb)
+static void wfd_vidbuf_buf_cleanup(struct vb2_buffer *vb)
 {
 	int rc = 0;
 	struct vb2_queue *q = vb->vb2_queue;
 	struct file *priv_data = (struct file *)(q->drv_priv);
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(priv_data);
-	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct wfd_inst *inst = file_to_inst(priv_data);
 	struct mem_info *minfo = vb2_plane_cookie(vb, 0);
 	struct mem_region mregion;
 
@@ -574,7 +587,7 @@
 {
 	int rc = 0, no_sig_wait = 0;
 	struct file *filp = (struct file *)data;
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(filp);
 	struct mdp_buf_info obuf_mdp = {inst->mdp_inst, 0, 0, 0};
@@ -633,12 +646,12 @@
 	return rc;
 }
 
-int wfd_vidbuf_start_streaming(struct vb2_queue *q, unsigned int count)
+static int wfd_vidbuf_start_streaming(struct vb2_queue *q, unsigned int count)
 {
 	struct file *priv_data = (struct file *)(q->drv_priv);
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(priv_data);
-	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct wfd_inst *inst = file_to_inst(priv_data);
 	int rc = 0;
 
 	WFD_MSG_ERR("Stream on called\n");
@@ -657,6 +670,7 @@
 		WFD_MSG_ERR("Failed to start vsg\n");
 		goto subdev_start_fail;
 	}
+
 	init_completion(&inst->stop_mdp_thread);
 	inst->mdp_task = kthread_run(mdp_output_thread, priv_data,
 				"mdp_output_thread");
@@ -673,12 +687,12 @@
 	return rc;
 }
 
-int wfd_vidbuf_stop_streaming(struct vb2_queue *q)
+static int wfd_vidbuf_stop_streaming(struct vb2_queue *q)
 {
 	struct file *priv_data = (struct file *)(q->drv_priv);
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(priv_data);
-	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct wfd_inst *inst = file_to_inst(priv_data);
 	int rc = 0;
 	WFD_MSG_DBG("mdp stop\n");
 	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
@@ -707,14 +721,14 @@
 	return rc;
 }
 
-void wfd_vidbuf_buf_queue(struct vb2_buffer *vb)
+static void wfd_vidbuf_buf_queue(struct vb2_buffer *vb)
 {
 	int rc = 0;
 	struct vb2_queue *q = vb->vb2_queue;
 	struct file *priv_data = (struct file *)(q->drv_priv);
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(priv_data);
-	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct wfd_inst *inst = file_to_inst(priv_data);
 	struct mem_region mregion;
 	struct mem_info *minfo = vb2_plane_cookie(vb, 0);
 	mregion.fd = minfo->fd;
@@ -787,7 +801,7 @@
 static int wfdioc_g_fmt(struct file *filp, void *fh,
 			struct v4l2_format *fmt)
 {
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	unsigned long flags;
 	if (!fmt) {
 		WFD_MSG_ERR("Invalid argument\n");
@@ -811,7 +825,7 @@
 			struct v4l2_format *fmt)
 {
 	int rc = 0;
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	struct wfd_device *wfd_dev = video_drvdata(filp);
 	struct mdp_prop prop;
 	unsigned long flags;
@@ -862,7 +876,7 @@
 static int wfdioc_reqbufs(struct file *filp, void *fh,
 		struct v4l2_requestbuffers *b)
 {
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	struct wfd_device *wfd_dev = video_drvdata(filp);
 	unsigned long flags;
 	int rc = 0;
@@ -918,7 +932,7 @@
 		struct v4l2_buffer *b)
 {
 	int rc = 0;
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	if (!inst || !b ||
 			(b->index < 0 || b->index >= inst->buf_count)) {
 		WFD_MSG_ERR("Invalid input parameters to QBUF IOCTL\n");
@@ -943,7 +957,7 @@
 		enum v4l2_buf_type i)
 {
 	int rc = 0;
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	unsigned long flags;
 	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		WFD_MSG_ERR("stream on for buffer type = %d is not "
@@ -969,7 +983,7 @@
 static int wfdioc_streamoff(struct file *filp, void *fh,
 		enum v4l2_buf_type i)
 {
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	unsigned long flags;
 
 	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
@@ -993,7 +1007,7 @@
 static int wfdioc_dqbuf(struct file *filp, void *fh,
 		struct v4l2_buffer *b)
 {
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	int rc;
 
 	WFD_MSG_DBG("Waiting to dequeue buffer\n");
@@ -1057,7 +1071,7 @@
 {
 	int rc = 0;
 	struct wfd_device *wfd_dev = video_drvdata(filp);
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	int64_t frame_interval = 0,
 		max_frame_interval = 0; /* both in nsecs*/
 	struct v4l2_qcom_frameskip frameskip, *usr_frameskip;
@@ -1112,7 +1126,7 @@
 {
 	int rc = 0;
 	struct wfd_device *wfd_dev = video_drvdata(filp);
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	struct v4l2_qcom_frameskip frameskip;
 	int64_t frame_interval, max_frame_interval;
 	void *extendedmode = NULL;
@@ -1200,6 +1214,22 @@
 	return rc;
 }
 
+static int wfdioc_subscribe_event(struct v4l2_fh *fh,
+		struct v4l2_event_subscription *sub)
+{
+	struct wfd_inst *inst = container_of(fh, struct wfd_inst,
+			event_handler);
+	return v4l2_event_subscribe(&inst->event_handler, sub, MAX_EVENTS);
+}
+
+static int wfdioc_unsubscribe_event(struct v4l2_fh *fh,
+		struct v4l2_event_subscription *sub)
+{
+	struct wfd_inst *inst = container_of(fh, struct wfd_inst,
+			event_handler);
+	return v4l2_event_unsubscribe(&inst->event_handler, sub);
+}
+
 static const struct v4l2_ioctl_ops g_wfd_ioctl_ops = {
 	.vidioc_querycap = wfdioc_querycap,
 	.vidioc_s_fmt_vid_cap = wfdioc_s_fmt,
@@ -1213,13 +1243,16 @@
 	.vidioc_s_ctrl = wfdioc_s_ctrl,
 	.vidioc_g_parm = wfdioc_g_parm,
 	.vidioc_s_parm = wfdioc_s_parm,
+	.vidioc_subscribe_event = wfdioc_subscribe_event,
+	.vidioc_unsubscribe_event = wfdioc_unsubscribe_event,
+
 };
 static int wfd_set_default_properties(struct file *filp)
 {
 	unsigned long flags;
 	struct v4l2_format fmt;
 	struct v4l2_control ctrl;
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	if (!inst) {
 		WFD_MSG_ERR("Invalid argument\n");
 		return -EINVAL;
@@ -1249,7 +1282,7 @@
 			struct mem_region *mregion)
 {
 	struct file *filp = cookie;
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	struct vsg_buf_info buf;
 	struct mdp_buf_info mdp_buf = {0};
 	struct wfd_device *wfd_dev =
@@ -1273,10 +1306,33 @@
 
 }
 
+static void venc_on_event(void *cookie, enum venc_event e)
+{
+	struct file *filp = cookie;
+	struct wfd_inst *inst = file_to_inst(filp);
+	struct v4l2_event event;
+	int type = 0;
+
+	switch (e) {
+	case VENC_EVENT_HARDWARE_ERROR:
+		type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
+		break;
+	default:
+		/* Whatever~~ */
+		break;
+	}
+
+	if (type) {
+		event.id = 0;
+		event.type = type;
+		v4l2_event_queue_fh(&inst->event_handler, &event);
+	}
+}
+
 static int vsg_release_input_frame(void *cookie, struct vsg_buf_info *buf)
 {
 	struct file *filp = cookie;
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(filp);
 	int rc = 0;
@@ -1296,7 +1352,7 @@
 static int vsg_encode_frame(void *cookie, struct vsg_buf_info *buf)
 {
 	struct file *filp = cookie;
-	struct wfd_inst *inst = filp->private_data;
+	struct wfd_inst *inst = file_to_inst(filp);
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(filp);
 	struct venc_buf_info venc_buf;
@@ -1389,11 +1445,15 @@
 		rc = -ENOMEM;
 		goto err_mdp_open;
 	}
-	filp->private_data = inst;
+	filp->private_data = &inst->event_handler;
 	spin_lock_init(&inst->inst_lock);
 	INIT_LIST_HEAD(&inst->input_mem_list);
 	INIT_LIST_HEAD(&inst->minfo_list);
 
+	/* Set up userspace event handlers */
+	v4l2_fh_init(&inst->event_handler, wfd_dev->pvdev);
+	v4l2_fh_add(&inst->event_handler);
+
 	wfd_stats_init(&inst->stats, MINOR(filp->f_dentry->d_inode->i_rdev));
 
 	mdp_mops.secure = wfd_dev->secure;
@@ -1411,8 +1471,10 @@
 		WFD_MSG_ERR("Failed to load video encoder firmware: %d\n", rc);
 		goto err_venc;
 	}
+
 	enc_mops.op_buffer_done = venc_op_buffer_done;
 	enc_mops.ip_buffer_done = venc_ip_buffer_done;
+	enc_mops.on_event = venc_on_event;
 	enc_mops.cbdata = filp;
 	enc_mops.secure = wfd_dev->secure;
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, OPEN,
@@ -1444,9 +1506,12 @@
 	v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
 				MDP_CLOSE, (void *)inst->mdp_inst);
 err_mdp_open:
+	v4l2_fh_del(&inst->event_handler);
+
 	mutex_lock(&wfd_dev->dev_lock);
 	wfd_dev->in_use = false;
 	mutex_unlock(&wfd_dev->dev_lock);
+
 	kfree(inst);
 err_dev_busy:
 	return rc;
@@ -1459,7 +1524,7 @@
 	int rc = 0;
 	wfd_dev = video_drvdata(filp);
 	WFD_MSG_DBG("wfd_close: E\n");
-	inst = filp->private_data;
+	inst = file_to_inst(filp);
 	if (inst) {
 		wfdioc_streamoff(filp, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 		vb2_queue_release(&inst->vid_bufq);
@@ -1484,6 +1549,8 @@
 		kfree(inst);
 	}
 
+	v4l2_fh_del(&inst->event_handler);
+
 	mutex_lock(&wfd_dev->dev_lock);
 	wfd_dev->in_use = false;
 	mutex_unlock(&wfd_dev->dev_lock);
@@ -1491,12 +1558,28 @@
 	WFD_MSG_DBG("wfd_close: X\n");
 	return 0;
 }
+
+unsigned int wfd_poll(struct file *filp, struct poll_table_struct *pt)
+{
+	struct wfd_inst *inst = file_to_inst(filp);
+	unsigned int flags = 0;
+
+	poll_wait(filp, &inst->event_handler.wait, pt);
+
+	if (v4l2_event_pending(&inst->event_handler))
+		flags |= POLLPRI;
+
+	return flags;
+}
+
 static const struct v4l2_file_operations g_wfd_fops = {
 	.owner = THIS_MODULE,
 	.open = wfd_open,
 	.release = wfd_close,
-	.ioctl = video_ioctl2
+	.ioctl = video_ioctl2,
+	.poll = wfd_poll,
 };
+
 void release_video_device(struct video_device *pvdev)
 {
 
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 9e22ffb..77a412f 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -57,7 +57,6 @@
 #define QSEOS_CHECK_VERSION_CMD		0x00001803
 
 #define QSEE_CE_CLK_100MHZ		100000000
-#define QSEE_CE_CLK_50MHZ		50000000
 
 #define QSEECOM_MAX_SG_ENTRY	512
 
@@ -1387,6 +1386,14 @@
 	}
 	/* Populate the remaining parameters */
 	load_req.qsee_cmd_id = QSEOS_LOAD_SERV_IMAGE_COMMAND;
+	/* Vote for the SFPB clock */
+	ret = qsee_vote_for_clock(data, CLK_SFPB);
+	if (ret) {
+		pr_err("Unable to vote for SFPB clock: ret = %d", ret);
+		kzfree(img_data);
+		return -EIO;
+	}
+
 	/* SCM_CALL to load the image */
 	ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
 				sizeof(struct qseecom_load_lib_image_ireq),
@@ -1417,6 +1424,7 @@
 		}
 	}
 	kzfree(img_data);
+	qsee_disable_clock_vote(data, CLK_SFPB);
 	return ret;
 }
 
@@ -1746,6 +1754,50 @@
 	return 0;
 }
 
+static int __qseecom_enable_clk(void)
+{
+	int rc = 0;
+
+	/* Enable CE core clk */
+	rc = clk_prepare_enable(ce_core_clk);
+	if (rc) {
+		pr_err("Unable to enable/prepare CE core clk\n");
+		goto err;
+	} else {
+		/* Enable CE clk */
+		rc = clk_prepare_enable(ce_clk);
+		if (rc) {
+			pr_err("Unable to enable/prepare CE iface clk\n");
+			goto ce_clk_err;
+		} else {
+			/* Enable AXI clk */
+			rc = clk_prepare_enable(ce_bus_clk);
+			if (rc) {
+				pr_err("Unable to enable/prepare CE bus clk\n");
+				goto ce_bus_clk_err;
+			}
+		}
+	}
+	return 0;
+
+ce_bus_clk_err:
+	clk_disable_unprepare(ce_clk);
+ce_clk_err:
+	clk_disable_unprepare(ce_core_clk);
+err:
+	return -EIO;
+}
+
+static void __qseecom_disable_clk(void)
+{
+	if (ce_clk != NULL)
+		clk_disable_unprepare(ce_clk);
+	if (ce_core_clk != NULL)
+		clk_disable_unprepare(ce_core_clk);
+	if (ce_bus_clk != NULL)
+		clk_disable_unprepare(ce_bus_clk);
+}
+
 static int qsee_vote_for_clock(struct qseecom_dev_handle *data,
 						int32_t clk_type)
 {
@@ -1763,10 +1815,14 @@
 						qsee_perf_client, 3);
 			else {
 				if (ce_core_src_clk != NULL)
-					clk_set_rate(ce_core_src_clk,
-							QSEE_CE_CLK_100MHZ);
-				ret = msm_bus_scale_client_update_request(
+					ret = __qseecom_enable_clk();
+				if (!ret) {
+					ret =
+					msm_bus_scale_client_update_request(
 						qsee_perf_client, 1);
+					if ((ret) && (ce_core_src_clk != NULL))
+						__qseecom_disable_clk();
+				}
 			}
 			if (ret)
 				pr_err("DFAB Bandwidth req failed (%d)\n",
@@ -1789,10 +1845,14 @@
 						qsee_perf_client, 3);
 			else {
 				if (ce_core_src_clk != NULL)
-					clk_set_rate(ce_core_src_clk,
-							QSEE_CE_CLK_100MHZ);
-				ret = msm_bus_scale_client_update_request(
+					ret = __qseecom_enable_clk();
+				if (!ret) {
+					ret =
+					msm_bus_scale_client_update_request(
 						qsee_perf_client, 2);
+					if ((ret) && (ce_core_src_clk != NULL))
+						__qseecom_disable_clk();
+				}
 			}
 
 			if (ret)
@@ -1839,9 +1899,8 @@
 			else {
 				ret = msm_bus_scale_client_update_request(
 						qsee_perf_client, 0);
-				if (ce_core_src_clk != NULL)
-					clk_set_rate(ce_core_src_clk,
-							QSEE_CE_CLK_50MHZ);
+				if ((!ret) && (ce_core_src_clk != NULL))
+					__qseecom_disable_clk();
 			}
 			if (ret)
 				pr_err("SFPB Bandwidth req fail (%d)\n",
@@ -1870,9 +1929,8 @@
 			else {
 				ret = msm_bus_scale_client_update_request(
 						qsee_perf_client, 0);
-				if (ce_core_src_clk != NULL)
-					clk_set_rate(ce_core_src_clk,
-							QSEE_CE_CLK_50MHZ);
+				if ((!ret) && (ce_core_src_clk != NULL))
+					__qseecom_disable_clk();
 			}
 			if (ret)
 				pr_err("SFPB Bandwidth req fail (%d)\n",
@@ -1941,6 +1999,13 @@
 		ret = -EFAULT;
 		goto qseecom_load_external_elf_set_cpu_err;
 	}
+	/* Vote for the SFPB clock */
+	ret = qsee_vote_for_clock(data, CLK_SFPB);
+	if (ret) {
+		pr_err("Unable to vote for SFPB clock: ret = %d", ret);
+		ret = -EIO;
+		goto qseecom_load_external_elf_set_cpu_err;
+	}
 
 	/*  SCM_CALL to load the external elf */
 	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,  &load_req,
@@ -1980,7 +2045,7 @@
 	/* Deallocate the handle */
 	if (!IS_ERR_OR_NULL(ihandle))
 		ion_free(qseecom.ion_clnt, ihandle);
-
+	qsee_disable_clock_vote(data, CLK_SFPB);
 	return ret;
 }
 
@@ -2350,46 +2415,6 @@
 		.release = qseecom_release
 };
 
-static int __qseecom_enable_clk(void)
-{
-	int rc = 0;
-
-	/* Enable CE core clk */
-	rc = clk_prepare_enable(ce_core_clk);
-	if (rc) {
-		pr_err("Unable to enable/prepare CE core clk\n");
-		return -EIO;
-	} else {
-		/* Enable CE clk */
-		rc = clk_prepare_enable(ce_clk);
-		if (rc) {
-			pr_err("Unable to enable/prepare CE iface clk\n");
-			clk_disable_unprepare(ce_core_clk);
-			return -EIO;
-		} else {
-			/* Enable AXI clk */
-			rc = clk_prepare_enable(ce_bus_clk);
-			if (rc) {
-				pr_err("Unable to enable/prepare CE iface clk\n");
-				clk_disable_unprepare(ce_core_clk);
-				clk_disable_unprepare(ce_clk);
-				return -EIO;
-			}
-		}
-	}
-	return rc;
-}
-
-static void __qseecom_disable_clk(void)
-{
-	if (ce_clk != NULL)
-		clk_disable_unprepare(ce_clk);
-	if (ce_core_clk != NULL)
-		clk_disable_unprepare(ce_core_clk);
-	if (ce_bus_clk != NULL)
-		clk_disable_unprepare(ce_bus_clk);
-}
-
 static int __qseecom_init_clk(void)
 {
 	int rc = 0;
@@ -2399,8 +2424,8 @@
 	/* Get CE3 src core clk. */
 	ce_core_src_clk = clk_get(pdev, "core_clk_src");
 	if (!IS_ERR(ce_core_src_clk)) {
-		/* Set the core src clk @50Mhz */
-		rc = clk_set_rate(ce_core_src_clk, QSEE_CE_CLK_50MHZ);
+		/* Set the core src clk @100Mhz */
+		rc = clk_set_rate(ce_core_src_clk, QSEE_CE_CLK_100MHZ);
 		if (rc) {
 			clk_put(ce_core_src_clk);
 			pr_err("Unable to set the core src clk @100Mhz.\n");
@@ -2561,11 +2586,7 @@
 		ret = __qseecom_init_clk();
 		if (ret)
 			goto err;
-		ret = __qseecom_enable_clk();
-		if (ret) {
-			__qseecom_deinit_clk();
-			goto err;
-		}
+
 		qseecom_platform_support = (struct msm_bus_scale_pdata *)
 						msm_bus_cl_get_pdata(pdev);
 		if (qseecom.qsee_version >= (QSEE_VERSION_02)) {
@@ -2675,10 +2696,9 @@
 	if (qsee_perf_client)
 		msm_bus_scale_client_update_request(qsee_perf_client, 0);
 	/* register client for bus scaling */
-	if (pdev->dev.of_node) {
-		__qseecom_disable_clk();
+	if (pdev->dev.of_node)
 		__qseecom_deinit_clk();
-	}
+
 	return ret;
 };
 
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index 0227ee4..eeb98e9 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -43,6 +43,7 @@
 	struct sps_mem_buffer desc_mem_buf;
 	struct sps_register_event register_event;
 	struct list_head free_desc_list;
+	bool valid;
 };
 
 struct ipa_bridge_context {
@@ -465,6 +466,7 @@
 	}
 
 	*clnt_hdl = ipa_ep_idx;
+	sys->valid = true;
 
 	return 0;
 
@@ -620,6 +622,8 @@
 		}
 	}
 
+	sys->valid = true;
+
 	return 0;
 
 event_reg_failed:
@@ -809,12 +813,15 @@
 
 	for (; lo <= hi; lo++) {
 		sys = &bridge[type].pipe[lo];
-		sps_disconnect(sys->pipe);
-		dma_free_coherent(NULL, sys->desc_mem_buf.size,
-				  sys->desc_mem_buf.base,
-				  sys->desc_mem_buf.phys_base);
-		sps_free_endpoint(sys->pipe);
-		ipa_bridge_free_resources(sys);
+		if (sys->valid) {
+			sps_disconnect(sys->pipe);
+			dma_free_coherent(NULL, sys->desc_mem_buf.size,
+					  sys->desc_mem_buf.base,
+					  sys->desc_mem_buf.phys_base);
+			sps_free_endpoint(sys->pipe);
+			ipa_bridge_free_resources(sys);
+			sys->valid = false;
+		}
 	}
 
 	memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index e954741..a4b7e22 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -13,6 +13,8 @@
 #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];
@@ -31,56 +33,17 @@
 
 static int ipa_disable_data_path(u32 clnt_hdl)
 {
-	DECLARE_COMPLETION_ONSTACK(tag_rsp);
-	struct ipa_desc desc = {0};
-	struct ipa_ip_packet_tag cmd;
 	struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
-	struct ipa_tree_node *node;
-	int result = 0;
 
 	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL) {
 		/* IPA_HW_MODE_VIRTUAL lacks support for TAG IC & EP suspend */
 		return 0;
 	}
 
-	node = kmem_cache_zalloc(ipa_ctx->tree_node_cache, GFP_KERNEL);
-	if (!node) {
-		IPAERR("failed to alloc tree node object\n");
-		result = -ENOMEM;
-		goto fail_alloc;
-	}
-
 	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1 && !ep->suspended) {
 		ipa_write_reg(ipa_ctx->mmio,
 				IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
 
-		cmd.tag = (u32) &tag_rsp;
-
-		desc.pyld = &cmd;
-		desc.len = sizeof(struct ipa_ip_packet_tag);
-		desc.type = IPA_IMM_CMD_DESC;
-		desc.opcode = IPA_IP_PACKET_TAG;
-
-		IPADBG("Wait on TAG %p clnt=%d\n", &tag_rsp, clnt_hdl);
-
-		node->hdl = cmd.tag;
-		mutex_lock(&ipa_ctx->lock);
-		if (ipa_insert(&ipa_ctx->tag_tree, node)) {
-			IPAERR("failed to add to tree\n");
-			result = -EINVAL;
-			mutex_unlock(&ipa_ctx->lock);
-			goto fail_insert;
-		}
-		mutex_unlock(&ipa_ctx->lock);
-
-		if (ipa_send_cmd(1, &desc)) {
-			ipa_write_reg(ipa_ctx->mmio,
-				IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 0);
-			IPAERR("fail to send TAG command\n");
-			result = -EPERM;
-			goto fail_send;
-		}
-		wait_for_completion(&tag_rsp);
 		if (IPA_CLIENT_IS_CONS(ep->client) &&
 				ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
 				ep->cfg.aggr.aggr_time_limit)
@@ -89,13 +52,6 @@
 	}
 
 	return 0;
-
-fail_send:
-	rb_erase(&node->node, &ipa_ctx->tag_tree);
-fail_insert:
-	kmem_cache_free(ipa_ctx->tree_node_cache, node);
-fail_alloc:
-	return result;
 }
 
 static int ipa_connect_configure_sps(const struct ipa_connect_params *in,
@@ -294,6 +250,20 @@
 	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_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index dabf86f..bd1da2c 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -528,8 +528,6 @@
 	struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_IN];
 	struct ipa_ep_context *ep;
 	int cnt = 0;
-	struct completion *compl;
-	struct ipa_tree_node *node;
 	unsigned int src_pipe;
 
 	while ((in_poll_state ? atomic_read(&ipa_ctx->curr_polling_state) :
@@ -584,35 +582,6 @@
 		IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
 		IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
 
-		if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
-			if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
-				/* retrieve the compl object from tag value */
-				mux_hdr++;
-				compl = (struct completion *)
-					ntohl(*((u32 *)mux_hdr));
-				IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
-						*((u32 *)mux_hdr + 1), compl);
-
-				mutex_lock(&ipa_ctx->lock);
-				node = ipa_search(&ipa_ctx->tag_tree,
-						(u32)compl);
-				if (node) {
-					complete_all(compl);
-					rb_erase(&node->node,
-							&ipa_ctx->tag_tree);
-					kmem_cache_free(
-						ipa_ctx->tree_node_cache, node);
-				} else {
-					WARN_ON(1);
-				}
-				mutex_unlock(&ipa_ctx->lock);
-			}
-			dev_kfree_skb(rx_skb);
-			ipa_replenish_rx_cache();
-			++cnt;
-			continue;
-		}
-
 		/*
 		 * Any packets arriving over AMPDU_TX should be dispatched
 		 * to the regular WLAN RX data-path.
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index f9ae3c2..a5fac9e 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -52,6 +52,28 @@
 	struct sps_connect *sps_connections;
 };
 
+/**
+* struct usb_bam_ctx_type - represents the usb bam driver entity
+* @usb_bam_sps: holds the sps pipes the usb bam driver holds
+*	against the sps driver.
+* @usb_bam_pdev: the platfrom device that represents the usb bam.
+* @usb_bam_wq: Worqueue used for managing states of reset against
+*	a peer bam.
+* @qscratch_ram1_reg: The memory region mapped to the qscratch
+*	registers.
+* @max_connections: The maximum number of pipes that are configured
+*	in the platform data.
+* @mem_clk: Clock that controls the usb bam driver memory in
+*	case the usb bam uses its private memory for the pipes.
+* @mem_iface_clk: Clock that controls the usb bam private memory in
+*	case the usb bam uses its private memory for the pipes.
+* @qdss_core_name: Stores the name of the core ("ssusb", "hsusb" or "hsic")
+*	that it used as a peer of the qdss in bam2bam mode.
+* @h_bam: This array stores for each BAM ("ssusb", "hsusb" or "hsic") the
+*	handle/device of the sps driver.
+* @pipes_enabled_per_bam: This array stores for each BAM
+*	("ssusb", "hsusb" or "hsic") the number of pipes currently enabled.
+*/
 struct usb_bam_ctx_type {
 	struct usb_bam_sps_type usb_bam_sps;
 	struct platform_device *usb_bam_pdev;
@@ -61,8 +83,8 @@
 	struct clk *mem_clk;
 	struct clk *mem_iface_clk;
 	char qdss_core_name[USB_BAM_MAX_STR_LEN];
-	char bam_enabled_list[USB_BAM_MAX_STR_LEN];
 	u32 h_bam[MAX_BAMS];
+	u8 pipes_enabled_per_bam[MAX_BAMS];
 };
 
 static char *bam_enable_strings[3] = {
@@ -442,7 +464,6 @@
 int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
 {
 	int ret;
-	enum usb_bam bam;
 	struct usb_bam_pipe_connect *pipe_connect = &usb_bam_connections[idx];
 	struct msm_usb_bam_platform_data *pdata;
 
@@ -467,13 +488,11 @@
 		pr_err("idx is wrong %d", idx);
 		return -EINVAL;
 	}
-	bam = pipe_connect->bam_type;
-	if (bam < 0)
-		return -EINVAL;
 
-	/* Check if BAM requires RESET before connect */
-	if (pdata->reset_on_connect[bam] == true)
-		sps_device_reset(ctx.h_bam[bam]);
+	/* Check if BAM requires RESET before connect and reset of first pipe */
+	if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
+	    (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
+		sps_device_reset(ctx.h_bam[pipe_connect->bam_type]);
 
 	ret = connect_pipe(idx, bam_pipe_idx);
 	if (ret) {
@@ -482,6 +501,7 @@
 	}
 
 	pipe_connect->enabled = 1;
+	ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
 
 	return 0;
 }
@@ -548,6 +568,8 @@
 	u8 idx;
 	struct usb_bam_pipe_connect *pipe_connect;
 	int ret;
+	struct msm_usb_bam_platform_data *pdata =
+					ctx.usb_bam_pdev->dev.platform_data;
 
 	if (!ipa_params) {
 		pr_err("%s: Invalid ipa params\n",
@@ -573,8 +595,13 @@
 		return 0;
 	}
 
+	/* Check if BAM requires RESET before connect and reset of first pipe */
+	if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
+	    (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
+		sps_device_reset(ctx.h_bam[pipe_connect->bam_type]);
+
 	ret = connect_pipe_ipa(idx, ipa_params);
-	ipa_rm_request_resource(IPA_CLIENT_USB_PROD);
+	ipa_rm_request_resource(IPA_RM_RESOURCE_USB_PROD);
 
 	if (ret) {
 		pr_err("%s: dst pipe connection failure\n", __func__);
@@ -582,6 +609,7 @@
 	}
 
 	pipe_connect->enabled = 1;
+	ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
 
 	return 0;
 }
@@ -799,6 +827,11 @@
 	}
 
 	pipe_connect->enabled = 0;
+	if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0)
+		pr_err("%s: wrong pipes enabled counter for bam_type=%d\n",
+			__func__, pipe_connect->bam_type);
+	else
+		ctx.pipes_enabled_per_bam[pipe_connect->bam_type] -= 1;
 
 	return 0;
 }
@@ -853,7 +886,7 @@
 		}
 	}
 
-	ipa_rm_release_resource(IPA_CLIENT_USB_PROD);
+	ipa_rm_release_resource(IPA_RM_RESOURCE_USB_PROD);
 	return 0;
 }
 EXPORT_SYMBOL(usb_bam_disconnect_ipa);
@@ -993,6 +1026,7 @@
 				__func__);
 			goto err;
 		}
+		bam = usb_bam_connections[i].bam_type;
 
 		rc = of_property_read_u32(node, "qcom,peer-bam",
 			&usb_bam_connections[i].peer_bam);
@@ -1220,6 +1254,9 @@
 			usb_bam_work);
 	}
 
+	for (i = 0; i < MAX_BAMS; i++)
+		ctx.pipes_enabled_per_bam[i] = 0;
+
 	spin_lock_init(&usb_bam_lock);
 	INIT_WORK(&peer_handshake_info.reset_event.event_w, usb_bam_sm_work);
 
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 180ca0d..2794fcc 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -190,8 +190,8 @@
  * @safe_current:		battery safety current setting
  * @maxinput_usb_ma:		Maximum Input current USB
  * @maxinput_dc_ma:		Maximum Input current DC
- * @warm_bat_degc		Warm battery temperature in degree Celsius
- * @cool_bat_degc		Cool battery temperature in degree Celsius
+ * @warm_bat_decidegc		Warm battery temperature in degree Celsius
+ * @cool_bat_decidegc		Cool battery temperature in degree Celsius
  * @revision:			PMIC revision
  * @thermal_levels		amount of thermal mitigation levels
  * @thermal_mitigation		thermal mitigation level values
@@ -242,8 +242,8 @@
 	unsigned int			term_current;
 	unsigned int			maxinput_usb_ma;
 	unsigned int			maxinput_dc_ma;
-	unsigned int			warm_bat_degc;
-	unsigned int			cool_bat_degc;
+	unsigned int			warm_bat_decidegc;
+	unsigned int			cool_bat_decidegc;
 	unsigned int			safe_current;
 	unsigned int			revision;
 	unsigned int			thermal_levels;
@@ -546,6 +546,12 @@
 	if (chip->batt_present ^ batt_present) {
 		chip->batt_present = batt_present;
 		power_supply_changed(&chip->batt_psy);
+
+		if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
+						&& batt_present) {
+			if (qpnp_adc_tm_channel_measure(&chip->adc_param))
+				pr_err("request ADC error\n");
+		}
 	}
 
 	if (chip->bms_psy)
@@ -1019,7 +1025,8 @@
 
 	/* Only honour requests while USB is present */
 	if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
-		if (ret.intval <= 2) {
+		if (ret.intval <= 2 && !chip->use_default_batt_values &&
+						get_prop_batt_present(chip)) {
 			qpnp_chg_usb_suspend_enable(chip, 1);
 			qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
 		} else {
@@ -1304,7 +1311,7 @@
 	}
 }
 
-#define TEMP_HYSTERISIS_DEGC 2
+#define HYSTERISIS_DECIDEGC 20
 static void
 qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
 {
@@ -1323,22 +1330,22 @@
 			bat_warm = true;
 			bat_cool = false;
 			chip->adc_param.low_temp =
-				chip->warm_bat_degc - TEMP_HYSTERISIS_DEGC;
+				chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
 		} else if (chip->bat_is_cool) {
 			bat_warm = false;
 			bat_cool = false;
-			chip->adc_param.high_temp = chip->warm_bat_degc;
+			chip->adc_param.high_temp = chip->warm_bat_decidegc;
 		}
 	} else {
 		if (!chip->bat_is_cool) {
 			bat_cool = true;
 			bat_warm = false;
 			chip->adc_param.high_temp =
-				chip->cool_bat_degc + TEMP_HYSTERISIS_DEGC;
+				chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
 		} else if (chip->bat_is_warm) {
 			bat_cool = false;
 			bat_warm = false;
-			chip->adc_param.low_temp = chip->cool_bat_degc;
+			chip->adc_param.low_temp = chip->cool_bat_decidegc;
 		}
 	}
 
@@ -1353,7 +1360,7 @@
 	}
 
 	/* re-arm ADC interrupt */
-	qpnp_adc_tm_btm_configure(&chip->adc_param);
+	qpnp_adc_tm_channel_measure(&chip->adc_param);
 }
 
 static int
@@ -1743,8 +1750,8 @@
 
 	/* Get the warm-bat-degc property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-warm-bat-degc",
-				&chip->warm_bat_degc);
+				"qcom,chg-warm-bat-decidegc",
+				&chip->warm_bat_decidegc);
 	if (rc && rc != -EINVAL) {
 		pr_err("Error reading warm-bat-degc property %d\n", rc);
 		goto fail_chg_enable;
@@ -1752,14 +1759,14 @@
 
 	/* Get the cool-bat-degc property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-cool-bat-degc",
-				&chip->cool_bat_degc);
+				"qcom,chg-cool-bat-decidegc",
+				&chip->cool_bat_decidegc);
 	if (rc && rc != -EINVAL) {
 		pr_err("Error reading cool-bat-degc property %d\n", rc);
 		goto fail_chg_enable;
 	}
 
-	if (chip->cool_bat_degc && chip->warm_bat_degc) {
+	if (chip->cool_bat_decidegc && chip->warm_bat_decidegc) {
 		rc = qpnp_adc_tm_is_ready();
 		if (rc) {
 			pr_err("tm not ready %d\n", rc);
@@ -1997,19 +2004,22 @@
 		}
 	}
 
-	if (chip->cool_bat_degc && chip->warm_bat_degc) {
-		chip->adc_param.low_temp = chip->cool_bat_degc;
-		chip->adc_param.high_temp = chip->warm_bat_degc;
+	if (chip->cool_bat_decidegc && chip->warm_bat_decidegc) {
+		chip->adc_param.low_temp = chip->cool_bat_decidegc;
+		chip->adc_param.high_temp = chip->warm_bat_decidegc;
 		chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
 		chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
 		chip->adc_param.btm_ctx = chip;
 		chip->adc_param.threshold_notification =
 						qpnp_chg_adc_notification;
+		chip->adc_param.channel = LR_MUX1_BATT_THERM;
 
-		rc = qpnp_adc_tm_btm_configure(&chip->adc_param);
-		if (rc) {
-			pr_err("request ADC error %d\n", rc);
-			goto fail_chg_enable;
+		if (get_prop_batt_present(chip)) {
+			rc = qpnp_adc_tm_channel_measure(&chip->adc_param);
+			if (rc) {
+				pr_err("request ADC error %d\n", rc);
+				goto fail_chg_enable;
+			}
 		}
 	}
 
@@ -2038,6 +2048,10 @@
 qpnp_charger_remove(struct spmi_device *spmi)
 {
 	struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
+	if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
+						&& chip->batt_present) {
+		qpnp_adc_tm_disable_chan_meas(&chip->adc_param);
+	}
 	dev_set_drvdata(&spmi->dev, NULL);
 	kfree(chip);
 
diff --git a/drivers/staging/ste_rmi4/Kconfig b/drivers/staging/ste_rmi4/Kconfig
index e867950..6570368 100644
--- a/drivers/staging/ste_rmi4/Kconfig
+++ b/drivers/staging/ste_rmi4/Kconfig
@@ -1,9 +1,12 @@
-config TOUCHSCREEN_SYNAPTICS_I2C_RMI4
-	tristate "Synaptics i2c rmi4 touchscreen"
+config TOUCHSCREEN_SYNAPTICS_I2C_RMI4_STAGING
+	tristate "Synaptics i2c rmi4 touchscreen staging"
 	depends on I2C && INPUT
 	help
 	  Say Y here if you have a Synaptics RMI4 and
-	  want to enable support for the built-in touchscreen.
+	  want to enable support for the built-in touchscreen
+	  through staging driver.  Not to be confused with
+	  TOUCHSCREEN_SYNAPTICS_I2C_RMI4 in
+          drivers/input/touchscreen directory.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called synaptics_rmi4_ts.
diff --git a/drivers/staging/ste_rmi4/Makefile b/drivers/staging/ste_rmi4/Makefile
index e4c0335..ee9a53e 100644
--- a/drivers/staging/ste_rmi4/Makefile
+++ b/drivers/staging/ste_rmi4/Makefile
@@ -1,5 +1,6 @@
 #
 # Makefile for the RMI4 touchscreen driver.
 #
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4_STAGING) \
+	+= synaptics_i2c_rmi4_staging.o
 obj-$(CONFIG_MACH_MOP500) += board-mop500-u8500uib-rmi4.o
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.c
similarity index 99%
rename from drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
rename to drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.c
index 11728a0..43115c3 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.c
@@ -31,7 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/regulator/consumer.h>
 #include <linux/module.h>
-#include "synaptics_i2c_rmi4.h"
+#include "synaptics_i2c_rmi4_staging.h"
 
 /* TODO: for multiple device support will need a per-device mutex */
 #define DRIVER_NAME "synaptics_rmi4_i2c"
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.h
similarity index 100%
rename from drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
rename to drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.h
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 17ae34f..c02db14 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.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
@@ -35,6 +35,8 @@
 #include <linux/platform_device.h>
 
 /* QPNP VADC TM register definition */
+#define QPNP_REVISION3					0x3
+#define QPNP_REVISION_EIGHT_CHANNEL_SUPPORT		2
 #define QPNP_STATUS1					0x8
 #define QPNP_STATUS1_OP_MODE				4
 #define QPNP_STATUS1_MEAS_INTERVAL_EN_STS		BIT(2)
@@ -79,22 +81,41 @@
 #define QPNP_M0_LOW_THR_MSB				0x5d
 #define QPNP_M0_HIGH_THR_LSB				0x5e
 #define QPNP_M0_HIGH_THR_MSB				0x5f
+#define QPNP_M1_ADC_CH_SEL_CTL				0x68
 #define QPNP_M1_LOW_THR_LSB				0x69
 #define QPNP_M1_LOW_THR_MSB				0x6a
 #define QPNP_M1_HIGH_THR_LSB				0x6b
 #define QPNP_M1_HIGH_THR_MSB				0x6c
+#define QPNP_M2_ADC_CH_SEL_CTL				0x70
 #define QPNP_M2_LOW_THR_LSB				0x71
 #define QPNP_M2_LOW_THR_MSB				0x72
 #define QPNP_M2_HIGH_THR_LSB				0x7b
 #define QPNP_M2_HIGH_THR_MSB				0x7c
+#define QPNP_M3_ADC_CH_SEL_CTL				0x78
 #define QPNP_M3_LOW_THR_LSB				0x79
 #define QPNP_M3_LOW_THR_MSB				0x7a
 #define QPNP_M3_HIGH_THR_LSB				0x7b
 #define QPNP_M3_HIGH_THR_MSB				0x7c
+#define QPNP_M4_ADC_CH_SEL_CTL				0x80
 #define QPNP_M4_LOW_THR_LSB				0x81
 #define QPNP_M4_LOW_THR_MSB				0x82
 #define QPNP_M4_HIGH_THR_LSB				0x83
 #define QPNP_M4_HIGH_THR_MSB				0x84
+#define QPNP_M5_ADC_CH_SEL_CTL				0x88
+#define QPNP_M5_LOW_THR_LSB				0x89
+#define QPNP_M5_LOW_THR_MSB				0x8a
+#define QPNP_M5_HIGH_THR_LSB				0x8b
+#define QPNP_M5_HIGH_THR_MSB				0x8c
+#define QPNP_M6_ADC_CH_SEL_CTL				0x90
+#define QPNP_M6_LOW_THR_LSB				0x91
+#define QPNP_M6_LOW_THR_MSB				0x92
+#define QPNP_M6_HIGH_THR_LSB				0x93
+#define QPNP_M6_HIGH_THR_MSB				0x94
+#define QPNP_M7_ADC_CH_SEL_CTL				0x98
+#define QPNP_M7_LOW_THR_LSB				0x99
+#define QPNP_M7_LOW_THR_MSB				0x9a
+#define QPNP_M7_HIGH_THR_LSB				0x9b
+#define QPNP_M7_HIGH_THR_MSB				0x9c
 
 #define QPNP_ADC_TM_MULTI_MEAS_EN			0x41
 #define QPNP_ADC_TM_MULTI_MEAS_EN_M0			BIT(0)
@@ -102,24 +123,36 @@
 #define QPNP_ADC_TM_MULTI_MEAS_EN_M2			BIT(2)
 #define QPNP_ADC_TM_MULTI_MEAS_EN_M3			BIT(3)
 #define QPNP_ADC_TM_MULTI_MEAS_EN_M4			BIT(4)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M5			BIT(5)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M6			BIT(6)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M7			BIT(7)
 #define QPNP_ADC_TM_LOW_THR_INT_EN			0x42
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M0			BIT(0)
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M1			BIT(1)
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M2			BIT(2)
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M3			BIT(3)
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M4			BIT(4)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M5			BIT(5)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M6			BIT(6)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M7			BIT(7)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN			0x43
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M0			BIT(0)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M1			BIT(1)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M2			BIT(2)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M3			BIT(3)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M4			BIT(4)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M5			BIT(5)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M6			BIT(6)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M7			BIT(7)
 
-#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL			0x57
+#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL			0x59
 #define QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL			0x6d
 #define QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL			0x75
 #define QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL			0x7d
 #define QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL			0x85
+#define QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL			0x8d
+#define QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL			0x95
+#define QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL			0x9d
 #define QPNP_ADC_TM_STATUS1				0x8
 #define QPNP_ADC_TM_STATUS_LOW				0xa
 #define QPNP_ADC_TM_STATUS_HIGH				0xb
@@ -131,6 +164,9 @@
 #define QPNP_ADC_TM_THR_LSB_MASK(val)			(val & 0xff)
 #define QPNP_ADC_TM_THR_MSB_MASK(val)			((val & 0xff00) >> 8)
 
+#define QPNP_MIN_TIME			2000
+#define QPNP_MAX_TIME			2100
+
 struct qpnp_adc_tm_sensor {
 	struct thermal_zone_device	*tz_dev;
 	enum thermal_device_mode	mode;
@@ -140,16 +176,19 @@
 	uint32_t			low_thr;
 	uint32_t			high_thr;
 	uint32_t			btm_channel_num;
+	uint32_t			vadc_channel_num;
 	struct work_struct		work;
+	struct qpnp_adc_tm_btm_param	*btm_param;
+	bool				thermal_node;
+	bool				low_thr_notify;
+	bool				high_thr_notify;
+	uint32_t			scale_type;
 };
 
 struct qpnp_adc_tm_drv {
 	struct qpnp_adc_drv		*adc;
-	struct qpnp_adc_tm_usbid_param	*usb_id_param;
-	struct work_struct		usbid_work;
-	struct qpnp_adc_tm_btm_param	*battery_param;
-	struct work_struct		batt_work;
 	bool				adc_tm_initialized;
+	int				max_channels_available;
 	struct qpnp_adc_tm_sensor	sensor[0];
 };
 
@@ -163,29 +202,57 @@
 	u8 multi_meas_en;
 	u8 low_thr_int_chan_en;
 	u8 high_thr_int_chan_en;
+	u8 meas_interval_ctl;
 };
 
 static struct qpnp_adc_tm_trip_reg_type adc_tm_data[] = {
 	[QPNP_ADC_TM_M0_ADC_CH_SEL_CTL] = {QPNP_M0_LOW_THR_LSB,
 		QPNP_M0_LOW_THR_MSB, QPNP_M0_HIGH_THR_LSB,
 		QPNP_M0_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M0,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0,
+		QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL},
 	[QPNP_ADC_TM_M1_ADC_CH_SEL_CTL] = {QPNP_M1_LOW_THR_LSB,
 		QPNP_M1_LOW_THR_MSB, QPNP_M1_HIGH_THR_LSB,
 		QPNP_M1_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M1,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1,
+		QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL},
 	[QPNP_ADC_TM_M2_ADC_CH_SEL_CTL] = {QPNP_M2_LOW_THR_LSB,
 		QPNP_M2_LOW_THR_MSB, QPNP_M2_HIGH_THR_LSB,
 		QPNP_M2_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M2,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2,
+		QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL},
 	[QPNP_ADC_TM_M3_ADC_CH_SEL_CTL] = {QPNP_M3_LOW_THR_LSB,
 		QPNP_M3_LOW_THR_MSB, QPNP_M3_HIGH_THR_LSB,
 		QPNP_M3_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M3,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3,
+		QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL},
 	[QPNP_ADC_TM_M4_ADC_CH_SEL_CTL] = {QPNP_M4_LOW_THR_LSB,
 		QPNP_M4_LOW_THR_MSB, QPNP_M4_HIGH_THR_LSB,
 		QPNP_M4_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M4,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4,
+		QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL},
+	[QPNP_ADC_TM_M5_ADC_CH_SEL_CTL] = {QPNP_M5_LOW_THR_LSB,
+		QPNP_M5_LOW_THR_MSB, QPNP_M5_HIGH_THR_LSB,
+		QPNP_M5_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M5,
+		QPNP_ADC_TM_LOW_THR_INT_EN_M5, QPNP_ADC_TM_HIGH_THR_INT_EN_M5,
+		QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL},
+	[QPNP_ADC_TM_M6_ADC_CH_SEL_CTL] = {QPNP_M6_LOW_THR_LSB,
+		QPNP_M6_LOW_THR_MSB, QPNP_M6_HIGH_THR_LSB,
+		QPNP_M6_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M6,
+		QPNP_ADC_TM_LOW_THR_INT_EN_M6, QPNP_ADC_TM_HIGH_THR_INT_EN_M6,
+		QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL},
+	[QPNP_ADC_TM_M7_ADC_CH_SEL_CTL] = {QPNP_M7_LOW_THR_LSB,
+		QPNP_M7_LOW_THR_MSB, QPNP_M7_HIGH_THR_LSB,
+		QPNP_M7_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M7,
+		QPNP_ADC_TM_LOW_THR_INT_EN_M7, QPNP_ADC_TM_HIGH_THR_INT_EN_M7,
+		QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL},
+};
+
+static struct qpnp_adc_tm_reverse_scale_fn adc_tm_rscale_fn[] = {
+	[SCALE_R_VBATT] = {qpnp_adc_vbatt_rscaler},
+	[SCALE_RBATT_THERM] = {qpnp_adc_btm_scaler},
+	[SCALE_R_USB_ID] = {qpnp_adc_usb_scaler},
+	[SCALE_RPMIC_THERM] = {qpnp_adc_scale_millidegc_pmic_voltage_thr},
 };
 
 static int32_t qpnp_adc_tm_read_reg(int16_t reg, u8 *data)
@@ -217,40 +284,63 @@
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_enable(bool state)
+static int32_t qpnp_adc_tm_enable(void)
 {
 	int rc = 0;
-	u8 data = 0, enable_check = 0;
+	u8 data = 0;
 
-	if (state) {
-		data = QPNP_ADC_TM_EN;
-		rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1,
-					data);
-		if (rc < 0)
-			pr_err("adc-tm enable failed\n");
-	} else {
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MULTI_MEAS_EN,
-					&enable_check);
+	data = QPNP_ADC_TM_EN;
+	rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
+	if (rc < 0)
+		pr_err("adc-tm enable failed\n");
+
+	return rc;
+}
+
+static int32_t qpnp_adc_tm_disable(void)
+{
+	u8 data = 0;
+	int rc = 0;
+
+	rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
+	if (rc < 0)
+		pr_err("adc-tm disable failed\n");
+
+	return rc;
+}
+
+static int32_t qpnp_adc_tm_enable_if_channel_meas(void)
+{
+	u8 adc_tm_meas_en = 0;
+	int rc = 0;
+
+	/* Check if a measurement request is still required */
+	rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MULTI_MEAS_EN,
+							&adc_tm_meas_en);
+	if (rc) {
+		pr_err("adc-tm-tm read status high failed with %d\n", rc);
+		return rc;
+	}
+
+	/* Enable only if there are pending measurement requests */
+	if (adc_tm_meas_en) {
+		qpnp_adc_tm_enable();
+
+		/* Request conversion */
+		rc = qpnp_adc_tm_write_reg(QPNP_CONV_REQ, QPNP_CONV_REQ_SET);
 		if (rc < 0) {
-			pr_err("multi measurement read failed\n");
+			pr_err("adc-tm request conversion failed\n");
 			return rc;
 		}
-
-		if (!enable_check) {
-			data = 0;
-			rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
-			if (rc < 0)
-				pr_err("adc-tm disable failed\n");
-		}
 	}
 
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_enable_req_sts_check(void)
+static int32_t qpnp_adc_tm_req_sts_check(void)
 {
 	u8 status1;
-	int rc;
+	int rc, count = 0;
 
 	/* The VADC_TM bank needs to be disabled for new conversion request */
 	rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS1, &status1);
@@ -260,19 +350,45 @@
 	}
 
 	/* Disable the bank if a conversion is occuring */
-	if (status1 & QPNP_STATUS1_REQ_STS) {
-		rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, 0);
+	while ((status1 & QPNP_STATUS1_REQ_STS) && (count < 5)) {
+		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS1, &status1);
 		if (rc < 0)
 			pr_err("adc-tm disable failed\n");
+		/* Wait time is based on the optimum sampling rate
+		 * and adding enough time buffer to account for ADC conversions
+		 * occuring on different peripheral banks */
+		usleep_range(QPNP_MIN_TIME, QPNP_MAX_TIME);
+		count++;
 	}
 
 	return rc;
 }
 
+static int32_t qpnp_adc_tm_check_revision(uint32_t btm_chan_num)
+{
+	u8 rev;
+	int rc = 0;
+
+	rc = qpnp_adc_tm_read_reg(QPNP_REVISION3, &rev);
+	if (rc) {
+		pr_err("adc-tm revision read failed\n");
+		return rc;
+	}
+
+	if ((rev < QPNP_REVISION_EIGHT_CHANNEL_SUPPORT) &&
+		(btm_chan_num > QPNP_ADC_TM_M4_ADC_CH_SEL_CTL)) {
+		pr_debug("Version does not support more than 5 channels\n");
+		return -EINVAL;
+	}
+
+	return rc;
+}
 static int32_t qpnp_adc_tm_mode_select(u8 mode_ctl)
 {
 	int rc;
 
+	mode_ctl |= (QPNP_ADC_TRIM_EN | QPNP_AMUX_TRIM_EN);
+
 	/* VADC_BTM current sets mode to recurring measurements */
 	rc = qpnp_adc_tm_write_reg(QPNP_MODE_CTL, mode_ctl);
 	if (rc < 0)
@@ -281,13 +397,13 @@
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_timer_interval_select(
+static int32_t qpnp_adc_tm_timer_interval_select(uint32_t btm_chan,
 		struct qpnp_vadc_chan_properties *chan_prop)
 {
 	int rc;
 	u8 meas_interval_timer2 = 0;
 
-	/* Configure USB_ID to timer1, batt_therm to timer2 */
+	/* Configure kernel clients to timer1 */
 	switch (chan_prop->timer_select) {
 	case ADC_MEAS_TIMER_SELECT1:
 		rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL,
@@ -298,6 +414,7 @@
 		}
 	break;
 	case ADC_MEAS_TIMER_SELECT2:
+		/* Thermal channels uses timer2, default to 1 second */
 		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
 				&meas_interval_timer2);
 		if (rc < 0) {
@@ -315,7 +432,6 @@
 		}
 	break;
 	case ADC_MEAS_TIMER_SELECT3:
-		/* Thermal channels uses timer3, default to 1 second */
 		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
 				&meas_interval_timer2);
 		if (rc < 0) {
@@ -336,34 +452,40 @@
 		return -EINVAL;
 	}
 
+	/* Select the timer to use for the corresponding channel */
+	adc_tm_data[btm_chan].meas_interval_ctl = chan_prop->timer_select;
+
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_meas_int_update(uint16_t reg_addr_src,
-		u8 reg_addr_dst, bool state)
+static int32_t qpnp_adc_tm_reg_update(uint16_t addr,
+		u8 mask, bool state)
 {
-	u8 bit_mask_check = 0;
+	u8 reg_value = 0;
 	int rc = 0;
 
-	rc = qpnp_adc_tm_read_reg(reg_addr_src, &bit_mask_check);
+	rc = qpnp_adc_tm_read_reg(addr, &reg_value);
 	if (rc < 0) {
-		pr_err("read failed for addr:%x\n", reg_addr_src);
+		pr_err("read failed for addr:0x%x\n", addr);
 		return rc;
 	}
 
+	reg_value = reg_value & ~mask;
 	if (state)
-		bit_mask_check |= reg_addr_dst;
-	else
-		bit_mask_check &= ~reg_addr_dst;
+		reg_value |= mask;
 
-	rc = qpnp_adc_tm_write_reg(reg_addr_src, bit_mask_check);
-	if (rc < 0)
-		pr_err("write failed for addr:%x\n", reg_addr_src);
+	pr_debug("state:%d, reg:0x%x with bits:0x%x and mask:0x%x\n",
+					state, addr, reg_value, ~mask);
+	rc = qpnp_adc_tm_write_reg(addr, reg_value);
+	if (rc < 0) {
+		pr_err("write failed for addr:%x\n", addr);
+		return rc;
+	}
 
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_usbid_btm_thr_en(uint32_t btm_chan,
+static int32_t qpnp_adc_tm_thr_update(uint32_t btm_chan,
 			struct qpnp_vadc_chan_properties *chan_prop)
 {
 	int rc = 0;
@@ -398,6 +520,9 @@
 	if (rc < 0)
 		pr_err("high threshold msb setting failed\n");
 
+	pr_debug("client requested low:%d and high:%d\n",
+		chan_prop->low_thr, chan_prop->high_thr);
+
 	return rc;
 }
 
@@ -405,13 +530,29 @@
 			struct qpnp_vadc_chan_properties *chan_prop,
 			uint32_t amux_channel)
 {
-	int rc = 0;
+	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
+	int rc = 0, i = 0, chan_idx = 0;
+	bool chan_found = false;
+	u8 sensor_mask = 0;
 
-	switch (btm_chan) {
-	case QPNP_ADC_TM_M0_ADC_CH_SEL_CTL:
-	case QPNP_ADC_TM_M1_ADC_CH_SEL_CTL:
+	while (i < adc_tm->max_channels_available) {
+		if (adc_tm->sensor[i].btm_channel_num == btm_chan) {
+			chan_idx = i;
+			chan_found = true;
+			i++;
+		} else
+			i++;
+	}
+
+	if ((i == adc_tm->max_channels_available) && (!chan_found)) {
+		pr_err("Channel not found\n");
+		return -EINVAL;
+	}
+
+	sensor_mask = 1 << chan_idx;
+	if (!adc_tm->sensor[chan_idx].thermal_node) {
 		/* Update low and high notification thresholds */
-		rc = qpnp_adc_tm_usbid_btm_thr_en(btm_chan,
+		rc = qpnp_adc_tm_thr_update(btm_chan,
 				chan_prop);
 		if (rc < 0) {
 			pr_err("setting chan:%d threshold failed\n", btm_chan);
@@ -422,11 +563,11 @@
 					ADC_TM_LOW_THR_ENABLE) ||
 			(chan_prop->state_request ==
 					ADC_TM_HIGH_LOW_THR_ENABLE)) {
+			pr_debug("low sensor mask:%x with state:%d\n",
+					sensor_mask, chan_prop->state_request);
 			/* Enable low threshold's interrupt */
-			rc = qpnp_adc_tm_meas_int_update(
-				QPNP_ADC_TM_LOW_THR_INT_EN,
-				adc_tm_data[btm_chan].low_thr_int_chan_en,
-				true);
+			rc = qpnp_adc_tm_reg_update(
+				QPNP_ADC_TM_LOW_THR_INT_EN, sensor_mask, true);
 			if (rc < 0) {
 				pr_err("low thr enable err:%d\n", btm_chan);
 				return rc;
@@ -438,37 +579,22 @@
 			(chan_prop->state_request ==
 					ADC_TM_HIGH_LOW_THR_ENABLE)) {
 			/* Enable high threshold's interrupt */
-			rc = qpnp_adc_tm_meas_int_update(
-				QPNP_ADC_TM_HIGH_THR_INT_EN,
-				adc_tm_data[btm_chan].high_thr_int_chan_en,
-				true);
+			pr_debug("high sensor mask:%x\n", sensor_mask);
+			rc = qpnp_adc_tm_reg_update(
+				QPNP_ADC_TM_HIGH_THR_INT_EN, sensor_mask, true);
 			if (rc < 0) {
 				pr_err("high thr enable err:%d\n", btm_chan);
 				return rc;
 			}
 		}
-	/* intention fall through to configure common chan meas */
-	case QPNP_ADC_TM_M2_ADC_CH_SEL_CTL:
-	case QPNP_ADC_TM_M3_ADC_CH_SEL_CTL:
-	case QPNP_ADC_TM_M4_ADC_CH_SEL_CTL:
-		/* Configure AMUX control register for channel selection */
-		rc = qpnp_adc_tm_write_reg(btm_chan, amux_channel);
-		if (rc < 0) {
-			pr_err("btm_chan:%d selection failed\n", btm_chan);
-			return rc;
-		}
+	}
 
-		/* Enable corresponding BTM channel measurement */
-		rc = qpnp_adc_tm_meas_int_update(
-			QPNP_ADC_TM_MULTI_MEAS_EN,
-			adc_tm_data[btm_chan].multi_meas_en, true);
-		if (rc < 0) {
-			pr_err("multi measurement en failed\n");
-			return rc;
-		}
-	break;
-	default:
-		return -EINVAL;
+	/* Enable corresponding BTM channel measurement */
+	rc = qpnp_adc_tm_reg_update(
+		QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, true);
+	if (rc < 0) {
+		pr_err("multi measurement en failed\n");
+		return rc;
 	}
 
 	return rc;
@@ -477,12 +603,17 @@
 static int32_t qpnp_adc_tm_configure(
 			struct qpnp_adc_amux_properties *chan_prop)
 {
-	u8 decimation = 0;
+	u8 decimation = 0, op_cntrl = 0;
 	int rc = 0;
 	uint32_t btm_chan = 0;
 
+	/* Disable bank */
+	rc = qpnp_adc_tm_disable();
+	if (rc)
+		return rc;
+
 	/* Check if a conversion is in progress */
-	rc = qpnp_adc_tm_enable_req_sts_check();
+	rc = qpnp_adc_tm_req_sts_check();
 	if (rc < 0) {
 		pr_err("adc-tm req_sts check failed\n");
 		return rc;
@@ -495,9 +626,9 @@
 		return rc;
 	}
 
-	/* Configure AMUX channel */
-	rc = qpnp_adc_tm_write_reg(QPNP_ADC_CH_SEL_CTL,
-				chan_prop->amux_channel);
+	/* Configure AMUX channel select for the corresponding BTM channel*/
+	btm_chan = chan_prop->chan_prop->tm_channel_select;
+	rc = qpnp_adc_tm_write_reg(btm_chan, chan_prop->amux_channel);
 	if (rc < 0) {
 		pr_err("adc-tm channel selection err\n");
 		return rc;
@@ -529,14 +660,14 @@
 	}
 
 	/* Measurement interval setup */
-	rc = qpnp_adc_tm_timer_interval_select(chan_prop->chan_prop);
+	rc = qpnp_adc_tm_timer_interval_select(btm_chan,
+						chan_prop->chan_prop);
 	if (rc < 0) {
 		pr_err("adc-tm timer select failed\n");
 		return rc;
 	}
 
 	/* Channel configuration setup */
-	btm_chan = chan_prop->chan_prop->tm_channel_select;
 	rc = qpnp_adc_tm_channel_configure(btm_chan, chan_prop->chan_prop,
 					chan_prop->amux_channel);
 	if (rc < 0) {
@@ -544,19 +675,21 @@
 		return rc;
 	}
 
-	/* Enable bank */
-	rc = qpnp_adc_tm_enable(true);
-	if (rc)
-		return rc;
-
 	/* Recurring interval measurement enable */
-	rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_MEAS_INTERVAL_OP_CTL,
-			QPNP_ADC_MEAS_INTERVAL_OP, true);
+	rc = qpnp_adc_tm_read_reg(QPNP_ADC_MEAS_INTERVAL_OP_CTL, &op_cntrl);
+	op_cntrl |= QPNP_ADC_MEAS_INTERVAL_OP;
+	rc = qpnp_adc_tm_reg_update(QPNP_ADC_MEAS_INTERVAL_OP_CTL,
+			op_cntrl, true);
 	if (rc < 0) {
 		pr_err("adc-tm meas interval op configure failed\n");
 		return rc;
 	}
 
+	/* Enable bank */
+	rc = qpnp_adc_tm_enable();
+	if (rc)
+		return rc;
+
 	/* Request conversion */
 	rc = qpnp_adc_tm_write_reg(QPNP_CONV_REQ, QPNP_CONV_REQ_SET);
 	if (rc < 0) {
@@ -570,12 +703,13 @@
 static int qpnp_adc_tm_get_mode(struct thermal_zone_device *thermal,
 			      enum thermal_device_mode *mode)
 {
-	struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
+	struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
 
-	if (!adc_tm || !mode)
+	if (!adc_tm_sensor || qpnp_adc_tm_check_revision(
+			adc_tm_sensor->btm_channel_num) || !mode)
 		return -EINVAL;
 
-	*mode = adc_tm->mode;
+	*mode = adc_tm_sensor->mode;
 
 	return 0;
 }
@@ -586,12 +720,14 @@
 	struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
 	struct qpnp_adc_tm_drv *adc_drv = qpnp_adc_tm;
 	int rc = 0, channel;
+	u8 sensor_mask = 0;
 
-	if (!adc_tm)
+	if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num))
 		return -EINVAL;
 
 	if (mode == THERMAL_DEVICE_ENABLED) {
-		adc_drv->adc->amux_prop->amux_channel = adc_tm->sensor_num;
+		adc_drv->adc->amux_prop->amux_channel =
+					adc_tm->vadc_channel_num;
 		channel = adc_tm->sensor_num;
 		adc_drv->adc->amux_prop->decimation =
 			adc_drv->adc->adc_channels[channel].adc_decimation;
@@ -616,17 +752,31 @@
 			return -EINVAL;
 		}
 	} else if (mode == THERMAL_DEVICE_DISABLED) {
-		rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_MULTI_MEAS_EN,
-			adc_tm_data[adc_tm->btm_channel_num].multi_meas_en,
-			false);
+		sensor_mask = 1 << adc_tm->sensor_num;
+		/* Disable bank */
+		rc = qpnp_adc_tm_disable();
+		if (rc < 0) {
+			pr_err("adc-tm disable failed\n");
+			return rc;
+		}
+
+		/* Check if a conversion is in progress */
+		rc = qpnp_adc_tm_req_sts_check();
+		if (rc < 0) {
+			pr_err("adc-tm req_sts check failed\n");
+			return rc;
+		}
+
+		rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_MULTI_MEAS_EN,
+			sensor_mask, false);
 		if (rc < 0) {
 			pr_err("multi measurement update failed\n");
 			return rc;
 		}
 
-		rc = qpnp_adc_tm_enable(false);
+		rc = qpnp_adc_tm_enable_if_channel_meas();
 		if (rc < 0) {
-			pr_err("adc-tm disable failed\n");
+			pr_err("re-enabling measurement failed\n");
 			return rc;
 		}
 	}
@@ -641,7 +791,8 @@
 {
 	struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
 
-	if (!adc_tm || !type || type < 0)
+	if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num)
+						|| !type || type < 0)
 		return -EINVAL;
 
 	switch (trip) {
@@ -669,7 +820,8 @@
 	uint16_t reg_low_thr_lsb, reg_low_thr_msb;
 	uint16_t reg_high_thr_lsb, reg_high_thr_msb;
 
-	if (!adc_tm)
+	if (!adc_tm || qpnp_adc_tm_check_revision(
+					adc_tm_sensor->btm_channel_num))
 		return -EINVAL;
 
 	btm_channel_num = adc_tm_sensor->btm_channel_num;
@@ -733,10 +885,11 @@
 	uint16_t reg_high_thr_lsb, reg_high_thr_msb;
 	int rc = 0, btm_channel_num;
 
-	if (!adc_tm)
+	if (!adc_tm || qpnp_adc_tm_check_revision(
+				adc_tm_sensor->btm_channel_num))
 		return -EINVAL;
 
-	tm_config.channel = adc_tm_sensor->sensor_num;
+	tm_config.channel = adc_tm_sensor->vadc_channel_num;
 	switch (trip) {
 	case ADC_TM_TRIP_HIGH_WARM:
 		tm_config.high_thr_temp = temp;
@@ -748,6 +901,8 @@
 		return -EINVAL;
 	}
 
+	pr_debug("requested a high - %d and low - %d with trip - %d\n",
+			tm_config.high_thr_temp, tm_config.low_thr_temp, trip);
 	rc = qpnp_adc_tm_scale_therm_voltage_pu2(&tm_config);
 	if (rc < 0) {
 		pr_err("Failed to lookup the adc-tm thresholds\n");
@@ -801,131 +956,102 @@
 	return 0;
 }
 
-static void notify_uspace_qpnp_adc_tm_fn(struct work_struct *work)
+static void notify_battery_therm(struct qpnp_adc_tm_sensor *adc_tm)
+{
+	/* Battery therm's warm temperature translates to low voltage */
+	if (adc_tm->low_thr_notify) {
+		/* HIGH_STATE = WARM_TEMP for battery client */
+		adc_tm->btm_param->threshold_notification(
+		ADC_TM_WARM_STATE, adc_tm->btm_param->btm_ctx);
+		adc_tm->low_thr_notify = false;
+	}
+
+	/* Battery therm's cool temperature translates to high voltage */
+	if (adc_tm->high_thr_notify) {
+		/* LOW_STATE = COOL_TEMP for battery client */
+		adc_tm->btm_param->threshold_notification(
+		ADC_TM_COOL_STATE, adc_tm->btm_param->btm_ctx);
+		adc_tm->high_thr_notify = false;
+	}
+
+	return;
+}
+
+static void notify_clients(struct qpnp_adc_tm_sensor *adc_tm)
+{
+	/* For non batt therm clients */
+	if (adc_tm->low_thr_notify) {
+		pr_debug("notify kernel with low state\n");
+		adc_tm->btm_param->threshold_notification(
+		ADC_TM_LOW_STATE, adc_tm->btm_param->btm_ctx);
+		adc_tm->low_thr_notify = false;
+	}
+
+	if (adc_tm->high_thr_notify) {
+		pr_debug("notify kernel with high state\n");
+		adc_tm->btm_param->threshold_notification(
+		ADC_TM_HIGH_STATE, adc_tm->btm_param->btm_ctx);
+		adc_tm->high_thr_notify = false;
+	}
+
+	return;
+}
+
+static void notify_adc_tm_fn(struct work_struct *work)
 {
 	struct qpnp_adc_tm_sensor *adc_tm = container_of(work,
 		struct qpnp_adc_tm_sensor, work);
 
-	sysfs_notify(&adc_tm->tz_dev->device.kobj,
+	if (adc_tm->thermal_node) {
+		sysfs_notify(&adc_tm->tz_dev->device.kobj,
 					NULL, "btm");
-}
-
-static void notify_usb_fn(struct work_struct *work)
-{
-	struct qpnp_adc_tm_drv *adc_tm = container_of(work,
-		struct qpnp_adc_tm_drv, usbid_work);
-	int rc;
-	u8 status_low, status_high;
-
-	if (adc_tm->usb_id_param->threshold_notification != NULL) {
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW,
-							&status_low);
-		if (rc) {
-			pr_err("adc-tm read low status failed\n");
-			return;
+		pr_debug("notifying uspace client\n");
+	} else {
+		if (adc_tm->btm_param->threshold_notification != NULL) {
+			if (adc_tm->scale_type == SCALE_RBATT_THERM)
+				notify_battery_therm(adc_tm);
+			else
+				notify_clients(adc_tm);
 		}
-
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH,
-							&status_high);
-		if (rc) {
-			pr_err("adc-tm read high status failed\n");
-			return;
-		}
-
-		if (status_low & 1)
-			adc_tm->usb_id_param->threshold_notification(
-			ADC_TM_LOW_STATE, adc_tm->usb_id_param->usbid_ctx);
-		else if (status_high & 1)
-			adc_tm->usb_id_param->threshold_notification(
-			ADC_TM_HIGH_STATE, adc_tm->usb_id_param->usbid_ctx);
 	}
 
 	return;
 }
 
-static void notify_batt_fn(struct work_struct *work)
-{
-	struct qpnp_adc_tm_drv *adc_tm = container_of(work,
-		struct qpnp_adc_tm_drv, batt_work);
-	int rc;
-	u8 status_low, status_high;
-
-	if (adc_tm->battery_param->threshold_notification != NULL) {
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW,
-							&status_low);
-		if (rc) {
-			pr_err("adc-tm read low status failed\n");
-			return;
-		}
-
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH,
-							&status_high);
-		if (rc) {
-			pr_err("adc-tm read high status failed\n");
-			return;
-		}
-
-		if (status_low & QPNP_ADC_TM_LOW_THR_INT_EN_M1)
-			adc_tm->battery_param->threshold_notification(
-			ADC_TM_LOW_STATE, adc_tm->battery_param->btm_ctx);
-		else if (status_high & QPNP_ADC_TM_HIGH_THR_INT_EN_M1)
-			adc_tm->battery_param->threshold_notification(
-			ADC_TM_HIGH_STATE, adc_tm->battery_param->btm_ctx);
-	}
-
-	return;
-}
-
-static int qpnp_adc_tm_activate_trip_type_fn(uint32_t btm_channel_num,
-	enum thermal_trip_activation_mode mode, u8 *data, uint32_t reg)
-{
-	u8 thr_int = 0;
-	int rc = 0;
-
-	rc = qpnp_adc_tm_read_reg(reg, &thr_int);
-	if (rc) {
-		pr_err("multi meas read failed\n");
-		return rc;
-	}
-
-	thr_int = adc_tm_data[btm_channel_num].low_thr_int_chan_en;
-
-	if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
-		thr_int |= *data;
-	else
-		thr_int &= ~*data;
-
-	rc = qpnp_adc_tm_write_reg(reg, thr_int);
-	if (rc)
-		pr_err("multi meas write failed\n");
-
-	return rc;
-}
-
 static int qpnp_adc_tm_activate_trip_type(struct thermal_zone_device *thermal,
 			int trip, enum thermal_trip_activation_mode mode)
 {
 	struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
-	int rc = 0;
+	int rc = 0, sensor_mask = 0;
 	u8 thr_int_en = 0;
+	bool state = false;
 
-	if (!adc_tm)
+	if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num))
 		return -EINVAL;
 
+	if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
+		state = true;
+
+	sensor_mask = 1 << adc_tm->sensor_num;
+
+	pr_debug("Sensor number:%x with state:%d\n", adc_tm->sensor_num, state);
+
 	switch (trip) {
 	case ADC_TM_TRIP_HIGH_WARM:
+		/* low_thr (lower voltage) for higher temp */
 		thr_int_en = adc_tm_data[adc_tm->btm_channel_num].
 							low_thr_int_chan_en;
-		rc = qpnp_adc_tm_activate_trip_type_fn(adc_tm->btm_channel_num,
-				mode, &thr_int_en, QPNP_ADC_TM_LOW_THR_INT_EN);
+		rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_LOW_THR_INT_EN,
+				sensor_mask, state);
 		if (rc)
 			pr_err("channel:%x failed\n", adc_tm->btm_channel_num);
 	break;
 	case ADC_TM_TRIP_LOW_COOL:
+		/* high_thr (higher voltage) for cooler temp */
 		thr_int_en = adc_tm_data[adc_tm->btm_channel_num].
 							high_thr_int_chan_en;
-		rc = qpnp_adc_tm_activate_trip_type_fn(adc_tm->btm_channel_num,
-				mode, &thr_int_en, QPNP_ADC_TM_HIGH_THR_INT_EN);
+		rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
+				sensor_mask, state);
 		if (rc)
 			pr_err("channel:%x failed\n", adc_tm->btm_channel_num);
 	break;
@@ -941,12 +1067,20 @@
 	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
 	u8 status_low = 0, status_high = 0, qpnp_adc_tm_meas_en = 0;
 	u8 adc_tm_low_enable = 0, adc_tm_high_enable = 0;
-	u8 thr_int_disable = 0;
-	int rc = 0, sensor_notify_num = 0;
+	u8 sensor_mask = 0;
+	int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0, btm_chan_num;
 
 	if (!adc_tm || !adc_tm->adc_tm_initialized)
 		return -ENODEV;
 
+	mutex_lock(&adc_tm->adc->adc_lock);
+
+	rc = qpnp_adc_tm_req_sts_check();
+	if (rc) {
+		pr_err("adc-tm-tm req sts check failed with %d\n", rc);
+		goto fail;
+	}
+
 	rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW, &status_low);
 	if (rc) {
 		pr_err("adc-tm-tm read status low failed with %d\n", rc);
@@ -972,100 +1106,107 @@
 	adc_tm_high_enable = qpnp_adc_tm_meas_en & status_high;
 
 	if (adc_tm_high_enable) {
-		sensor_notify_num = (adc_tm_high_enable >> 3);
-		switch (adc_tm_high_enable) {
-		case 1:
-		case 2:
-		{
-			if (adc_tm_high_enable == 1)
-				thr_int_disable =
-					QPNP_ADC_TM_HIGH_THR_INT_EN_M0;
-			else if (adc_tm_high_enable == 2)
-				thr_int_disable =
-					QPNP_ADC_TM_HIGH_THR_INT_EN_M1;
+		sensor_notify_num = adc_tm_high_enable;
+		while (i < adc_tm->max_channels_available) {
+			if ((sensor_notify_num & 0x1) == 1)
+				sensor_num = i;
+			sensor_notify_num >>= 1;
+			i++;
+		}
 
-			rc = qpnp_adc_tm_meas_int_update(
+		btm_chan_num = adc_tm->sensor[sensor_num].btm_channel_num;
+		pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+			sensor_num, adc_tm_high_enable, adc_tm_low_enable,
+			qpnp_adc_tm_meas_en);
+		if (!adc_tm->sensor[sensor_num].thermal_node) {
+			/* For non thermal registered clients
+				such as usb_id, vbatt, pmic_therm */
+			sensor_mask = 1 << sensor_num;
+			pr_debug("non thermal node - mask:%x\n", sensor_mask);
+			rc = qpnp_adc_tm_reg_update(
 				QPNP_ADC_TM_HIGH_THR_INT_EN,
-				thr_int_disable, false);
+				sensor_mask, false);
 			if (rc < 0) {
 				pr_err("high threshold int read failed\n");
 				goto fail;
 			}
-
-			if (adc_tm_high_enable == 1)
-				schedule_work(&adc_tm->usbid_work);
-			else if (adc_tm_high_enable == 2)
-				schedule_work(&adc_tm->batt_work);
-		}
-		break;
-		case 4:
-		case 8:
-		case 16:
-		{
-			/* High voltage threshold is triggered by low temp */
+			adc_tm->sensor[sensor_num].high_thr_notify = true;
+		} else {
+			/* Uses the thermal sysfs registered device to disable
+				the corresponding high voltage threshold which
+				 is triggered by low temp */
+			pr_debug("thermal node with mask:%x\n", sensor_mask);
 			rc = qpnp_adc_tm_activate_trip_type(
-				adc_tm->sensor[sensor_notify_num].tz_dev,
+				adc_tm->sensor[sensor_num].tz_dev,
 				ADC_TM_TRIP_LOW_COOL,
 				THERMAL_TRIP_ACTIVATION_DISABLED);
 			if (rc < 0) {
-				pr_err("notify error:%d\n", sensor_notify_num);
+				pr_err("notify error:%d\n", sensor_num);
 				goto fail;
 			}
-			schedule_work(&adc_tm->sensor[sensor_notify_num].work);
-		}
-		break;
-		default:
-			rc = -EINVAL;
 		}
 	}
 
 	if (adc_tm_low_enable) {
-		sensor_notify_num = (adc_tm_low_enable >> 3);
-		switch (adc_tm_low_enable) {
-		case 1:
-		case 2:
-		{
-			if (adc_tm_low_enable == 1)
-				thr_int_disable = QPNP_ADC_TM_LOW_THR_INT_EN_M0;
-			else if (adc_tm_low_enable == 2)
-				thr_int_disable = QPNP_ADC_TM_LOW_THR_INT_EN_M1;
+		sensor_notify_num = adc_tm_low_enable;
+		i = 0;
+		while (i < adc_tm->max_channels_available) {
+			if ((sensor_notify_num & 0x1) == 1)
+				sensor_num = i;
+			sensor_notify_num >>= 1;
+			i++;
+		}
 
-			rc = qpnp_adc_tm_meas_int_update(
+		btm_chan_num = adc_tm->sensor[sensor_num].btm_channel_num;
+		pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+			sensor_num, adc_tm_high_enable, adc_tm_low_enable,
+			qpnp_adc_tm_meas_en);
+		if (!adc_tm->sensor[sensor_num].thermal_node) {
+			/* For non thermal registered clients
+				such as usb_id, vbatt, pmic_therm */
+			pr_debug("non thermal node - mask:%x\n", sensor_mask);
+			sensor_mask = 1 << sensor_num;
+			rc = qpnp_adc_tm_reg_update(
 				QPNP_ADC_TM_LOW_THR_INT_EN,
-				thr_int_disable, false);
+				sensor_mask, false);
 			if (rc < 0) {
-				pr_err("low threshold int disable failed\n");
+				pr_err("low threshold int read failed\n");
 				goto fail;
 			}
-
-			if (adc_tm_low_enable == 1)
-				schedule_work(&adc_tm->usbid_work);
-			else if (adc_tm_low_enable == 2)
-				schedule_work(&adc_tm->batt_work);
-		}
-		break;
-		case 4:
-		case 8:
-		case 16:
-		{
-			/* Low voltage threshold is triggered by high temp */
+			adc_tm->sensor[sensor_num].low_thr_notify = true;
+		} else {
+			/* Uses the thermal sysfs registered device to disable
+				the corresponding low voltage threshold which
+				 is triggered by high temp */
+			pr_debug("thermal node with mask:%x\n", sensor_mask);
 			rc = qpnp_adc_tm_activate_trip_type(
-				adc_tm->sensor[sensor_notify_num].tz_dev,
+				adc_tm->sensor[sensor_num].tz_dev,
 				ADC_TM_TRIP_HIGH_WARM,
 				THERMAL_TRIP_ACTIVATION_DISABLED);
 			if (rc < 0) {
-				pr_err("notify error:%d\n", sensor_notify_num);
+				pr_err("notify error:%d\n", sensor_num);
 				goto fail;
 			}
-			schedule_work(&adc_tm->sensor[sensor_notify_num].work);
-		}
-		break;
-		default:
-			rc = -EINVAL;
 		}
 	}
 
+	rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_MULTI_MEAS_EN,
+		sensor_mask, false);
+	if (rc < 0) {
+		pr_err("multi meas disable for channel failed\n");
+		goto fail;
+	}
+
+	rc = qpnp_adc_tm_enable_if_channel_meas();
+	if (rc < 0) {
+		pr_err("re-enabling measurement failed\n");
+		return rc;
+	}
 fail:
+	mutex_unlock(&adc_tm->adc->adc_lock);
+
+	schedule_work(&adc_tm->sensor[sensor_num].work);
+
 	return rc;
 }
 
@@ -1074,6 +1215,8 @@
 	int rc;
 
 	rc = qpnp_adc_tm_read_status();
+	if (rc < 0)
+		pr_err("adc-tm high thr work failed\n");
 
 	return;
 }
@@ -1082,6 +1225,8 @@
 
 static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
 {
+	qpnp_adc_tm_disable();
+
 	schedule_work(&trigger_completion_adc_tm_high_thr_work);
 
 	return IRQ_HANDLED;
@@ -1092,6 +1237,8 @@
 	int rc;
 
 	rc = qpnp_adc_tm_read_status();
+	if (rc < 0)
+		pr_err("adc-tm low thr work failed\n");
 
 	return;
 }
@@ -1099,6 +1246,8 @@
 
 static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
 {
+	qpnp_adc_tm_disable();
+
 	schedule_work(&trigger_completion_adc_tm_low_thr_work);
 
 	return IRQ_HANDLED;
@@ -1120,7 +1269,7 @@
 	struct qpnp_vadc_result result;
 	int rc = 0;
 
-	rc = qpnp_vadc_read(adc_tm_sensor->sensor_num, &result);
+	rc = qpnp_vadc_read(adc_tm_sensor->vadc_channel_num, &result);
 	if (rc)
 		return rc;
 
@@ -1139,24 +1288,47 @@
 	.set_trip_temp = qpnp_adc_tm_set_trip_temp,
 };
 
-int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_usbid_param *param)
+int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_btm_param *param)
 {
 	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
-	uint32_t channel;
+	uint32_t channel, dt_index = 0, scale_type = 0;
 	int rc = 0;
 
 	if (!adc_tm || !adc_tm->adc_tm_initialized)
 		return -ENODEV;
 
 	if (param->threshold_notification == NULL) {
-		pr_err("No USB_ID high/low voltage notificaton??\n");
+		pr_err("No notification for high/low temp??\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&adc_tm->adc->adc_lock);
 
-	adc_tm->adc->amux_prop->amux_channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
-	channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
+	channel = param->channel;
+	while ((adc_tm->adc->adc_channels[dt_index].channel_num
+		!= channel) && (dt_index < adc_tm->max_channels_available))
+		dt_index++;
+
+	if (dt_index >= adc_tm->max_channels_available) {
+		pr_err("not a valid ADC_TM channel\n");
+		rc = -EINVAL;
+		goto fail_unlock;
+	}
+
+	rc = qpnp_adc_tm_check_revision(
+			adc_tm->sensor[dt_index].btm_channel_num);
+	if (rc < 0)
+		goto fail_unlock;
+
+	scale_type = adc_tm->adc->adc_channels[dt_index].adc_scale_fn;
+	if (scale_type >= SCALE_RSCALE_NONE) {
+		rc = -EBADF;
+		goto fail_unlock;
+	}
+
+	pr_debug("channel:%d, scale_type:%d, dt_idx:%d",
+					channel, scale_type, dt_index);
+	adc_tm->adc->amux_prop->amux_channel = channel;
 	adc_tm->adc->amux_prop->decimation =
 			adc_tm->adc->adc_channels[channel].adc_decimation;
 	adc_tm->adc->amux_prop->hw_settle_time =
@@ -1167,10 +1339,11 @@
 		ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
 	adc_tm->adc->amux_prop->chan_prop->meas_interval1 =
 						ADC_MEAS1_INTERVAL_1S;
-	qpnp_adc_usb_scaler(param, &adc_tm->adc->amux_prop->chan_prop->low_thr,
+	adc_tm_rscale_fn[scale_type].chan(param,
+			&adc_tm->adc->amux_prop->chan_prop->low_thr,
 			&adc_tm->adc->amux_prop->chan_prop->high_thr);
 	adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
-					QPNP_ADC_TM_M0_ADC_CH_SEL_CTL;
+				adc_tm->sensor[dt_index].btm_channel_num;
 	adc_tm->adc->amux_prop->chan_prop->timer_select =
 					ADC_MEAS_TIMER_SELECT1;
 	adc_tm->adc->amux_prop->chan_prop->state_request =
@@ -1181,144 +1354,103 @@
 		goto fail_unlock;
 	}
 
-	adc_tm->usb_id_param = param;
+	adc_tm->sensor[dt_index].btm_param = param;
+	adc_tm->sensor[dt_index].scale_type = scale_type;
 
 fail_unlock:
 	mutex_unlock(&adc_tm->adc->adc_lock);
 
 	return rc;
 }
+EXPORT_SYMBOL(qpnp_adc_tm_channel_measure);
+
+int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_btm_param *param)
+{
+	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
+	uint32_t channel, dt_index = 0, btm_chan_num;
+	u8 sensor_mask = 0;
+	int rc = 0;
+
+	if (!adc_tm || !adc_tm->adc_tm_initialized)
+		return -ENODEV;
+
+	mutex_lock(&adc_tm->adc->adc_lock);
+
+	/* Disable bank */
+	rc = qpnp_adc_tm_disable();
+	if (rc < 0) {
+		pr_err("adc-tm disable failed\n");
+		goto fail;
+	}
+
+	/* Check if a conversion is in progress */
+	rc = qpnp_adc_tm_req_sts_check();
+	if (rc < 0) {
+		pr_err("adc-tm req_sts check failed\n");
+		goto fail;
+	}
+
+	channel = param->channel;
+	while ((adc_tm->adc->adc_channels[dt_index].channel_num
+		!= channel) && (dt_index < adc_tm->max_channels_available))
+		dt_index++;
+
+	if (dt_index >= adc_tm->max_channels_available) {
+		pr_err("not a valid ADC_TMN channel\n");
+		rc = -EINVAL;
+		goto fail;
+	}
+
+	btm_chan_num = adc_tm->sensor[dt_index].btm_channel_num;
+	sensor_mask = 1 << adc_tm->sensor[dt_index].sensor_num;
+
+	rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_LOW_THR_INT_EN,
+		sensor_mask, false);
+	if (rc < 0) {
+		pr_err("low threshold int write failed\n");
+		goto fail;
+	}
+
+	rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
+		sensor_mask, false);
+	if (rc < 0) {
+		pr_err("high threshold int enable failed\n");
+		goto fail;
+	}
+
+	rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_MULTI_MEAS_EN,
+		sensor_mask, false);
+	if (rc < 0) {
+		pr_err("multi measurement en failed\n");
+		goto fail;
+	}
+
+	rc = qpnp_adc_tm_enable_if_channel_meas();
+	if (rc < 0)
+		pr_err("re-enabling measurement failed\n");
+
+fail:
+	mutex_unlock(&adc_tm->adc->adc_lock);
+
+	return rc;
+}
+EXPORT_SYMBOL(qpnp_adc_tm_disable_chan_meas);
+
+int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_btm_param *param)
+{
+	param->channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
+	return qpnp_adc_tm_channel_measure(param);
+}
 EXPORT_SYMBOL(qpnp_adc_tm_usbid_configure);
 
-static int32_t qpnp_adc_tm_chan_usbid_chan_btm_end(
-				uint32_t btm_chan_num)
-{
-	int32_t rc = 0;
-
-	rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_LOW_THR_INT_EN,
-		adc_tm_data[btm_chan_num].low_thr_int_chan_en,
-		false);
-	if (rc < 0) {
-		pr_err("low threshold int write failed\n");
-		return rc;
-	}
-
-	rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
-		adc_tm_data[btm_chan_num].high_thr_int_chan_en,
-		false);
-	if (rc < 0) {
-		pr_err("high threshold int enable failed\n");
-		return rc;
-	}
-
-	rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_MULTI_MEAS_EN,
-		adc_tm_data[btm_chan_num].multi_meas_en,
-		false);
-	if (rc < 0) {
-		pr_err("multi measurement en failed\n");
-		return rc;
-	}
-
-	rc = qpnp_adc_tm_enable(false);
-	if (rc < 0)
-		pr_err("TM disable failed\n");
-
-	return rc;
-}
-
 int32_t qpnp_adc_tm_usbid_end(void)
 {
-	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
-	int rc = 0;
+	struct qpnp_adc_tm_btm_param param;
 
-	if (!adc_tm || !adc_tm->adc_tm_initialized)
-		return -ENODEV;
-
-	mutex_lock(&adc_tm->adc->adc_lock);
-
-	rc = qpnp_adc_tm_chan_usbid_chan_btm_end(
-				QPNP_ADC_TM_M0_ADC_CH_SEL_CTL);
-	if (rc < 0)
-		pr_err("disabling thresholds for usb channel failed\n");
-
-	mutex_unlock(&adc_tm->adc->adc_lock);
-
-	return rc;
+	return qpnp_adc_tm_disable_chan_meas(&param);
 }
 EXPORT_SYMBOL(qpnp_adc_tm_usbid_end);
 
-int32_t qpnp_adc_tm_btm_configure(struct qpnp_adc_tm_btm_param *param)
-{
-	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
-	uint32_t channel;
-	int rc = 0;
-
-	if (!adc_tm || !adc_tm->adc_tm_initialized)
-		return -ENODEV;
-
-	if (param->threshold_notification == NULL) {
-		pr_err("No battery high/low temp notificaton??\n");
-		return -EINVAL;
-	}
-
-	mutex_lock(&adc_tm->adc->adc_lock);
-
-	adc_tm->adc->amux_prop->amux_channel = LR_MUX1_BATT_THERM;
-	channel = LR_MUX1_BATT_THERM;
-	adc_tm->adc->amux_prop->decimation =
-			adc_tm->adc->adc_channels[channel].adc_decimation;
-	adc_tm->adc->amux_prop->hw_settle_time =
-			adc_tm->adc->adc_channels[channel].hw_settle_time;
-	adc_tm->adc->amux_prop->fast_avg_setup =
-			adc_tm->adc->adc_channels[channel].fast_avg_setup;
-	adc_tm->adc->amux_prop->mode_sel =
-		ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
-	adc_tm->adc->amux_prop->chan_prop->meas_interval2 =
-						ADC_MEAS2_INTERVAL_1S;
-	qpnp_adc_btm_scaler(param, &adc_tm->adc->amux_prop->chan_prop->low_thr,
-			&adc_tm->adc->amux_prop->chan_prop->high_thr);
-	adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
-					QPNP_ADC_TM_M1_ADC_CH_SEL_CTL;
-	adc_tm->adc->amux_prop->chan_prop->timer_select =
-					ADC_MEAS_TIMER_SELECT2;
-	adc_tm->adc->amux_prop->chan_prop->state_request =
-					param->state_request;
-	rc = qpnp_adc_tm_configure(adc_tm->adc->amux_prop);
-	if (rc) {
-		pr_err("adc-tm configure failed with %d\n", rc);
-		goto fail_unlock;
-	}
-
-	adc_tm->battery_param = param;
-
-fail_unlock:
-	mutex_unlock(&adc_tm->adc->adc_lock);
-
-	return rc;
-}
-EXPORT_SYMBOL(qpnp_adc_tm_btm_configure);
-
-int32_t qpnp_adc_tm_btm_end(void)
-{
-	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
-	int rc = 0;
-
-	if (!adc_tm || !adc_tm->adc_tm_initialized)
-		return -ENODEV;
-
-	mutex_lock(&adc_tm->adc->adc_lock);
-
-	rc = qpnp_adc_tm_chan_usbid_chan_btm_end(
-				QPNP_ADC_TM_M1_ADC_CH_SEL_CTL);
-	if (rc < 0)
-		pr_err("disabling thresholds for batt channel failed\n");
-
-	mutex_unlock(&adc_tm->adc->adc_lock);
-
-	return rc;
-}
-EXPORT_SYMBOL(qpnp_adc_tm_btm_end);
-
 int32_t qpnp_adc_tm_is_ready(void)
 {
 	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
@@ -1335,7 +1467,7 @@
 	struct device_node *node = spmi->dev.of_node, *child;
 	struct qpnp_adc_tm_drv *adc_tm;
 	struct qpnp_adc_drv *adc_qpnp;
-	int32_t count_adc_channel_list = 0, rc, i = 0, j = 0;
+	int32_t count_adc_channel_list = 0, rc, sen_idx = 0;
 	u8 thr_init = 0;
 
 	if (!node)
@@ -1363,6 +1495,7 @@
 		return -ENOMEM;
 	}
 
+	qpnp_adc_tm = adc_tm;
 	adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
 			GFP_KERNEL);
 	if (!adc_qpnp) {
@@ -1430,41 +1563,45 @@
 	for_each_child_of_node(node, child) {
 		char name[25];
 		int btm_channel_num;
+		bool thermal_node = false;
+
 		rc = of_property_read_u32(child,
 				"qcom,btm-channel-number", &btm_channel_num);
 		if (rc) {
 			pr_err("Invalid btm channel number\n");
 			goto fail;
 		}
-
-		if ((btm_channel_num != QPNP_ADC_TM_M0_ADC_CH_SEL_CTL) &&
-			(btm_channel_num != QPNP_ADC_TM_M1_ADC_CH_SEL_CTL)) {
+		adc_tm->sensor[sen_idx].btm_channel_num = btm_channel_num;
+		adc_tm->sensor[sen_idx].vadc_channel_num =
+				adc_tm->adc->adc_channels[sen_idx].channel_num;
+		adc_tm->sensor[sen_idx].sensor_num = sen_idx;
+		pr_debug("btm_chan:%x, vadc_chan:%x\n", btm_channel_num,
+			adc_tm->adc->adc_channels[sen_idx].channel_num);
+		if (thermal_node) {
 			/* Register with the thermal zone */
-			adc_tm->sensor[i].mode = THERMAL_DEVICE_DISABLED;
-			snprintf(name, sizeof(name), "qpnp_adc_tm_sensor%d", i);
-			adc_tm->sensor[i].sensor_num =
-				adc_tm->adc->adc_channels[j].channel_num;
-			adc_tm->sensor[i].btm_channel_num = btm_channel_num;
-			adc_tm->sensor[i].meas_interval =
+			pr_debug("thermal node%x\n", btm_channel_num);
+			adc_tm->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
+			adc_tm->sensor[sen_idx].thermal_node = true;
+			snprintf(name, sizeof(name),
+				adc_tm->adc->adc_channels[sen_idx].name);
+			adc_tm->sensor[sen_idx].meas_interval =
 				QPNP_ADC_TM_MEAS_INTERVAL;
-			adc_tm->sensor[i].low_thr = QPNP_ADC_TM_M0_LOW_THR;
-			adc_tm->sensor[i].high_thr = QPNP_ADC_TM_M0_HIGH_THR;
-			adc_tm->sensor[i].tz_dev =
+			adc_tm->sensor[sen_idx].low_thr =
+						QPNP_ADC_TM_M0_LOW_THR;
+			adc_tm->sensor[sen_idx].high_thr =
+						QPNP_ADC_TM_M0_HIGH_THR;
+			adc_tm->sensor[sen_idx].tz_dev =
 				thermal_zone_device_register(name,
 				ADC_TM_TRIP_NUM,
-				&adc_tm->sensor[i],
+				&adc_tm->sensor[sen_idx],
 				&qpnp_adc_tm_thermal_ops, 0, 0, 0, 0);
-			if (IS_ERR(adc_tm->sensor[i].tz_dev))
+			if (IS_ERR(adc_tm->sensor[sen_idx].tz_dev))
 				pr_err("thermal device register failed.\n");
-				INIT_WORK(&adc_tm->sensor[i].work,
-					notify_uspace_qpnp_adc_tm_fn);
-			i++;
 		}
-		j++;
+		INIT_WORK(&adc_tm->sensor[sen_idx].work, notify_adc_tm_fn);
+		sen_idx++;
 	}
-	INIT_WORK(&adc_tm->usbid_work, notify_usb_fn);
-	INIT_WORK(&adc_tm->batt_work, notify_batt_fn);
-	qpnp_adc_tm = adc_tm;
+	adc_tm->max_channels_available = count_adc_channel_list;
 	dev_set_drvdata(&spmi->dev, adc_tm);
 	rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_HIGH_THR_INT_EN, thr_init);
 	if (rc < 0) {
@@ -1486,6 +1623,7 @@
 
 	adc_tm->adc_tm_initialized = true;
 
+	pr_debug("OK\n");
 	return 0;
 fail:
 	qpnp_adc_tm = NULL;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 4710110..9fad90c 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -188,7 +188,7 @@
 	enum usb_chg_state	chg_state;
 	int			pmic_id_irq;
 	struct work_struct	id_work;
-	struct qpnp_adc_tm_usbid_param	adc_param;
+	struct qpnp_adc_tm_btm_param	adc_param;
 	struct delayed_work	init_adc_work;
 	bool			id_adc_detect;
 	u8			dcd_retries;
@@ -2086,16 +2086,25 @@
 static void dwc3_id_work(struct work_struct *w)
 {
 	struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, id_work);
+	int ret;
 
 	/* Give external client a chance to handle */
-	if (!mdwc->ext_inuse) {
-		if (usb_ext) {
-			int ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
-						  dwc3_ext_notify_online);
-			dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
-				__func__, ret);
-			mdwc->ext_inuse = (ret == 0);
+	if (!mdwc->ext_inuse && usb_ext) {
+		if (mdwc->pmic_id_irq)
+			disable_irq(mdwc->pmic_id_irq);
+
+		ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
+				      dwc3_ext_notify_online);
+		dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
+			__func__, ret);
+
+		if (mdwc->pmic_id_irq) {
+			/* ID may have changed while IRQ disabled; update it */
+			mdwc->id_state = !!irq_read_line(mdwc->pmic_id_irq);
+			enable_irq(mdwc->pmic_id_irq);
 		}
+
+		mdwc->ext_inuse = (ret == 0);
 	}
 
 	if (!mdwc->ext_inuse) { /* notify OTG */
@@ -2107,10 +2116,14 @@
 static irqreturn_t dwc3_pmic_id_irq(int irq, void *data)
 {
 	struct dwc3_msm *mdwc = data;
+	enum dwc3_id_state id;
 
 	/* If we can't read ID line state for some reason, treat it as float */
-	mdwc->id_state = !!irq_read_line(irq);
-	queue_work(system_nrt_wq, &mdwc->id_work);
+	id = !!irq_read_line(irq);
+	if (mdwc->id_state != id) {
+		mdwc->id_state = id;
+		queue_work(system_nrt_wq, &mdwc->id_work);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -2159,7 +2172,7 @@
 	mdwc->adc_param.high_thr = adc_high_threshold;
 	mdwc->adc_param.timer_interval = adc_meas_interval;
 	mdwc->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
-	mdwc->adc_param.usbid_ctx = mdwc;
+	mdwc->adc_param.btm_ctx = mdwc;
 	mdwc->adc_param.threshold_notification = dwc3_adc_notification;
 
 	ret = qpnp_adc_tm_usbid_configure(&mdwc->adc_param);
@@ -2370,7 +2383,7 @@
 		goto free_hs_ldo_init;
 	}
 
-	msm->ext_xceiv.id = DWC3_ID_FLOAT;
+	msm->id_state = msm->ext_xceiv.id = DWC3_ID_FLOAT;
 	msm->ext_xceiv.otg_capability = of_property_read_bool(node,
 				"qcom,otg-capability");
 	msm->charger.charging_disabled = of_property_read_bool(node,
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index dd41638..c847ee6 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -90,6 +90,8 @@
 	u32 smp_mb_cnt;
 	u32 smp_mb_size;
 
+	u32 rot_block_size;
+
 	struct mdss_hw_settings *hw_settings;
 
 	struct mdss_mdp_pipe *vig_pipes;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index e8a3795..b93efd9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -2283,15 +2283,14 @@
 		/* If power down is already underway, wait for it to finish */
 		flush_work_sync(&hdmi_ctrl->power_off_work);
 
-		if (!hdmi_ctrl->panel_power_on) {
+		if (!hdmi_ctrl->panel_power_on)
 			hdmi_tx_hpd_off(hdmi_ctrl);
-		} else {
+		else
 			hdmi_ctrl->hpd_off_pending = true;
 
-			hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
-			DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
-				hdmi_ctrl->sdev.state);
-		}
+		hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
+		DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
+			hdmi_ctrl->sdev.state);
 	}
 
 	return rc;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 749afd8..217ac18 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -127,6 +127,7 @@
 static int mdss_mdp_parse_dt_prop_len(struct platform_device *pdev,
 				       char *prop_name);
 static int mdss_mdp_parse_dt_smp(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_misc(struct platform_device *pdev);
 
 int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd,
 			  u32 size, u32 *phys, void **virt)
@@ -1029,7 +1030,7 @@
 
 	vbif_arr = of_get_property(pdev->dev.of_node, "qcom,vbif-settings",
 			&vbif_len);
-	if (!vbif_arr || (mdp_len & 1)) {
+	if (!vbif_arr || (vbif_len & 1)) {
 		pr_warn("MDSS VBIF settings not found\n");
 		vbif_len = 0;
 	}
@@ -1100,6 +1101,12 @@
 		return rc;
 	}
 
+	rc = mdss_mdp_parse_dt_misc(pdev);
+	if (rc) {
+		pr_err("Error in device tree : misc\n");
+		return rc;
+	}
+
 	return 0;
 }
 
@@ -1384,6 +1391,19 @@
 	return rc;
 }
 
+static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
+{
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+	u32 data;
+	int rc;
+
+	rc = of_property_read_u32(pdev->dev.of_node, "qcom,mdss-rot-block-size",
+		&data);
+	mdata->rot_block_size = (!rc ? data : 128);
+
+	return 0;
+}
+
 static int mdss_mdp_parse_dt_handler(struct platform_device *pdev,
 		char *prop_name, u32 *offsets, int len)
 {
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index f8cd0ce..18c38a0 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -164,6 +164,9 @@
 #define MDSS_MDP_REG_SSPP_STILE_FRAME_SIZE		0x02C
 #define MDSS_MDP_REG_SSPP_SRC_FORMAT			0x030
 #define MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN		0x034
+#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_0		0x050
+#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_1		0x054
+#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_2		0x058
 
 #define MDSS_MDP_REG_SSPP_SRC_OP_MODE			0x038
 #define MDSS_MDP_OP_DEINTERLACE			BIT(22)
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index c6b6e3f..b7b3c23 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -17,8 +17,6 @@
 #include "mdss_mdp.h"
 #include "mdss_mdp_rotator.h"
 
-#define ROT_BLK_SIZE	128
-
 enum mdss_mdp_writeback_type {
 	MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
 	MDSS_MDP_WRITEBACK_TYPE_LINE,
@@ -251,7 +249,7 @@
 	pr_debug("rot setup wb_num=%d\n", ctx->wb_num);
 
 	ctx->opmode = BIT(6); /* ROT EN */
-	if (ROT_BLK_SIZE == 128)
+	if (ctl->mdata->rot_block_size == 128)
 		ctx->opmode |= BIT(4); /* block size 128 */
 
 	ctx->opmode |= rot->bwc_mode;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 7ff6414..ca741b1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -19,7 +19,9 @@
 
 #include "mdss_mdp.h"
 
-#define SMP_MB_CNT (mdss_res->smp_mb_cnt)
+#define SMP_MB_SIZE		(mdss_res->smp_mb_size)
+#define SMP_MB_CNT		(mdss_res->smp_mb_cnt)
+#define SMP_ENTRIES_PER_MB	(SMP_MB_SIZE / 16)
 
 static DEFINE_MUTEX(mdss_mdp_sspp_lock);
 static DEFINE_MUTEX(mdss_mdp_smp_lock);
@@ -29,6 +31,17 @@
 						  u32 ndx);
 static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
 
+static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
+				       u32 reg, u32 val)
+{
+	writel_relaxed(val, pipe->base + reg);
+}
+
+static inline u32 mdss_mdp_pipe_read(struct mdss_mdp_pipe *pipe, u32 reg)
+{
+	return readl_relaxed(pipe->base + reg);
+}
+
 static u32 mdss_mdp_smp_mmb_reserve(unsigned long *smp, size_t n)
 {
 	u32 i, mmb;
@@ -45,9 +58,10 @@
 	return i;
 }
 
-static void mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp)
+static int mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp)
 {
 	u32 mmb, off, data, s;
+	int cnt = 0;
 
 	for_each_set_bit(mmb, smp, SMP_MB_CNT) {
 		off = (mmb / 3) * 4;
@@ -57,7 +71,9 @@
 		data |= client_id << s;
 		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SMP_ALLOC_W0 + off, data);
 		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SMP_ALLOC_R0 + off, data);
+		cnt++;
 	}
+	return cnt;
 }
 
 static void mdss_mdp_smp_mmb_free(unsigned long *smp)
@@ -70,6 +86,24 @@
 	}
 }
 
+static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
+{
+	u32 entries, val, wm[3];
+
+	entries = mb_cnt * SMP_ENTRIES_PER_MB;
+	val = entries >> 2;
+
+	wm[0] = val;
+	wm[1] = wm[0] + val;
+	wm[2] = wm[1] + val;
+
+	pr_debug("pnum=%d watermarks %u,%u,%u\n", pipe->num,
+			wm[0], wm[1], wm[2]);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_0, wm[0]);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_1, wm[1]);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_2, wm[2]);
+}
+
 static void mdss_mdp_smp_free(struct mdss_mdp_pipe *pipe)
 {
 	mutex_lock(&mdss_mdp_smp_lock);
@@ -103,8 +137,7 @@
 
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < ps.num_planes; i++) {
-		num_blks = DIV_ROUND_UP(2 * ps.ystride[i],
-			mdss_res->smp_mb_size);
+		num_blks = DIV_ROUND_UP(2 * ps.ystride[i], SMP_MB_SIZE);
 
 		if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
 			num_blks = roundup_pow_of_two(num_blks);
@@ -131,9 +164,12 @@
 static int mdss_mdp_smp_alloc(struct mdss_mdp_pipe *pipe)
 {
 	int i;
+	int cnt = 0;
+
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < MAX_PLANES; i++)
-		mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
+		cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
+	mdss_mdp_smp_set_wm_levels(pipe, cnt);
 	mutex_unlock(&mdss_mdp_smp_lock);
 	return 0;
 }
@@ -327,17 +363,6 @@
 
 }
 
-static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
-				       u32 reg, u32 val)
-{
-	writel_relaxed(val, pipe->base + reg);
-}
-
-static inline u32 mdss_mdp_pipe_read(struct mdss_mdp_pipe *pipe, u32 reg)
-{
-	return readl_relaxed(pipe->base + reg);
-}
-
 static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe)
 {
 	u32 img_size, src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 077b4e4..b54e0ec 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -405,8 +405,7 @@
 			if (data->flags & MDP_SECURE_OVERLAY_SESSION) {
 				domain = MDSS_IOMMU_DOMAIN_SECURE;
 				ret = msm_ion_secure_buffer(iclient,
-					data->srcp_ihdl, 0x2,
-					ION_UNSECURE_DELAYED);
+					data->srcp_ihdl, 0x2, 0);
 				if (IS_ERR_VALUE(ret)) {
 					ion_free(iclient, data->srcp_ihdl);
 					pr_err("failed to secure handle (%d)\n",
@@ -419,8 +418,7 @@
 
 			ret = ion_map_iommu(iclient, data->srcp_ihdl,
 					    mdss_get_iommu_domain(domain),
-					    0, SZ_4K, 0, start, len, 0,
-					    ION_IOMMU_UNMAP_DELAYED);
+					    0, SZ_4K, 0, start, len, 0, 0);
 		} else {
 			ret = ion_phys(iclient, data->srcp_ihdl, start,
 				       (size_t *) len);
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index 2341068..96e8b67 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -339,8 +339,8 @@
 {
 	int key_press = (key_code & 0x80) == 0;
 
-	pr_debug("%s: send key events[%x][%d]\n",
-		 __func__, key_code, key_press);
+	pr_debug("%s: send key events[%x][%x][%d]\n",
+		 __func__, key_code, input_key_code, key_press);
 	input_report_key(mhl_ctrl->input, input_key_code, key_press);
 	input_sync(mhl_ctrl->input);
 }
@@ -504,6 +504,7 @@
 			/* SET_INT: GRT_WRT */
 			pr_debug("%s: recvd req to permit/grant write",
 				 __func__);
+			complete_all(&mhl_ctrl->req_write_done);
 			mhl_msc_write_burst(
 				mhl_ctrl,
 				MHL_SCRATCHPAD_OFFSET,
@@ -599,31 +600,53 @@
 				   u8 start_reg,
 				   u8 length, u8 *data)
 {
-	int rc = 0;
+	int i, reg;
+	int timeout, retry = 20;
 
 	if (!(mhl_ctrl->devcap[DEVCAP_OFFSET_FEATURE_FLAG] &
 	      MHL_FEATURE_SP_SUPPORT)) {
 		pr_debug("MHL: SCRATCHPAD_NOT_SUPPORTED\n");
-		rc = -EFAULT;
-	} else {
-		if (mhl_ctrl->scrpd_busy) {
-			pr_debug("MHL: scratchpad_busy\n");
-			rc = -EBUSY;
-		} else {
-			int i, reg;
-			for (i = 0, reg = start_reg; (i < length) &&
-				     (reg < MHL_SCRATCHPAD_SIZE); i++, reg++)
-				mhl_ctrl->scrpd.data[reg] = data[i];
-			mhl_ctrl->scrpd.length = length;
-			mhl_ctrl->scrpd.offset = start_reg;
-			mhl_msc_send_set_int(
-				mhl_ctrl,
-				MHL_RCHANGE_INT,
-				MHL_INT_REQ_WRT,
-				MSC_PRIORITY_SEND);
-		}
+		return -EFAULT;
 	}
-	return rc;
+
+	/*
+	 * scratchpad remains busy as long as a peer's permission or
+	 * write bursts are pending; experimentally it was found that
+	 * 50ms is optimal
+	 */
+	while (mhl_ctrl->scrpd_busy && retry--)
+		msleep(50);
+	if (!retry) {
+		pr_debug("MHL: scratchpad_busy\n");
+		return -EBUSY;
+	}
+
+	for (i = 0, reg = start_reg; (i < length) &&
+		     (reg < MHL_SCRATCHPAD_SIZE); i++, reg++)
+		mhl_ctrl->scrpd.data[reg] = data[i];
+	mhl_ctrl->scrpd.length = length;
+	mhl_ctrl->scrpd.offset = start_reg;
+
+	retry = 5;
+	do {
+		init_completion(&mhl_ctrl->req_write_done);
+		mhl_msc_send_set_int(
+			mhl_ctrl,
+			MHL_RCHANGE_INT,
+			MHL_INT_REQ_WRT,
+			MSC_PRIORITY_SEND);
+		timeout = wait_for_completion_interruptible_timeout(
+			&mhl_ctrl->req_write_done,
+			msecs_to_jiffies(MHL_BURST_WAIT));
+		if (!timeout)
+			mhl_ctrl->scrpd_busy = false;
+	} while (retry-- && timeout == 0);
+	if (!timeout) {
+		pr_err("%s: timed out!\n", __func__);
+		return -EAGAIN;
+	}
+
+	return 0;
 }
 
 /* write scratchpad entry */
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index ccddf44..a3a1a4e 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -36,7 +36,7 @@
 #define COMPATIBLE_NAME "qcom,mhl-sii8334"
 #define MAX_CURRENT 700000
 
-#define pr_debug_intr(...) pr_debug("\n")
+#define pr_debug_intr(...)
 
 #define MSC_START_BIT_MSC_CMD        (0x01 << 0)
 #define MSC_START_BIT_VS_CMD        (0x01 << 1)
@@ -475,9 +475,10 @@
 	POWER_SUPPLY_PROP_CURRENT_MAX,
 };
 
-static void cbus_reset(struct i2c_client *client)
+static void cbus_reset(struct mhl_tx_ctrl *mhl_ctrl)
 {
 	uint8_t i;
+	struct i2c_client *client = mhl_ctrl->i2c_handle;
 
 	/*
 	 * REG_SRST
@@ -492,7 +493,10 @@
 	MHL_SII_REG_NAME_WR(REG_INTR4_MASK,
 		BIT0 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
 
-	MHL_SII_REG_NAME_WR(REG_INTR5_MASK, 0x00);
+	if (mhl_ctrl->chip_rev_id < 1)
+		MHL_SII_REG_NAME_WR(REG_INTR5_MASK, BIT3 | BIT4);
+	else
+		MHL_SII_REG_NAME_WR(REG_INTR5_MASK, 0x00);
 
 	/* Unmask CBUS1 Intrs */
 	MHL_SII_REG_NAME_WR(REG_CBUS_INTR_ENABLE,
@@ -523,7 +527,7 @@
 	/* Increase DDC translation layer timer*/
 	MHL_SII_CBUS_WR(0x0007, 0xF2);
 	/* Drive High Time */
-	MHL_SII_CBUS_WR(0x0036, 0x03);
+	MHL_SII_CBUS_WR(0x0036, 0x0B);
 	/* Use programmed timing */
 	MHL_SII_CBUS_WR(0x0039, 0x30);
 	/* CBUS Drive Strength */
@@ -590,6 +594,8 @@
 static void mhl_init_reg_settings(struct mhl_tx_ctrl *mhl_ctrl,
 	bool mhl_disc_en)
 {
+	uint8_t regval;
+
 	/*
 	 * ============================================
 	 * POWER UP
@@ -599,11 +605,6 @@
 
 	/* Power up 1.2V core */
 	MHL_SII_PAGE1_WR(0x003D, 0x3F);
-	/*
-	 * Wait for the source power to be enabled
-	 * before enabling pll clocks.
-	 */
-	msleep(50);
 	/* Enable Tx PLL Clock */
 	MHL_SII_PAGE2_WR(0x0011, 0x01);
 	/* Enable Tx Clock Path and Equalizer */
@@ -611,22 +612,26 @@
 	/* Tx Source Termination ON */
 	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0x10);
 	/* Enable 1X MHL Clock output */
-	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL6, 0xAC);
+	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL6, 0xBC);
 	/* Tx Differential Driver Config */
 	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL2, 0x3C);
-	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL4, 0xD9);
+	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL4, 0xC8);
 	/* PLL Bandwidth Control */
-	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL8, 0x02);
+	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL7, 0x03);
+	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL8, 0x0A);
 	/*
 	 * ============================================
 	 * Analog PLL Control
 	 * ============================================
 	 */
 	/* Enable Rx PLL clock */
-	MHL_SII_REG_NAME_WR(REG_TMDS_CCTRL,  0x00);
-	MHL_SII_PAGE0_WR(0x00F8, 0x0C);
+	MHL_SII_REG_NAME_WR(REG_TMDS_CCTRL,  0x08);
+	MHL_SII_PAGE0_WR(0x00F8, 0x8C);
 	MHL_SII_PAGE0_WR(0x0085, 0x02);
 	MHL_SII_PAGE2_WR(0x0000, 0x00);
+	regval = MHL_SII_PAGE2_RD(0x0005);
+	regval &= ~BIT5;
+	MHL_SII_PAGE2_WR(0x0005, regval);
 	MHL_SII_PAGE2_WR(0x0013, 0x60);
 	/* PLL Cal ref sel */
 	MHL_SII_PAGE2_WR(0x0017, 0x03);
@@ -646,6 +651,7 @@
 	/* Rx PLL Bandwidth value from I2C */
 	MHL_SII_PAGE2_WR(0x0045, 0x06);
 	MHL_SII_PAGE2_WR(0x004B, 0x06);
+	MHL_SII_PAGE2_WR(0x004C, 0x60);
 	/* Manual zone control */
 	MHL_SII_PAGE2_WR(0x004C, 0xE0);
 	/* PLL Mode value */
@@ -658,20 +664,21 @@
 	 */
 	MHL_SII_REG_NAME_WR(REG_DISC_CTRL2, 0xAD);
 	/* 1.8V CBUS VTH */
-	MHL_SII_REG_NAME_WR(REG_DISC_CTRL5, 0x55);
+	MHL_SII_REG_NAME_WR(REG_DISC_CTRL5, 0x57);
 	/* RGND and single Discovery attempt */
 	MHL_SII_REG_NAME_WR(REG_DISC_CTRL6, 0x11);
 	/* Ignore VBUS */
 	MHL_SII_REG_NAME_WR(REG_DISC_CTRL8, 0x82);
-	MHL_SII_REG_NAME_WR(REG_DISC_CTRL9, 0x24);
 
 	/* Enable CBUS Discovery */
 	if (mhl_disc_en) {
+		MHL_SII_REG_NAME_WR(REG_DISC_CTRL9, 0x24);
 		/* Enable MHL Discovery */
 		MHL_SII_REG_NAME_WR(REG_DISC_CTRL1, 0x27);
 		/* Pull-up resistance off for IDLE state */
 		MHL_SII_REG_NAME_WR(REG_DISC_CTRL4, 0x8C);
 	} else {
+		MHL_SII_REG_NAME_WR(REG_DISC_CTRL9, 0x26);
 		/* Disable MHL Discovery */
 		MHL_SII_REG_NAME_WR(REG_DISC_CTRL1, 0x26);
 		MHL_SII_REG_NAME_WR(REG_DISC_CTRL4, 0x8C);
@@ -684,14 +691,14 @@
 	MHL_SII_PAGE3_WR(0x3C, 0x80);
 
 	if (mhl_ctrl->cur_state != POWER_STATE_D3)
-		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT5 | BIT4, BIT4);
+		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT6 | BIT5 | BIT4, BIT4);
 
 	/* Enable Auto Soft RESET */
 	MHL_SII_REG_NAME_WR(REG_SRST, 0x084);
 	/* HDMI Transcode mode enable */
 	MHL_SII_PAGE0_WR(0x000D, 0x1C);
 
-	cbus_reset(client);
+	cbus_reset(mhl_ctrl);
 	init_cbus_regs(client);
 }
 
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index d208f1e..7939832 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -26,6 +26,7 @@
 #define UART_MODE			4
 #define SOCKET_MODE			5
 #define CALLBACK_MODE			6
+#define MEMORY_DEVICE_MODE_NRT		7
 /* different values that go in for diag_data_type */
 #define DATA_TYPE_EVENT         	0
 #define DATA_TYPE_F3            	1
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index d6f8356..d8eb494 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -157,6 +157,7 @@
 	struct scrpd_struct scrpd;
 	int scrpd_busy;
 	int wr_burst_pending;
+	struct completion req_write_done;
 };
 
 int mhl_i2c_reg_read(struct i2c_client *client,
diff --git a/include/linux/mhl_defs.h b/include/linux/mhl_defs.h
index aa63e03..f5dacfd 100644
--- a/include/linux/mhl_defs.h
+++ b/include/linux/mhl_defs.h
@@ -135,7 +135,7 @@
 
 /* manually define highest number */
 #define		MHL_MAX_BUFFER_SIZE			MHL_SCRATCHPAD_SIZE
-
+#define		MHL_BURST_WAIT		(1000)
 
 
 enum {
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 05d75ce..fc6ab91 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -195,7 +195,7 @@
 };
 
 /**
- * enum qpnp_adc_scale_fn_type - Scaling function for pm8921 pre calibrated
+ * enum qpnp_adc_scale_fn_type - Scaling function for pm8941 pre calibrated
  *				   digital data relative to ADC reference.
  * %ADC_SCALE_DEFAULT: Default scaling to convert raw adc code to voltage.
  * %ADC_SCALE_BATT_THERM: Conversion to temperature based on btm parameters.
@@ -217,6 +217,26 @@
 	SCALE_NONE,
 };
 
+
+/**
+ * enum qpnp_adc_tm_rscale_fn_type - Scaling function used to convert the
+ *	channels input voltage/temperature to corresponding ADC code that is
+ *	applied for thresholds. Check the corresponding channels scaling to
+ *	determine the appropriate temperature/voltage units that are passed
+ *	to the scaling function. Example battery follows the power supply
+ *	framework that needs its units to be in decidegreesC so it passes
+ *	deci-degreesC. PA_THERM clients pass the temperature in degrees.
+ *	The order below should match the one in the driver for
+ *	adc_tm_rscale_fn[].
+ */
+enum qpnp_adc_tm_rscale_fn_type {
+	SCALE_R_VBATT = 0,
+	SCALE_RBATT_THERM,
+	SCALE_R_USB_ID,
+	SCALE_RPMIC_THERM,
+	SCALE_RSCALE_NONE,
+};
+
 /**
  * enum qpnp_adc_fast_avg_ctl - Provides ability to obtain single result
  *		from the ADC that is an average of multiple measurement
@@ -560,16 +580,11 @@
 };
 
 /**
- * Channel selection registers for each of the 5 configurable measurements
- * Channels allotment is fixed for the given channels below.
- * The USB_ID and BATT_THERM channels are used only by the kernel space
- * USB and Battery drivers.
+ * Channel selection registers for each of the configurable measurements
+ * Channels allotment is set at device config for a channel.
+ * The USB_ID, BATT_THERM, PMIC_THERM and VBAT channels are used by the
+ * kernel space USB, Battery and IADC drivers.
  * The other 3 channels are configurable for use by userspace clients.
- * USB_ID uses QPNP_ADC_TM_M0_ADC_CH_SEL_CTL
- * BATT_TEMP uses QPNP_ADC_TM_M1_ADC_CH_SEL_CTL
- * PA_THERM1 uses QPNP_ADC_TM_M2_ADC_CH_SEL_CTL
- * PA_THERM2 uses QPNP_ADC_TM_M3_ADC_CH_SEL_CTL
- * EMMC_THERM uses QPNP_ADC_TM_M4_ADC_CH_SEL_CTL
  */
 enum qpnp_adc_tm_channel_select	{
 	QPNP_ADC_TM_M0_ADC_CH_SEL_CTL = 0x48,
@@ -577,6 +592,9 @@
 	QPNP_ADC_TM_M2_ADC_CH_SEL_CTL = 0x70,
 	QPNP_ADC_TM_M3_ADC_CH_SEL_CTL = 0x78,
 	QPNP_ADC_TM_M4_ADC_CH_SEL_CTL = 0x80,
+	QPNP_ADC_TM_M5_ADC_CH_SEL_CTL = 0x88,
+	QPNP_ADC_TM_M6_ADC_CH_SEL_CTL = 0x90,
+	QPNP_ADC_TM_M7_ADC_CH_SEL_CTL = 0x98,
 	QPNP_ADC_TM_CH_SELECT_NONE
 };
 
@@ -619,75 +637,84 @@
  * enum qpnp_tm_state - This lets the client know whether the threshold
  *		that was crossed was high/low.
  * %ADC_TM_HIGH_STATE: Client is notified of crossing the requested high
- *			threshold.
+ *			voltage threshold.
+ * %ADC_TM_COOL_STATE: Client is notified of crossing the requested cool
+ *			temperature threshold.
  * %ADC_TM_LOW_STATE: Client is notified of crossing the requested low
- *			threshold.
+ *			voltage threshold.
+ * %ADC_TM_WARM_STATE: Client is notified of crossing the requested high
+ *			temperature threshold.
  */
 enum qpnp_tm_state {
 	ADC_TM_HIGH_STATE = 0,
+	ADC_TM_COOL_STATE = ADC_TM_HIGH_STATE,
 	ADC_TM_LOW_STATE,
+	ADC_TM_WARM_STATE = ADC_TM_LOW_STATE,
 	ADC_TM_STATE_NUM,
 };
 
 /**
  * enum qpnp_state_request - Request to enable/disable the corresponding
  *			high/low voltage/temperature thresholds.
- * %ADC_TM_HIGH_THR_ENABLE: Enable high voltage/temperature threshold.
+ * %ADC_TM_HIGH_THR_ENABLE: Enable high voltage threshold.
+ * %ADC_TM_COOL_THR_ENABLE = Enables cool temperature threshold.
  * %ADC_TM_LOW_THR_ENABLE: Enable low voltage/temperature threshold.
+ * %ADC_TM_WARM_THR_ENABLE = Enables warm temperature threshold.
  * %ADC_TM_HIGH_LOW_THR_ENABLE: Enable high and low voltage/temperature
  *				threshold.
  * %ADC_TM_HIGH_THR_DISABLE: Disable high voltage/temperature threshold.
+ * %ADC_TM_COOL_THR_ENABLE = Disables cool temperature threshold.
  * %ADC_TM_LOW_THR_DISABLE: Disable low voltage/temperature threshold.
+ * %ADC_TM_WARM_THR_ENABLE = Disables warm temperature threshold.
  * %ADC_TM_HIGH_THR_DISABLE: Disable high and low voltage/temperature
  *				threshold.
  */
 enum qpnp_state_request {
 	ADC_TM_HIGH_THR_ENABLE = 0,
+	ADC_TM_COOL_THR_ENABLE = ADC_TM_HIGH_THR_ENABLE,
 	ADC_TM_LOW_THR_ENABLE,
+	ADC_TM_WARM_THR_ENABLE = ADC_TM_LOW_THR_ENABLE,
 	ADC_TM_HIGH_LOW_THR_ENABLE,
 	ADC_TM_HIGH_THR_DISABLE,
+	ADC_TM_COOL_THR_DISABLE = ADC_TM_HIGH_THR_DISABLE,
 	ADC_TM_LOW_THR_DISABLE,
+	ADC_TM_WARM_THR_DISABLE = ADC_TM_LOW_THR_DISABLE,
 	ADC_TM_HIGH_LOW_THR_DISABLE,
 	ADC_TM_THR_NUM,
 };
 
 /**
- * struct qpnp_adc_tm_usbid_param - Represent USB_ID threshold
- *				monitoring configuration.
- * @high_thr: High voltage threshold for which notification is requested.
- * @low_thr: Low voltage threshold for which notification is requested.
- * @state_request: Enable/disable the corresponding high and low voltage
- *		thresholds.
- * @timer_interval: Select polling rate from qpnp_adc_meas_timer_1 type.
- * @threshold_notification: Notification callback once threshold are crossed.
- * @usbid_ctx: A context of void type.
- */
-struct qpnp_adc_tm_usbid_param {
-	int32_t					high_thr;
-	int32_t					low_thr;
-	enum qpnp_state_request			state_request;
-	enum qpnp_adc_meas_timer_1		timer_interval;
-	void					*usbid_ctx;
-	void	(*threshold_notification) (enum qpnp_tm_state state,
-				void *ctx);
-};
-
-/**
  * struct qpnp_adc_tm_btm_param - Represent Battery temperature threshold
  *				monitoring configuration.
  * @high_temp: High temperature threshold for which notification is requested.
  * @low_temp: Low temperature threshold for which notification is requested.
+ * @high_thr_voltage: High voltage for which notification is requested.
+ * @low_thr_voltage: Low voltage for which notification is requested.
  * @state_request: Enable/disable the corresponding high and low temperature
  *		thresholds.
- * @timer_interval: Select polling rate from qpnp_adc_meas_timer_2 type.
+ * @timer_interval1: Select polling rate from qpnp_adc_meas_timer_1 type.
+ * @timer_interval2: Select polling rate from qpnp_adc_meas_timer_2 type.
+ * @timer_interval3: Select polling rate from qpnp_adc_meas_timer_3 type.
  * @btmid_ctx: A context of void type.
  * @threshold_notification: Notification callback once threshold are crossed.
+ * units to be used for High/Low temperature and voltage notification -
+ * This depends on the clients usage. Check the rscaling function
+ * for the appropriate channel nodes.
+ * @Batt therm clients temperature units is decidegreesCentigrate.
+ * @USB_ID inputs the voltage units in milli-volts.
+ * @PA_THERM inputs the units in degC.
+ * @PMIC_THERM inputs the units in millidegC.
  */
 struct qpnp_adc_tm_btm_param {
 	int32_t					high_temp;
 	int32_t					low_temp;
+	int32_t					high_thr;
+	int32_t					low_thr;
+	enum qpnp_vadc_channels			channel;
 	enum qpnp_state_request			state_request;
-	enum qpnp_adc_meas_timer_2		timer_interval;
+	enum qpnp_adc_meas_timer_1		timer_interval;
+	enum qpnp_adc_meas_timer_2		timer_interval2;
+	enum qpnp_adc_meas_timer_3		timer_interval3;
 	void					*btm_ctx;
 	void	(*threshold_notification) (enum qpnp_tm_state state,
 						void *ctx);
@@ -841,6 +868,17 @@
 };
 
 /**
+ * struct qpnp_adc_tm_reverse_scale_fn - Reverse scaling prototype
+ * @chan: Function pointer to one of the scaling functions
+ *	which takes the adc properties, channel properties,
+ *	and returns the physical result
+ */
+struct qpnp_adc_tm_reverse_scale_fn {
+	int32_t (*chan) (struct qpnp_adc_tm_btm_param *,
+		uint32_t *, uint32_t *);
+};
+
+/**
  * struct qpnp_iadc_calib - IADC channel calibration structure.
  * @channel - Channel for which the historical offset and gain is
  *	      calculated. Available channels are internal rsense,
@@ -1107,6 +1145,21 @@
 int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_linear_graph *param,
 			enum qpnp_adc_calib_type calib_type);
 /**
+ * qpnp_adc_scale_millidegc_pmic_voltage_thr() - Performs reverse calibration
+ *		on the low/high temperature threshold values passed by the
+ *		client. The function coverts milldegC to voltage threshold
+ *		and accounts for the corresponding channels scaling as (2mV/K).
+ * @param:	The input parameters that contain the low/high temperature
+ *		values.
+ * @low_threshold: The low threshold value that needs to be updated with
+ *		the above calibrated voltage value.
+ * @high_threshold: The low threshold value that needs to be updated with
+ *		the above calibrated voltage value.
+ */
+int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+		struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold);
+/**
  * qpnp_adc_btm_scaler() - Performs reverse calibration on the low/high
  *		temperature threshold values passed by the client.
  *		The function maps the temperature to voltage and applies
@@ -1147,7 +1200,21 @@
  * @high_threshold: The low threshold value that needs to be updated with
  *		the above calibrated voltage value.
  */
-int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_usbid_param *param,
+int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold);
+/**
+ * qpnp_adc_vbatt_rscaler() - Performs reverse calibration on the low/high
+ *		voltage threshold values passed by the client.
+ *		The function applies ratiometric calibration on the
+ *		voltage values.
+ * @param:	The input parameters that contain the low/high voltage
+ *		threshold values.
+ * @low_threshold: The low threshold value that needs to be updated with
+ *		the above calibrated voltage value.
+ * @high_threshold: The low threshold value that needs to be updated with
+ *		the above calibrated voltage value.
+ */
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold);
 /**
  * qpnp_vadc_iadc_sync_request() - Performs Voltage ADC read and
@@ -1217,13 +1284,21 @@
 			enum qpnp_adc_calib_type calib_type)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_usb_scaler(
-		struct qpnp_adc_tm_usbid_param *param,
+		struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_vbatt_rscaler(
+		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_btm_scaler(
 		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 { return -ENXIO; }
+static inline int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+		struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold)
+{ return -ENXIO; }
 static inline int32_t qpnp_adc_tm_scale_therm_voltage_pu2(
 				struct qpnp_adc_tm_config *param)
 { return -ENXIO; }
@@ -1314,7 +1389,7 @@
  *		Clients pass the low/high voltage along with the threshold
  *		notification callback.
  */
-int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_usbid_param *param);
+int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_btm_param *param);
 /**
  * qpnp_adc_tm_usbid_end() - Disables the monitoring of channel 0 thats
  *		assigned for monitoring USB_ID. Disables the low/high
@@ -1323,23 +1398,25 @@
  */
 int32_t qpnp_adc_tm_usbid_end(void);
 /**
- * qpnp_adc_tm_usbid_configure() - Configures Channel 1 of VADC_BTM to
- *		monitor batt_therm channel using 100k internal pull-up.
- *		Battery driver passes the high/low voltage threshold along
+ * qpnp_adc_tm_channel_measure() - Configures kernel clients a channel to
+ *		monitor the corresponding ADC channel for threshold detection.
+ *		Driver passes the high/low voltage threshold along
  *		with the notification callback once the set thresholds
  *		are crossed.
  * @param:	Structure pointer of qpnp_adc_tm_btm_param type.
  *		Clients pass the low/high temperature along with the threshold
  *		notification callback.
  */
-int32_t qpnp_adc_tm_btm_configure(struct qpnp_adc_tm_btm_param *param);
+int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_btm_param *param);
 /**
- * qpnp_adc_tm_btm_end() - Disables the monitoring of channel 1 thats
- *		assigned for monitoring batt_therm. Disables the low/high
- *		threshold activation for channel 1 as well.
- * @param:	none.
+ * qpnp_adc_tm_disable_chan_meas() - Disables the monitoring of channel thats
+ *		assigned for monitoring kernel clients. Disables the low/high
+ *		threshold activation for the corresponding channel.
+ * @param:	Structure pointer of qpnp_adc_tm_btm_param type.
+ *		This is used to identify the channel for which the corresponding
+ *		channels high/low threshold notification will be disabled.
  */
-int32_t qpnp_adc_tm_btm_end(void);
+int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_btm_param *param);
 /**
  * qpnp_adc_tm_is_ready() - Clients can use this API to check if the
  *			  device is ready to use.
@@ -1349,14 +1426,14 @@
 int32_t	qpnp_adc_tm_is_ready(void);
 #else
 static inline int32_t qpnp_adc_tm_usbid_configure(
-			struct qpnp_adc_tm_usbid_param *param)
+			struct qpnp_adc_tm_btm_param *param)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_tm_usbid_end(void)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_tm_btm_configure(
+static inline int32_t qpnp_adc_tm_channel_measure(
 		struct qpnp_adc_tm_btm_param *param)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_tm_btm_end(void)
+static inline int32_t qpnp_adc_tm_disable_chan_meas(void)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_tm_is_ready(void)
 { return -ENXIO; }
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index f88c817..1484f16 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -2418,6 +2418,16 @@
 	u32 sample_rate;
 } __packed;
 
+struct asm_amrwbplus_cfg {
+	u32  size_bytes;
+	u32  version;
+	u32  num_channels;
+	u32  amr_band_mode;
+	u32  amr_dtx_mode;
+	u32  amr_frame_fmt;
+	u32  amr_lsf_idx;
+} __packed;
+
 struct asm_softpause_params {
 	u32 enable;
 	u32 period;
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 5744a43..f9d2a40 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -294,6 +294,8 @@
 int q6asm_media_format_block_wmapro(struct audio_client *ac,
 			void *cfg);
 
+int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
+			struct asm_amrwbplus_cfg *cfg);
 /* PP specific */
 int q6asm_equalizer(struct audio_client *ac, void *eq);
 
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 7aac5f6..fcde89a 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -511,7 +511,7 @@
 	int error;
 
 	if (state == PM_SUSPEND_ON
-	    && !(strncmp(buf, "off", 3) && strncmp(buf, "off\n", 4)))
+	    && strcmp(buf, "off") && strcmp(buf, "off\n"))
 		return -EINVAL;
 
 	error = pm_autosleep_set_state(state);
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 634493b..ca8cfaa 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -2135,12 +2135,12 @@
 
 	dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
 	if (w->shift == 5) {
-		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
-		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
-		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
-	} else if (w->shift == 4) {
 		e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
 		e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
+	} else if (w->shift == 4) {
+		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
+		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
 		req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
 	} else {
 		pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 80738ba..9c234a7 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -3869,7 +3869,7 @@
 					taiko->comp_fs[comp_rx_path[j]]
 					= compander_fs;
 			}
-			if (j <= 2)
+			if (j < 2)
 				rx_mix_1_reg_1 += 3;
 			else
 				rx_mix_1_reg_1 += 2;
@@ -5420,6 +5420,12 @@
 	TAIKO_REG_VAL(TAIKO_A_CDC_TX9_MUX_CTL, 0x48),
 	TAIKO_REG_VAL(TAIKO_A_CDC_TX10_MUX_CTL, 0x48),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B4_CTL, 0x8),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B4_CTL, 0x8),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B4_CTL, 0x8),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B4_CTL, 0x8),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B4_CTL, 0x8),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B4_CTL, 0x8),
+	TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B4_CTL, 0x8),
 	TAIKO_REG_VAL(TAIKO_A_CDC_VBAT_GAIN_UPD_MON, 0x0),
 	TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B1_CTL, 0x0),
 	TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B2_CTL, 0x0),
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 5b54e1b..764f4c6 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -3018,14 +3018,19 @@
 	switch (event) {
 	case WCD9XXX_EVENT_PRE_MICBIAS_1_ON:
 		ret = MBHC_MICBIAS1;
+		break;
 	case WCD9XXX_EVENT_PRE_MICBIAS_2_ON:
 		ret = MBHC_MICBIAS2;
+		break;
 	case WCD9XXX_EVENT_PRE_MICBIAS_3_ON:
 		ret = MBHC_MICBIAS3;
+		break;
 	case WCD9XXX_EVENT_PRE_MICBIAS_4_ON:
 		ret = MBHC_MICBIAS4;
+		break;
 	default:
 		ret = MBHC_MICBIAS_INVALID;
+		break;
 	}
 	return ret;
 }
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 4dc6505..b97d9dc 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -772,20 +772,19 @@
 		.codec_name = "snd-soc-dummy",
 	},
 	{
-		.name = "VoLTE",
-		.stream_name = "VoLTE",
-		.cpu_dai_name   = "VoLTE",
+		.name = "Voice2",
+		.stream_name = "Voice2",
+		.cpu_dai_name   = "Voice2",
 		.platform_name  = "msm-pcm-voice",
 		.dynamic = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-				SND_SOC_DPCM_TRIGGER_POST},
+			    SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
-		.be_id = MSM_FRONTEND_DAI_VOLTE,
 	},
 	{
 		.name = "MSM8226 LowLatency",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 819512d..e7c13cd 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -565,6 +565,8 @@
 		session_id = voc_get_session_id(VOICE_SESSION_NAME);
 	else if (val == MSM_FRONTEND_DAI_VOLTE)
 		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+	else if (val == MSM_FRONTEND_DAI_VOICE2)
+		session_id = voc_get_session_id(VOICE2_SESSION_NAME);
 	else
 		session_id = voc_get_session_id(VOIP_SESSION_NAME);
 
@@ -1550,6 +1552,9 @@
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1565,6 +1570,9 @@
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1580,6 +1588,9 @@
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1595,6 +1606,9 @@
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1613,6 +1627,9 @@
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1631,6 +1648,9 @@
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1649,6 +1669,9 @@
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1667,6 +1690,9 @@
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1720,6 +1746,27 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new tx_voice2_mixer_controls[] = {
+	SOC_SINGLE_EXT("PRI_TX_Voice2", MSM_BACKEND_DAI_PRI_I2S_TX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("MI2S_TX_Voice2", MSM_BACKEND_DAI_MI2S_TX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SLIM_0_TX_Voice2", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice2",
+	MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_VOICE2, 1, 0,
+	msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX_Voice2", MSM_BACKEND_DAI_AFE_PCM_TX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AUX_PCM_TX_Voice2", MSM_BACKEND_DAI_AUXPCM_TX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new tx_volte_mixer_controls[] = {
 	SOC_SINGLE_EXT("PRI_TX_VoLTE", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
@@ -2235,6 +2282,8 @@
 	SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("VOICE2_DL", "Voice2 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("VOICE2_UL", "Voice2 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("VoLTE_UL", "VoLTE Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
@@ -2419,6 +2468,9 @@
 	SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
 				SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
 				ARRAY_SIZE(tx_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Voice2_Tx Mixer",
+			   SND_SOC_NOPM, 0, 0, tx_voice2_mixer_controls,
+			   ARRAY_SIZE(tx_voice2_mixer_controls)),
 	SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
 				SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
 				ARRAY_SIZE(tx_voip_mixer_controls)),
@@ -2595,48 +2647,56 @@
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
 	{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 	{"MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
 
 	{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"PRI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PRI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
 
 	{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SEC_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SEC_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
 
 	{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SLIM_0_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"SLIM_0_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SLIM_0_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
 
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
 
 	{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"AFE_PCM_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
 
 	{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"AUX_PCM_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
 
 	{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"HDMI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"HDMI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
@@ -2644,6 +2704,7 @@
 	{"HDMI", NULL, "HDMI_DL_HL"},
 
 	{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"MI2S_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
@@ -2656,6 +2717,15 @@
 	{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
 	{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
 	{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
+
+	{"Voice2_Tx Mixer", "PRI_TX_Voice2", "PRI_I2S_TX"},
+	{"Voice2_Tx Mixer", "MI2S_TX_Voice2", "MI2S_TX"},
+	{"Voice2_Tx Mixer", "SLIM_0_TX_Voice2", "SLIMBUS_0_TX"},
+	{"Voice2_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice2", "INT_BT_SCO_TX"},
+	{"Voice2_Tx Mixer", "AFE_PCM_TX_Voice2", "PCM_TX"},
+	{"Voice2_Tx Mixer", "AUX_PCM_TX_Voice2", "AUX_PCM_TX"},
+	{"VOICE2_UL", NULL, "Voice2_Tx Mixer"},
+
 	{"VoLTE_Tx Mixer", "PRI_TX_VoLTE", "PRI_I2S_TX"},
 	{"VoLTE_Tx Mixer", "SLIM_0_TX_VoLTE", "SLIMBUS_0_TX"},
 	{"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 798f676..1c1029c 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -73,6 +73,7 @@
 	MSM_FRONTEND_DAI_VOLTE,
 	MSM_FRONTEND_DAI_DTMF_RX,
 	MSM_FRONTEND_DAI_LSM1,
+	MSM_FRONTEND_DAI_VOICE2,
 	MSM_FRONTEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 333ee48..4df66d0 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.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
@@ -59,6 +59,29 @@
 		return false;
 }
 
+static int is_voice2(struct msm_voice *pvoice2)
+{
+	if (pvoice2 == &voice_info[VOICE2_SESSION_INDEX])
+		return true;
+	else
+		return false;
+}
+
+static uint16_t get_session_id(struct msm_voice *pvoc)
+{
+	uint16_t session_id = 0;
+
+	if (is_volte(pvoc))
+		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+	else if (is_voice2(pvoc))
+		session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+	else
+		session_id = voc_get_session_id(VOICE_SESSION_NAME);
+
+	return session_id;
+}
+
+
 static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
@@ -92,11 +115,15 @@
 	if (!strncmp("VoLTE", substream->pcm->id, 5)) {
 		voice = &voice_info[VOLTE_SESSION_INDEX];
 		pr_debug("%s: Open VoLTE Substream Id=%s\n",
-				__func__, substream->pcm->id);
+			 __func__, substream->pcm->id);
+	} else if (!strncmp("Voice2", substream->pcm->id, 6)) {
+		voice = &voice_info[VOICE2_SESSION_INDEX];
+		pr_debug("%s: Open Voice2 Substream Id=%s\n",
+			 __func__, substream->pcm->id);
 	} else {
 		voice = &voice_info[VOICE_SESSION_INDEX];
 		pr_debug("%s: Open VOICE Substream Id=%s\n",
-				__func__, substream->pcm->id);
+			 __func__, substream->pcm->id);
 	}
 	mutex_lock(&voice->lock);
 
@@ -160,11 +187,10 @@
 	prtd->instance--;
 	if (!prtd->playback_start && !prtd->capture_start) {
 		pr_debug("end voice call\n");
-		if (is_volte(prtd))
-			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
-		else
-			session_id = voc_get_session_id(VOICE_SESSION_NAME);
-		voc_end_voice_call(session_id);
+
+		session_id = get_session_id(prtd);
+		if (session_id)
+			voc_end_voice_call(session_id);
 	}
 	mutex_unlock(&prtd->lock);
 
@@ -185,11 +211,9 @@
 		ret = msm_pcm_capture_prepare(substream);
 
 	if (prtd->playback_start && prtd->capture_start) {
-		if (is_volte(prtd))
-			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
-		else
-			session_id = voc_get_session_id(VOICE_SESSION_NAME);
-		voc_start_voice_call(session_id);
+		session_id = get_session_id(prtd);
+		if (session_id)
+			voc_start_voice_call(session_id);
 	}
 	mutex_unlock(&prtd->lock);
 
@@ -215,10 +239,8 @@
 	uint16_t session_id = 0;
 
 	pr_debug("%s: cmd = %d\n", __func__, cmd);
-	if (is_volte(prtd))
-		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
-	else
-		session_id = voc_get_session_id(VOICE_SESSION_NAME);
+
+	session_id = get_session_id(prtd);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -233,8 +255,10 @@
 			ret = msm_pcm_playback_prepare(substream);
 		else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 			ret = msm_pcm_capture_prepare(substream);
-		if (prtd->playback_start && prtd->capture_start)
-			voc_resume_voice_call(session_id);
+		if (prtd->playback_start && prtd->capture_start) {
+			if (session_id)
+				voc_resume_voice_call(session_id);
+		}
 	break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -247,7 +271,8 @@
 			if (prtd->capture_start)
 				prtd->capture_start = 0;
 		}
-		voc_standby_voice_call(session_id);
+		if (session_id)
+			voc_standby_voice_call(session_id);
 		break;
 	default:
 		ret = -EINVAL;
@@ -290,6 +315,24 @@
 	return 0;
 }
 
+static int msm_voice2_volume_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int msm_voice2_volume_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	int volume = ucontrol->value.integer.value[0];
+	pr_debug("%s: volume: %d\n", __func__, volume);
+
+	voc_set_rx_vol_index(voc_get_session_id(VOICE2_SESSION_NAME),
+						RX_PATH, volume);
+	return 0;
+}
+
 static int msm_voice_mute_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -328,6 +371,25 @@
 	return 0;
 }
 
+static int msm_voice2_mute_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int msm_voice2_mute_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_tx_mute(voc_get_session_id(VOICE2_SESSION_NAME), TX_PATH, mute);
+
+	return 0;
+}
+
 static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -368,6 +430,26 @@
 	return 0;
 }
 
+static int msm_voice2_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] =
+		voc_get_rx_device_mute(voc_get_session_id(VOICE2_SESSION_NAME));
+	return 0;
+}
+
+static int msm_voice2_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_rx_device_mute(voc_get_session_id(VOICE2_SESSION_NAME), mute);
+
+	return 0;
+}
+
 static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
 static const struct soc_enum msm_tty_mode_enum[] = {
 		SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -389,6 +471,7 @@
 	pr_debug("%s: tty_mode=%d\n", __func__, tty_mode);
 
 	voc_set_tty_mode(voc_get_session_id(VOICE_SESSION_NAME), tty_mode);
+	voc_set_tty_mode(voc_get_session_id(VOICE2_SESSION_NAME), tty_mode);
 
 	return 0;
 }
@@ -401,6 +484,8 @@
 
 	voc_set_widevoice_enable(voc_get_session_id(VOICE_SESSION_NAME),
 				 wv_enable);
+	voc_set_widevoice_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+				 wv_enable);
 
 	return 0;
 }
@@ -422,7 +507,9 @@
 	pr_debug("%s: st enable=%d\n", __func__, st_enable);
 
 	voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
-			MODULE_ID_VOICE_MODULE_ST, st_enable);
+			  MODULE_ID_VOICE_MODULE_ST, st_enable);
+	voc_set_pp_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+			  MODULE_ID_VOICE_MODULE_ST, st_enable);
 
 	return 0;
 }
@@ -444,7 +531,9 @@
 	pr_debug("%s: fens enable=%d\n", __func__, fens_enable);
 
 	voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
-			MODULE_ID_VOICE_MODULE_FENS, fens_enable);
+			  MODULE_ID_VOICE_MODULE_FENS, fens_enable);
+	voc_set_pp_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+			  MODULE_ID_VOICE_MODULE_FENS, fens_enable);
 
 	return 0;
 }
@@ -481,6 +570,13 @@
 				msm_volte_mute_get, msm_volte_mute_put),
 	SOC_SINGLE_EXT("VoLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
 				msm_volte_volume_get, msm_volte_volume_put),
+	SOC_SINGLE_EXT("Voice2 Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+		       msm_voice2_rx_device_mute_get,
+		       msm_voice2_rx_device_mute_put),
+	SOC_SINGLE_EXT("Voice2 Tx Mute", SND_SOC_NOPM, 0, 1, 0,
+		       msm_voice2_mute_get, msm_voice2_mute_put),
+	SOC_SINGLE_EXT("Voice2 Rx Volume", SND_SOC_NOPM, 0, 5, 0,
+		       msm_voice2_volume_get, msm_voice2_volume_put),
 };
 
 static struct snd_pcm_ops msm_pcm_ops = {
@@ -550,9 +646,12 @@
 
 static int __init msm_soc_platform_init(void)
 {
+	int i = 0;
+
 	memset(&voice_info, 0, sizeof(voice_info));
-	mutex_init(&voice_info[VOICE_SESSION_INDEX].lock);
-	mutex_init(&voice_info[VOLTE_SESSION_INDEX].lock);
+
+	for (i = 0; i < VOICE_SESSION_INDEX_MAX; i++)
+		mutex_init(&voice_info[i].lock);
 
 	return platform_driver_register(&msm_pcm_driver);
 }
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
index a25fb2a..5425c46 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
@@ -16,6 +16,7 @@
 enum {
 	VOICE_SESSION_INDEX,
 	VOLTE_SESSION_INDEX,
+	VOICE2_SESSION_INDEX,
 	VOICE_SESSION_INDEX_MAX,
 };
 
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 65ac79b..ea2b5c6 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1651,6 +1651,9 @@
 	case FORMAT_AMRWB:
 		open.dec_fmt_id = ASM_MEDIA_FMT_AMRWB_FS;
 		break;
+	case FORMAT_AMR_WB_PLUS:
+		open.dec_fmt_id = ASM_MEDIA_FMT_AMR_WB_PLUS_V2;
+		break;
 	case FORMAT_V13K:
 		open.dec_fmt_id = ASM_MEDIA_FMT_V13K_FS;
 		break;
@@ -2532,6 +2535,42 @@
 	return -EINVAL;
 }
 
+int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
+				struct asm_amrwbplus_cfg *cfg)
+{
+	struct asm_amrwbplus_fmt_blk_v2 fmt;
+	int rc = 0;
+
+	pr_debug("%s:session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
+		__func__,
+		ac->session,
+		cfg->amr_band_mode,
+		cfg->amr_frame_fmt,
+		cfg->num_channels);
+
+	q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+
+	fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+	fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+					sizeof(fmt.fmtblk);
+	fmt.amr_frame_fmt = cfg->amr_frame_fmt;
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+	if (rc < 0) {
+		pr_err("%s:Comamnd media format update failed..\n", __func__);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+				(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return -EINVAL;
+}
+
 int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
 				uint32_t bufsz, uint32_t bufcnt)
 {
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 12e83b0..754a4fa 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -35,10 +35,6 @@
 #define CMD_STATUS_SUCCESS 0
 #define CMD_STATUS_FAIL 1
 
-#define VOC_PATH_PASSIVE 0
-#define VOC_PATH_FULL 1
-#define VOC_PATH_VOLTE_PASSIVE 2
-
 /* CVP CAL Size: 245760 = 240 * 1024 */
 #define CVP_CAL_SIZE 245760
 /* CVS CAL Size: 49152 = 48 * 1024 */
@@ -180,6 +176,9 @@
 	if (name != NULL) {
 		if (!strncmp(name, "Voice session", 13))
 			session_id = common.voice[VOC_PATH_PASSIVE].session_id;
+		else if (!strncmp(name, "Voice2 session", 14))
+			session_id =
+			common.voice[VOC_PATH_VOICE2_PASSIVE].session_id;
 		else if (!strncmp(name, "VoLTE session", 13))
 			session_id =
 			common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
@@ -223,6 +222,11 @@
 	return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id);
 }
 
+static bool is_voice2_session(u16 session_id)
+{
+	return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
+}
+
 static int voice_apr_register(void)
 {
 	void *modem_mvm, *modem_cvs, *modem_cvp;
@@ -347,7 +351,8 @@
 	}
 	pr_debug("%s: VoLTE command to MVM\n", __func__);
 	if (is_volte_session(v->session_id) ||
-		is_voice_session(v->session_id)) {
+		is_voice_session(v->session_id) ||
+		is_voice2_session(v->session_id)) {
 		mvm_handle = voice_get_mvm_handle(v);
 		mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
 						APR_MSG_TYPE_SEQ_CMD,
@@ -421,7 +426,8 @@
 
 	if (!mvm_handle) {
 		if (is_voice_session(v->session_id) ||
-				is_volte_session(v->session_id)) {
+			is_volte_session(v->session_id) ||
+			is_voice2_session(v->session_id)) {
 			mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
 						APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -441,8 +447,12 @@
 				strlcpy(mvm_session_cmd.mvm_session.name,
 				"default volte voice",
 				sizeof(mvm_session_cmd.mvm_session.name));
+			} else if (is_voice2_session(v->session_id)) {
+				strlcpy(mvm_session_cmd.mvm_session.name,
+				VOICE2_SESSION_VSID,
+				sizeof(mvm_session_cmd.mvm_session.name));
 			} else {
-			strlcpy(mvm_session_cmd.mvm_session.name,
+				strlcpy(mvm_session_cmd.mvm_session.name,
 				"default modem voice",
 				sizeof(mvm_session_cmd.mvm_session.name));
 			}
@@ -503,7 +513,8 @@
 	/* send cmd to create cvs session */
 	if (!cvs_handle) {
 		if (is_voice_session(v->session_id) ||
-			is_volte_session(v->session_id)) {
+			is_volte_session(v->session_id) ||
+			is_voice2_session(v->session_id)) {
 			pr_debug("%s: creating CVS passive session\n",
 				 __func__);
 
@@ -524,6 +535,10 @@
 				strlcpy(cvs_session_cmd.cvs_session.name,
 				"default volte voice",
 				sizeof(cvs_session_cmd.cvs_session.name));
+			} else if (is_voice2_session(v->session_id)) {
+				strlcpy(cvs_session_cmd.cvs_session.name,
+				VOICE2_SESSION_VSID,
+				sizeof(cvs_session_cmd.cvs_session.name));
 			} else {
 			strlcpy(cvs_session_cmd.cvs_session.name,
 				"default modem voice",
@@ -4167,6 +4182,7 @@
 			case VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL:
 			case VSS_IMVM_CMD_SET_CAL_NETWORK:
 			case VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE:
+			case VSS_IMEMORY_CMD_MAP_PHYSICAL:
 			case VSS_IMEMORY_CMD_UNMAP:
 			case VSS_IMVM_CMD_STANDBY_VOICE:
 				pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 98bd002..babfddc 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1275,7 +1275,7 @@
 	void *buf;
 };
 
-#define MAX_VOC_SESSIONS 3
+#define MAX_VOC_SESSIONS 4
 #define SESSION_ID_BASE 0xFFF0
 
 struct common_data {
@@ -1327,6 +1327,20 @@
 	TX_PATH,
 };
 
+
+#define VOC_PATH_PASSIVE 0
+#define VOC_PATH_FULL 1
+#define VOC_PATH_VOLTE_PASSIVE 2
+#define VOC_PATH_VOICE2_PASSIVE 3
+
+#define MAX_SESSION_NAME_LEN 32
+#define VOICE_SESSION_NAME  "Voice session"
+#define VOIP_SESSION_NAME   "VoIP session"
+#define VOLTE_SESSION_NAME  "VoLTE session"
+#define VOICE2_SESSION_NAME "Voice2 session"
+
+#define VOICE2_SESSION_VSID "10dc1000"
+
 /* called  by alsa driver */
 int voc_set_pp_enable(uint16_t session_id, uint32_t module_id,
 		      uint32_t enable);
@@ -1353,10 +1367,6 @@
 int voc_enable_dtmf_rx_detection(uint16_t session_id, uint32_t enable);
 void voc_disable_dtmf_det_on_active_sessions(void);
 
-#define MAX_SESSION_NAME_LEN 32
-#define VOICE_SESSION_NAME "Voice session"
-#define VOIP_SESSION_NAME "VoIP session"
-#define VOLTE_SESSION_NAME "VoLTE session"
 uint16_t voc_get_session_id(char *name);
 
 int voc_start_playback(uint32_t set);