Merge "msm: kgsl: Add support for VBIF and VBIF_PWR performance counters"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt b/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt
index a665431..c7a19ef 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt
@@ -29,7 +29,7 @@
 	qcom,wdt@f9017000 {
 		compatible = "qcom,msm-watchdog";
 		reg = <0xf9017000 0x1000>;
-		interrupts = <0 3 0 0 4 0>;
+		interrupts = <0 3 0>, <0 4 0>;
 		qcom,bark-time = <11000>;
 		qcom,pet-time = <10000>;
 		qcom,ipi-ping;
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 383da0c..2d20794 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -17,6 +17,8 @@
 - vdd_mx-supply:      Reference to the regulator that supplies the memory rail.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
 - qcom,gpio-err-fatal: GPIO used by the modem to indicate error fatal to the apps.
+- qcom,gpio-proxy-unvote: GPIO used by the modem to trigger proxy unvoting in
+  the apps.
 - qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
 
 Optional properties:
@@ -47,6 +49,7 @@
 
 		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 5b22752..6d093f0 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -26,12 +26,9 @@
 			That is to say,
 				if (abs(shutdown-soc - current-soc) < limit)
 				then use old SoC.
-- qcom,adjust-soc-low-threshold : The low threshold for the "flat portion"
-			of the charging curve. The BMS will not adjust SoC
-			based on voltage during this time.
-- qcom,adjust-soc-high-threshold : The high threshold for the "flat
-			portion" of the charging curve. The BMS will not
-			adjust SoC based on voltage during this time.
+- qcom,adjust-soc-low-threshold : The low threshold for when the BMS algorithm
+			starts adjusting. If the estimated SoC is not below
+			this percentage, do not adjust.
 - qcom,ocv-voltage-low-threshold-uv : The low voltage threshold for the
 			"flat portion" of the discharge curve. The bms will not
 			accept new ocvs between these thresholds.
@@ -59,6 +56,14 @@
 - qcom,batt-type: Type of battery used. This is an integer that corresponds
 			to the enum defined in
 			include/linux/mfd/pm8xxx/batterydata-lib.h
+- qcom,high-ocv-correction-limit-uv: how much the bms will correct OCV when
+			voltage is above the flat portion of the discharge
+			curve.
+- qcom,low-ocv-correction-limit-uv: how much the bms will correct OCV when
+			voltage is below the flat portion of the discharge
+			curve.
+- qcom,hold-soc-est: if the voltage-based estimated SoC is above this percent,
+			the BMS will clamp SoC to be at least 1.
 
 Parent node optional properties:
 - qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
@@ -107,14 +112,16 @@
 	qcom,shutdown-soc-valid-limit = <20>;
 	qcom,ocv-voltage-low-threshold-uv = <3650000>;
 	qcom,ocv-voltage-high-threshold-uv = <3750000>;
-	qcom,adjust-soc-low-threshold = <25>;
-	qcom,adjust-soc-high-threshold = <45>;
+	qcom,adjust-soc-low-threshold = <15>;
 	qcom,low-soc-calculate-soc-threshold = <15>;
 	qcom,low-voltage-threshold = <3420000>;
 	qcom,low-soc-calculate-soc-ms = <5000>;
 	qcom,calculate-soc-ms = <20000>;
 	qcom,chg-term-ua = <100000>;
 	qcom,batt-type = <0>;
+	qcom,low-ocv-correction-limit-uv = <100>;
+	qcom,high-ocv-correction-limit-uv = <50>;
+	qcom,hold-soc-est = <3>;
 
 	qcom,bms-iadc@3800 {
 		reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 72de900..f702abb 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -162,10 +162,9 @@
 			qcom,r-sense-uohm = <10000>;
 			qcom,v-cutoff-uv = <3400000>;
 			qcom,max-voltage-uv = <4200000>;
-			qcom,r-conn-mohm = <18>;
+			qcom,r-conn-mohm = <0>;
 			qcom,shutdown-soc-valid-limit = <20>;
-			qcom,adjust-soc-low-threshold = <25>;
-			qcom,adjust-soc-high-threshold = <45>;
+			qcom,adjust-soc-low-threshold = <15>;
 			qcom,ocv-voltage-high-threshold-uv = <3750000>;
 			qcom,ocv-voltage-low-threshold-uv = <3650000>;
 			qcom,low-soc-calculate-soc-threshold = <15>;
@@ -173,6 +172,10 @@
 			qcom,calculate-soc-ms = <20000>;
 			qcom,chg-term-ua = <100000>;
 			qcom,batt-type = <0>;
+			qcom,low-ocv-correction-limit-uv = <100>;
+			qcom,high-ocv-correction-limit-uv = <50>;
+			qcom,hold-soc-est = <3>;
+			qcom,low-voltage-threshold = <3420000>;
 
 			qcom,bms-iadc@3800 {
 				reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 6042f23..d712e5f 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -107,8 +107,7 @@
 			qcom,max-voltage-uv = <4200000>;
 			qcom,r-conn-mohm = <0>;
 			qcom,shutdown-soc-valid-limit = <20>;
-			qcom,adjust-soc-low-threshold = <25>;
-			qcom,adjust-soc-high-threshold = <45>;
+			qcom,adjust-soc-low-threshold = <15>;
 			qcom,ocv-voltage-high-threshold-uv = <3750000>;
 			qcom,ocv-voltage-low-threshold-uv = <3650000>;
 			qcom,low-soc-calculate-soc-threshold = <15>;
@@ -117,6 +116,9 @@
 			qcom,chg-term-ua = <100000>;
 			qcom,batt-type = <0>;
 			qcom,low-voltage-threshold = <3420000>;
+			qcom,low-ocv-correction-limit-uv = <100>;
+			qcom,high-ocv-correction-limit-uv = <50>;
+			qcom,hold-soc-est = <3>;
 
 			qcom,bms-iadc@3800 {
 				reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
similarity index 97%
copy from arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi
copy to arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index b7f837f..c47d48d 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -25,7 +25,7 @@
 
 	actuator0: qcom,actuator@6e {
 		cell-index = <3>;
-		reg = <0x6c 0x0>;
+		reg = <0x6c>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
@@ -38,7 +38,7 @@
 		qcom,csid-sd-index = <0>;
 		qcom,actuator-src = <&actuator0>;
 		qcom,led-flash-src = <&led_flash0>;
-		qcom,mount-angle = <90>;
+		qcom,mount-angle = <0>;
 		qcom,sensor-name = "ov8825";
 		cam_vdig-supply = <&pm8226_l5>;
 		cam_vana-supply = <&pm8226_l19>;
@@ -74,7 +74,7 @@
 		qcom,slave-id = <0x20 0x0 0x9724>;
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <0>;
-		qcom,mount-angle = <90>;
+		qcom,mount-angle = <0>;
 		qcom,sensor-name = "ov9724";
 		cam_vdig-supply = <&pm8226_l5>;
 		cam_vana-supply = <&pm8226_l19>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
index 02089be..1f7ba89 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
@@ -25,7 +25,7 @@
 
 	actuator0: qcom,actuator@6e {
 		cell-index = <3>;
-		reg = <0x6c 0x0>;
+		reg = <0x6c>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
@@ -38,7 +38,7 @@
 		qcom,csid-sd-index = <0>;
 		qcom,actuator-src = <&actuator0>;
 		qcom,led-flash-src = <&led_flash0>;
-		qcom,mount-angle = <90>;
+		qcom,mount-angle = <0>;
 		qcom,sensor-name = "ov8825";
 		cam_vdig-supply = <&pm8226_l5>;
 		cam_vana-supply = <&pm8226_l19>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
similarity index 98%
rename from arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi
rename to arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index b7f837f..5ea02b4 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -25,7 +25,7 @@
 
 	actuator0: qcom,actuator@6e {
 		cell-index = <3>;
-		reg = <0x6c 0x0>;
+		reg = <0x6c>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
@@ -38,7 +38,7 @@
 		qcom,csid-sd-index = <0>;
 		qcom,actuator-src = <&actuator0>;
 		qcom,led-flash-src = <&led_flash0>;
-		qcom,mount-angle = <90>;
+		qcom,mount-angle = <270>;
 		qcom,sensor-name = "ov8825";
 		cam_vdig-supply = <&pm8226_l5>;
 		cam_vana-supply = <&pm8226_l19>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 7b8dd59..0186e54 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -13,7 +13,7 @@
 /dts-v1/;
 /include/ "msm8226.dtsi"
 /include/ "dsi-panel-nt35590-720p-video.dtsi"
-/include/ "msm8226-camera-sensor-cdp-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 CDP";
diff --git a/arch/arm/boot/dts/msm8226-fluid.dts b/arch/arm/boot/dts/msm8226-fluid.dts
index 02a0b0b..d70ef6e 100644
--- a/arch/arm/boot/dts/msm8226-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-fluid.dts
@@ -21,4 +21,8 @@
 	serial@f991f000 {
 		status = "disabled";
 	};
-};
\ No newline at end of file
+};
+
+&pm8226_bms {
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8226-ion.dtsi b/arch/arm/boot/dts/msm8226-ion.dtsi
index 9a35507..9cef5a9 100644
--- a/arch/arm/boot/dts/msm8226-ion.dtsi
+++ b/arch/arm/boot/dts/msm8226-ion.dtsi
@@ -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
@@ -20,6 +20,10 @@
 			reg = <30>;
 		};
 
+		qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+			reg = <21>;
+		};
+
 		qcom,ion-heap@8 { /* CP_MM HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <8>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index dab15ae..b0a4a3d 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -299,3 +299,7 @@
 		qcom,fast-avg-setup = <0>;
 	};
 };
+
+&pm8226_bms {
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index 4879691..7d4f0d5 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -13,7 +13,7 @@
 /dts-v1/;
 /include/ "msm8226.dtsi"
 /include/ "dsi-panel-nt35590-720p-video.dtsi"
-/include/ "msm8226-camera-sensor-cdp-qrd.dtsi"
+/include/ "msm8226-camera-sensor-qrd.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 QRD";
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 75cf6e5..a51d4b8 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -686,8 +686,9 @@
 		qcom,firmware-name = "mba";
 		qcom,pil-self-auth;
 
-		/* GPIO input from mss */
+		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index d523c67..5b0eb33 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -17,10 +17,65 @@
 / {
 	model = "Qualcomm MSM 8610 CDP";
 	compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
-	qcom,msm-id = <147 1 0>;
+	qcom,msm-id = <147 1 0>, <165 1 0>;
 
-	serial@f991f000 {
+	serial@f991e000 {
 		status = "ok";
 	};
 };
 
+&sdhc_1 {
+	vdd-supply = <&pm8110_l17>;
+	qcom,vdd-always-on;
+	qcom,vdd-lpm-sup;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 400000>;
+
+	vdd-io-supply = <&pm8110_l6>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 60000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+	qcom,nonremovable;
+
+	status = "ok";
+};
+
+&sdhc_2 {
+	vdd-supply = <&pm8110_l18>;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	vdd-io-supply = <&pm8110_l21>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 50000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msmgpio 42 0x3>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msmgpio 42 0x1>;
+
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 89a00f1..a0a2c14 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -113,7 +113,7 @@
 		coresight-nr-inports = <4>;
 		coresight-outports = <0>;
 		coresight-child-list = <&funnel_in1>;
-		coresight-child-ports = <5>;
+		coresight-child-ports = <6>;
 	};
 
 	stm: stm@fc302000 {
@@ -126,7 +126,7 @@
 		coresight-name = "coresight-stm";
 		coresight-nr-inports = <0>;
 		coresight-outports = <0>;
-		coresight-child-list = <&funnel_in1>;
+		coresight-child-list = <&funnel_in0>;
 		coresight-child-ports = <7>;
 	};
 
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 107961d..848a6f5 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -20,6 +20,10 @@
 			reg = <30>;
 		};
 
+		qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+			reg = <21>;
+		};
+
 		qcom,ion-heap@25 { /* IOMMU HEAP */
 			reg = <25>;
 		};
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index f718d5e..e3eed72 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -17,10 +17,65 @@
 / {
 	model = "Qualcomm MSM 8610 MTP";
 	compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
-	qcom,msm-id = <147 8 0>;
+	qcom,msm-id = <147 8 0>, <165 8 0>;
 
 	serial@f991f000 {
 		status = "ok";
 	};
 };
 
+&sdhc_1 {
+	vdd-supply = <&pm8110_l17>;
+	qcom,vdd-always-on;
+	qcom,vdd-lpm-sup;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 400000>;
+
+	vdd-io-supply = <&pm8110_l6>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 60000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+	qcom,nonremovable;
+
+	status = "ok";
+};
+
+&sdhc_2 {
+	vdd-supply = <&pm8110_l18>;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	vdd-io-supply = <&pm8110_l21>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 50000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msmgpio 42 0x3>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msmgpio 42 0x1>;
+
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8610-smp2p.dtsi b/arch/arm/boot/dts/msm8610-smp2p.dtsi
index 4a5273b..91029e2 100644
--- a/arch/arm/boot/dts/msm8610-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8610-smp2p.dtsi
@@ -12,8 +12,7 @@
 / {
 	qcom,smp2p-modem {
 		compatible = "qcom,smp2p";
-		reg = <0xfa006000 0x1000>, <0x8 0x0>;
-		reg-names = "irq-reg-base", "irq-reg-offset";
+		reg = <0xf9011008 0x4>;
 		qcom,remote-pid = <1>;
 		qcom,irq-bitmask = <0x4000>;
 		interrupts = <0 27 1>;
@@ -21,8 +20,7 @@
 
 	qcom,smp2p-adsp {
 		compatible = "qcom,smp2p";
-		reg = <0xfa006000 0x1000>, <0x8 0x0>;
-		reg-names = "irq-reg-base", "irq-reg-offset";
+		reg = <0xf9011008 0x4>;
 		qcom,remote-pid = <2>;
 		qcom,irq-bitmask = <0x400>;
 		interrupts = <0 158 1>;
@@ -30,8 +28,7 @@
 
 	qcom,smp2p-wcnss {
 		compatible = "qcom,smp2p";
-		reg = <0xfa006000 0x1000>, <0x8 0x0>;
-		reg-names = "irq-reg-base", "irq-reg-offset";
+		reg = <0xf9011008 0x4>;
 		qcom,remote-pid = <4>;
 		qcom,irq-bitmask = <0x40000>;
 		interrupts = <0 143 1>;
@@ -177,6 +174,27 @@
 		#interrupt-cells = <2>;
 	};
 
+	smp2pgpio_ssr_smp2p_4_in: qcom,smp2pgpio-ssr-smp2p-4-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "slave-kernel";
+		qcom,remote-pid = <4>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	smp2pgpio_ssr_smp2p_4_out: qcom,smp2pgpio-ssr-smp2p-4-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "master-kernel";
+		qcom,remote-pid = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
 	qcom,smp2pgpio_test_smp2p_4_out {
 		compatible = "qcom,smp2pgpio_test_smp2p_4_out";
 		gpios = <&smp2pgpio_smp2p_4_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 5967dfb..6052131 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -47,6 +47,8 @@
 
 	aliases {
 		spi0 = &spi_0;
+		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
 	};
 
 	timer {
@@ -72,6 +74,13 @@
 		status = "disabled";
 	};
 
+	serial@f991e000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf991e000 0x1000>;
+		interrupts = <0 108 0>;
+		status = "disabled";
+	};
+
 	qcom,vidc@fdc00000 {
 		compatible = "qcom,msm-vidc";
 		qcom,vidc-ns-map = <0x40000000 0x40000000>;
@@ -94,8 +103,17 @@
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
-		qcom,hsusb-otg-otg-control = <1>;
+		qcom,hsusb-otg-otg-control = <2>;
 		qcom,hsusb-otg-disable-reset;
+		qcom,dp-manual-pullup;
+
+		qcom,msm-bus,name = "usb2";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<87 512 0 0>,
+				<87 512 60000 960000>;
 	};
 
 	android_usb@fe8050c8 {
@@ -135,6 +153,8 @@
 		qcom,bus-width = <8>;
 		qcom,nonremovable;
 		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+
+		status = "disabled";
 	};
 
 	sdcc2: qcom,sdcc@f98a4000 {
@@ -166,6 +186,32 @@
 		qcom,xpc;
 		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
 		qcom,current-limit = <800>;
+
+		status = "disabled";
+	};
+
+	sdhc_1: sdhci@f9824900 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0xf9824900 0x11c>, <0xf9824000 0x800>;
+		reg-names = "hc_mem", "core_mem";
+
+		interrupts = <0 123 0>, <0 138 0>;
+		interrupt-names = "hc_irq", "pwr_irq";
+
+		qcom,bus-width = <8>;
+		status = "disabled";
+	};
+
+	sdhc_2: sdhci@f98a4900 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>;
+		reg-names = "hc_mem", "core_mem";
+
+		interrupts = <0 125 0>, <0 221 0>;
+		interrupt-names = "hc_irq", "pwr_irq";
+
+		qcom,bus-width = <4>;
+		status = "disabled";
 	};
 
 	qcom,sps {
@@ -173,9 +219,9 @@
 		qcom,device-type = <3>;
 	};
 
-	qcom,smem@d600000 {
+	qcom,smem@d900000 {
 		compatible = "qcom,smem";
-		reg = <0xd600000 0x200000>,
+		reg = <0xd900000 0x200000>,
 			<0xf9011000 0x1000>,
 			<0xfc428000 0x4000>;
 		reg-names = "smem", "irq-reg-base", "aux-mem1";
@@ -250,7 +296,7 @@
 
 	qcom,msm-mem-hole {
 		compatible = "qcom,msm-mem-hole";
-		qcom,memblock-remove = <0x07C00000 0x6000000>; /* Address and Size of Hole */
+		qcom,memblock-remove = <0x07B00000 0x6400000>; /* Address and Size of Hole */
 	};
 
 	qcom,wdt@f9017000 {
@@ -331,6 +377,12 @@
 		vdd_pronto_pll-supply = <&pm8110_l10>;
 
 		qcom,firmware-name = "wcnss";
+
+		/* GPIO input from wcnss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+
+		/* GPIO output to wcnss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
 	};
 
 	sound {
@@ -458,8 +510,9 @@
 		qcom,firmware-name = "mba";
 		qcom,pil-self-auth;
 
-		/* GPIO input from mss */
+		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 0bd303f..3a78a15 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -104,7 +104,7 @@
 		cell-index = <0>;
 		compatible = "qcom,vfe40";
 		reg = <0xfda10000 0x1000>,
-                      <0xfda40000 0x200>;
+			<0xfda40000 0x200>;
 		reg-names = "vfe", "vfe_vbif";
 		interrupts = <0 57 0>;
 		interrupt-names = "vfe";
@@ -115,7 +115,7 @@
 		cell-index = <1>;
 		compatible = "qcom,vfe40";
 		reg = <0xfda14000 0x1000>,
-                      <0xfda40000 0x200>;
+			<0xfda40000 0x200>;
 		reg-names = "vfe", "vfe_vbif";
 		interrupts = <0 58 0>;
 		interrupt-names = "vfe";
@@ -129,7 +129,7 @@
 		reg-names = "jpeg";
 		interrupts = <0 59 0>;
 		interrupt-names = "jpeg";
-                vdd-supply = <&gdsc_jpeg>;
+		vdd-supply = <&gdsc_jpeg>;
 	};
 
 	qcom,jpeg@fda20000 {
@@ -163,8 +163,8 @@
 		cell-index = <0>;
 		compatible = "qcom,cpp";
 		reg = <0xfda04000 0x100>,
-		      <0xfda40000 0x200>,
-		      <0xfda18000 0x008>;
+			<0xfda40000 0x200>,
+			<0xfda18000 0x008>;
 		reg-names = "cpp", "cpp_vbif", "cpp_hw";
 		interrupts = <0 49 0>;
 		interrupt-names = "cpp";
@@ -182,7 +182,7 @@
 		cell-index = <0>;
 		compatible = "qcom,cci";
 		reg = <0xfda0C000 0x1000>;
-                #address-cells = <1>;
+		#address-cells = <1>;
 		#size-cells = <0>;
 		reg-names = "cci";
 		interrupts = <0 50 0>;
@@ -194,9 +194,9 @@
 		qcom,gpio-tbl-num = <0 1 2 3>;
 		qcom,gpio-tbl-flags = <1 1 1 1>;
 		qcom,gpio-tbl-label = "CCI_I2C_DATA0",
-				      "CCI_I2C_CLK0",
-				      "CCI_I2C_DATA1",
-				      "CCI_I2C_CLK1";
+					"CCI_I2C_CLK0",
+					"CCI_I2C_DATA1",
+					"CCI_I2C_CLK1";
 		qcom,hw-thigh = <78>;
 		qcom,hw-tlow = <114>;
 		qcom,hw-tsu-sto = <28>;
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index a7544ab..28d1d61 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -67,14 +67,14 @@
 
 			qcom,gpu-pwrlevel@1 {
 				reg = <1>;
-				qcom,gpu-freq = <300000000>;
+				qcom,gpu-freq = <320000000>;
 				qcom,bus-freq = <4>;
 				qcom,io-fraction = <66>;
 			};
 
 			qcom,gpu-pwrlevel@2 {
 				reg = <2>;
-				qcom,gpu-freq = <300000000>;
+				qcom,gpu-freq = <320000000>;
 				qcom,bus-freq = <3>;
 				qcom,io-fraction = <66>;
 			};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 5c42b2c..88641f9 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -49,7 +49,7 @@
 				     <0x017C 0x0FFF0FFF>,
 				     <0x0160 0x22222222>,
 				     <0x0164 0x00002222>;
-		qcom,mdp-settings = <0x02E0 0x000000AA>,
+		qcom,mdp-settings = <0x02E0 0x000000E9>,
 				    <0x02E4 0x00000055>,
 				    <0x03AC 0xC0000CCC>,
 				    <0x03B4 0xC0000CCC>,
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 61f2c4f..777d26c 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -48,17 +48,15 @@
 		/* Nominal / SVS */
 		<26 512 0 4656000>, <89 604 0 3000000>,
 		/* Nominal */
-		<26 512 0 4656000>, <89 604 0 5334880>,
+		<26 512 0 4656000>, <89 604 0 5120000>,
 		/* Turbo / Nominal */
-		<26 512 0 7464000>, <89 604 0 5334880>,
+		<26 512 0 7464000>, <89 604 0 5120000>,
 		/* Turbo */
 		<26 512 0 7464000>, <89 604 0 6400000>;
 };
 
 &mdss_mdp {
 	qcom,vbif-settings = <0x0004 0x00000001>;
-	qcom,mdp-settings = <0x02E0 0x000000A9>,
-			    <0x02E4 0x00000055>;
 
 	qcom,mdss-wb-off = <0x00011100 0x00011500
 			    0x00011900 0x00011D00 0x00012100>;
@@ -67,6 +65,13 @@
 	qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
 };
 
+&mdss_hdmi_tx {
+	reg =	<0xfd922100 0x370>,
+		<0xfd922500 0x7C>,
+		<0xfc4b8000 0x60F0>;
+	reg-names = "core_physical", "phy_physical", "qfprom_physical";
+};
+
 &msm_vidc {
 	qcom,vidc-ns-map = <0x40000000 0x40000000>;
 	qcom,load-freq-tbl = <979200 465000000>,
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 9a5a5d2..56234a1 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1036,8 +1036,9 @@
 		qcom,firmware-name = "mba";
 		qcom,pil-self-auth;
 
-		/* GPIO input from mss */
+		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
@@ -1153,7 +1154,7 @@
 	qcom,wdt@f9017000 {
 		compatible = "qcom,msm-watchdog";
 		reg = <0xf9017000 0x1000>;
-		interrupts = <0 3 0 0 4 0>;
+		interrupts = <0 3 0>, <0 4 0>;
 		qcom,bark-time = <11000>;
 		qcom,pet-time = <10000>;
 		qcom,ipi-ping;
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index fe81fa9..ee61dc3 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -689,8 +689,9 @@
 		compatible = "qcom,pil-q6v5-mss";
 		interrupts = <0 24 1>;
 
-		/* GPIO input from mss */
+		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
diff --git a/arch/arm/boot/dts/msmkrypton-sim.dts b/arch/arm/boot/dts/msmkrypton-sim.dts
new file mode 100644
index 0000000..1872a36
--- /dev/null
+++ b/arch/arm/boot/dts/msmkrypton-sim.dts
@@ -0,0 +1,25 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msmkrypton.dtsi"
+
+/ {
+	model = "Qualcomm MSM KRYPTON SIM";
+	compatible = "qcom,msmkrypton-sim", "qcom,msmkrypton", "qcom,sim";
+	qcom,msm-id = <187 16 0>;
+};
+
+&uartdm3{
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
new file mode 100644
index 0000000..db61dab
--- /dev/null
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -0,0 +1,54 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM KRYPTON";
+	compatible = "qcom,msmkrypton";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@f9000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0xf9000000 0x1000>,
+		      <0xf9002000 0x1000>;
+	};
+
+	msmgpio: gpio@fd510000 {
+		compatible = "qcom,msm-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd510000 0x4000>;
+		ngpio = <89>;
+		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
+	};
+
+	timer: msm-qtimer@f9021000 {
+		compatible = "arm,armv7-timer";
+		reg = <0xf9021000 0x1000>;
+		interrupts = <0 7 0>;
+		irq-is-not-percpu;
+		clock-frequency = <19200000>;
+	};
+
+	uartdm3: serial@f991f000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf991f000 0x1000>;
+		interrupts = <0 109 0>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 5e520f3..45f0868 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -241,6 +241,7 @@
 CONFIG_GPIO_QPNP_PIN=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_QPNP_CHARGER=y
+CONFIG_QPNP_BMS=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
 CONFIG_THERMAL=y
@@ -302,7 +303,10 @@
 CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 4e6cb05..f90e5f3 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -483,6 +483,7 @@
 CONFIG_SPS_SUPPORT_BAMDMA=y
 CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_IOMMU=y
+CONFIG_IOMMU_PGTABLES_L2=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_CORESIGHT=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index c4fffb9..f699dee 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -485,6 +485,7 @@
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
 CONFIG_MSM_IOMMU=y
+CONFIG_IOMMU_PGTABLES_L2=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_CORESIGHT=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index f76f810..f67cb0d 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -431,6 +431,7 @@
 CONFIG_QPNP_REVID=y
 CONFIG_QPNP_COINCELL=y
 CONFIG_MSM_IOMMU=y
+CONFIG_IOMMU_PGTABLES_L2=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_CORESIGHT=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 6112134..b5e67fd 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -440,6 +440,7 @@
 CONFIG_QPNP_REVID=y
 CONFIG_QPNP_COINCELL=y
 CONFIG_MSM_IOMMU=y
+CONFIG_IOMMU_PGTABLES_L2=y
 CONFIG_MSM_IOMMU_PMON=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msmzinc_defconfig b/arch/arm/configs/msmzinc_defconfig
index 678b086..d0ea87a 100644
--- a/arch/arm/configs/msmzinc_defconfig
+++ b/arch/arm/configs/msmzinc_defconfig
@@ -335,6 +335,7 @@
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
 CONFIG_MSM_IOMMU=y
+CONFIG_IOMMU_PGTABLES_L2=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 601fcfa..c510889 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -391,6 +391,21 @@
 	select MEMORY_HOLE_CARVEOUT
 	select MSM_RPM_LOG
 
+config ARCH_MSMKRYPTON
+	bool "MSMKRYPTON"
+	select ARM_GIC
+	select CPU_V7
+	select MSM_GPIOMUX
+	select MSM_RPM_SMD
+	select MSM_NATIVE_RESTART
+	select MSM_RESTART_V2
+	select MSM_SPM_V2
+	select MSM_PM8X60 if PM
+	select MULTI_IRQ_HANDLER
+	select GPIO_MSM_V3
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+
 config ARCH_MSM8610
 	bool "MSM8610"
 	select ARM_GIC
@@ -1074,6 +1089,7 @@
 	default "0x00000000" if ARCH_MSM8610
 	default "0x10000000" if ARCH_FSM9XXX
 	default "0x00200000" if ARCH_MSM9625
+	default "0x00200000" if ARCH_MSMKRYPTON
 	default "0x00200000" if !MSM_STACKED_MEMORY
 	default "0x00000000" if ARCH_QSD8X50 && MSM_SOC_REV_A
 	default "0x20000000" if ARCH_QSD8X50
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1c14ac6..7c78395 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -121,6 +121,7 @@
 ifndef CONFIG_ARCH_MPQ8092
 ifndef CONFIG_ARCH_MSM8610
 ifndef CONFIG_ARCH_MSMZINC
+ifndef CONFIG_ARCH_MSMKRYPTON
 	obj-y += nand_partitions.o
 endif
 endif
@@ -131,6 +132,7 @@
 endif
 endif
 endif
+endif
 obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
 obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -304,6 +306,7 @@
 obj-$(CONFIG_ARCH_MSM8226) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
+obj-$(CONFIG_ARCH_MSMKRYPTON) += board-krypton.o board-krypton-gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
@@ -368,6 +371,7 @@
 obj-$(CONFIG_ARCH_MSM9615) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8974) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSMKRYPTON) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MPQ8092) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index e3b8d73..f20f6ae 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -62,6 +62,9 @@
    zreladdr-$(CONFIG_ARCH_MSMZINC)	:= 0x00008000
         dtb-$(CONFIG_ARCH_MSMZINC)	+= msmzinc-sim.dtb
 
+# MSMKRYPTON
+   zreladdr-$(CONFIG_ARCH_MSMKRYPTON)	:= 0x00208000
+	dtb-$(CONFIG_ARCH_MSMKRYPTON)	+= msmkrypton-sim.dtb
 
 # MSM9615
    zreladdr-$(CONFIG_ARCH_MSM9615)	:= 0x40808000
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index b673f93..c60e89a 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -39,6 +39,8 @@
 	.user_val = 0x8,
 	.user_vco_mask = BIT(20),
 	.config_val = 0x04D0405D,
+	.has_lock_status = true,
+	.status_offset = 0x1C,
 	.low_vco_l_max = 65,
 	.low_vdd_l_max = 52,
 	.nom_vdd_l_max = 104,
@@ -651,32 +653,32 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  75000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  75000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  75000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  75000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  75000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  76000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  77000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  78000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  79000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  80000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  81000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  82000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  83000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  84000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  85000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  86000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  87000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  87500, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  88500, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  89500, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  90500, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  91500, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  92000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  93000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  94000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  95000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  875000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  885000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  895000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  905000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  915000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  920000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  930000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  940000, 3200000 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  950000, 3200000 },
 	{ 0, { 0 } }
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
index ca7fc2b..74ca145 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.c
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -121,7 +121,7 @@
 	writel_relaxed(regval, apcs_rcg_cmd);
 
 	/* Wait for the update to take effect */
-	rc = readl_poll_timeout(apcs_rcg_cmd, regval,
+	rc = readl_poll_timeout_noirq(apcs_rcg_cmd, regval,
 		   !(regval & r->poll_mask),
 		   POLL_INTERVAL_US,
 		   APCS_RCG_UPDATE_TIMEOUT_US);
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index a6f4423..e3a3f54 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -22,6 +22,7 @@
 #include <linux/cpufreq.h>
 #include <linux/cpu.h>
 #include <linux/regulator/consumer.h>
+#include <linux/iopoll.h>
 
 #include <asm/mach-types.h>
 #include <asm/cpu.h>
@@ -131,8 +132,14 @@
 	writel_relaxed(0x6, sc->hfpll_base + drv.hfpll_data->mode_offset);
 
 	/* Wait for PLL to lock. */
-	mb();
-	udelay(60);
+	if (drv.hfpll_data->has_lock_status) {
+		u32 regval;
+		readl_tight_poll(sc->hfpll_base + drv.hfpll_data->status_offset,
+			   regval, regval & BIT(16));
+	} else {
+		mb();
+		udelay(60);
+	}
 
 	/* Enable PLL output. */
 	writel_relaxed(0x7, sc->hfpll_base + drv.hfpll_data->mode_offset);
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 11d58dd..f02af98 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -171,8 +171,10 @@
  * @user_val: Value to initialize the @user_offset register to.
  * @user_vco_mask: Bit in the @user_offset to enable high-frequency VCO mode.
  * @has_droop_ctl: Indicates the presence of a voltage droop controller.
+ * @has_lock_status: Indicates the presence of a lock status bit.
  * @droop_offset: Droop controller register offset from base address.
  * @droop_val: Value to initialize the @config_offset register to.
+ * @status_offset: PLL status register offset.
  * @low_vdd_l_max: Maximum "L" value supported at HFPLL_VDD_LOW.
  * @nom_vdd_l_max: Maximum "L" value supported at HFPLL_VDD_NOM.
  * @low_vco_l_max: Maximum "L" value supported in low-frequency VCO mode.
@@ -190,8 +192,10 @@
 	const u32 user_val;
 	const u32 user_vco_mask;
 	const bool has_droop_ctl;
+	const bool has_lock_status;
 	const u32 droop_offset;
 	const u32 droop_val;
+	const u32 status_offset;
 	u32 low_vdd_l_max;
 	u32 nom_vdd_l_max;
 	const u32 low_vco_l_max;
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 92be927..a0644e6 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -1979,6 +1979,8 @@
 	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
+	a2_props.constrained_logging = true;
+	a2_props.logging_number = 1;
 	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	/* need to free on tear down */
diff --git a/arch/arm/mach-msm/bms-batterydata-desay.c b/arch/arm/mach-msm/bms-batterydata-desay.c
index dd3f346..e2b62be 100644
--- a/arch/arm/mach-msm/bms-batterydata-desay.c
+++ b/arch/arm/mach-msm/bms-batterydata-desay.c
@@ -84,4 +84,5 @@
 	.pc_sf_lut		= &desay_5200_pc_sf,
 	.default_rbatt_mohm	= 156,
 	.rbatt_capacitive_mohm	= 50,
+	.flat_ocv_threshold_uv	= 3800000,
 };
diff --git a/arch/arm/mach-msm/bms-batterydata-oem.c b/arch/arm/mach-msm/bms-batterydata-oem.c
index 036bf88..e4c42d7 100644
--- a/arch/arm/mach-msm/bms-batterydata-oem.c
+++ b/arch/arm/mach-msm/bms-batterydata-oem.c
@@ -105,4 +105,5 @@
 	.pc_temp_ocv_lut	= &pc_temp_ocv,
 	.rbatt_sf_lut		= &rbatt_sf,
 	.default_rbatt_mohm	= 236,
+	.flat_ocv_threshold_uv	= 3800000,
 };
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index 0c39df6..dc98c57 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -106,4 +106,5 @@
 	.rbatt_sf_lut		= &rbatt_sf,
 	.default_rbatt_mohm	= 236,
 	.rbatt_capacitive_mohm	= 50,
+	.flat_ocv_threshold_uv	= 3800000,
 };
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index e36884e..707abef 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2344,6 +2344,8 @@
 static struct msm_pcie_platform msm_pcie_platform_data = {
 	.axi_addr = PCIE_AXI_BAR_PHYS,
 	.axi_size = PCIE_AXI_BAR_SIZE,
+	.parf_deemph = 0x282828,
+	.parf_swing = 0x7F7F,
 };
 
 /* FSM8064_EP PCIe gpios */
@@ -2357,7 +2359,9 @@
 	.axi_addr = PCIE_AXI_BAR_PHYS,
 	.axi_size = PCIE_AXI_BAR_SIZE,
 	.wake_n = PM8921_GPIO_IRQ(PM8921_IRQ_BASE, PCIE_EP_WAKE_N_PMIC_GPIO),
-	.vreg_n = 4
+	.vreg_n = 4,
+	.parf_deemph = 0x101010,
+	.parf_swing = 0x6B6B,
 };
 
 static int __init mpq8064_pcie_enabled(void)
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 6371b9d..3582914 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -25,6 +25,7 @@
 #include <linux/of_irq.h>
 #include <linux/memory.h>
 #include <linux/regulator/qpnp-regulator.h>
+#include <linux/msm_tsens.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
@@ -112,7 +113,7 @@
 		msm_clock_init(&msm8226_rumi_clock_init_data);
 	else
 		msm_clock_init(&msm8226_clock_init_data);
-
+	tsens_tm_init_driver();
 	msm_thermal_device_init();
 }
 
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 9495b72..67334d5 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -24,6 +24,7 @@
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/memory.h>
+#include <linux/msm_tsens.h>
 #include <asm/mach/map.h>
 #include <asm/arch_timer.h>
 #include <asm/hardware/gic.h>
@@ -72,6 +73,10 @@
 			"msm_sdcc.1", NULL),
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
 			"msm_sdcc.2", NULL),
+	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9824900, \
+			"msm_sdcc.1", NULL),
+	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
+			"msm_sdcc.2", NULL),
 	{}
 };
 
@@ -101,6 +106,7 @@
 	msm_lpmrs_module_init();
 	msm_spm_device_init();
 	qpnp_regulator_init();
+	tsens_tm_init_driver();
 	msm_thermal_device_init();
 
 	if (of_board_is_rumi())
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 35f3f99..e30d0ba 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -100,6 +100,18 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting ath_gpio_active_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting ath_gpio_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct gpiomux_setting gpio_i2c_config = {
 	.func = GPIOMUX_FUNC_3,
 	/*
@@ -831,6 +843,24 @@
 	},
 };
 
+
+static struct msm_gpiomux_config ath_gpio_configs[] = {
+	{
+		.gpio = 51,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &ath_gpio_active_cfg,
+			[GPIOMUX_SUSPENDED] = &ath_gpio_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 79,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &ath_gpio_active_cfg,
+			[GPIOMUX_SUSPENDED] = &ath_gpio_suspend_cfg,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm_taiko_config[] __initdata = {
 	{
 		.gpio	= 63,		/* SYS_RST_N */
@@ -1034,7 +1064,8 @@
 			 ARRAY_SIZE(msm_blsp2_uart7_configs));
 	msm_gpiomux_install(wcnss_5wire_interface,
 				ARRAY_SIZE(wcnss_5wire_interface));
-
+	msm_gpiomux_install_nowrite(ath_gpio_configs,
+				ARRAY_SIZE(ath_gpio_configs));
 	msm_gpiomux_install(msm8974_slimbus_config,
 			ARRAY_SIZE(msm8974_slimbus_config));
 
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 9b69c8f..0ca55d1 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -22,6 +22,7 @@
 #include <linux/memory.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/krait-regulator.h>
+#include <linux/msm_tsens.h>
 #include <linux/msm_thermal.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/gic.h>
@@ -101,6 +102,7 @@
 		msm_clock_init(&msm8974_rumi_clock_init_data);
 	else
 		msm_clock_init(&msm8974_clock_init_data);
+	tsens_tm_init_driver();
 	msm_thermal_device_init();
 }
 
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 923dc2a..3bb00bb 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -21,6 +21,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/memory.h>
+#include <linux/msm_tsens.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
@@ -237,6 +238,7 @@
 	msm_spm_device_init();
 	msm_clock_init(&msm9625_clock_init_data);
 	msm9625_init_buses();
+	tsens_tm_init_driver();
 }
 
 void __init msm9625_init(void)
diff --git a/arch/arm/mach-msm/board-krypton-gpiomux.c b/arch/arm/mach-msm/board-krypton-gpiomux.c
new file mode 100644
index 0000000..3d86ba7
--- /dev/null
+++ b/arch/arm/mach-msm/board-krypton-gpiomux.c
@@ -0,0 +1,52 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+
+static struct gpiomux_setting gpio_uart_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
+	{
+		.gpio      = 8,	       /* BLSP1 UART TX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
+		},
+	},
+	{
+		.gpio      = 9,	       /* BLSP1 UART RX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
+		},
+	},
+};
+
+void __init msmkrypton_init_gpiomux(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init_dt();
+	if (rc) {
+		pr_err("%s failed %d\n", __func__, rc);
+		return;
+	}
+
+	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+}
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
new file mode 100644
index 0000000..aada3b0
--- /dev/null
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -0,0 +1,84 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memory.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
+#include <mach/restart.h>
+#include <mach/socinfo.h>
+#include <mach/clk-provider.h>
+#include "board-dt.h"
+#include "clock.h"
+#include "devices.h"
+
+static struct clk_lookup msm_clocks_dummy[] = {
+	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
+};
+
+static struct clock_init_data msm_dummy_clock_init_data __initdata = {
+	.table = msm_clocks_dummy,
+	.size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init msmkrypton_add_drivers(void)
+{
+	msm_smd_init();
+	msm_clock_init(&msm_dummy_clock_init_data);
+}
+
+static void __init msmkrypton_map_io(void)
+{
+	msm_map_msmkrypton_io();
+}
+
+void __init msmkrypton_init(void)
+{
+	if (socinfo_init() < 0)
+		pr_err("%s: socinfo_init() failed\n", __func__);
+
+	msmkrypton_init_gpiomux();
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	msmkrypton_add_drivers();
+}
+
+static const char *msmkrypton_dt_match[] __initconst = {
+	"qcom,msmkrypton",
+	NULL
+};
+
+DT_MACHINE_START(MSMKRYPTON_DT, "Qualcomm MSM Krypton (Flattened Device Tree)")
+	.map_io = msmkrypton_map_io,
+	.init_irq = msm_dt_init_irq,
+	.init_machine = msmkrypton_init,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_dt_timer,
+	.dt_compat = msmkrypton_dt_match,
+	.restart = msm_restart,
+MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 4079b5a..80907c8 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2810,6 +2810,9 @@
 
 static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, LONG_MAX);
 
+static DEFINE_CLK_VOTER(qseecom_ce1_clk_src, &ce1_clk_src.c, LONG_MAX);
+static DEFINE_CLK_VOTER(scm_ce1_clk_src, &ce1_clk_src.c, LONG_MAX);
+
 static DEFINE_CLK_BRANCH_VOTER(cxo_otg_clk, &xo.c);
 static DEFINE_CLK_BRANCH_VOTER(cxo_pil_lpass_clk, &xo.c);
 static DEFINE_CLK_BRANCH_VOTER(cxo_pil_mss_clk, &xo.c);
@@ -3171,12 +3174,14 @@
 	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,         "qseecom"),
 	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,     "qseecom"),
 	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,     "qseecom"),
-	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,         "qseecom"),
+	CLK_LOOKUP("core_clk_src", qseecom_ce1_clk_src.c, "qseecom"),
 
 	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,         "scm"),
 	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,     "scm"),
 	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,     "scm"),
-	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,         "scm"),
+	CLK_LOOKUP("core_clk_src", scm_ce1_clk_src.c,     "scm"),
+
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,     ""),
 
 	/* SDCC */
 	CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "f9824000.qcom,sdcc"),
diff --git a/arch/arm/mach-msm/ebi_erp.c b/arch/arm/mach-msm/ebi_erp.c
index eb38101..6b300d8 100644
--- a/arch/arm/mach-msm/ebi_erp.c
+++ b/arch/arm/mach-msm/ebi_erp.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
@@ -18,6 +18,9 @@
 #include <linux/errno.h>
 #include <linux/proc_fs.h>
 #include <linux/cpu.h>
+#include <mach/usb_trace.h>
+
+DEFINE_TRACE(usb_daytona_invalid_access);
 
 #define MODULE_NAME "msm_ebi_erp"
 
@@ -113,6 +116,11 @@
 	err_cntl |= CNTL_CLEAR_ERR;
 	writel_relaxed(err_cntl, base + SLV_ERR_CNTL);
 	mb();	/* Ensure interrupt is cleared before returning */
+
+	if ((err_apacket0 & AMID_MASK) == 0x00000102)
+		trace_usb_daytona_invalid_access(err_addr, err_apacket0,
+							 err_apacket1);
+
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 35257b2..72f5051 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -601,6 +601,7 @@
 void msm_map_fsm9xxx_io(void);
 void msm_map_8974_io(void);
 void msm_map_zinc_io(void);
+void msm_map_msmkrypton_io(void);
 void msm_map_msm8625_io(void);
 void msm_map_msm9625_io(void);
 void msm_init_irq(void);
@@ -611,6 +612,7 @@
 void msm_8974_init_gpiomux(void);
 void msmzinc_init_gpiomux(void);
 void msm9625_init_gpiomux(void);
+void msmkrypton_init_gpiomux(void);
 void msm_map_mpq8092_io(void);
 void mpq8092_init_gpiomux(void);
 void msm_map_msm8226_io(void);
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8610.h b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
index b07ddba..2a62460 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
@@ -22,7 +22,7 @@
  *
  */
 
-#define MSM8610_MSM_SHARED_RAM_PHYS	0x0D600000
+#define MSM8610_MSM_SHARED_RAM_PHYS	0x0D900000
 
 #define MSM8610_APCS_GCC_PHYS	0xF9011000
 #define MSM8610_APCS_GCC_SIZE	SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
new file mode 100644
index 0000000..a8b9da5
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 __ASM_ARCH_MSM_IOMAP_MSMKRYPTON_H
+#define __ASM_ARCH_MSM_IOMAP_MSMKRYPTON_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * io desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSMKRYPTON_SHARED_RAM_PHYS		0x00000000
+
+#define MSMKRYPTON_TLMM_PHYS			0xFD510000
+#define MSMKRYPTON_TLMM_SIZE			SZ_16K
+
+#define MSMKRYPTON_MPM2_PSHOLD_PHYS		0xFC4AB000
+#define MSMKRYPTON_MPM2_PSHOLD_SIZE		SZ_4K
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index d3706cd..f27eb36 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -134,6 +134,7 @@
 #include "msm_iomap-8092.h"
 #include "msm_iomap-8226.h"
 #include "msm_iomap-8610.h"
+#include "msm_iomap-krypton.h"
 
 #endif
 
diff --git a/arch/arm/mach-msm/include/mach/msm_pcie.h b/arch/arm/mach-msm/include/mach/msm_pcie.h
index 790a390..99d1a4d 100644
--- a/arch/arm/mach-msm/include/mach/msm_pcie.h
+++ b/arch/arm/mach-msm/include/mach/msm_pcie.h
@@ -37,6 +37,8 @@
 	uint32_t                      axi_size;
 	uint32_t                      wake_n;
 	uint32_t                      vreg_n;
+	uint32_t                      parf_deemph;
+	uint32_t                      parf_swing;
 };
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_serial_hs.h b/arch/arm/mach-msm/include/mach/msm_serial_hs.h
index dd53911..e6b677e 100644
--- a/arch/arm/mach-msm/include/mach/msm_serial_hs.h
+++ b/arch/arm/mach-msm/include/mach/msm_serial_hs.h
@@ -51,6 +51,7 @@
 unsigned int msm_hs_tx_empty(struct uart_port *uport);
 void msm_hs_request_clock_off(struct uart_port *uport);
 void msm_hs_request_clock_on(struct uart_port *uport);
+struct uart_port *msm_hs_get_uart_port(int port_index);
 void msm_hs_set_mctrl(struct uart_port *uport,
 				    unsigned int mctrl);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index abb5653..8539dcc 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -85,6 +85,12 @@
 	atomic_long_t z_stat[NR_OCMEM_ZSTAT_ITEMS];
 	struct gen_pool *z_pool;
 	struct ocmem_zone_ops *z_ops;
+	unsigned int max_alloc_time;
+	unsigned int min_alloc_time;
+	u64 total_alloc_time;
+	unsigned int max_free_time;
+	unsigned int min_free_time;
+	u64 total_free_time;
 };
 
 enum op_code {
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
index ff39929..2e15cae 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.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
@@ -97,6 +97,10 @@
 
 /* Max size of the client name */
 #define USF_MAX_CLIENT_NAME_SIZE	20
+
+/* Max number of the ports (mics/speakers) */
+#define USF_MAX_PORT_NUM                8
+
 /* Info structure common for TX and RX */
 struct us_xx_info_type {
 /* Input:  general info */
@@ -115,7 +119,7 @@
 /* Number of the microphones (TX) or speakers(RX) */
 	uint16_t port_cnt;
 /* Microphones(TX) or speakers(RX) indexes in their enumeration */
-	uint8_t  port_id[4];
+	uint8_t  port_id[USF_MAX_PORT_NUM];
 /* Bits per sample 16 or 32 */
 	uint16_t bits_per_sample;
 /* Input:  Transparent info for encoder in the LPASS */
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 662655b..25cbc87 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -410,6 +410,11 @@
 
 	u32 sec_config;
 	struct sps_bam_sec_config_props *p_sec_config_props;
+
+	/* Logging control */
+
+	bool constrained_logging;
+	u32 logging_number;
 };
 
 /**
diff --git a/arch/arm/mach-msm/include/mach/usb_trace.h b/arch/arm/mach-msm/include/mach/usb_trace.h
new file mode 100644
index 0000000..02ca8ca
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/usb_trace.h
@@ -0,0 +1,27 @@
+/* include/asm-arm/arch-msm/usbtrace.h
+ *
+ * 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 _USB_TRACE_H_
+#define _USB_TRACE_H_
+
+#include <linux/tracepoint.h>
+
+DECLARE_TRACE(usb_daytona_invalid_access,
+	TP_PROTO(unsigned int ebi_addr,
+	 unsigned int ebi_apacket0, unsigned int ebi_apacket1),
+	TP_ARGS(ebi_addr, ebi_apacket0, ebi_apacket1));
+
+#endif
+
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 19c7acd..ecac4a5 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -507,6 +507,25 @@
 }
 #endif /* CONFIG_ARCH_MSM9625 */
 
+#ifdef CONFIG_ARCH_MSMKRYPTON
+static struct map_desc msmkrypton_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(TLMM, MSMKRYPTON),
+	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSMKRYPTON),
+	{
+		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
+		.length =   MSM_SHARED_RAM_SIZE,
+		.type =     MT_DEVICE,
+	},
+};
+
+void __init msm_map_msmkrypton_io(void)
+{
+	msm_shared_ram_phys = MSMKRYPTON_SHARED_RAM_PHYS;
+	msm_map_io(msmkrypton_io_desc, ARRAY_SIZE(msmkrypton_io_desc));
+	of_scan_flat_dt(msm_scan_dt_map_imem, NULL);
+}
+#endif /* CONFIG_ARCH_MSMKRYPTON */
+
 #ifdef CONFIG_ARCH_MPQ8092
 static struct map_desc mpq8092_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index edfb45b..d71787c 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/memory_alloc.h>
 #include <linux/memblock.h>
+#include <asm/memblock.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/mach/map.h>
@@ -160,42 +161,18 @@
 
 static void __init reserve_memory_for_mempools(void)
 {
-	int memtype, memreg_type;
+	int memtype;
 	struct memtype_reserve *mt;
-	struct memblock_region *mr, *mr_candidate = NULL;
-	int ret;
+	phys_addr_t alignment;
 
 	mt = &reserve_info->memtype_reserve_table[0];
 	for (memtype = 0; memtype < MEMTYPE_MAX; memtype++, mt++) {
 		if (mt->flags & MEMTYPE_FLAGS_FIXED || !mt->size)
 			continue;
-
-		/* Choose the memory block with the highest physical
-		 * address which is large enough, so that we will not
-		 * take memory from the lowest memory bank which the kernel
-		 * is in (and cause boot problems) and so that we might
-		 * be able to steal memory that would otherwise become
-		 * highmem.
-		 */
-		for_each_memblock(memory, mr) {
-			memreg_type =
-				reserve_info->paddr_to_memtype(mr->base);
-			if (memtype != memreg_type)
-				continue;
-			if (mr->size >= mt->size
-				&& (mr_candidate == NULL
-					|| mr->base > mr_candidate->base))
-				mr_candidate = mr;
-		}
-		BUG_ON(mr_candidate == NULL);
-		/* bump mt up against the top of the region */
-		mt->start = mr_candidate->base + mr_candidate->size - mt->size;
-		ret = memblock_reserve(mt->start, mt->size);
-		BUG_ON(ret);
-		ret = memblock_free(mt->start, mt->size);
-		BUG_ON(ret);
-		ret = memblock_remove(mt->start, mt->size);
-		BUG_ON(ret);
+		alignment = (mt->flags & MEMTYPE_FLAGS_1M_ALIGN) ?
+			SZ_1M : PAGE_SIZE;
+		mt->start = arm_memblock_steal(mt->size, alignment);
+		BUG_ON(!mt->start);
 	}
 }
 
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 4685f02..d31f3c4 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -587,6 +587,34 @@
 	.release = seq_release,
 };
 
+static int ocmem_timing_show(struct seq_file *f, void *dummy)
+{
+	unsigned i = 0;
+	for (i = OCMEM_GRAPHICS; i < OCMEM_CLIENT_MAX; i++) {
+		struct ocmem_zone *z = get_zone(i);
+		if (z && z->active == true)
+			seq_printf(f, "zone %s\t: alloc_delay:[max:%d, min:%d, total:%llu,cnt:%lu] free_delay:[max:%d, min:%d, total:%llu, cnt:%lu]\n",
+				get_name(z->owner), z->max_alloc_time,
+				z->min_alloc_time, z->total_alloc_time,
+				get_ocmem_stat(z, 1), z->max_free_time,
+				z->min_free_time, z->total_free_time,
+				get_ocmem_stat(z, 6));
+	}
+	return 0;
+}
+
+static int ocmem_timing_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ocmem_timing_show, inode->i_private);
+}
+
+static const struct file_operations timing_show_fops = {
+	.open = ocmem_timing_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
 static int ocmem_zone_init(struct platform_device *pdev)
 {
 
@@ -656,6 +684,13 @@
 		zone->max_regions = 0;
 		INIT_LIST_HEAD(&zone->req_list);
 		zone->z_ops = z_ops;
+		zone->max_alloc_time = 0;
+		zone->min_alloc_time = 0xFFFFFFFF;
+		zone->total_alloc_time = 0;
+		zone->max_free_time = 0;
+		zone->min_free_time = 0xFFFFFFFF;
+		zone->total_free_time = 0;
+
 		if (part->p_tail) {
 			z_ops->allocate = allocate_tail;
 			z_ops->free = free_tail;
@@ -688,6 +723,12 @@
 		return -EBUSY;
 	}
 
+	if (!debugfs_create_file("timing", S_IRUGO, pdata->debug_node,
+					NULL, &timing_show_fops)) {
+		dev_err(dev, "Unable to create debugfs node for timing\n");
+		return -EBUSY;
+	}
+
 	dev_dbg(dev, "Total active zones = %d\n", active_zones);
 	return 0;
 }
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
index 16dd8b8..13c4c1a 100644
--- a/arch/arm/mach-msm/ocmem_api.c
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -105,6 +105,11 @@
 {
 	bool can_block = false;
 	bool can_wait = true;
+	struct ocmem_buf *buffer;
+	struct timeval start_time;
+	struct timeval end_time;
+	unsigned int delay;
+	struct ocmem_zone *zone;
 
 	if (!check_id(client_id)) {
 		pr_err("ocmem: Invalid client id: %d\n", client_id);
@@ -129,8 +134,33 @@
 		return NULL;
 	}
 
-	return __ocmem_allocate_range(client_id, size, size,
+	zone = get_zone(client_id);
+	if (!zone) {
+		pr_err("ocmem: Zone not found for client %d\n", client_id);
+		return NULL;
+	}
+
+	do_gettimeofday(&start_time);
+
+	buffer = __ocmem_allocate_range(client_id, size, size,
 					size, can_block, can_wait);
+
+	do_gettimeofday(&end_time);
+
+	if (!buffer)
+		return NULL;
+
+	delay = (end_time.tv_sec * USEC_PER_SEC + end_time.tv_usec)
+		 - (start_time.tv_sec * USEC_PER_SEC + start_time.tv_usec);
+
+	if (delay > zone->max_alloc_time)
+		zone->max_alloc_time = delay;
+	if (delay < zone->min_alloc_time)
+		zone->min_alloc_time = delay;
+	zone->total_alloc_time += delay;
+	inc_ocmem_stat(zone, NR_SYNC_ALLOCATIONS);
+
+	return buffer;
 }
 EXPORT_SYMBOL(ocmem_allocate);
 
@@ -250,6 +280,12 @@
 
 int ocmem_free(int client_id, struct ocmem_buf *buffer)
 {
+	int rc;
+	struct timeval start_time;
+	struct timeval end_time;
+	unsigned int delay;
+	struct ocmem_zone *zone;
+
 	if (!check_id(client_id)) {
 		pr_err("ocmem: Invalid client id: %d\n", client_id);
 		return -EINVAL;
@@ -261,12 +297,38 @@
 		return -EINVAL;
 	}
 
+	zone = get_zone(client_id);
+	if (!zone) {
+		pr_err("ocmem: Zone not found for client %d\n", client_id);
+		return -EINVAL;
+	}
+
 	if (!buffer) {
 		pr_err("ocmem: Invalid buffer\n");
 		return -EINVAL;
 	}
 
-	return __ocmem_free(client_id, buffer);
+	do_gettimeofday(&start_time);
+
+	rc = __ocmem_free(client_id, buffer);
+
+	do_gettimeofday(&end_time);
+
+	if (rc < 0)
+		return rc;
+
+	delay = (end_time.tv_sec * USEC_PER_SEC + end_time.tv_usec)
+		 - (start_time.tv_sec * USEC_PER_SEC + start_time.tv_usec);
+
+	if (delay > zone->max_free_time)
+		zone->max_free_time = delay;
+	if (delay < zone->min_free_time)
+		zone->min_free_time = delay;
+	zone->total_free_time += delay;
+	inc_ocmem_stat(zone, NR_FREES);
+
+	return rc;
+
 }
 EXPORT_SYMBOL(ocmem_free);
 
@@ -473,6 +535,7 @@
 	}
 	return process_quota(client_id);
 }
+EXPORT_SYMBOL(get_max_quota);
 
 /* Synchronous eviction/restore calls */
 /* Only a single eviction or restoration is allowed */
diff --git a/arch/arm/mach-msm/pcie.c b/arch/arm/mach-msm/pcie.c
index 6305abc..c2ba6c1 100644
--- a/arch/arm/mach-msm/pcie.c
+++ b/arch/arm/mach-msm/pcie.c
@@ -528,8 +528,8 @@
 	msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
 
 	/* PARF programming */
-	writel_relaxed(0x282828, dev->parf + PCIE20_PARF_PCS_DEEMPH);
-	writel_relaxed(0x7F7F, dev->parf + PCIE20_PARF_PCS_SWING);
+	writel_relaxed(dev->parf_deemph, dev->parf + PCIE20_PARF_PCS_DEEMPH);
+	writel_relaxed(dev->parf_swing, dev->parf + PCIE20_PARF_PCS_SWING);
 	writel_relaxed((4<<24), dev->parf + PCIE20_PARF_CONFIG_BITS);
 	/* ensure that hardware registers the PARF configuration */
 	wmb();
@@ -621,6 +621,8 @@
 	msm_pcie_dev.gpio = pdata->gpio;
 	msm_pcie_dev.wake_n = pdata->wake_n;
 	msm_pcie_dev.vreg_n = pdata->vreg_n;
+	msm_pcie_dev.parf_deemph = pdata->parf_deemph;
+	msm_pcie_dev.parf_swing = pdata->parf_swing;
 	msm_pcie_dev.vreg = msm_pcie_vreg_info;
 	msm_pcie_dev.clk = msm_pcie_clk_info;
 	msm_pcie_dev.res = msm_pcie_res_info;
diff --git a/arch/arm/mach-msm/pcie.h b/arch/arm/mach-msm/pcie.h
index 31371c2..051e475 100644
--- a/arch/arm/mach-msm/pcie.h
+++ b/arch/arm/mach-msm/pcie.h
@@ -71,6 +71,8 @@
 
 	uint32_t                      wake_n;
 	uint32_t                      vreg_n;
+	uint32_t                      parf_deemph;
+	uint32_t                      parf_swing;
 };
 
 extern uint32_t msm_pcie_irq_init(struct msm_pcie_dev_t *dev);
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index ef13c34..72253fd 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -47,7 +47,7 @@
 	void *ramdump_dev;
 	int wdog_irq;
 	struct work_struct work;
-	void *riva_notif_hdle;
+	void *wcnss_notif_hdle;
 	void *modem_notif_hdle;
 	int crash_shutdown;
 };
@@ -189,24 +189,19 @@
 	.shutdown = pil_lpass_shutdown_trusted,
 };
 
-static int riva_notifier_cb(struct notifier_block *this, unsigned long code,
+static int wcnss_notifier_cb(struct notifier_block *this, unsigned long code,
 								void *ss_handle)
 {
 	int ret;
-	switch (code) {
-	case SUBSYS_BEFORE_SHUTDOWN:
-		pr_debug("%s: R-Notify: Shutdown started\n", __func__);
-		ret = sysmon_send_event(SYSMON_SS_LPASS, "wcnss",
-				SUBSYS_BEFORE_SHUTDOWN);
-		if (ret < 0)
-			pr_err("%s: sysmon_send_event error %d", __func__, ret);
-		break;
-	}
+	pr_debug("%s: W-Notify: event %lu\n", __func__, code);
+	ret = sysmon_send_event(SYSMON_SS_LPASS, "wcnss", code);
+	if (ret < 0)
+		pr_err("%s: sysmon_send_event error %d", __func__, ret);
 	return NOTIFY_DONE;
 }
 
-static struct notifier_block rnb = {
-	.notifier_call = riva_notifier_cb,
+static struct notifier_block wnb = {
+	.notifier_call = wcnss_notifier_cb,
 };
 
 static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
@@ -480,10 +475,10 @@
 	if (ret < 0)
 		goto err_smsm;
 
-	drv->riva_notif_hdle = subsys_notif_register_notifier("riva", &rnb);
-	if (IS_ERR(drv->riva_notif_hdle)) {
-		ret = PTR_ERR(drv->riva_notif_hdle);
-		goto err_notif_riva;
+	drv->wcnss_notif_hdle = subsys_notif_register_notifier("wcnss", &wnb);
+	if (IS_ERR(drv->wcnss_notif_hdle)) {
+		ret = PTR_ERR(drv->wcnss_notif_hdle);
+		goto err_notif_wcnss;
 	}
 
 	drv->modem_notif_hdle = subsys_notif_register_notifier("modem", &mnb);
@@ -510,8 +505,8 @@
 err_kobj:
 	kobject_put(lpass_status);
 err_notif_modem:
-	subsys_notif_unregister_notifier(drv->riva_notif_hdle, &rnb);
-err_notif_riva:
+	subsys_notif_unregister_notifier(drv->wcnss_notif_hdle, &wnb);
+err_notif_wcnss:
 	smsm_state_cb_deregister(SMSM_Q6_STATE, SMSM_RESET,
 			adsp_smsm_state_cb, drv);
 err_smsm:
@@ -527,7 +522,7 @@
 static int __devexit pil_lpass_driver_exit(struct platform_device *pdev)
 {
 	struct lpass_data *drv = platform_get_drvdata(pdev);
-	subsys_notif_unregister_notifier(drv->riva_notif_hdle, &rnb);
+	subsys_notif_unregister_notifier(drv->wcnss_notif_hdle, &wnb);
 	subsys_notif_unregister_notifier(drv->modem_notif_hdle, &mnb);
 	smsm_state_cb_deregister(SMSM_Q6_STATE, SMSM_RESET,
 			adsp_smsm_state_cb, drv);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 06de8cc..cfd8daf 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -709,6 +709,15 @@
 	struct resource *res;
 	int ret;
 
+	int clk_ready = of_get_named_gpio(pdev->dev.of_node,
+			"qcom,gpio-proxy-unvote", 0);
+	if (clk_ready < 0)
+		return clk_ready;
+
+	clk_ready = gpio_to_irq(clk_ready);
+	if (clk_ready < 0)
+		return clk_ready;
+
 	q6 = pil_q6v5_init(pdev);
 	if (IS_ERR(q6))
 		return PTR_ERR(q6);
@@ -718,6 +727,7 @@
 	q6_desc->ops = &pil_mss_ops;
 	q6_desc->owner = THIS_MODULE;
 	q6_desc->proxy_timeout = PROXY_TIMEOUT_MS;
+	q6_desc->proxy_unvote_irq = clk_ready;
 
 	drv->self_auth = of_property_read_bool(pdev->dev.of_node,
 							"qcom,pil-self-auth");
@@ -781,6 +791,7 @@
 	mba_desc->ops = &pil_mba_ops;
 	mba_desc->owner = THIS_MODULE;
 	mba_desc->proxy_timeout = PROXY_TIMEOUT_MS;
+	mba_desc->proxy_unvote_irq = clk_ready;
 
 	ret = pil_desc_init(mba_desc);
 	if (ret)
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 5d744a1..64ee880 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -769,13 +769,13 @@
 static int audio_aio_ion_add(struct q6audio_aio *audio,
 				struct msm_audio_ion_info *info)
 {
-	ion_phys_addr_t paddr;
-	size_t len;
+	ion_phys_addr_t paddr = 0;
+	size_t len = 0;
 	struct audio_aio_ion_region *region;
 	int rc = -EINVAL;
-	struct ion_handle *handle;
+	struct ion_handle *handle = NULL;
 	unsigned long ionflag;
-	void *kvaddr;
+	void *kvaddr = NULL;
 
 	pr_debug("%s[%p]:\n", __func__, audio);
 	region = kmalloc(sizeof(*region), GFP_KERNEL);
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
index 91ea1dc..d37a325 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.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
@@ -27,8 +27,8 @@
 #include "usfcdev.h"
 
 /* The driver version*/
-#define DRV_VERSION "1.4.1"
-#define USF_VERSION_ID 0x0141
+#define DRV_VERSION "1.4.2"
+#define USF_VERSION_ID 0x0142
 
 /* Standard timeout in the asynchronous ops */
 #define USF_TIMEOUT_JIFFIES (1*HZ) /* 1 sec */
@@ -430,12 +430,14 @@
 {
 	int rc = 0;
 	uint16_t data_map_size = 0;
+	uint16_t min_map_size = 0;
 
 	if ((usf_xx == NULL) ||
 	    (config == NULL))
 		return -EINVAL;
 
 	data_map_size = sizeof(usf_xx->encdec_cfg.cfg_common.data_map);
+	min_map_size = min(data_map_size, config->port_cnt);
 
 	if (config->client_name != NULL) {
 		if (strncpy_from_user(usf_xx->client_name,
@@ -454,20 +456,13 @@
 		__func__, config->buf_num, config->stream_format,
 		config->port_cnt, config->params_data_size);
 
-	pr_debug("%s: p_id[0]=%d, p_id[1]=%d, p_id[2]=%d, p_id[3]=%d\n",
+	pr_debug("%s: id[0]=%d, id[1]=%d, id[2]=%d, id[3]=%d, id[4]=%d\n",
 		__func__,
 		config->port_id[0],
 		config->port_id[1],
 		config->port_id[2],
-		config->port_id[3]);
-
-	if (data_map_size < config->port_cnt) {
-		pr_err("%s: number of supported ports:%d < requested:%d\n",
-			__func__,
-			data_map_size,
-			config->port_cnt);
-		return -EINVAL;
-	}
+		config->port_id[3],
+		config->port_id[4]);
 
 	/* q6usm allocation & configuration */
 	usf_xx->buffer_size = config->buf_size;
@@ -481,7 +476,8 @@
 	usf_xx->encdec_cfg.cfg_common.ch_cfg = config->port_cnt;
 	memcpy((void *)&usf_xx->encdec_cfg.cfg_common.data_map,
 	       (void *)config->port_id,
-	       config->port_cnt);
+	       min_map_size);
+
 	if (rc) {
 		pr_err("%s: ports offsets copy failure\n", __func__);
 		return -EINVAL;
@@ -897,8 +893,10 @@
 	rc = q6usm_us_client_buf_alloc(OUT, usf_xx->usc,
 				       usf_xx->buffer_size,
 				       usf_xx->buffer_count);
-	if (rc)
+	if (rc) {
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
 		return rc;
+	}
 
 	rc = q6usm_enc_cfg_blk(usf_xx->usc,
 			       &usf_xx->encdec_cfg);
@@ -908,7 +906,9 @@
 					   &config_tx.input_info);
 	}
 
-	if (!rc)
+	if (rc)
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+	else
 		usf_xx->usf_state = USF_CONFIGURED_STATE;
 
 	return rc;
@@ -948,13 +948,17 @@
 					usf_xx->usc,
 					usf_xx->buffer_size,
 					usf_xx->buffer_count);
-		if (rc)
+		if (rc) {
+			(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
 			return rc;
+		}
 	}
 
 	rc = q6usm_dec_cfg_blk(usf_xx->usc,
 			       &usf_xx->encdec_cfg);
-	if (!rc) {
+	if (rc)
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+	else {
 		init_waitqueue_head(&usf_xx->wait);
 		usf_xx->usf_state = USF_CONFIGURED_STATE;
 	}
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index b7271bb..f48b538 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -46,55 +46,6 @@
 
 static struct clk *scm_clocks[NUM_CLKS];
 
-int pas_init_image(enum pas_id id, const u8 *metadata, size_t size)
-{
-	int ret;
-	struct pas_init_image_req {
-		u32	proc;
-		u32	image_addr;
-	} request;
-	u32 scm_ret = 0;
-	/* Make memory physically contiguous */
-	void *mdata_buf = kmemdup(metadata, size, GFP_KERNEL);
-
-	if (!mdata_buf)
-		return -ENOMEM;
-
-	request.proc = id;
-	request.image_addr = virt_to_phys(mdata_buf);
-
-	ret = scm_call(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD, &request,
-			sizeof(request), &scm_ret, sizeof(scm_ret));
-	kfree(mdata_buf);
-
-	if (ret)
-		return ret;
-	return scm_ret;
-}
-EXPORT_SYMBOL(pas_init_image);
-
-int pas_mem_setup(enum pas_id id, u32 start_addr, u32 len)
-{
-	int ret;
-	struct pas_init_image_req {
-		u32	proc;
-		u32	start_addr;
-		u32	len;
-	} request;
-	u32 scm_ret = 0;
-
-	request.proc = id;
-	request.start_addr = start_addr;
-	request.len = len;
-
-	ret = scm_call(SCM_SVC_PIL, PAS_MEM_SETUP_CMD, &request,
-			sizeof(request), &scm_ret, sizeof(scm_ret));
-	if (ret)
-		return ret;
-	return scm_ret;
-}
-EXPORT_SYMBOL(pas_mem_setup);
-
 static struct msm_bus_paths scm_pas_bw_tbl[] = {
 	{
 		.vectors = (struct msm_bus_vectors[]){
@@ -176,18 +127,78 @@
 	mutex_unlock(&scm_pas_bw_mutex);
 }
 
+int pas_init_image(enum pas_id id, const u8 *metadata, size_t size)
+{
+	int ret;
+	struct pas_init_image_req {
+		u32	proc;
+		u32	image_addr;
+	} request;
+	u32 scm_ret = 0;
+	void *mdata_buf;
+
+	ret = scm_pas_enable_bw();
+	if (ret)
+		return ret;
+
+	/* Make memory physically contiguous */
+	mdata_buf = kmemdup(metadata, size, GFP_KERNEL);
+
+	if (!mdata_buf)
+		return -ENOMEM;
+
+	request.proc = id;
+	request.image_addr = virt_to_phys(mdata_buf);
+
+	ret = scm_call(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD, &request,
+			sizeof(request), &scm_ret, sizeof(scm_ret));
+
+	kfree(mdata_buf);
+	scm_pas_disable_bw();
+
+	if (ret)
+		return ret;
+	return scm_ret;
+}
+EXPORT_SYMBOL(pas_init_image);
+
+int pas_mem_setup(enum pas_id id, u32 start_addr, u32 len)
+{
+	int ret;
+	struct pas_init_image_req {
+		u32	proc;
+		u32	start_addr;
+		u32	len;
+	} request;
+	u32 scm_ret = 0;
+
+	request.proc = id;
+	request.start_addr = start_addr;
+	request.len = len;
+
+	ret = scm_call(SCM_SVC_PIL, PAS_MEM_SETUP_CMD, &request,
+			sizeof(request), &scm_ret, sizeof(scm_ret));
+	if (ret)
+		return ret;
+	return scm_ret;
+}
+EXPORT_SYMBOL(pas_mem_setup);
+
 int pas_auth_and_reset(enum pas_id id)
 {
-	int ret, bus_ret;
+	int ret;
 	u32 proc = id, scm_ret = 0;
 
-	bus_ret = scm_pas_enable_bw();
+	ret = scm_pas_enable_bw();
+	if (ret)
+		return ret;
+
 	ret = scm_call(SCM_SVC_PIL, PAS_AUTH_AND_RESET_CMD, &proc,
 			sizeof(proc), &scm_ret, sizeof(scm_ret));
 	if (ret)
 		scm_ret = ret;
-	if (!bus_ret)
-		scm_pas_disable_bw();
+
+	scm_pas_disable_bw();
 
 	return scm_ret;
 }
@@ -251,7 +262,7 @@
 	rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
 	clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
 
-	if (cpu_is_msm8974() || cpu_is_msm8226()) {
+	if (cpu_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
 		scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
 		scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
 	} else {
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index ee6dfbf..5158f8e 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -328,6 +328,7 @@
 
 	/* 8610 IDs */
 	[147] = MSM_CPU_8610,
+	[165] = MSM_CPU_8610,
 
 	/* 8064AB IDs */
 	[153] = MSM_CPU_8064AB,
@@ -849,10 +850,6 @@
 		dummy_socinfo.id = 146;
 		strlcpy(dummy_socinfo.build_id, "mpq8092 - ",
 		sizeof(dummy_socinfo.build_id));
-	} else if (early_machine_is_msm8610()) {
-		dummy_socinfo.id = 147;
-		strlcpy(dummy_socinfo.build_id, "msm8610 - ",
-			sizeof(dummy_socinfo.build_id));
 	} else if (early_machine_is_msmzinc()) {
 		dummy_socinfo.id = 178;
 		strlcpy(dummy_socinfo.build_id, "msmzinc - ",
diff --git a/block/blk-core.c b/block/blk-core.c
index bd50c8e..69764df 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1080,6 +1080,16 @@
 
 	BUG_ON(blk_queued_rq(rq));
 
+	if (rq->cmd_flags & REQ_URGENT) {
+		/*
+		 * It's not compliant with the design to re-insert
+		 * urgent requests. We want to be able to track this
+		 * down.
+		 */
+		pr_err("%s(): requeueing an URGENT request", __func__);
+		WARN_ON(!q->dispatched_urgent);
+		q->dispatched_urgent = false;
+	}
 	elv_requeue_request(q, rq);
 }
 EXPORT_SYMBOL(blk_requeue_request);
@@ -1107,6 +1117,16 @@
 		blk_queue_end_tag(q, rq);
 
 	BUG_ON(blk_queued_rq(rq));
+	if (rq->cmd_flags & REQ_URGENT) {
+		/*
+		 * It's not compliant with the design to re-insert
+		 * urgent requests. We want to be able to track this
+		 * down.
+		 */
+		pr_err("%s(): requeueing an URGENT request", __func__);
+		WARN_ON(!q->dispatched_urgent);
+		q->dispatched_urgent = false;
+	}
 
 	return elv_reinsert_request(q, rq);
 }
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 8b7259a..0de37c9 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.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
@@ -712,6 +712,40 @@
 }
 EXPORT_SYMBOL(genlock_get_handle_fd);
 
+/*
+ * Get a file descriptor reference to a lock suitable for sharing with
+ * other processes
+ */
+
+int genlock_get_fd_handle(struct genlock_handle *handle)
+{
+	int ret;
+	struct genlock *lock;
+
+	if (IS_ERR_OR_NULL(handle))
+		return -EINVAL;
+
+	lock = handle->lock;
+
+	if (IS_ERR(lock))
+		return PTR_ERR(lock);
+
+	if (!lock->file) {
+		GENLOCK_LOG_ERR("No file attached to the lock\n");
+		return -EINVAL;
+	}
+
+	ret = get_unused_fd_flags(0);
+
+	if (ret < 0)
+		return ret;
+
+	fd_install(ret, lock->file);
+
+	return ret;
+}
+EXPORT_SYMBOL(genlock_get_fd_handle);
+
 #ifdef CONFIG_GENLOCK_MISCDEVICE
 
 static long genlock_dev_ioctl(struct file *filep, unsigned int cmd,
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index ba0fd7c..739a753 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -610,7 +610,8 @@
 			/* write xts du size */
 			pce = cmdlistinfo->encr_xts_du_size;
 			if (use_pipe_key == true)
-				pce->data = QCE_SECTOR_SIZE;
+				pce->data = min((unsigned int)QCE_SECTOR_SIZE,
+						creq->cryptlen);
 			else
 				pce->data = creq->cryptlen;
 		}
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 2440404..408e705 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1530,6 +1530,45 @@
 
 }
 
+static int qcedev_check_cipher_key(struct qcedev_cipher_op_req *req,
+						struct qcedev_control *podev)
+{
+	/* if intending to use HW key make sure key fields are set
+	 * correctly and HW key is indeed supported in target
+	 */
+	if (req->encklen == 0) {
+		int i;
+		for (i = 0; i < QCEDEV_MAX_KEY_SIZE; i++)
+			if (req->enckey[i])
+				goto error;
+		if ((req->op != QCEDEV_OPER_ENC_NO_KEY) &&
+			(req->op != QCEDEV_OPER_DEC_NO_KEY))
+			if (!podev->platform_support.hw_key_support)
+				goto error;
+	} else {
+		if (req->encklen == QCEDEV_AES_KEY_192) {
+			if (!podev->ce_support.aes_key_192)
+				goto error;
+		} else {
+			/* if not using HW key make sure key
+			 * length is valid
+			 */
+			if ((req->mode == QCEDEV_AES_MODE_XTS)) {
+				if (!((req->encklen == QCEDEV_AES_KEY_128*2) ||
+					(req->encklen == QCEDEV_AES_KEY_256*2)))
+					goto error;
+			} else {
+				if (!((req->encklen == QCEDEV_AES_KEY_128) ||
+					(req->encklen == QCEDEV_AES_KEY_256)))
+					goto error;
+			}
+		}
+	}
+	return 0;
+error:
+	return -EINVAL;
+}
+
 static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
 						struct qcedev_control *podev)
 {
@@ -1542,36 +1581,13 @@
 	if ((req->alg >= QCEDEV_ALG_LAST) ||
 		(req->mode >= QCEDEV_AES_DES_MODE_LAST))
 		goto error;
-	if (req->alg == QCEDEV_ALG_AES) {
-		if ((req->mode == QCEDEV_AES_MODE_XTS) &&
-					(!podev->ce_support.aes_xts))
-			goto error;
-		/* if intending to use HW key make sure key fields are set
-		 * correctly and HW key is indeed supported in target
-		 */
-		if (req->encklen == 0) {
-			int i;
-			for (i = 0; i < QCEDEV_MAX_KEY_SIZE; i++)
-				if (req->enckey[i])
+
+	if ((req->mode == QCEDEV_AES_MODE_XTS) && (!podev->ce_support.aes_xts))
 					goto error;
-			if ((req->op != QCEDEV_OPER_ENC_NO_KEY) &&
-				(req->op != QCEDEV_OPER_DEC_NO_KEY))
-				if (!podev->platform_support.hw_key_support)
+
+	if (req->alg == QCEDEV_ALG_AES)
+		if (qcedev_check_cipher_key(req, podev))
 					goto error;
-		} else {
-			if (req->encklen == QCEDEV_AES_KEY_192) {
-				if (!podev->ce_support.aes_key_192)
-					goto error;
-			} else {
-				/* if not using HW key make sure key
-				 * length is valid
-				 */
-				if (!((req->encklen == QCEDEV_AES_KEY_128) ||
-					(req->encklen == QCEDEV_AES_KEY_256)))
-					goto error;
-			}
-		}
-	}
 	/* if using a byteoffset, make sure it is CTR mode using vbuf */
 	if (req->byteoffset) {
 		if (req->mode != QCEDEV_AES_MODE_CTR)
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 05ef87c..85c25c7 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -677,12 +677,10 @@
 	return 0;
 };
 
-static int _qcrypto_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key,
-		unsigned int len)
+
+static int _qcrypto_check_aes_keylen(struct crypto_ablkcipher *cipher,
+		struct crypto_priv *cp, unsigned int len)
 {
-	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
-	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
-	struct crypto_priv *cp = ctx->cp;
 
 	switch (len) {
 	case AES_KEYSIZE_128:
@@ -695,8 +693,40 @@
 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	};
-	ctx->enc_key_len = len;
-	memcpy(ctx->enc_key, key, len);
+
+	return 0;
+}
+
+static int _qcrypto_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key,
+		unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_priv *cp = ctx->cp;
+
+	if (_qcrypto_check_aes_keylen(cipher, cp, len)) {
+		return -EINVAL;
+	} else {
+		ctx->enc_key_len = len;
+		memcpy(ctx->enc_key, key, len);
+	}
+	return 0;
+};
+
+static int _qcrypto_setkey_aes_xts(struct crypto_ablkcipher *cipher,
+		const u8 *key, unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_priv *cp = ctx->cp;
+
+
+	if (_qcrypto_check_aes_keylen(cipher, cp, len/2)) {
+		return -EINVAL;
+	} else {
+		ctx->enc_key_len = len;
+		memcpy(ctx->enc_key, key, len);
+	}
 	return 0;
 };
 
@@ -3124,7 +3154,7 @@
 			.ivsize		= AES_BLOCK_SIZE,
 			.min_keysize	= AES_MIN_KEY_SIZE,
 			.max_keysize	= AES_MAX_KEY_SIZE,
-			.setkey		= _qcrypto_setkey_aes,
+			.setkey		= _qcrypto_setkey_aes_xts,
 			.encrypt	= _qcrypto_enc_aes_xts,
 			.decrypt	= _qcrypto_dec_aes_xts,
 		},
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index ce25bfd..d3434d8 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -456,7 +456,7 @@
 	struct ion_handle *handle;
 	struct ion_device *dev = client->dev;
 	struct ion_buffer *buffer = NULL;
-	unsigned long secure_allocation = flags & ION_SECURE;
+	unsigned long secure_allocation = flags & ION_FLAG_SECURE;
 	const unsigned int MAX_DBG_STR_LEN = 64;
 	char dbg_str[MAX_DBG_STR_LEN];
 	unsigned int dbg_str_idx = 0;
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index d7a5920..0fbcfbf 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -117,7 +117,7 @@
 			    unsigned long len, unsigned long align,
 			    unsigned long flags)
 {
-	unsigned long secure_allocation = flags & ION_SECURE;
+	unsigned long secure_allocation = flags & ION_FLAG_SECURE;
 	struct ion_secure_cma_buffer_info *buf = NULL;
 
 	if (!secure_allocation) {
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 7bcae01..88addab 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -289,8 +289,8 @@
 				      unsigned long flags)
 {
 	unsigned long offset;
-	unsigned long secure_allocation = flags & ION_SECURE;
-	unsigned long force_contig = flags & ION_FORCE_CONTIGUOUS;
+	unsigned long secure_allocation = flags & ION_FLAG_SECURE;
+	unsigned long force_contig = flags & ION_FLAG_FORCE_CONTIGUOUS;
 
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
@@ -460,7 +460,7 @@
 	buf->want_delayed_unsecure = 0;
 	atomic_set(&buf->secure_cnt, 0);
 	mutex_init(&buf->lock);
-	buf->is_secure = flags & ION_SECURE ? 1 : 0;
+	buf->is_secure = flags & ION_FLAG_SECURE ? 1 : 0;
 	buffer->priv_virt = buf;
 
 	return 0;
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 28ef1a5..8d45f9d 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -23,44 +23,9 @@
 #include <linux/mutex.h>
 #include <linux/rbtree.h>
 #include <linux/ion.h>
-#include <linux/iommu.h>
 #include <linux/seq_file.h>
 
-enum {
-	DI_PARTITION_NUM = 0,
-	DI_DOMAIN_NUM = 1,
-	DI_MAX,
-};
-
-/**
- * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
- * @iova_addr - iommu virtual address
- * @node - rb node to exist in the buffer's tree of iommu mappings
- * @domain_info - contains the partition number and domain number
- *		domain_info[1] = domain number
- *		domain_info[0] = partition number
- * @ref - for reference counting this mapping
- * @mapped_size - size of the iova space mapped
- *		(may not be the same as the buffer size)
- * @flags - iommu domain/partition specific flags.
- *
- * Represents a mapping of one ion buffer to a particular iommu domain
- * and address range. There may exist other mappings of this buffer in
- * different domains or address ranges. All mappings will have the same
- * cacheability and security.
- */
-struct ion_iommu_map {
-	unsigned long iova_addr;
-	struct rb_node node;
-	union {
-		int domain_info[DI_MAX];
-		uint64_t key;
-	};
-	struct ion_buffer *buffer;
-	struct kref ref;
-	int mapped_size;
-	unsigned long flags;
-};
+#include "msm_ion_priv.h"
 
 struct ion_buffer *ion_handle_buffer(struct ion_handle *handle);
 
@@ -190,26 +155,6 @@
 bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
 
 /**
- * struct mem_map_data - represents information about the memory map for a heap
- * @node:		rb node used to store in the tree of mem_map_data
- * @addr:		start address of memory region.
- * @addr:		end address of memory region.
- * @size:		size of memory region
- * @client_name:		name of the client who owns this buffer.
- *
- */
-struct mem_map_data {
-	struct rb_node node;
-	ion_phys_addr_t addr;
-	ion_phys_addr_t addr_end;
-	unsigned long size;
-	const char *client_name;
-};
-
-#define iommu_map_domain(__m)		((__m)->domain_info[1])
-#define iommu_map_partition(__m)	((__m)->domain_info[0])
-
-/**
  * ion_device_create - allocates and returns an ion device
  * @custom_ioctl:	arch specific ioctl function if applicable
  *
@@ -251,15 +196,6 @@
 struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *);
 void ion_carveout_heap_destroy(struct ion_heap *);
 
-struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *);
-void ion_iommu_heap_destroy(struct ion_heap *);
-
-struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *);
-void ion_cp_heap_destroy(struct ion_heap *);
-
-struct ion_heap *ion_reusable_heap_create(struct ion_platform_heap *);
-void ion_reusable_heap_destroy(struct ion_heap *);
-
 /**
  * kernel api to allocate/free from carveout -- used when carveout is
  * used to back an architecture specific custom heap
@@ -269,88 +205,10 @@
 void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
 		       unsigned long size);
 
-#ifdef CONFIG_CMA
-struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *);
-void ion_cma_heap_destroy(struct ion_heap *);
-
-struct ion_heap *ion_secure_cma_heap_create(struct ion_platform_heap *);
-void ion_secure_cma_heap_destroy(struct ion_heap *);
-#endif
-
-struct ion_heap *msm_get_contiguous_heap(void);
 /**
- * The carveout/cp heap returns physical addresses, since 0 may be a valid
+ * The carveout heap returns physical addresses, since 0 may be a valid
  * physical address, this is used to indicate allocation failed
  */
 #define ION_CARVEOUT_ALLOCATE_FAIL -1
-#define ION_CP_ALLOCATE_FAIL -1
 
-/**
- * The reserved heap returns physical addresses, since 0 may be a valid
- * physical address, this is used to indicate allocation failed
- */
-#define ION_RESERVED_ALLOCATE_FAIL -1
-
-/**
- * ion_map_fmem_buffer - map fmem allocated memory into the kernel
- * @buffer - buffer to map
- * @phys_base - physical base of the heap
- * @virt_base - virtual base of the heap
- * @flags - flags for the heap
- *
- * Map fmem allocated memory into the kernel address space. This
- * is designed to be used by other heaps that need fmem behavior.
- * The virtual range must be pre-allocated.
- */
-void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base,
-				void *virt_base, unsigned long flags);
-
-/**
- * ion_do_cache_op - do cache operations.
- *
- * @client - pointer to ION client.
- * @handle - pointer to buffer handle.
- * @uaddr -  virtual address to operate on.
- * @offset - offset from physical address.
- * @len - Length of data to do cache operation on.
- * @cmd - Cache operation to perform:
- *		ION_IOC_CLEAN_CACHES
- *		ION_IOC_INV_CACHES
- *		ION_IOC_CLEAN_INV_CACHES
- *
- * Returns 0 on success
- */
-int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
-			void *uaddr, unsigned long offset, unsigned long len,
-			unsigned int cmd);
-
-void ion_cp_heap_get_base(struct ion_heap *heap, unsigned long *base,
-			unsigned long *size);
-
-void ion_mem_map_show(struct ion_heap *heap);
-
-
-
-int ion_secure_handle(struct ion_client *client, struct ion_handle *handle,
-			int version, void *data, int flags);
-
-int ion_unsecure_handle(struct ion_client *client, struct ion_handle *handle);
-
-int ion_heap_allow_secure_allocation(enum ion_heap_type type);
-
-int ion_heap_allow_heap_secure(enum ion_heap_type type);
-
-int ion_heap_allow_handle_secure(enum ion_heap_type type);
-
-/**
- * ion_create_chunked_sg_table - helper function to create sg table
- * with specified chunk size
- * @buffer_base:	The starting address used for the sg dma address
- * @chunk_size:		The size of each entry in the sg table
- * @total_size:		The total size of the sg table (i.e. the sum of the
- *			entries). This will be rounded up to the nearest
- *			multiple of `chunk_size'
- */
-struct sg_table *ion_create_chunked_sg_table(phys_addr_t buffer_base,
-					size_t chunk_size, size_t total_size);
 #endif /* _ION_PRIV_H */
diff --git a/drivers/gpu/ion/msm_ion_priv.h b/drivers/gpu/ion/msm_ion_priv.h
new file mode 100644
index 0000000..44f434a
--- /dev/null
+++ b/drivers/gpu/ion/msm_ion_priv.h
@@ -0,0 +1,150 @@
+/*
+ * drivers/gpu/ion/ion_priv.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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_ION_PRIV_H
+#define _MSM_ION_PRIV_H
+
+#include <linux/kref.h>
+#include <linux/mm_types.h>
+#include <linux/mutex.h>
+#include <linux/rbtree.h>
+#include <linux/ion.h>
+#include <linux/iommu.h>
+#include <linux/seq_file.h>
+
+enum {
+	DI_PARTITION_NUM = 0,
+	DI_DOMAIN_NUM = 1,
+	DI_MAX,
+};
+
+/**
+ * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
+ * @iova_addr - iommu virtual address
+ * @node - rb node to exist in the buffer's tree of iommu mappings
+ * @domain_info - contains the partition number and domain number
+ *		domain_info[1] = domain number
+ *		domain_info[0] = partition number
+ * @ref - for reference counting this mapping
+ * @mapped_size - size of the iova space mapped
+ *		(may not be the same as the buffer size)
+ * @flags - iommu domain/partition specific flags.
+ *
+ * Represents a mapping of one ion buffer to a particular iommu domain
+ * and address range. There may exist other mappings of this buffer in
+ * different domains or address ranges. All mappings will have the same
+ * cacheability and security.
+ */
+struct ion_iommu_map {
+	unsigned long iova_addr;
+	struct rb_node node;
+	union {
+		int domain_info[DI_MAX];
+		uint64_t key;
+	};
+	struct ion_buffer *buffer;
+	struct kref ref;
+	int mapped_size;
+	unsigned long flags;
+};
+
+/**
+ * struct mem_map_data - represents information about the memory map for a heap
+ * @node:		rb node used to store in the tree of mem_map_data
+ * @addr:		start address of memory region.
+ * @addr:		end address of memory region.
+ * @size:		size of memory region
+ * @client_name:		name of the client who owns this buffer.
+ *
+ */
+struct mem_map_data {
+	struct rb_node node;
+	ion_phys_addr_t addr;
+	ion_phys_addr_t addr_end;
+	unsigned long size;
+	const char *client_name;
+};
+
+#define iommu_map_domain(__m)		((__m)->domain_info[1])
+#define iommu_map_partition(__m)	((__m)->domain_info[0])
+
+struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *);
+void ion_iommu_heap_destroy(struct ion_heap *);
+
+struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *);
+void ion_cp_heap_destroy(struct ion_heap *);
+
+#ifdef CONFIG_CMA
+struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *);
+void ion_cma_heap_destroy(struct ion_heap *);
+
+struct ion_heap *ion_secure_cma_heap_create(struct ion_platform_heap *);
+void ion_secure_cma_heap_destroy(struct ion_heap *);
+#endif
+
+#define ION_CP_ALLOCATE_FAIL -1
+#define ION_RESERVED_ALLOCATE_FAIL -1
+
+/**
+ * ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @uaddr -  virtual address to operate on.
+ * @offset - offset from physical address.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ *		ION_IOC_CLEAN_CACHES
+ *		ION_IOC_INV_CACHES
+ *		ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+			void *uaddr, unsigned long offset, unsigned long len,
+			unsigned int cmd);
+
+void ion_cp_heap_get_base(struct ion_heap *heap, unsigned long *base,
+			unsigned long *size);
+
+void ion_mem_map_show(struct ion_heap *heap);
+
+
+
+int ion_secure_handle(struct ion_client *client, struct ion_handle *handle,
+			int version, void *data, int flags);
+
+int ion_unsecure_handle(struct ion_client *client, struct ion_handle *handle);
+
+int ion_heap_allow_secure_allocation(enum ion_heap_type type);
+
+int ion_heap_allow_heap_secure(enum ion_heap_type type);
+
+int ion_heap_allow_handle_secure(enum ion_heap_type type);
+
+/**
+ * ion_create_chunked_sg_table - helper function to create sg table
+ * with specified chunk size
+ * @buffer_base:	The starting address used for the sg dma address
+ * @chunk_size:		The size of each entry in the sg table
+ * @total_size:		The total size of the sg table (i.e. the sum of the
+ *			entries). This will be rounded up to the nearest
+ *			multiple of `chunk_size'
+ */
+struct sg_table *ion_create_chunked_sg_table(phys_addr_t buffer_base,
+					size_t chunk_size, size_t total_size);
+#endif /* _MSM_ION_PRIV_H */
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 70e7973..c768bb7 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -683,11 +683,11 @@
 #define A305C_RBBM_CLOCK_CTL_DEFAULT  0xAAAAAAAA
 #define A320_RBBM_CLOCK_CTL_DEFAULT   0xBFFFFFFF
 #define A330_RBBM_CLOCK_CTL_DEFAULT   0xBFFCFFFF
-#define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
+#define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
 #define A305B_RBBM_CLOCK_CTL_DEFAULT  0xAAAAAAAA
 
 #define A330_RBBM_GPR0_CTL_DEFAULT    0x00000000
-#define A330v2_RBBM_GPR0_CTL_DEFAULT  0x00000000
+#define A330v2_RBBM_GPR0_CTL_DEFAULT  0x05515455
 
 /* COUNTABLE FOR SP PERFCOUNTER */
 #define SP_FS_FULL_ALU_INSTRUCTIONS    0x0E
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 62b6a71..5589ff0 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1859,7 +1859,8 @@
 	}
 	if (status)
 		KGSL_FT_ERR(rb->device,
-		"Failed to find the command sequence after eop timestamp\n");
+		"Failed to find the command sequence after eop timestamp %x\n",
+		global_eop);
 	return status;
 }
 
@@ -1972,44 +1973,38 @@
 
 	/* find the start of bad command sequence in rb */
 	context = idr_find(&device->context_idr, ft_data->context_id);
-	/* Look for the command stream that is right after the global eop */
-
-	if (!context) {
-		/*
-		 * If there is no context then fault tolerance does not need to
-		 * replay anything, just reset GPU and thats it
-		 */
-		return;
-	}
 
 	ft_data->ft_policy = adreno_dev->ft_policy;
 
 	if (!ft_data->ft_policy)
 		ft_data->ft_policy = KGSL_FT_DEFAULT_POLICY;
 
+	/* Look for the command stream that is right after the global eop */
 	ret = _find_cmd_seq_after_eop_ts(rb, &rb_rptr,
 					ft_data->global_eop + 1, false);
 	if (ret) {
 		ft_data->ft_policy |= KGSL_FT_TEMP_DISABLE;
 		return;
-	} else
+	} else {
+		ft_data->start_of_replay_cmds = rb_rptr;
 		ft_data->ft_policy &= ~KGSL_FT_TEMP_DISABLE;
+	}
 
-	ft_data->start_of_replay_cmds = rb_rptr;
-
-	adreno_context = context->devctxt;
-	if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
-		if (ft_data->ib1) {
-			ret = _find_hanging_ib_sequence(rb,
-					&rb_rptr, ft_data->ib1);
-			if (ret) {
-				KGSL_FT_ERR(device,
-				"Start not found for replay IB sequence\n");
-				ret = 0;
-				return;
+	if (context) {
+		adreno_context = context->devctxt;
+		if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
+			if (ft_data->ib1) {
+				ret = _find_hanging_ib_sequence(rb,
+						&rb_rptr, ft_data->ib1);
+				if (ret) {
+					KGSL_FT_ERR(device,
+					"Start not found for replay IB seq\n");
+					ret = 0;
+					return;
+				}
+				ft_data->start_of_replay_cmds = rb_rptr;
+				ft_data->replay_for_snapshot = rb_rptr;
 			}
-			ft_data->start_of_replay_cmds = rb_rptr;
-			ft_data->replay_for_snapshot = rb_rptr;
 		}
 	}
 }
@@ -2046,9 +2041,6 @@
 _adreno_ft_restart_device(struct kgsl_device *device,
 			   struct kgsl_context *context)
 {
-
-	struct adreno_context *adreno_context = context->devctxt;
-
 	/* restart device */
 	if (adreno_stop(device)) {
 		KGSL_FT_ERR(device, "Device stop failed\n");
@@ -2065,9 +2057,11 @@
 		return 1;
 	}
 
-	if (context)
+	if (context) {
+		struct adreno_context *adreno_context = context->devctxt;
 		kgsl_mmu_setstate(&device->mmu, adreno_context->pagetable,
 			KGSL_MEMSTORE_GLOBAL);
+	}
 
 	/* If iommu is used then we need to make sure that the iommu clocks
 	 * are on since there could be commands in pipeline that touch iommu */
@@ -2168,13 +2162,22 @@
 	struct adreno_context *adreno_context = NULL;
 	struct adreno_context *last_active_ctx = adreno_dev->drawctxt_active;
 	unsigned int long_ib = 0;
+	static int no_context_ft;
 
 	context = idr_find(&device->context_idr, ft_data->context_id);
 	if (context == NULL) {
 		KGSL_FT_ERR(device, "Last context unknown id:%d\n",
 			ft_data->context_id);
-		goto play_good_cmds;
+		if (no_context_ft) {
+			/*
+			 * If 2 consecutive no context ft occurred then
+			 * just reset GPU
+			 */
+			no_context_ft = 0;
+			goto play_good_cmds;
+		}
 	} else {
+		no_context_ft = 0;
 		adreno_context = context->devctxt;
 		adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
 		/*
@@ -2230,7 +2233,7 @@
 	}
 
 	/* Do not try the reply if hang is due to a pagefault */
-	if (adreno_context->pagefault) {
+	if (adreno_context && adreno_context->pagefault) {
 		if ((ft_data->context_id == adreno_context->id) &&
 			(ft_data->global_eop == adreno_context->pagefault_ts)) {
 			ft_data->ft_policy &= ~KGSL_FT_REPLAY;
@@ -2295,7 +2298,7 @@
 
 		/* EOF not found in RB, discard till EOF in
 		   next IB submission */
-		if (i == ft_data->bad_rb_size) {
+		if (adreno_context && (i == ft_data->bad_rb_size)) {
 			adreno_context->flags |= CTXT_FLAGS_SKIP_EOF;
 			KGSL_FT_INFO(device,
 			"EOF not found in RB, skip next issueib till EOF\n");
@@ -2332,8 +2335,14 @@
 			ft_data->good_rb_buffer, ft_data->good_rb_size);
 
 	if (ret) {
-		/* If we fail here we can try to invalidate another
-		 * context and try fault tolerance again */
+		/*
+		 * If we fail here we can try to invalidate another
+		 * context and try fault tolerance again, although
+		 * we will only try ft with no context once to avoid
+		 * going into continuous loop of trying ft with no context
+		 */
+		if (!context)
+			no_context_ft = 1;
 		ret = -EAGAIN;
 		KGSL_FT_ERR(device, "Playing good commands unsuccessful\n");
 		goto done;
@@ -3166,6 +3175,31 @@
 					"Fault tolerance no context found\n");
 			}
 		}
+		for (i = 0; i < ft_detect_regs_count; i++) {
+			if (curr_reg_val[i] != prev_reg_val[i]) {
+				fast_hang_detected = 0;
+
+				/* Check for long IB here */
+				if ((i >=
+					LONG_IB_DETECT_REG_INDEX_START)
+					&&
+					(i <=
+					LONG_IB_DETECT_REG_INDEX_END))
+					long_ib_detected = 0;
+			}
+		}
+
+		if (fast_hang_detected) {
+			KGSL_FT_ERR(device,
+				"Proc %s, ctxt_id %d ts %d triggered fault tolerance"
+				" on global ts %d\n",
+				curr_context ? curr_context->pid_name : "",
+				curr_context ? curr_context->id : 0,
+				(kgsl_readtimestamp(device, context,
+				KGSL_TIMESTAMP_RETIRED) + 1),
+				curr_global_ts + 1);
+			return 1;
+		}
 
 		if (curr_context != NULL) {
 
@@ -3175,31 +3209,6 @@
 			curr_context->pid_name, curr_context->ib_gpu_time_used,
 			curr_global_ts+1);
 
-			for (i = 0; i < ft_detect_regs_count; i++) {
-				if (curr_reg_val[i] != prev_reg_val[i]) {
-					fast_hang_detected = 0;
-
-					/* Check for long IB here */
-					if ((i >=
-						LONG_IB_DETECT_REG_INDEX_START)
-						&&
-						(i <=
-						LONG_IB_DETECT_REG_INDEX_END))
-						long_ib_detected = 0;
-				}
-			}
-
-			if (fast_hang_detected) {
-				KGSL_FT_ERR(device,
-					"Proc %s, ctxt_id %d ts %d triggered fault tolerance"
-					" on global ts %d\n",
-					curr_context->pid_name, curr_context->id
-					, (kgsl_readtimestamp(device, context,
-					KGSL_TIMESTAMP_RETIRED)+1),
-					curr_global_ts+1);
-				return 1;
-			}
-
 			if ((long_ib_detected) &&
 				(!(curr_context->flags &
 				 CTXT_FLAGS_NO_FAULT_TOLERANCE))) {
@@ -3229,10 +3238,6 @@
 					}
 				}
 			}
-		} else {
-			KGSL_FT_ERR(device,
-				"Last context unknown id:%d\n",
-				curr_context_id);
 		}
 	} else {
 		/* GPU is moving forward */
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 11d6ffa..007f89a 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -18,6 +18,7 @@
 #include "drm.h"
 
 #include <linux/msm_ion.h>
+#include <linux/genlock.h>
 
 #include "kgsl.h"
 #include "kgsl_device.h"
@@ -119,6 +120,8 @@
 		uint32_t gpuaddr;
 	} bufs[DRM_KGSL_GEM_MAX_BUFFERS];
 
+	struct genlock_handle *glock_handle[DRM_KGSL_GEM_MAX_BUFFERS];
+
 	int bound;
 	int lockpid;
 	/* Put these here to avoid allocing all the time */
@@ -154,6 +157,7 @@
 kgsl_gem_alloc_memory(struct drm_gem_object *obj)
 {
 	struct drm_kgsl_gem_object *priv = obj->driver_private;
+	struct kgsl_mmu *mmu;
 	struct sg_table *sg_table;
 	struct scatterlist *s;
 	int index;
@@ -165,7 +169,17 @@
 		return 0;
 
 	if (priv->pagetable == NULL) {
-		priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+		/* Hard coded to use A2X device for MSM7X27 and MSM8625
+		 * Others to use A3X device
+		 */
+#if defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM8625)
+		mmu = &kgsl_get_device(KGSL_DEVICE_2D0)->mmu;
+#else
+		mmu = &kgsl_get_device(KGSL_DEVICE_3D0)->mmu;
+#endif
+
+		priv->pagetable = kgsl_mmu_getpagetable(mmu,
+					KGSL_MMU_GLOBAL_PT);
 
 		if (priv->pagetable == NULL) {
 			DRM_ERROR("Unable to get the GPU MMU pagetable\n");
@@ -259,8 +273,7 @@
 			priv->memdesc.sglen++;
 		}
 
-		result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
-				GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+		result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 		if (result) {
 			DRM_ERROR(
 			"kgsl_mmu_map failed.  result = %d\n", result);
@@ -293,6 +306,7 @@
 kgsl_gem_free_memory(struct drm_gem_object *obj)
 {
 	struct drm_kgsl_gem_object *priv = obj->driver_private;
+	int index;
 
 	if (!kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
 		return;
@@ -311,6 +325,11 @@
 
 	memset(&priv->memdesc, 0, sizeof(priv->memdesc));
 
+	for (index = 0; index < priv->bufcount; index++) {
+		if (priv->glock_handle[index])
+			genlock_put_handle(priv->glock_handle[index]);
+	}
+
 	kgsl_mmu_putpagetable(priv->pagetable);
 	priv->pagetable = NULL;
 
@@ -552,6 +571,7 @@
 	struct scatterlist *s;
 	int ret, handle;
 	unsigned long size;
+	struct kgsl_mmu *mmu;
 
 	ion_handle = ion_import_dma_buf(kgsl_drm_ion_client, args->ion_fd);
 	if (IS_ERR_OR_NULL(ion_handle)) {
@@ -591,7 +611,13 @@
 	priv->type = DRM_KGSL_GEM_TYPE_KMEM;
 	list_add(&priv->list, &kgsl_mem_list);
 
-	priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+#if defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM8625)
+	mmu = &kgsl_get_device(KGSL_DEVICE_2D0)->mmu;
+#else
+	mmu = &kgsl_get_device(KGSL_DEVICE_3D0)->mmu;
+#endif
+
+	priv->pagetable = kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT);
 
 	priv->memdesc.pagetable = priv->pagetable;
 
@@ -619,8 +645,7 @@
 		priv->memdesc.sglen++;
 	}
 
-	ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
-		GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 	if (ret) {
 		DRM_ERROR("kgsl_mmu_map failed.  ret = %d\n", ret);
 		ion_free(kgsl_drm_ion_client,
@@ -877,6 +902,68 @@
 	return ret;
 }
 
+/* Get the genlock handles base off the GEM handle
+ */
+
+int
+kgsl_gem_get_glock_handles_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file_priv)
+{
+	struct drm_kgsl_gem_glockinfo *args = data;
+	struct drm_gem_object *obj;
+	struct drm_kgsl_gem_object *priv;
+	int index;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+
+	if (obj == NULL) {
+		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
+		return -EBADF;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+	priv = obj->driver_private;
+
+	for (index = 0; index < priv->bufcount; index++) {
+		args->glockhandle[index] = genlock_get_fd_handle(
+						priv->glock_handle[index]);
+	}
+
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+}
+
+int
+kgsl_gem_set_glock_handles_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file_priv)
+{
+	struct drm_kgsl_gem_glockinfo *args = data;
+	struct drm_gem_object *obj;
+	struct drm_kgsl_gem_object *priv;
+	int index;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+
+	if (obj == NULL) {
+		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
+		return -EBADF;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+	priv = obj->driver_private;
+
+	for (index = 0; index < priv->bufcount; index++) {
+		priv->glock_handle[index] = genlock_get_handle_fd(
+						args->glockhandle[index]);
+	}
+
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
 int
 kgsl_gem_set_bufcount_ioctl(struct drm_device *dev, void *data,
 			  struct drm_file *file_priv)
@@ -919,6 +1006,32 @@
 }
 
 int
+kgsl_gem_get_bufcount_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	struct drm_kgsl_gem_bufcount *args = data;
+	struct drm_gem_object *obj;
+	struct drm_kgsl_gem_object *priv;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+
+	if (obj == NULL) {
+		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
+		return -EBADF;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+	priv = obj->driver_private;
+
+	args->bufcount =  priv->bufcount;
+
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+int
 kgsl_gem_set_active_ioctl(struct drm_device *dev, void *data,
 			  struct drm_file *file_priv)
 {
@@ -1375,9 +1488,15 @@
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_BUFINFO, kgsl_gem_get_bufinfo_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_ION_FD, kgsl_gem_get_ion_fd_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_CREATE_FROM_ION,
-		kgsl_gem_create_from_ion_ioctl, 0),
+				kgsl_gem_create_from_ion_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_BUFCOUNT,
-		      kgsl_gem_set_bufcount_ioctl, 0),
+				kgsl_gem_set_bufcount_ioctl, 0),
+	DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_BUFCOUNT,
+				kgsl_gem_get_bufcount_ioctl, 0),
+	DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_GLOCK_HANDLES_INFO,
+				kgsl_gem_set_glock_handles_ioctl, 0),
+	DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_GLOCK_HANDLES_INFO,
+				kgsl_gem_get_glock_handles_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_ACTIVE, kgsl_gem_set_active_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_LOCK_HANDLE,
 				  kgsl_gem_lock_handle_ioctl, 0),
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 0e3e046..813305a 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -69,6 +69,7 @@
 
 struct kgsl_fence_event_priv {
 	struct kgsl_context *context;
+	unsigned int timestamp;
 };
 
 /**
@@ -85,7 +86,7 @@
 	void *priv, u32 context_id, u32 timestamp)
 {
 	struct kgsl_fence_event_priv *ev = priv;
-	kgsl_sync_timeline_signal(ev->context->timeline, timestamp);
+	kgsl_sync_timeline_signal(ev->context->timeline, ev->timestamp);
 	kgsl_context_put(ev->context);
 	kfree(ev);
 }
@@ -125,6 +126,7 @@
 	if (event == NULL)
 		return -ENOMEM;
 	event->context = context;
+	event->timestamp = timestamp;
 	kgsl_context_get(context);
 
 	pt = kgsl_sync_pt_create(context->timeline, timestamp);
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 330c850..f35f0e7 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -49,7 +49,6 @@
 config IOMMU_PGTABLES_L2
 	bool "Allow SMMU page tables in the L2 cache (Experimental)"
 	depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
-	default y
         help
          Improves TLB miss latency at the expense of potential L2 pollution.
          However, with large multimedia buffers, the TLB should mostly contain
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index ca61bcf..219970b 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -2373,8 +2373,18 @@
 		return 0;
 	}
 
-	if ((dmxdevfilter->params.pes.output == DMX_OUT_DECODER) ||
-		(buffer->error)) {
+	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
+		if (DMX_OVERRUN_ERROR == dmx_data_ready->status) {
+			dprintk("dmxdev: buffer overflow\n");
+			event.type = DMX_EVENT_BUFFER_OVERFLOW;
+			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
+		}
+		spin_unlock(&dmxdevfilter->dev->lock);
+		wake_up_all(&buffer->queue);
+		return 0;
+	}
+
+	if (buffer->error) {
 		spin_unlock(&dmxdevfilter->dev->lock);
 		wake_up_all(&buffer->queue);
 		return 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 4740a80..3f73c4d 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -376,6 +376,10 @@
 	else
 		ccok = ((feed->cc + 1) & 0x0f) == cc;
 
+	/* discard TS packets holding sections with TEI bit set */
+	if (buf[1] & 0x80)
+		return -EINVAL;
+
 	feed->first_cc = 0;
 	feed->cc = cc;
 
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 32aa4ef..802349a 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -38,6 +38,7 @@
 struct camera_v4l2_private {
 	struct v4l2_fh fh;
 	unsigned int stream_id;
+	unsigned int is_vb2_valid; /*0 if no vb2 buffers on stream, else 1*/
 	struct vb2_queue vb2_q;
 };
 
@@ -314,6 +315,7 @@
 		rc = camera_check_event_status(&event);
 		if (rc < 0)
 			goto set_fmt_fail;
+		sp->is_vb2_valid = 1;
 	}
 
 	return rc;
@@ -550,8 +552,8 @@
 {
 	int rc = 0;
 	struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
-
-	rc = vb2_poll(&sp->vb2_q, filep, wait);
+	if (sp->is_vb2_valid == 1)
+		rc = vb2_poll(&sp->vb2_q, filep, wait);
 
 	poll_wait(filep, &sp->fh.wait, wait);
 	if (v4l2_event_pending(&sp->fh))
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 31fa39e..d4f6a07 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -24,7 +24,7 @@
 
 #define VFE32_BURST_LEN 3
 #define VFE32_UB_SIZE 1024
-#define VFE32_EQUAL_SLICE_UB 117
+#define VFE32_EQUAL_SLICE_UB 204
 #define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx)
 #define VFE32_RDI_BASE(idx) (idx ? 0x734 + 0x4 * (idx - 1) : 0x06FC)
 #define VFE32_XBAR_BASE(idx) (0x40 + 0x4 * (idx / 4))
@@ -592,7 +592,7 @@
 			stream_cfg_cmd->plane_cfg[plane_idx].
 			output_stride) << 16 |
 			(stream_cfg_cmd->plane_cfg[plane_idx].
-			output_height - 1) << 4 | VFE32_BURST_LEN >> 2;
+			output_height - 1) << 4 | VFE32_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
 	} else {
 		msm_camera_io_w(0x2, vfe_dev->vfe_base + wm_base);
@@ -602,7 +602,7 @@
 			stream_cfg_cmd->plane_cfg[plane_idx].
 			output_width) << 16 |
 			(stream_cfg_cmd->plane_cfg[plane_idx].
-			output_height - 1) << 4 | VFE32_BURST_LEN >> 2;
+			output_height - 1) << 4 | VFE32_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
 	}
 	return;
@@ -945,7 +945,7 @@
 }
 
 struct msm_vfe_axi_hardware_info msm_vfe32_axi_hw_info = {
-	.num_wm = 7,
+	.num_wm = 4,
 	.num_comp_mask = 3,
 	.num_rdi = 3,
 	.num_rdi_master = 3,
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index e50ac3a..56ec259 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -90,6 +90,7 @@
 	/* real streams(either data or metadate) owned by one
 	 * session struct msm_stream */
 	struct msm_queue_head stream_q;
+	struct mutex lock;
 };
 
 static struct v4l2_device *msm_v4l2_dev;
@@ -393,6 +394,7 @@
 	msm_init_queue(&session->command_ack_q);
 	msm_init_queue(&session->stream_q);
 	msm_enqueue(msm_session_q, &session->list);
+	mutex_init(&session->lock);
 	return 0;
 }
 
@@ -408,10 +410,12 @@
 		list, __msm_queue_find_session, &session_id);
 	if (!session)
 		return -EINVAL;
-
+	mutex_lock(&session->lock);
 	cmd_ack = kzalloc(sizeof(*cmd_ack), GFP_KERNEL);
-	if (!cmd_ack)
+	if (!cmd_ack) {
+		mutex_unlock(&session->lock);
 		return -ENOMEM;
+	}
 
 	msm_init_queue(&cmd_ack->command_q);
 	INIT_LIST_HEAD(&cmd_ack->list);
@@ -420,7 +424,7 @@
 
 	msm_enqueue(&session->command_ack_q, &cmd_ack->list);
 	session->command_ack_q.len++;
-
+	mutex_unlock(&session->lock);
 	return 0;
 }
 
@@ -543,7 +547,7 @@
 
 	msm_destroy_session_streams(session);
 	msm_remove_session_cmd_ack_q(session);
-
+	mutex_destroy(&session->lock);
 	msm_delete_entry(msm_session_q, struct msm_session,
 		list, session);
 
@@ -683,33 +687,43 @@
 		list, __msm_queue_find_session, &session_id);
 	if (WARN_ON(!session))
 		return -EIO;
-
+	mutex_lock(&session->lock);
 	cmd_ack = msm_queue_find(&session->command_ack_q,
 		struct msm_command_ack, list,
 		__msm_queue_find_command_ack_q, &stream_id);
-	if (WARN_ON(!cmd_ack))
+	if (WARN_ON(!cmd_ack)) {
+		mutex_unlock(&session->lock);
 		return -EIO;
+	}
 
 	v4l2_event_queue(vdev, event);
 
-	if (timeout < 0)
+	if (timeout < 0) {
+		mutex_unlock(&session->lock);
 		return rc;
+	}
 
 	/* should wait on session based condition */
 	rc = wait_event_interruptible_timeout(cmd_ack->wait,
 		!list_empty_careful(&cmd_ack->command_q.list),
 		msecs_to_jiffies(timeout));
 	if (list_empty_careful(&cmd_ack->command_q.list)) {
-		if (!rc)
+		if (!rc) {
+			pr_err("%s: Ankit Timed out\n", __func__);
 			rc = -ETIMEDOUT;
-		if (rc < 0)
+		}
+		if (rc < 0) {
+			mutex_unlock(&session->lock);
 			return rc;
+		}
 	}
 
 	cmd = msm_dequeue(&cmd_ack->command_q,
 		struct msm_command, list);
-	if (!cmd)
+	if (!cmd) {
+		mutex_unlock(&session->lock);
 		return -EINVAL;
+	}
 
 	event_data = (struct msm_v4l2_event_data *)cmd->event.u.data;
 
@@ -721,6 +735,7 @@
 	*event = cmd->event;
 
 	kzfree(cmd);
+	mutex_unlock(&session->lock);
 	return rc;
 }
 
@@ -730,7 +745,7 @@
 	struct msm_v4l2_event_data *event_data =
 		(struct msm_v4l2_event_data *)&event.u.data[0];
 	struct msm_session *session = d1;
-
+	mutex_lock(&session->lock);
 	event.type = MSM_CAMERA_V4L2_EVENT_TYPE;
 	event.id   = MSM_CAMERA_MSM_NOTIFY;
 	event_data->command = MSM_CAMERA_PRIV_SHUTDOWN;
@@ -739,7 +754,7 @@
 
 	msm_destroy_session_streams(session);
 	msm_remove_session_cmd_ack_q(session);
-
+	mutex_unlock(&session->lock);
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 7c315d9..1a481ce 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -622,8 +622,77 @@
 		mpq_demux->sdmx_process_time_max = process_time;
 }
 
-/* Extend dvb-demux debugfs with HW statistics */
-void mpq_dmx_init_hw_statistics(struct mpq_demux *mpq_demux)
+static int mpq_sdmx_log_level_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t mpq_sdmx_log_level_read(struct file *fp,
+	char __user *user_buffer, size_t count, loff_t *position)
+{
+	char user_str[16];
+	struct mpq_demux *mpq_demux = fp->private_data;
+	int ret;
+
+	ret = scnprintf(user_str, 16, "%d", mpq_demux->sdmx_log_level);
+	ret = simple_read_from_buffer(user_buffer, count, position,
+		user_str, ret+1);
+
+	return ret;
+}
+
+static ssize_t mpq_sdmx_log_level_write(struct file *fp,
+	const char __user *user_buffer, size_t count, loff_t *position)
+{
+	char user_str[16];
+	int ret;
+	int ret_count;
+	int level;
+	struct mpq_demux *mpq_demux = fp->private_data;
+
+	if (count >= 16)
+		return -EINVAL;
+
+	ret_count = simple_write_to_buffer(user_str, 16, position, user_buffer,
+		count);
+	if (ret_count < 0)
+		return ret_count;
+
+	ret = sscanf(user_str, "%d", &level);
+	if (ret != 1)
+		return -EINVAL;
+
+	if (level < SDMX_LOG_NO_PRINT || level > SDMX_LOG_VERBOSE)
+		return -EINVAL;
+
+	mutex_lock(&mpq_demux->mutex);
+	mpq_demux->sdmx_log_level = level;
+	if (mpq_demux->sdmx_session_handle != SDMX_INVALID_SESSION_HANDLE) {
+		ret = sdmx_set_log_level(mpq_demux->sdmx_session_handle,
+			mpq_demux->sdmx_log_level);
+		if (ret) {
+			MPQ_DVB_ERR_PRINT(
+				"%s: Could not set sdmx log level. ret = %d\n",
+				__func__, ret);
+			mutex_unlock(&mpq_demux->mutex);
+			return -EINVAL;
+		}
+	}
+
+	mutex_unlock(&mpq_demux->mutex);
+	return ret_count;
+}
+
+static const struct file_operations sdmx_debug_fops = {
+	.open = mpq_sdmx_log_level_open,
+	.read = mpq_sdmx_log_level_read,
+	.write = mpq_sdmx_log_level_write,
+	.owner = THIS_MODULE,
+};
+
+/* Extend dvb-demux debugfs with common plug-in entries */
+void mpq_dmx_init_debugfs_entries(struct mpq_demux *mpq_demux)
 {
 	/*
 	 * Extend dvb-demux debugfs with HW statistics.
@@ -745,8 +814,14 @@
 		S_IRUGO | S_IWUSR | S_IWGRP,
 		mpq_demux->demux.dmx.debugfs_demux_dir,
 		&mpq_demux->sdmx_process_packets_min);
+
+	debugfs_create_file("sdmx_log_level",
+		S_IRUGO | S_IWUSR | S_IWGRP,
+		mpq_demux->demux.dmx.debugfs_demux_dir,
+		mpq_demux,
+		&sdmx_debug_fops);
 }
-EXPORT_SYMBOL(mpq_dmx_init_hw_statistics);
+EXPORT_SYMBOL(mpq_dmx_init_debugfs_entries);
 
 /* Update dvb-demux debugfs with HW notification statistics */
 void mpq_dmx_update_hw_statistics(struct mpq_demux *mpq_demux)
@@ -908,6 +983,7 @@
 		mpq_demux->sdmx_filter_count = 0;
 		mpq_demux->sdmx_session_handle = SDMX_INVALID_SESSION_HANDLE;
 		mpq_demux->sdmx_eos = 0;
+		mpq_demux->sdmx_log_level = SDMX_LOG_NO_PRINT;
 
 		if (mpq_demux->demux.feednum > MPQ_MAX_DMX_FILES) {
 			MPQ_DVB_ERR_PRINT(
@@ -1128,7 +1204,7 @@
 		goto map_buffer_failed_free_buff;
 	}
 
-	if (ionflag & ION_SECURE) {
+	if (ionflag & ION_FLAG_SECURE) {
 		MPQ_DVB_DBG_PRINT("%s: secured buffer\n", __func__);
 		*kernel_mem = NULL;
 	} else {
@@ -1208,7 +1284,7 @@
 		return -EINVAL;
 	}
 
-	if (!(ionflag & ION_SECURE))
+	if (!(ionflag & ION_FLAG_SECURE))
 		ion_unmap_kernel(mpq_demux->ion_client, ion_handle);
 
 	ion_free(mpq_demux->ion_client, ion_handle);
@@ -3493,6 +3569,15 @@
 		return -EINVAL;
 	}
 
+	ret = sdmx_set_log_level(mpq_demux->sdmx_session_handle,
+		mpq_demux->sdmx_log_level);
+	if (ret != SDMX_SUCCESS) {
+		MPQ_DVB_ERR_PRINT("%s: Could not set log level. ret=%d\n",
+				__func__, ret);
+		/* Don't fail open session if just log level setting failed */
+		ret = 0;
+	}
+
 	mpq_demux->sdmx_process_count = 0;
 	mpq_demux->sdmx_process_time_sum = 0;
 	mpq_demux->sdmx_process_time_average = 0;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index 4abf088..4c2a9f4 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -438,6 +438,7 @@
 	u32 sdmx_process_packets_sum;
 	u32 sdmx_process_packets_average;
 	u32 sdmx_process_packets_min;
+	enum sdmx_log_level sdmx_log_level;
 
 	struct timespec decoder_out_last_time;
 	struct timespec last_notification_time;
@@ -622,12 +623,13 @@
 int mpq_dmx_process_pcr_packet(struct dvb_demux_feed *feed, const u8 *buf);
 
 /**
- * mpq_dmx_init_hw_statistics -
- * Extend dvb-demux debugfs with HW statistics.
+ * mpq_dmx_init_debugfs_entries -
+ * Extend dvb-demux debugfs with mpq related entries (HW statistics and secure
+ * demux log level).
  *
  * @mpq_demux: The mpq_demux device to initialize.
  */
-void mpq_dmx_init_hw_statistics(struct mpq_demux *mpq_demux);
+void mpq_dmx_init_debugfs_entries(struct mpq_demux *mpq_demux);
 
 /**
  * mpq_dmx_update_hw_statistics -
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 026d1cb..0d40520 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -719,7 +719,7 @@
 	}
 
 	/* Extend dvb-demux debugfs with TSIF statistics. */
-	mpq_dmx_init_hw_statistics(mpq_demux);
+	mpq_dmx_init_debugfs_entries(mpq_demux);
 
 	return 0;
 
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index e263aef..f0f8fa9 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1774,7 +1774,7 @@
 	}
 
 	/* Extend dvb-demux debugfs with TSPP statistics. */
-	mpq_dmx_init_hw_statistics(mpq_demux);
+	mpq_dmx_init_debugfs_entries(mpq_demux);
 
 	return 0;
 
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c
index 946b055..14d3a39 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c
@@ -38,7 +38,9 @@
 	SDMX_PROCESS_CMD,
 	SDMX_GET_DBG_COUNTERS_CMD,
 	SDMX_RESET_DBG_COUNTERS_CMD,
-	SDMX_GET_VERSION_CMD
+	SDMX_GET_VERSION_CMD,
+	SDMX_INVALIDATE_KL_CMD,
+	SDMX_SET_LOG_LEVEL_CMD
 };
 
 struct sdmx_proc_req {
@@ -184,6 +186,15 @@
 	int32_t version;
 };
 
+struct sdmx_set_log_level_req {
+	enum sdmx_cmd_id cmd_id;
+	enum sdmx_log_level level;
+	u32 session_handle;
+};
+
+struct sdmx_set_log_level_rsp {
+	enum sdmx_status ret;
+};
 static void get_cmd_rsp_buffers(int handle_index,
 	void **cmd,
 	int *cmd_len,
@@ -935,3 +946,48 @@
 	return ret;
 }
 EXPORT_SYMBOL(sdmx_reset_dbg_counters);
+
+/*
+ * Set debug log verbosity level
+ *
+ * @session_handle: secure demux instance
+ * @level: requested log level
+ *
+ * Return error code
+ */
+int sdmx_set_log_level(int session_handle, enum sdmx_log_level level)
+{
+	int res, cmd_len, rsp_len;
+	struct sdmx_set_log_level_req *cmd;
+	struct sdmx_set_log_level_rsp *rsp;
+	enum sdmx_status ret;
+
+	cmd_len = sizeof(struct sdmx_set_log_level_req);
+	rsp_len = sizeof(struct sdmx_set_log_level_rsp);
+
+	/* Get command and response buffers */
+	get_cmd_rsp_buffers(session_handle, (void **)&cmd, &cmd_len,
+		(void **)&rsp, &rsp_len);
+
+	/* Lock shared memory */
+	mutex_lock(&sdmx_lock[session_handle]);
+
+	/* Populate command struct */
+	cmd->cmd_id = SDMX_SET_LOG_LEVEL_CMD;
+	cmd->session_handle = session_handle;
+	cmd->level = level;
+
+	/* Issue QSEECom command */
+	res = qseecom_send_command(sdmx_qseecom_handles[session_handle],
+		(void *)cmd, cmd_len, (void *)rsp, rsp_len);
+	if (res < 0) {
+		mutex_unlock(&sdmx_lock[session_handle]);
+		return SDMX_STATUS_GENERAL_FAILURE;
+	}
+	ret = rsp->ret;
+
+	/* Unlock */
+	mutex_unlock(&sdmx_lock[session_handle]);
+	return ret;
+}
+
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
index f9d85aa..6b669e4 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
@@ -78,6 +78,13 @@
 	SDMX_195_BYTE_PKT = 195,
 };
 
+enum sdmx_log_level {
+	SDMX_LOG_NO_PRINT,
+	SDMX_LOG_MSG_ERROR,
+	SDMX_LOG_DEBUG,
+	SDMX_LOG_VERBOSE
+};
+
 enum sdmx_status {
 	SDMX_SUCCESS = 0,
 	SDMX_STATUS_GENERAL_FAILURE = -1,
@@ -250,4 +257,6 @@
 
 int sdmx_reset_dbg_counters(int session_handle);
 
+int sdmx_set_log_level(int session_handle, enum sdmx_log_level level);
+
 #endif /* _MPQ_SDMX_H */
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index addd235..f46abcf 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -896,6 +896,19 @@
 		pkt->size += sizeof(u32) + sizeof(struct hfi_bitrate);
 		break;
 	}
+	case HAL_CONFIG_VENC_MAX_BITRATE:
+	{
+		struct hfi_bitrate *hfi;
+
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE;
+		hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
+		hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
+		hfi->layer_id = ((struct hal_bitrate *)pdata)->layer_id;
+
+		pkt->size += sizeof(u32) + sizeof(struct hfi_bitrate);
+		break;
+	}
 	case HAL_PARAM_PROFILE_LEVEL_CURRENT:
 	{
 		struct hfi_profile_level *hfi;
diff --git a/drivers/media/platform/msm/vidc/msm_smem.h b/drivers/media/platform/msm/vidc/msm_smem.h
index b80d63e..4425909 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.h
+++ b/drivers/media/platform/msm/vidc/msm_smem.h
@@ -25,7 +25,7 @@
 
 enum smem_prop {
 	SMEM_CACHED = ION_FLAG_CACHED,
-	SMEM_SECURE = ION_SECURE,
+	SMEM_SECURE = ION_FLAG_SECURE,
 };
 
 enum hal_buffer {
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index bbd56fb..160d450 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -239,6 +239,18 @@
 		.cluster = MSM_VENC_CTRL_CLUSTER_BITRATE,
 	},
 	{
+		.id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+		.name = "Peak Bit Rate",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = MIN_BIT_RATE,
+		.maximum = MAX_BIT_RATE,
+		.default_value = DEFAULT_BIT_RATE,
+		.step = BIT_RATE_STEP,
+		.menu_skip_mask = 0,
+		.qmenu = NULL,
+		.cluster = MSM_VENC_CTRL_CLUSTER_BITRATE,
+	},
+	{
 		.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
 		.name = "Entropy Mode",
 		.type = V4L2_CTRL_TYPE_MENU,
@@ -1256,6 +1268,29 @@
 		bitrate.layer_id = 0;
 		pdata = &bitrate;
 		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+	{
+		struct v4l2_ctrl *avg_bitrate = TRY_GET_CTRL(
+			V4L2_CID_MPEG_VIDEO_BITRATE);
+
+		if (ctrl->val < avg_bitrate->val) {
+			dprintk(VIDC_ERR,
+				"Peak bitrate (%d) is lower than average bitrate (%d)",
+				ctrl->val, avg_bitrate->val);
+			rc = -EINVAL;
+			break;
+		} else if (ctrl->val < avg_bitrate->val * 2) {
+			dprintk(VIDC_WARN,
+				"Peak bitrate (%d) ideally should be twice the average bitrate (%d)",
+				ctrl->val, avg_bitrate->val);
+		}
+
+		property_id = HAL_CONFIG_VENC_MAX_BITRATE;
+		bitrate.bit_rate = ctrl->val;
+		bitrate.layer_id = 0;
+		pdata = &bitrate;
+		break;
+	}
 	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
 		temp_ctrl = TRY_GET_CTRL(
 			V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL);
@@ -1980,7 +2015,7 @@
 {
 	int rc = 0;
 	int i;
-	struct vidc_buffer_addr_info buffer_info;
+	struct vidc_buffer_addr_info buffer_info = {0};
 	struct hfi_device *hdev;
 	int extra_idx = 0;
 
@@ -2043,7 +2078,7 @@
 					struct v4l2_buffer *b)
 {
 	int i, rc = 0, extra_idx = 0;
-	struct vidc_buffer_addr_info buffer_info;
+	struct vidc_buffer_addr_info buffer_info = {0};
 	struct hfi_device *hdev;
 
 	if (!inst || !inst->core || !inst->core->device) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index adf6dec..dc08c64 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -373,7 +373,6 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	struct v4l2_control control = {0};
 	struct msm_vidc_cb_event *event_notify;
 	int event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
 	int rc = 0;
@@ -382,15 +381,7 @@
 		event_notify = (struct msm_vidc_cb_event *) response->data;
 		switch (event_notify->hal_event_type) {
 		case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
-			event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
-			control.id =
-				V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
-			rc = v4l2_g_ctrl(&inst->ctrl_handler, &control);
-			if (rc)
-				dprintk(VIDC_WARN,
-					"Failed to get Smooth streamng flag\n");
-			if (!rc && control.value == true)
-				event = V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
+			event = V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
 			break;
 		case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
 			event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index e20348d..3b82666 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -166,6 +166,7 @@
 	HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER,
 	HAL_PARAM_VDEC_SYNC_FRAME_DECODE,
 	HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,
+	HAL_CONFIG_VENC_MAX_BITRATE,
 };
 
 enum hal_domain {
diff --git a/drivers/media/platform/msm/wfd/enc-mfc-subdev.c b/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
index fee7b47..ceb0149 100644
--- a/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
@@ -2040,7 +2040,7 @@
 	}
 	heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
 	heap_mask |= inst->secure ? 0 : ION_HEAP(ION_IOMMU_HEAP_ID);
-	ion_flags |= inst->secure ? ION_SECURE : 0;
+	ion_flags |= inst->secure ? ION_FLAG_SECURE : 0;
 
 	if (vcd_get_ion_status()) {
 		for (i = 0; i < 4; ++i) {
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index b719b3f..4f7fb44 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -28,6 +28,7 @@
 #define BUF_TYPE_INPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
 
 static struct ion_client *venc_ion_client;
+static long venc_secure(struct v4l2_subdev *sd);
 
 struct index_bitmap {
 	unsigned long *bitmap;
@@ -321,8 +322,9 @@
 		goto venc_open_fail;
 	}
 
-	inst->secure = false;
 	inst->vmops = *vmops;
+	inst->secure = vmops->secure; /* We need to inform vidc, but defer
+					 until after s_fmt() */
 	INIT_LIST_HEAD(&inst->registered_output_bufs.list);
 	INIT_LIST_HEAD(&inst->registered_input_bufs.list);
 	init_completion(&inst->dq_complete);
@@ -903,6 +905,15 @@
 		WFD_MSG_ERR("Failed to format for input port\n");
 		goto venc_set_format_fail;
 	}
+
+	/* If the device was secured previously, we need to inform vidc _now_ */
+	if (inst->secure) {
+		rc = venc_secure(sd);
+		if (rc) {
+			WFD_MSG_ERR("Failed secure vidc\n");
+			goto venc_set_format_fail;
+		}
+	}
 venc_set_format_fail:
 	return rc;
 }
@@ -1329,12 +1340,6 @@
 		rc = -EEXIST;
 	}
 
-	if (inst->secure) {
-		/* Nothing to do! */
-		rc = 0;
-		goto secure_fail;
-	}
-
 	ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
 	rc = msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
 	if (rc) {
@@ -1342,7 +1347,6 @@
 		goto secure_fail;
 	}
 
-	inst->secure = true;
 secure_fail:
 	return rc;
 }
@@ -1419,9 +1423,6 @@
 	case SET_FRAMERATE_MODE:
 		rc = venc_set_framerate_mode(sd, arg);
 		break;
-	case ENC_SECURE:
-		rc = venc_secure(sd);
-		break;
 	default:
 		WFD_MSG_ERR("Unknown ioctl %d to enc-subdev\n", cmd);
 		rc = -ENOTSUPP;
diff --git a/drivers/media/platform/msm/wfd/mdp-5-subdev.c b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
index 16de0d4..55386b9 100644
--- a/drivers/media/platform/msm/wfd/mdp-5-subdev.c
+++ b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
@@ -26,6 +26,8 @@
 	struct switch_dev sdev;
 };
 
+static int mdp_secure(struct v4l2_subdev *sd, void *arg);
+
 int mdp_init(struct v4l2_subdev *sd, u32 val)
 {
 	return 0;
@@ -47,10 +49,6 @@
 		WFD_MSG_ERR("Invalid arguments\n");
 		rc = -EINVAL;
 		goto mdp_open_fail;
-	} else if (mops->secure) {
-		/* Deprecated API; use MDP_SECURE ioctl */
-		WFD_MSG_ERR("Deprecated API for securing subdevice\n");
-		return -ENOTSUPP;
 	}
 
 	fbi = msm_fb_get_writeback_fb();
@@ -66,12 +64,25 @@
 		WFD_MSG_ERR("WFD switch registration failed\n");
 		goto mdp_open_fail;
 	}
+
 	msm_fb_writeback_init(fbi);
+
 	inst->mdp = fbi;
 	inst->secure = mops->secure;
+	if (mops->secure) {
+		rc = mdp_secure(sd, inst);
+		if (rc) {
+			WFD_MSG_ERR("Couldn't secure MDP\n");
+			goto mdp_secure_fail;
+		}
+	}
+
 
 	mops->cookie = inst;
-	return rc;
+	return 0;
+mdp_secure_fail:
+	switch_dev_unregister(&inst->sdev);
+	msm_fb_writeback_terminate(inst->mdp);
 mdp_open_fail:
 	kfree(inst);
 	return rc;
@@ -118,7 +129,8 @@
 	}
 	return 0;
 }
-int mdp_close(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_close(struct v4l2_subdev *sd, void *arg)
 {
 	struct mdp_instance *inst = arg;
 	struct fb_info *fbi = NULL;
@@ -133,7 +145,8 @@
 	}
 	return 0;
 }
-int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
 {
 	int rc = 0;
 	struct mdp_buf_info *binfo = arg;
@@ -161,7 +174,8 @@
 		WFD_MSG_ERR("Failed to queue buffer\n");
 	return rc;
 }
-int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
 {
 	int rc = 0;
 	struct mdp_buf_info *obuf = arg;
@@ -184,7 +198,8 @@
 	obuf->cookie = (void *)fbdata.priv;
 	return rc;
 }
-int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
 {
 	struct mdp_prop *prop = (struct mdp_prop *)arg;
 	struct mdp_instance *inst = prop->inst;
@@ -197,7 +212,7 @@
 	return 0;
 }
 
-int mdp_mmap(struct v4l2_subdev *sd, void *arg)
+static int mdp_mmap(struct v4l2_subdev *sd, void *arg)
 {
 	int rc = 0, align = 0;
 	struct mem_region_map *mmap = arg;
@@ -250,7 +265,7 @@
 	return rc;
 }
 
-int mdp_munmap(struct v4l2_subdev *sd, void *arg)
+static int mdp_munmap(struct v4l2_subdev *sd, void *arg)
 {
 	struct mem_region_map *mmap = arg;
 	struct mem_region *mregion;
@@ -278,7 +293,7 @@
 	return 0;
 }
 
-int mdp_secure(struct v4l2_subdev *sd, void *arg)
+static int mdp_secure(struct v4l2_subdev *sd, void *arg)
 {
 	struct mdp_instance *inst = NULL;
 	int rc = 0;
@@ -331,9 +346,6 @@
 	case MDP_MUNMAP:
 		rc = mdp_munmap(sd, arg);
 		break;
-	case MDP_SECURE:
-		rc = mdp_secure(sd, arg);
-		break;
 	default:
 		WFD_MSG_ERR("IOCTL: %u not supported\n", cmd);
 		rc = -EINVAL;
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index e589878..af3cd69 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -168,7 +168,7 @@
 
 	if (secure) {
 		alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
-		ion_flags = ION_SECURE;
+		ion_flags = ION_FLAG_SECURE;
 		align = SZ_1M;
 	} else {
 		alloc_regions = ION_HEAP(ION_IOMMU_HEAP_ID);
@@ -1040,30 +1040,9 @@
 {
 	int rc = 0;
 	struct wfd_device *wfd_dev = video_drvdata(filp);
-	struct wfd_inst *inst = file_to_inst(filp);
 
-	switch (a->id) {
-	case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
-		rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
-				ioctl, ENC_SECURE, NULL);
-		if (rc) {
-			WFD_MSG_ERR("Couldn't secure encoder");
-			break;
-		}
-
-		rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core,
-				ioctl, MDP_SECURE, (void *)inst->mdp_inst);
-		if (rc) {
-			WFD_MSG_ERR("Couldn't secure MDP");
-			break;
-		}
-
-		wfd_dev->secure = true;
-		break;
-	default:
-		rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
-				ioctl, SET_PROP, a);
-	}
+	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
+			ioctl, SET_PROP, a);
 
 	if (rc)
 		WFD_MSG_ERR("Failed to set encoder property\n");
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 7c73d6c..e011d8f 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -15,6 +15,7 @@
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
 #include <linux/mfd/wcd9xxx/core.h>
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 4a063fd..9c30cd1 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -4959,6 +4959,10 @@
 	bam.callback = msmsdcc_sps_bam_global_irq_cb;
 	bam.user = (void *)host;
 
+	/* bam reset messages will be limited to 5 times */
+	bam.constrained_logging = true;
+	bam.logging_number = 5;
+
 	pr_info("%s: bam physical base=0x%x\n", mmc_hostname(host->mmc),
 			(u32)bam.phys_addr);
 	pr_info("%s: bam virtual base=0x%x\n", mmc_hostname(host->mmc),
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index ed67df4..114b23d 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -18,7 +18,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/sched.h>
-#include <linux/spinlock.h>
+#include <linux/atomic.h>
 #include <mach/ecm_ipa.h>
 
 #define DRIVER_NAME "ecm_ipa"
@@ -27,6 +27,9 @@
 #define ECM_IPA_IPV6_HDR_NAME "ecm_eth_ipv6"
 #define IPA_TO_USB_CLIENT	IPA_CLIENT_USB_CONS
 #define INACTIVITY_MSEC_DELAY 100
+#define DEFAULT_OUTSTANDING_HIGH 64
+#define DEFAULT_OUTSTANDING_LOW 32
+
 #define ECM_IPA_ERROR(fmt, args...) \
 	pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\
 			fmt, __func__, __LINE__, current->comm, ## args)
@@ -45,8 +48,6 @@
 
 /**
  * struct ecm_ipa_dev - main driver context parameters
- * @ack_spinlock: protect last sent skb
- * @last_out_skb: last sent skb saved until Tx notify is received from IPA
  * @net: network interface struct implemented by this driver
  * @folder: debugfs folder for various debuging switches
  * @tx_enable: flag that enable/disable Tx path to continue to IPA
@@ -56,15 +57,19 @@
  * @tx_file: saved debugfs entry to allow cleanup
  * @rx_file: saved debugfs entry to allow cleanup
  * @rm_file: saved debugfs entry to allow cleanup
+ * @outstanding_high_file saved debugfs entry to allow cleanup
+ * @outstanding_low_file saved debugfs entry to allow cleanup
  * @dma_file: saved debugfs entry to allow cleanup
  * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table
  * @eth_ipv6_hdr_hdl: saved handle for ipv6 header-insertion table
  * @usb_to_ipa_hdl: save handle for IPA pipe operations
  * @ipa_to_usb_hdl: save handle for IPA pipe operations
+ * @outstanding_pkts: number of packets sent to IPA without TX complete ACKed
+ * @outstanding_high: number of outstanding packets allowed
+ * @outstanding_low: number of outstanding packets which shall cause
+ *  to netdev queue start (after stopped due to outstanding_high reached)
  */
 struct ecm_ipa_dev {
-	spinlock_t ack_spinlock;
-	struct sk_buff *last_out_skb;
 	struct net_device *net;
 	bool tx_enable;
 	bool rx_enable;
@@ -74,11 +79,16 @@
 	struct dentry *tx_file;
 	struct dentry *rx_file;
 	struct dentry *rm_file;
+	struct dentry *outstanding_high_file;
+	struct dentry *outstanding_low_file;
 	struct dentry *dma_file;
 	uint32_t eth_ipv4_hdr_hdl;
 	uint32_t eth_ipv6_hdr_hdl;
 	u32 usb_to_ipa_hdl;
 	u32 ipa_to_usb_hdl;
+	atomic_t outstanding_pkts;
+	u8 outstanding_high;
+	u8 outstanding_low;
 };
 
 /**
@@ -104,7 +114,7 @@
 static void ecm_ipa_rm_notify(void *user_data, enum ipa_rm_event event,
 		unsigned long data);
 static int ecm_ipa_create_rm_resource(struct ecm_ipa_dev *dev);
-static void ecm_ipa_destory_rm_resource(void);
+static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *dev);
 static bool rx_filter(struct sk_buff *skb);
 static bool tx_filter(struct sk_buff *skb);
 static bool rm_enabled(struct ecm_ipa_dev *dev);
@@ -200,7 +210,9 @@
 	memset(dev, 0, sizeof(*dev));
 	dev->tx_enable = true;
 	dev->rx_enable = true;
-	spin_lock_init(&dev->ack_spinlock);
+	atomic_set(&dev->outstanding_pkts, 0);
+	dev->outstanding_high = DEFAULT_OUTSTANDING_HIGH;
+	dev->outstanding_low = DEFAULT_OUTSTANDING_LOW;
 	dev->net = net;
 	ecm_ipa_ctx = dev;
 	*priv = (void *)dev;
@@ -448,7 +460,7 @@
 fail_register_tx:
 fail_set_device_ethernet:
 	ecm_ipa_rules_destroy(dev);
-	ecm_ipa_destory_rm_resource();
+	ecm_ipa_destory_rm_resource(dev);
 	free_netdev(net);
 	return result;
 }
@@ -517,6 +529,10 @@
 	struct ipa_rm_create_params create_params = {0};
 	int result;
 	ECM_IPA_LOG_ENTRY();
+	if (!dev->rm_enable) {
+		pr_debug("RM feature not used\n");
+		return 0;
+	}
 	create_params.name = IPA_RM_RESOURCE_STD_ECM_PROD;
 	create_params.reg_params.user_data = dev;
 	create_params.reg_params.notify_cb = ecm_ipa_rm_notify;
@@ -550,10 +566,11 @@
 	return result;
 }
 
-static void ecm_ipa_destory_rm_resource(void)
+static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *dev)
 {
 	ECM_IPA_LOG_ENTRY();
-
+	if (!dev->rm_enable)
+		return;
 	ipa_rm_delete_dependency(IPA_RM_RESOURCE_STD_ECM_PROD,
 			IPA_RM_RESOURCE_USB_CONS);
 	ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_STD_ECM_PROD);
@@ -609,10 +626,10 @@
 		ECM_IPA_ERROR("dev NULL pointer\n");
 		return;
 	}
-	if (rm_enabled(dev)) {
-		ecm_ipa_destory_rm_resource();
-		ecm_ipa_debugfs_destroy(dev);
-	}
+
+	ecm_ipa_destory_rm_resource(dev);
+	ecm_ipa_debugfs_destroy(dev);
+
 	if (!dev->net) {
 		unregister_netdev(dev->net);
 		free_netdev(dev->net);
@@ -662,7 +679,6 @@
 	int ret;
 	netdev_tx_t status = NETDEV_TX_BUSY;
 	struct ecm_ipa_dev *dev = netdev_priv(net);
-	unsigned long flags;
 
 	if (unlikely(netif_queue_stopped(net))) {
 		ECM_IPA_ERROR("interface queue is stopped\n");
@@ -682,23 +698,24 @@
 		goto resource_busy;
 	}
 
-	spin_lock_irqsave(&dev->ack_spinlock, flags);
-	if (dev->last_out_skb) {
-		pr_debug("No Tx-ack received for previous packet\n");
-		spin_unlock_irqrestore(&dev->ack_spinlock, flags);
+	pr_debug("Before sending packet the outstanding packets counter is %d\n",
+				atomic_read(&dev->outstanding_pkts));
+
+	if (atomic_read(&dev->outstanding_pkts) >= dev->outstanding_high) {
+		pr_debug("Outstanding high boundary reached (%d)- stopping queue\n",
+				dev->outstanding_high);
 		netif_stop_queue(net);
 		status = -NETDEV_TX_BUSY;
 		goto out;
-	} else {
-		dev->last_out_skb = skb;
 	}
-	spin_unlock_irqrestore(&dev->ack_spinlock, flags);
 
 	ret = ipa_tx_dp(IPA_TO_USB_CLIENT, skb, NULL);
 	if (ret) {
 		ECM_IPA_ERROR("ipa transmit failed (%d)\n", ret);
 		goto fail_tx_packet;
 	}
+
+	atomic_inc(&dev->outstanding_pkts);
 	net->stats.tx_packets++;
 	net->stats.tx_bytes += skb->len;
 	status = NETDEV_TX_OK;
@@ -766,7 +783,6 @@
 {
 	struct sk_buff *skb = (struct sk_buff *)data;
 	struct ecm_ipa_dev *dev = priv;
-	unsigned long flags;
 
 	if (!dev) {
 		ECM_IPA_ERROR("dev is NULL pointer\n");
@@ -776,15 +792,16 @@
 		ECM_IPA_ERROR("unsupported event on Tx callback\n");
 		return;
 	}
-	spin_lock_irqsave(&dev->ack_spinlock, flags);
-	if (skb != dev->last_out_skb)
-		ECM_IPA_ERROR("ACKed/Sent not the same(FIFO expected)\n");
-	dev->last_out_skb = NULL;
-	spin_unlock_irqrestore(&dev->ack_spinlock, flags);
-	if (netif_queue_stopped(dev->net)) {
-		pr_debug("waking up queue\n");
+	atomic_dec(&dev->outstanding_pkts);
+	if (netif_queue_stopped(dev->net) &&
+		atomic_read(&dev->outstanding_pkts) < (dev->outstanding_low)) {
+		pr_debug("Outstanding low boundary reached (%d) - waking up queue\n",
+				dev->outstanding_low);
 		netif_wake_queue(dev->net);
 	}
+	pr_debug("After Tx-complete the outstanding packets counter is %d\n",
+				atomic_read(&dev->outstanding_pkts));
+
 	dev_kfree_skb_any(skb);
 	return;
 }
@@ -889,8 +906,8 @@
 
 static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *dev)
 {
-	const mode_t flags = S_IRUSR | S_IRGRP | S_IROTH |
-			S_IWUSR | S_IWGRP | S_IWOTH;
+	const mode_t flags = S_IRUGO | S_IWUGO;
+
 	int ret = -EINVAL;
 	ECM_IPA_LOG_ENTRY();
 	if (!dev)
@@ -929,6 +946,22 @@
 		ret = -EFAULT;
 		goto fail_file;
 	}
+
+	dev->outstanding_high_file = debugfs_create_u8("outstanding_high",
+			flags, dev->folder, &dev->outstanding_high);
+	if (!dev->outstanding_high_file) {
+		ECM_IPA_ERROR("could not create outstanding_high file\n");
+		ret = -EFAULT;
+		goto fail_file;
+	}
+	dev->outstanding_low_file = debugfs_create_u8("outstanding_low",
+			flags, dev->folder, &dev->outstanding_low);
+	if (!dev->outstanding_low_file) {
+		ECM_IPA_ERROR("could not create outstanding_low file\n");
+		ret = -EFAULT;
+		goto fail_file;
+	}
+
 	ECM_IPA_LOG_EXIT();
 	return 0;
 fail_file:
diff --git a/drivers/net/ethernet/msm/msm_rmnet_wwan.c b/drivers/net/ethernet/msm/msm_rmnet_wwan.c
index fe1ac46..f90ee3d 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_wwan.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_wwan.c
@@ -34,6 +34,7 @@
 #include <mach/ipa.h>
 
 #define WWAN_DEV_NAME "rmnet%d"
+#define WWAN_METADATA_SHFT 16
 #define WWAN_METADATA_MASK 0x00FF0000
 #define IPA_RM_INACTIVITY_TIMER 1000
 #define WWAN_DEVICE_COUNT (8)
@@ -304,13 +305,15 @@
 	rx_ipv4_property = &rx_properties.prop[0];
 	rx_ipv4_property->ip = IPA_IP_v4;
 	rx_ipv4_property->attrib.attrib_mask |= IPA_FLT_META_DATA;
-	rx_ipv4_property->attrib.meta_data = wwan_ptr->ch_id;
+	rx_ipv4_property->attrib.meta_data =
+		wwan_ptr->ch_id << WWAN_METADATA_SHFT;
 	rx_ipv4_property->attrib.meta_data_mask = WWAN_METADATA_MASK;
 	rx_ipv4_property->src_pipe = IPA_CLIENT_A2_EMBEDDED_PROD;
 	rx_ipv6_property = &rx_properties.prop[1];
 	rx_ipv6_property->ip = IPA_IP_v6;
 	rx_ipv6_property->attrib.attrib_mask |= IPA_FLT_META_DATA;
-	rx_ipv6_property->attrib.meta_data = wwan_ptr->ch_id;
+	rx_ipv6_property->attrib.meta_data =
+		wwan_ptr->ch_id << WWAN_METADATA_SHFT;
 	rx_ipv6_property->attrib.meta_data_mask = WWAN_METADATA_MASK;
 	rx_ipv6_property->src_pipe = IPA_CLIENT_A2_EMBEDDED_PROD;
 	rx_properties.num_props = 2;
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 6f2e2a4..cda1717 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -2434,7 +2434,7 @@
 
 static int __devinit msm_sps_probe(struct platform_device *pdev)
 {
-	int ret;
+	int ret = -ENODEV;
 
 	SPS_DBG2("sps:%s.", __func__);
 
@@ -2471,7 +2471,10 @@
 
 	sps->dfab_clk = clk_get(sps->dev, "dfab_clk");
 	if (IS_ERR(sps->dfab_clk)) {
-		SPS_ERR("sps:fail to get dfab_clk.");
+		if (IS_ERR(sps->dfab_clk) == -EPROBE_DEFER)
+			ret = -EPROBE_DEFER;
+		else
+			SPS_ERR("sps:fail to get dfab_clk.");
 		goto clk_err;
 	} else {
 		ret = clk_set_rate(sps->dfab_clk, 64000000);
@@ -2485,7 +2488,10 @@
 	if (!d_type) {
 		sps->pmem_clk = clk_get(sps->dev, "mem_clk");
 		if (IS_ERR(sps->pmem_clk)) {
-			SPS_ERR("sps:fail to get pmem_clk.");
+			if (IS_ERR(sps->pmem_clk) == -EPROBE_DEFER)
+				ret = -EPROBE_DEFER;
+			else
+				SPS_ERR("sps:fail to get pmem_clk.");
 			goto clk_err;
 		} else {
 			ret = clk_prepare_enable(sps->pmem_clk);
@@ -2499,7 +2505,10 @@
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
 	sps->bamdma_clk = clk_get(sps->dev, "dma_bam_pclk");
 	if (IS_ERR(sps->bamdma_clk)) {
-		SPS_ERR("sps:fail to get bamdma_clk.");
+		if (IS_ERR(sps->bamdma_clk) == -EPROBE_DEFER)
+			ret = -EPROBE_DEFER;
+		else
+			SPS_ERR("sps:fail to get bamdma_clk.");
 		goto clk_err;
 	} else {
 		ret = clk_prepare_enable(sps->bamdma_clk);
@@ -2539,7 +2548,7 @@
 alloc_chrdev_region_err:
 	class_destroy(sps->dev_class);
 
-	return -ENODEV;
+	return ret;
 }
 
 static int __devexit msm_sps_remove(struct platform_device *pdev)
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 3ebb1cd..a84d99e 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -105,7 +105,7 @@
 	for (n = 0; n < ARRAY_SIZE(opt_event_table); n++) {
 		if ((u32)opt_event_table[n].option !=
 			(u32)opt_event_table[n].pipe_irq) {
-			SPS_ERR("sps:SPS_O 0x%x != HAL IRQ 0x%x",
+			SPS_ERR("sps:SPS_O 0x%x != HAL IRQ 0x%x\n",
 				opt_event_table[n].option,
 				opt_event_table[n].pipe_irq);
 			return SPS_ERROR;
@@ -141,11 +141,11 @@
 		source = bam_check_irq_source(dev->base, dev->props.ee,
 						mask, &cb_case);
 
-		SPS_DBG1("sps:bam_isr:bam=0x%x;source=0x%x;mask=0x%x.",
+		SPS_DBG1("sps:bam_isr:bam=0x%x;source=0x%x;mask=0x%x.\n",
 				BAM_ID(dev), source, mask);
 
 		if ((source & (1UL << 31)) && (dev->props.callback)) {
-			SPS_INFO("sps:bam_isr:bam=0x%x;callback for case %d.",
+			SPS_INFO("sps:bam_isr:bam=0x%x;callback for case %d.\n",
 				BAM_ID(dev), cb_case);
 			dev->props.callback(cb_case, dev->props.user);
 		}
@@ -156,7 +156,7 @@
 		/* If MTIs are used, must poll each active pipe */
 		source = dev->pipe_active_mask;
 
-		SPS_DBG1("sps:bam_isr for MTI:bam=0x%x;source=0x%x.",
+		SPS_DBG1("sps:bam_isr for MTI:bam=0x%x;source=0x%x.\n",
 				BAM_ID(dev), source);
 	}
 
@@ -177,7 +177,7 @@
 
 	/* Process any inactive pipe sources */
 	if (source) {
-		SPS_ERR("sps:IRQ from BAM 0x%x inactive pipe(s) 0x%x",
+		SPS_ERR("sps:IRQ from BAM 0x%x inactive pipe(s) 0x%x\n",
 			BAM_ID(dev), source);
 		dev->irq_from_disabled_pipe++;
 	}
@@ -204,7 +204,7 @@
 
 	/* Is there any access to this BAM? */
 	if ((dev->props.manage & SPS_BAM_MGR_ACCESS_MASK) == SPS_BAM_MGR_NONE) {
-		SPS_ERR("sps:No local access to BAM 0x%x", BAM_ID(dev));
+		SPS_ERR("sps:No local access to BAM 0x%x\n", BAM_ID(dev));
 		return SPS_ERROR;
 	}
 
@@ -222,7 +222,7 @@
 				    IRQF_TRIGGER_HIGH, "sps", dev);
 
 		if (result) {
-			SPS_ERR("sps:Failed to enable BAM 0x%x IRQ %d",
+			SPS_ERR("sps:Failed to enable BAM 0x%x IRQ %d\n",
 				BAM_ID(dev), dev->props.irq);
 			return SPS_ERROR;
 		}
@@ -236,13 +236,13 @@
 			result = enable_irq_wake(dev->props.irq);
 
 			if (result) {
-				SPS_ERR("sps:Fail to enable wakeup irq "
-					"BAM 0x%x IRQ %d",
+				SPS_ERR(
+					"sps:Fail to enable wakeup irq for BAM 0x%x IRQ %d\n",
 					BAM_ID(dev), dev->props.irq);
 				return SPS_ERROR;
 			} else
-				SPS_DBG2("sps:Enable wakeup irq for "
-					"BAM 0x%x IRQ %d",
+				SPS_DBG2(
+					"sps:Enable wakeup irq for BAM 0x%x IRQ %d\n",
 					BAM_ID(dev), dev->props.irq);
 		}
 	}
@@ -262,7 +262,7 @@
 		rc = bam_check(dev->base, &dev->version, &num_pipes);
 
 	if (rc) {
-		SPS_ERR("sps:Fail to init BAM 0x%x IRQ %d",
+		SPS_ERR("sps:Fail to init BAM 0x%x IRQ %d\n",
 			BAM_ID(dev), dev->props.irq);
 		return SPS_ERROR;
 	}
@@ -281,7 +281,7 @@
 		 * must use MTI. Thus, force EE index to a non-zero value to
 		 * insure that EE zero globals can't be modified.
 		 */
-		SPS_ERR("sps:EE for satellite BAM must be set to non-zero.");
+		SPS_ERR("sps:EE for satellite BAM must be set to non-zero.\n");
 		return SPS_ERROR;
 	}
 
@@ -295,8 +295,9 @@
 		MTIenabled) {
 		if (dev->props.irq_gen_addr == 0 ||
 		    dev->props.irq_gen_addr == SPS_ADDR_INVALID) {
-			SPS_ERR("sps:MTI destination address not specified "
-				"for BAM 0x%x",	BAM_ID(dev));
+			SPS_ERR(
+				"sps:MTI destination address not specified for BAM 0x%x\n",
+				BAM_ID(dev));
 			return SPS_ERROR;
 		}
 		dev->state |= BAM_STATE_MTI;
@@ -304,13 +305,13 @@
 
 	if (num_pipes) {
 		dev->props.num_pipes = num_pipes;
-		SPS_DBG1("sps:BAM 0x%x number of pipes reported by hw: %d",
+		SPS_DBG1("sps:BAM 0x%x number of pipes reported by hw: %d\n",
 				 BAM_ID(dev), dev->props.num_pipes);
 	}
 
 	/* Check EE index */
 	if (!MTIenabled && dev->props.ee >= SPS_BAM_NUM_EES) {
-		SPS_ERR("sps:Invalid EE BAM 0x%x: %d", BAM_ID(dev),
+		SPS_ERR("sps:Invalid EE BAM 0x%x: %d\n", BAM_ID(dev),
 				dev->props.ee);
 		return SPS_ERROR;
 	}
@@ -323,8 +324,9 @@
 		struct sps_bam_sec_config_props *p_sec =
 						dev->props.p_sec_config_props;
 		if (p_sec == NULL) {
-			SPS_ERR("sps:EE config table is not specified for "
-				"BAM 0x%x", BAM_ID(dev));
+			SPS_ERR(
+				"sps:EE config table is not specified for BAM 0x%x\n",
+				BAM_ID(dev));
 			return SPS_ERROR;
 		}
 
@@ -351,9 +353,8 @@
 				for (i = n + 1; i < SPS_BAM_NUM_EES; i++) {
 					if ((p_sec->ees[n].pipe_mask &
 						p_sec->ees[i].pipe_mask) != 0) {
-						SPS_ERR("sps:Overlapping pipe "
-							"assignments for BAM "
-							"0x%x: EEs %d and %d",
+						SPS_ERR(
+							"sps:Overlapping pipe assignments for BAM 0x%x: EEs %d and %d\n",
 							BAM_ID(dev), n, i);
 						return SPS_ERROR;
 					}
@@ -403,9 +404,21 @@
 	}
 
 	dev->state |= BAM_STATE_ENABLED;
-	SPS_INFO("sps:BAM 0x%x (va:0x%x) enabled: ver:0x%x, number of pipes:%d",
-		BAM_ID(dev), (u32) dev->base, dev->version,
-		dev->props.num_pipes);
+
+	if (!dev->props.constrained_logging ||
+		(dev->props.constrained_logging && dev->props.logging_number)) {
+		if (dev->props.logging_number > 0)
+			dev->props.logging_number--;
+		SPS_INFO(
+			"sps:BAM 0x%x (va:0x%x) enabled: ver:0x%x, number of pipes:%d\n",
+			BAM_ID(dev), (u32) dev->base, dev->version,
+			dev->props.num_pipes);
+	} else
+		SPS_DBG2(
+			"sps:BAM 0x%x (va:0x%x) enabled: ver:0x%x, number of pipes:%d\n",
+			BAM_ID(dev), (u32) dev->base, dev->version,
+			dev->props.num_pipes);
+
 	return 0;
 }
 
@@ -420,7 +433,7 @@
 
 	/* Is there any access to this BAM? */
 	if ((dev->props.manage & SPS_BAM_MGR_ACCESS_MASK) == SPS_BAM_MGR_NONE) {
-		SPS_ERR("sps:No local access to BAM 0x%x", BAM_ID(dev));
+		SPS_ERR("sps:No local access to BAM 0x%x\n", BAM_ID(dev));
 		return SPS_ERROR;
 	}
 
@@ -444,7 +457,7 @@
 
 	dev->state &= ~BAM_STATE_ENABLED;
 
-	SPS_DBG2("sps:BAM 0x%x disabled", BAM_ID(dev));
+	SPS_DBG2("sps:BAM 0x%x disabled\n", BAM_ID(dev));
 
 	return 0;
 }
@@ -455,7 +468,7 @@
 int sps_bam_device_init(struct sps_bam *dev)
 {
 	if (dev->props.virt_addr == NULL) {
-		SPS_ERR("sps:NULL BAM virtual address");
+		SPS_ERR("sps:NULL BAM virtual address\n");
 		return SPS_ERROR;
 	}
 	dev->base = (void *) dev->props.virt_addr;
@@ -463,7 +476,7 @@
 	if (dev->props.num_pipes == 0) {
 		/* Assume max number of pipes until BAM registers can be read */
 		dev->props.num_pipes = BAM_MAX_PIPES;
-		SPS_DBG2("sps:BAM 0x%x: assuming max number of pipes: %d",
+		SPS_DBG2("sps:BAM 0x%x: assuming max number of pipes: %d\n",
 			BAM_ID(dev), dev->props.num_pipes);
 	}
 
@@ -479,11 +492,11 @@
 
 	if ((dev->props.options & SPS_BAM_OPT_ENABLE_AT_BOOT))
 		if (sps_bam_enable(dev)) {
-			SPS_ERR("sps:Fail to enable bam device");
+			SPS_ERR("sps:Fail to enable bam device\n");
 			return SPS_ERROR;
 		}
 
-	SPS_DBG2("sps:BAM device: phys 0x%x IRQ %d",
+	SPS_DBG2("sps:BAM device: phys 0x%x IRQ %d\n",
 			BAM_ID(dev), dev->props.irq);
 
 	return 0;
@@ -497,7 +510,7 @@
 {
 	int result;
 
-	SPS_DBG2("sps:BAM device DEINIT: phys 0x%x IRQ %d",
+	SPS_DBG2("sps:BAM device DEINIT: phys 0x%x IRQ %d\n",
 		BAM_ID(dev), dev->props.irq);
 
 	result = sps_bam_disable(dev);
@@ -515,7 +528,7 @@
 	u32 pipe_index;
 	int result;
 
-	SPS_DBG2("sps:BAM device RESET: phys 0x%x IRQ %d",
+	SPS_DBG2("sps:BAM device RESET: phys 0x%x IRQ %d\n",
 		BAM_ID(dev), dev->props.irq);
 
 	/* If BAM is enabled, then disable */
@@ -526,8 +539,8 @@
 		      pipe_index++) {
 			pipe = dev->pipes[pipe_index];
 			if (BAM_PIPE_IS_ASSIGNED(pipe)) {
-				SPS_ERR("sps:BAM device 0x%x RESET failed: "
-					"pipe %d in use",
+				SPS_ERR(
+					"sps:BAM device 0x%x RESET failed: pipe %d in use\n",
 					BAM_ID(dev), pipe_index);
 				result = SPS_ERROR;
 				break;
@@ -579,8 +592,9 @@
 	if (pipe_index == SPS_BAM_PIPE_INVALID) {
 		/* Allocate a pipe from the BAM */
 		if ((dev->props.manage & SPS_BAM_MGR_PIPE_NO_ALLOC)) {
-			SPS_ERR("sps:Restricted from allocating pipes "
-				"on BAM 0x%x", BAM_ID(dev));
+			SPS_ERR(
+				"sps:Restricted from allocating pipes on BAM 0x%x\n",
+				BAM_ID(dev));
 			return SPS_BAM_PIPE_INVALID;
 		}
 		for (pipe_index = 0, pipe_mask = 1;
@@ -593,24 +607,25 @@
 				break;	/* Found an available pipe */
 		}
 		if (pipe_index >= dev->props.num_pipes) {
-			SPS_ERR("sps:Fail to allocate pipe on BAM 0x%x",
+			SPS_ERR("sps:Fail to allocate pipe on BAM 0x%x\n",
 				BAM_ID(dev));
 			return SPS_BAM_PIPE_INVALID;
 		}
 	} else {
 		/* Check that client-specified pipe is available */
 		if (pipe_index >= dev->props.num_pipes) {
-			SPS_ERR("sps:Invalid pipe %d for allocate on BAM 0x%x",
+			SPS_ERR(
+				"sps:Invalid pipe %d for allocate on BAM 0x%x\n",
 				pipe_index, BAM_ID(dev));
 			return SPS_BAM_PIPE_INVALID;
 		}
 		if ((dev->props.restricted_pipes & (1UL << pipe_index))) {
-			SPS_ERR("sps:BAM 0x%x pipe %d is not local",
+			SPS_ERR("sps:BAM 0x%x pipe %d is not local\n",
 				BAM_ID(dev), pipe_index);
 			return SPS_BAM_PIPE_INVALID;
 		}
 		if (dev->pipes[pipe_index] != NULL) {
-			SPS_ERR("sps:Pipe %d already allocated on BAM 0x%x",
+			SPS_ERR("sps:Pipe %d already allocated on BAM 0x%x\n",
 				pipe_index, BAM_ID(dev));
 			return SPS_BAM_PIPE_INVALID;
 		}
@@ -631,7 +646,7 @@
 	struct sps_pipe *pipe;
 
 	if (pipe_index >= dev->props.num_pipes) {
-		SPS_ERR("sps:Invalid BAM 0x%x pipe: %d", BAM_ID(dev),
+		SPS_ERR("sps:Invalid BAM 0x%x pipe: %d\n", BAM_ID(dev),
 				pipe_index);
 		return;
 	}
@@ -642,8 +657,8 @@
 
 	/* Is the pipe currently allocated? */
 	if (pipe == NULL) {
-		SPS_ERR("sps:Attempt to free unallocated pipe %d on "
-			"BAM 0x%x", pipe_index, BAM_ID(dev));
+		SPS_ERR("sps:Attempt to free unallocated pipe %d on BAM 0x%x\n",
+			pipe_index, BAM_ID(dev));
 		return;
 	}
 
@@ -654,7 +669,7 @@
 	if (!list_empty(&pipe->sys.events_q)) {
 		struct sps_q_event *sps_event;
 
-		SPS_ERR("sps:Disconnect BAM 0x%x pipe %d with events pending",
+		SPS_ERR("sps:Disconnect BAM 0x%x pipe %d with events pending\n",
 			BAM_ID(dev), pipe_index);
 
 		sps_event = list_entry((&pipe->sys.events_q)->next,
@@ -718,7 +733,7 @@
 	dev = map_pipe->bam;
 	pipe_index = map_pipe->pipe_index;
 	if (pipe_index >= dev->props.num_pipes) {
-		SPS_ERR("sps:Invalid BAM 0x%x pipe: %d", BAM_ID(dev),
+		SPS_ERR("sps:Invalid BAM 0x%x pipe: %d\n", BAM_ID(dev),
 				pipe_index);
 		return SPS_ERROR;
 	}
@@ -729,14 +744,14 @@
 	/* Verify that control of this pipe is allowed */
 	if ((dev->props.manage & SPS_BAM_MGR_PIPE_NO_CTRL) ||
 	    (dev->props.restricted_pipes & (1UL << pipe_index))) {
-		SPS_ERR("sps:BAM 0x%x pipe %d is not local",
+		SPS_ERR("sps:BAM 0x%x pipe %d is not local\n",
 			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
 
 	/* Control without configuration permission is not supported yet */
 	if ((dev->props.manage & SPS_BAM_MGR_PIPE_NO_CONFIG)) {
-		SPS_ERR("sps:BAM 0x%x pipe %d remote config is not supported",
+		SPS_ERR("sps:BAM 0x%x pipe %d remote config is not supported\n",
 			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
@@ -754,8 +769,9 @@
 		if (map->desc.phys_base == SPS_ADDR_INVALID ||
 		    map->data.phys_base == SPS_ADDR_INVALID ||
 		    map->desc.size == 0 || map->data.size == 0) {
-			SPS_ERR("sps:FIFO buffers are not allocated for BAM "
-				"0x%x pipe %d.", BAM_ID(dev), pipe_index);
+			SPS_ERR(
+				"sps:FIFO buffers are not allocated for BAM 0x%x pipe %d.\n",
+				BAM_ID(dev), pipe_index);
 			return SPS_ERROR;
 		}
 		hw_params.data_base = map->data.phys_base;
@@ -787,8 +803,8 @@
 	/* Get virtual address for descriptor FIFO */
 	if (map->desc.phys_base != SPS_ADDR_INVALID) {
 		if (map->desc.size < (2 * sizeof(struct sps_iovec))) {
-			SPS_ERR("sps:Invalid descriptor FIFO size "
-				"for BAM 0x%x pipe %d: %d",
+			SPS_ERR(
+				"sps:Invalid descriptor FIFO size for BAM 0x%x pipe %d: %d\n",
 				BAM_ID(dev), pipe_index, map->desc.size);
 			return SPS_ERROR;
 		}
@@ -821,7 +837,7 @@
 
 	/* Check pipe allocation */
 	if (dev->pipes[pipe_index] != BAM_PIPE_UNASSIGNED) {
-		SPS_ERR("sps:Invalid pipe %d on BAM 0x%x for connect",
+		SPS_ERR("sps:Invalid pipe %d on BAM 0x%x for connect\n",
 			pipe_index, BAM_ID(dev));
 		return SPS_ERROR;
 	}
@@ -838,7 +854,7 @@
 	}
 
 	if (bam_pipe_init(dev->base, pipe_index, &hw_params, dev->props.ee)) {
-		SPS_ERR("sps:BAM 0x%x pipe %d init error",
+		SPS_ERR("sps:BAM 0x%x pipe %d init error\n",
 			BAM_ID(dev), pipe_index);
 		goto exit_err;
 	}
@@ -913,7 +929,7 @@
 	int result;
 
 	if (pipe_index >= dev->props.num_pipes) {
-		SPS_ERR("sps:Invalid BAM 0x%x pipe: %d", BAM_ID(dev),
+		SPS_ERR("sps:Invalid BAM 0x%x pipe: %d\n", BAM_ID(dev),
 				pipe_index);
 		return SPS_ERROR;
 	}
@@ -947,7 +963,7 @@
 	}
 
 	if (result)
-		SPS_ERR("sps:BAM 0x%x pipe %d already disconnected",
+		SPS_ERR("sps:BAM 0x%x pipe %d already disconnected\n",
 			BAM_ID(dev), pipe_index);
 
 	return result;
@@ -990,7 +1006,7 @@
 		irq_enable = BAM_DISABLE;
 		pipe->polled = true;
 		if (poll == 0 && pipe->irq_mask)
-			SPS_DBG2("sps:BAM 0x%x pipe %d forced to use polling",
+			SPS_DBG2("sps:BAM 0x%x pipe %d forced to use polling\n",
 				 BAM_ID(dev), pipe_index);
 	}
 	if ((pipe->state & BAM_STATE_MTI) == 0)
@@ -1038,8 +1054,8 @@
 	if (pipe->sys.desc_wr_count > 0 &&
 	    (no_queue != pipe->sys.no_queue
 	     || ack_xfers != pipe->sys.ack_xfers)) {
-		SPS_ERR("sps:Queue/ack mode change after transfer: "
-			"BAM 0x%x pipe %d opt 0x%x",
+		SPS_ERR(
+			"sps:Queue/ack mode change after transfer: BAM 0x%x pipe %d opt 0x%x\n",
 			BAM_ID(dev), pipe_index, options);
 		return SPS_ERROR;
 	}
@@ -1048,8 +1064,9 @@
 	/* Is client setting invalid options for a BAM-to-BAM connection? */
 	if ((pipe->state & BAM_STATE_BAM2BAM) &&
 	    (options & BAM2BAM_O_INVALID)) {
-		SPS_ERR("sps:Invalid option for BAM-to-BAM: BAM 0x%x pipe %d "
-			"opt 0x%x", BAM_ID(dev), pipe_index, options);
+		SPS_ERR(
+			"sps:Invalid option for BAM-to-BAM: BAM 0x%x pipe %d opt 0x%x\n",
+			BAM_ID(dev), pipe_index, options);
 		return SPS_ERROR;
 	}
 
@@ -1067,7 +1084,8 @@
 				vmalloc(pipe->desc_size + size);
 
 			if (pipe->sys.desc_cache == NULL) {
-				SPS_ERR("sps:No memory for pipe %d of BAM 0x%x",
+				SPS_ERR(
+					"sps:No memory for pipe %d of BAM 0x%x\n",
 					pipe_index, BAM_ID(dev));
 				return -ENOMEM;
 			}
@@ -1077,7 +1095,7 @@
 
 		if (pipe->sys.desc_cache == NULL) {
 			/*** MUST BE LAST POINT OF FAILURE (see below) *****/
-			SPS_ERR("sps:Desc cache error: BAM 0x%x pipe %d: %d",
+			SPS_ERR("sps:Desc cache error: BAM 0x%x pipe %d: %d\n",
 				BAM_ID(dev), pipe_index,
 				pipe->desc_size + size);
 			return SPS_ERROR;
@@ -1153,8 +1171,8 @@
 
 	if (pipe->sys.no_queue && reg->xfer_done != NULL &&
 	    reg->mode != SPS_TRIGGER_CALLBACK) {
-		SPS_ERR("sps:Only callback events support for NO_Q: "
-			"BAM 0x%x pipe %d mode %d",
+		SPS_ERR(
+			"sps:Only callback events support for NO_Q: BAM 0x%x pipe %d mode %d\n",
 			BAM_ID(dev), pipe_index, reg->mode);
 		return SPS_ERROR;
 	}
@@ -1168,9 +1186,9 @@
 
 		index = SPS_EVENT_INDEX(opt_event_table[n].event_id);
 		if (index < 0)
-			SPS_ERR("sps:Negative event index: "
-			"BAM 0x%x pipe %d mode %d",
-			BAM_ID(dev), pipe_index, reg->mode);
+			SPS_ERR(
+				"sps:Negative event index: BAM 0x%x pipe %d mode %d\n",
+				BAM_ID(dev), pipe_index, reg->mode);
 		else {
 			event_reg = &pipe->sys.event_regs[index];
 			event_reg->xfer_done = reg->xfer_done;
@@ -1199,7 +1217,7 @@
 
 	/* Is this a BAM-to-BAM or satellite connection? */
 	if ((pipe->state & (BAM_STATE_BAM2BAM | BAM_STATE_REMOTE))) {
-		SPS_ERR("sps:Transfer on BAM-to-BAM: BAM 0x%x pipe %d",
+		SPS_ERR("sps:Transfer on BAM-to-BAM: BAM 0x%x pipe %d\n",
 			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
@@ -1209,7 +1227,7 @@
 	 * SPS_O_NO_Q option.
 	 */
 	if (pipe->sys.no_queue && user != NULL) {
-		SPS_ERR("sps:User pointer arg non-NULL: BAM 0x%x pipe %d",
+		SPS_ERR("sps:User pointer arg non-NULL: BAM 0x%x pipe %d\n",
 			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
@@ -1230,24 +1248,27 @@
 			if (next_write == pipe->sys.acked_offset) {
 				if (!show_recom) {
 					show_recom = true;
-					SPS_ERR("sps:Client of BAM 0x%x pipe %d is recommended to have flow control",
+					SPS_ERR(
+						"sps:Client of BAM 0x%x pipe %d is recommended to have flow control\n",
 						BAM_ID(dev), pipe_index);
 				}
 
-				SPS_DBG2("sps:Descriptor FIFO is full for BAM "
-					"0x%x pipe %d after pipe_handler_eot",
+				SPS_DBG2(
+					"sps:Descriptor FIFO is full for BAM 0x%x pipe %d after pipe_handler_eot\n",
 					BAM_ID(dev), pipe_index);
 				return SPS_ERROR;
 			}
 		} else {
 			if (!show_recom) {
 				show_recom = true;
-				SPS_ERR("sps:Client of BAM 0x%x pipe %d is recommended to have flow control.",
+				SPS_ERR(
+					"sps:Client of BAM 0x%x pipe %d is recommended to have flow control.\n",
 					BAM_ID(dev), pipe_index);
 			}
 
-			SPS_DBG2("sps:Descriptor FIFO is full for "
-				"BAM 0x%x pipe %d", BAM_ID(dev), pipe_index);
+			SPS_DBG2(
+				"sps:Descriptor FIFO is full for BAM 0x%x pipe %d\n",
+				BAM_ID(dev), pipe_index);
 			return SPS_ERROR;
 		}
 	}
@@ -1323,14 +1344,14 @@
 	int result;
 
 	if (transfer->iovec_count == 0) {
-		SPS_ERR("sps:iovec count zero: BAM 0x%x pipe %d",
+		SPS_ERR("sps:iovec count zero: BAM 0x%x pipe %d\n",
 			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
 
 	sps_bam_get_free_count(dev, pipe_index, &count);
 	if (count < transfer->iovec_count) {
-		SPS_ERR("sps:Insufficient free desc: BAM 0x%x pipe %d: %d",
+		SPS_ERR("sps:Insufficient free desc: BAM 0x%x pipe %d: %d\n",
 			BAM_ID(dev), pipe_index, count);
 		return SPS_ERROR;
 	}
@@ -1401,18 +1422,18 @@
 			  struct sps_q_event *sps_event)
 {
 	if (sps_event == NULL) {
-		SPS_DBG("sps:trigger_event.sps_event is NULL.");
+		SPS_DBG("sps:trigger_event.sps_event is NULL.\n");
 		return;
 	}
 
 	if (event_reg->xfer_done) {
 		complete(event_reg->xfer_done);
-		SPS_DBG("sps:trigger_event.done=%d.",
+		SPS_DBG("sps:trigger_event.done=%d.\n",
 			event_reg->xfer_done->done);
 	}
 
 	if (event_reg->callback) {
-		SPS_DBG("sps:trigger_event.using callback.");
+		SPS_DBG("sps:trigger_event.using callback.\n");
 		event_reg->callback(&sps_event->notify);
 	}
 
@@ -1684,7 +1705,7 @@
 	pipe_index = pipe->pipe_index;
 	status = bam_pipe_get_and_clear_irq_status(dev->base, pipe_index);
 
-	SPS_DBG("sps:pipe_handler.bam 0x%x.pipe %d.status=0x%x.",
+	SPS_DBG("sps:pipe_handler.bam 0x%x.pipe %d.status=0x%x.\n",
 			BAM_ID(dev), pipe_index, status);
 
 	/* Check for enabled interrupt sources */
@@ -1756,8 +1777,8 @@
 	struct sps_q_event *event_queue;
 
 	if (pipe->sys.no_queue) {
-		SPS_ERR("sps:Invalid connection for event: "
-			"BAM 0x%x pipe %d context 0x%x",
+		SPS_ERR(
+			"sps:Invalid connection for event: BAM 0x%x pipe %d context 0x%x\n",
 			BAM_ID(dev), pipe_index, (u32) pipe);
 		notify->event_id = SPS_EVENT_INVALID;
 		return SPS_ERROR;
@@ -1770,9 +1791,10 @@
 	/* Pull an event off the synchronous event queue */
 	if (list_empty(&pipe->sys.events_q)) {
 		event_queue = NULL;
-		SPS_DBG("sps:events_q of bam 0x%x is empty.", BAM_ID(dev));
+		SPS_DBG("sps:events_q of bam 0x%x is empty.\n", BAM_ID(dev));
 	} else {
-		SPS_DBG("sps:events_q of bam 0x%x is not empty.", BAM_ID(dev));
+		SPS_DBG("sps:events_q of bam 0x%x is not empty.\n",
+			BAM_ID(dev));
 		event_queue =
 		list_first_entry(&pipe->sys.events_q, struct sps_q_event,
 				 list);
@@ -1861,7 +1883,7 @@
 
 	/* Is this a satellite connection? */
 	if ((pipe->state & BAM_STATE_REMOTE)) {
-		SPS_ERR("sps:Is empty on remote: BAM 0x%x pipe %d",
+		SPS_ERR("sps:Is empty on remote: BAM 0x%x pipe %d\n",
 			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
@@ -1900,8 +1922,9 @@
 
 	/* Is this a BAM-to-BAM or satellite connection? */
 	if ((pipe->state & (BAM_STATE_BAM2BAM | BAM_STATE_REMOTE))) {
-		SPS_ERR("sps:Free count on BAM-to-BAM or remote: BAM "
-			"0x%x pipe %d",	BAM_ID(dev), pipe_index);
+		SPS_ERR(
+			"sps:Free count on BAM-to-BAM or remote: BAM 0x%x pipe %d\n",
+			BAM_ID(dev), pipe_index);
 		*count = 0;
 		return SPS_ERROR;
 	}
@@ -1936,14 +1959,15 @@
 	 */
 	if ((dev->props.manage & SPS_BAM_MGR_MULTI_EE) == 0 ||
 	    (dev->props.manage & SPS_BAM_MGR_DEVICE_REMOTE)) {
-		SPS_ERR("sps:Cannot grant satellite control to BAM 0x%x "
-			"pipe %d", BAM_ID(dev), pipe_index);
+		SPS_ERR(
+			"sps:Cannot grant satellite control to BAM 0x%x pipe %d\n",
+			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
 
 	/* Is this pipe locally controlled? */
 	if ((dev->pipe_active_mask & (1UL << pipe_index)) == 0) {
-		SPS_ERR("sps:BAM 0x%x pipe %d not local and active",
+		SPS_ERR("sps:BAM 0x%x pipe %d not local and active\n",
 			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
@@ -1991,7 +2015,7 @@
 
 	/* Is this pipe locally controlled? */
 	if ((dev->pipe_active_mask & (1UL << pipe_index)) == 0) {
-		SPS_ERR("sps:BAM 0x%x pipe %d not local and active",
+		SPS_ERR("sps:BAM 0x%x pipe %d not local and active\n",
 			BAM_ID(dev), pipe_index);
 		return SPS_ERROR;
 	}
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 210964e..fd42c47 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -125,7 +125,6 @@
 	int				r_conn_mohm;
 	int				shutdown_soc_valid_limit;
 	int				adjust_soc_low_threshold;
-	int				adjust_soc_high_threshold;
 	int				chg_term_ua;
 	enum battery_type		batt_type;
 	unsigned int			fcc;
@@ -176,6 +175,7 @@
 	struct timespec			t_soc_queried;
 	int				last_soc;
 	int				last_soc_est;
+	int				last_soc_unbound;
 
 	int				charge_time_us;
 	int				catch_up_time_us;
@@ -195,6 +195,10 @@
 	bool				use_voltage_soc;
 
 	int				prev_batt_terminal_uv;
+	int				high_ocv_correction_limit_uv;
+	int				low_ocv_correction_limit_uv;
+	int				flat_ocv_threshold_uv;
+	int				hold_soc_est;
 
 	int				ocv_high_threshold_uv;
 	int				ocv_low_threshold_uv;
@@ -1363,6 +1367,7 @@
 	}
 }
 
+#define NO_ADJUST_HIGH_SOC_THRESHOLD	90
 static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
 							int soc, int batt_temp)
 {
@@ -1376,6 +1381,7 @@
 	int slope = 0;
 	int rc = 0;
 	int delta_ocv_uv_limit = 0;
+	int correction_limit_uv = 0;
 
 	rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
 	if (rc < 0) {
@@ -1411,18 +1417,15 @@
 
 	/*
 	 * do not adjust
-	 * if soc is same as what bms calculated
-	 * if soc_est is between 45 and 25, this is the flat portion of the
-	 * curve where soc_est is not so accurate. We generally don't want to
-	 * adjust when soc_est is inaccurate except for the cases when soc is
-	 * way far off (higher than 50 or lesser than 20).
-	 * Also don't adjust soc if it is above 90 becuase it might be pulled
-	 * low and cause a bad user experience
+	 * if soc_est is same as what bms calculated
+	 * OR if soc_est > adjust_soc_low_threshold
+	 * OR if soc is above 90
+	 * because we might pull it low
+	 * and cause a bad user experience
 	 */
 	if (soc_est == soc
-		|| (is_between(45, chip->adjust_soc_low_threshold, soc_est)
-		&& is_between(50, chip->adjust_soc_low_threshold - 5, soc))
-		|| soc >= 90)
+		|| soc_est > chip->adjust_soc_low_threshold
+		|| soc >= NO_ADJUST_HIGH_SOC_THRESHOLD)
 		goto out;
 
 	if (chip->last_soc_est == -EINVAL)
@@ -1467,6 +1470,21 @@
 		pr_debug("new delta ocv = %d\n", delta_ocv_uv);
 	}
 
+	if (chip->last_ocv_uv > chip->flat_ocv_threshold_uv)
+		correction_limit_uv = chip->high_ocv_correction_limit_uv;
+	else
+		correction_limit_uv = chip->low_ocv_correction_limit_uv;
+
+	if (abs(delta_ocv_uv) > correction_limit_uv) {
+		pr_debug("limiting delta ocv %d limit = %d\n",
+			delta_ocv_uv, correction_limit_uv);
+		if (delta_ocv_uv > 0)
+			delta_ocv_uv = correction_limit_uv;
+		else
+			delta_ocv_uv = -correction_limit_uv;
+		pr_debug("new delta ocv = %d\n", delta_ocv_uv);
+	}
+
 	chip->last_ocv_uv -= delta_ocv_uv;
 
 	if (chip->last_ocv_uv >= chip->max_voltage_uv)
@@ -1481,9 +1499,9 @@
 
 	/*
 	 * if soc_new is ZERO force it higher so that phone doesnt report soc=0
-	 * soc = 0 should happen only when soc_est == 0
+	 * soc = 0 should happen only when soc_est is above a set value
 	 */
-	if (soc_new == 0 && soc_est != 0)
+	if (soc_new == 0 && soc_est >= chip->hold_soc_est)
 		soc_new = 1;
 
 	soc = soc_new;
@@ -1881,9 +1899,18 @@
 		soc = scale_soc_while_chg(chip, delta_time_us,
 						soc, chip->last_soc);
 
+	if (chip->last_soc_unbound)
+		chip->last_soc_unbound = false;
+	else if (chip->last_soc != -EINVAL) {
+		if (soc < chip->last_soc && soc != 0)
+			soc = chip->last_soc - 1;
+		if (soc > chip->last_soc && soc != 100)
+			soc = chip->last_soc + 1;
+	}
+
 	pr_debug("last_soc = %d, calculated_soc = %d, soc = %d\n",
 			chip->last_soc, chip->calculated_soc, soc);
-	chip->last_soc = soc;
+	chip->last_soc = bound_soc(soc);
 	backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
 	pr_debug("Reported SOC = %d\n", chip->last_soc);
 	chip->t_soc_queried = now;
@@ -2150,6 +2177,7 @@
 	chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
 	chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
 	chip->rbatt_capacitive_mohm = batt_data->rbatt_capacitive_mohm;
+	chip->flat_ocv_threshold_uv = batt_data->flat_ocv_threshold_uv;
 
 	if (chip->pc_temp_ocv_lut == NULL) {
 		pr_err("temp ocv lut table is NULL\n");
@@ -2181,8 +2209,6 @@
 	SPMI_PROP_READ(chg_term_ua, "chg-term-ua", rc);
 	SPMI_PROP_READ(shutdown_soc_valid_limit,
 			"shutdown-soc-valid-limit", rc);
-	SPMI_PROP_READ(adjust_soc_high_threshold,
-			"adjust-soc-high-threshold", rc);
 	SPMI_PROP_READ(adjust_soc_low_threshold,
 			"adjust-soc-low-threshold", rc);
 	SPMI_PROP_READ(batt_type, "batt-type", rc);
@@ -2202,6 +2228,12 @@
 	chip->use_ocv_thresholds = of_property_read_bool(
 			chip->spmi->dev.of_node,
 			"qcom,use-ocv-thresholds");
+	SPMI_PROP_READ(high_ocv_correction_limit_uv,
+			"high-ocv-correction-limit-uv", rc);
+	SPMI_PROP_READ(low_ocv_correction_limit_uv,
+			"low-ocv-correction-limit-uv", rc);
+	SPMI_PROP_READ(hold_soc_est,
+			"hold-soc-est", rc);
 	SPMI_PROP_READ(ocv_high_threshold_uv,
 			"ocv-voltage-high-threshold-uv", rc);
 	SPMI_PROP_READ(ocv_low_threshold_uv,
@@ -2217,8 +2249,8 @@
 	pr_debug("r_conn:%d, shutdown_soc: %d, adjust_soc_low:%d\n",
 			chip->r_conn_mohm, chip->shutdown_soc_valid_limit,
 			chip->adjust_soc_low_threshold);
-	pr_debug("adjust_soc_high:%d, chg_term_ua:%d, batt_type:%d\n",
-			chip->adjust_soc_high_threshold, chip->chg_term_ua,
+	pr_debug("chg_term_ua:%d, batt_type:%d\n",
+			chip->chg_term_ua,
 			chip->batt_type);
 	pr_debug("ignore_shutdown_soc:%d, use_voltage_soc:%d\n",
 			chip->ignore_shutdown_soc, chip->use_voltage_soc);
@@ -2549,6 +2581,11 @@
 	if (rc) {
 		pr_err("Could not read current time: %d\n", rc);
 	} else if (tm_now_sec > chip->last_recalc_time) {
+		/*
+		 * unbind the last soc so that the next
+		 * recalculation is not limited to changing by 1%
+		 */
+		chip->last_soc_unbound = true;
 		time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
 		pr_debug("Time since last recalc: %lu\n",
 				time_since_last_recalc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index f4efa756..331c7f1 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -157,6 +157,11 @@
 /* smbb_misc_interrupts */
 #define TFTWDOG_IRQ			BIT(0)
 
+/* SMBB types */
+#define SMBB				BIT(1)
+#define SMBBP				BIT(2)
+#define SMBCL				BIT(3)
+
 /* Workaround flags */
 #define CHG_FLAGS_VCP_WA		BIT(0)
 
@@ -194,6 +199,8 @@
  * @warm_bat_decidegc		Warm battery temperature in degree Celsius
  * @cool_bat_decidegc		Cool battery temperature in degree Celsius
  * @revision:			PMIC revision
+ * @type:			SMBB type
+ * @tchg_mins			maximum allowed software initiated charge time
  * @thermal_levels		amount of thermal mitigation levels
  * @thermal_mitigation		thermal mitigation level values
  * @therm_lvl_sel		thermal mitigation level selection
@@ -247,6 +254,8 @@
 	unsigned int			cool_bat_decidegc;
 	unsigned int			safe_current;
 	unsigned int			revision;
+	unsigned int			type;
+	unsigned int			tchg_mins;
 	unsigned int			thermal_levels;
 	unsigned int			therm_lvl_sel;
 	unsigned int			*thermal_mitigation;
@@ -256,6 +265,7 @@
 	struct power_supply		batt_psy;
 	uint32_t			flags;
 	struct qpnp_adc_tm_btm_param	adc_param;
+	struct work_struct		adc_measure_work;
 };
 
 static struct of_device_id qpnp_charger_match_table[] = {
@@ -508,6 +518,15 @@
 			enable ? USB_SUSPEND_BIT : 0, 1);
 }
 
+static void qpnp_bat_if_adc_measure_work(struct work_struct *work)
+{
+	struct qpnp_chg_chip *chip = container_of(work,
+				struct qpnp_chg_chip, adc_measure_work);
+
+	if (qpnp_adc_tm_channel_measure(&chip->adc_param))
+		pr_err("request ADC error\n");
+}
+
 #define ENUM_T_STOP_BIT		BIT(0)
 static irqreturn_t
 qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
@@ -550,8 +569,7 @@
 
 		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");
+			schedule_work(&chip->adc_measure_work);
 		}
 	}
 
@@ -773,6 +791,7 @@
 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 	POWER_SUPPLY_PROP_TEMP,
@@ -813,16 +832,16 @@
 	int rc = 0;
 	struct qpnp_vadc_result results;
 
-	if (chip->revision > 0) {
+	if (chip->revision == 0 && chip->type == SMBB) {
+		pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
+		return 0;
+	} else {
 		rc = qpnp_vadc_read(VBAT_SNS, &results);
 		if (rc) {
 			pr_err("Unable to read vbat rc=%d\n", rc);
 			return 0;
 		}
 		return results.physical;
-	} else {
-		pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
-		return 0;
 	}
 }
 
@@ -912,6 +931,21 @@
 
 	return POWER_SUPPLY_STATUS_DISCHARGING;
 }
+static int
+get_prop_current_max(struct qpnp_chg_chip *chip)
+{
+	union power_supply_propval ret = {0,};
+
+	if (chip->bms_psy) {
+		chip->bms_psy->get_property(chip->bms_psy,
+			  POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
+		return ret.intval;
+	} else {
+		pr_debug("No BMS supply registered return 0\n");
+	}
+
+	return 0;
+}
 
 static int
 get_prop_current_now(struct qpnp_chg_chip *chip)
@@ -1090,6 +1124,9 @@
 	case POWER_SUPPLY_PROP_CAPACITY:
 		val->intval = get_prop_capacity(chip);
 		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		val->intval = get_prop_current_max(chip);
+		break;
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 		val->intval = get_prop_current_now(chip);
 		break;
@@ -1421,7 +1458,7 @@
 static void
 qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
 {
-	if (chip->revision > 0)
+	if (chip->revision > 0 && chip->type == SMBB)
 		chip->flags |= CHG_FLAGS_VCP_WA;
 }
 
@@ -1651,7 +1688,9 @@
 	case SMBBP_BOOST_SUBTYPE:
 		break;
 	case SMBB_MISC_SUBTYPE:
+		chip->type = SMBB;
 	case SMBBP_MISC_SUBTYPE:
+		chip->type = SMBBP;
 		pr_debug("Setting BOOT_DONE\n");
 		rc = qpnp_chg_masked_write(chip,
 			chip->misc_base + CHGR_MISC_BOOT_DONE,
@@ -2002,6 +2041,8 @@
 			pr_err("batt failed to register rc = %d\n", rc);
 			goto fail_chg_enable;
 		}
+		INIT_WORK(&chip->adc_measure_work,
+			qpnp_bat_if_adc_measure_work);
 	}
 
 	if (chip->dc_chgpth_base) {
@@ -2082,6 +2123,8 @@
 						&& chip->batt_present) {
 		qpnp_adc_tm_disable_chan_meas(&chip->adc_param);
 	}
+	cancel_work_sync(&chip->adc_measure_work);
+
 	dev_set_drvdata(&spmi->dev, NULL);
 	kfree(chip);
 
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 10c69c3..63d3750 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -761,7 +761,13 @@
 		pr_info("ADSP P.C. CTRL state:%d NGD not enumerated:0x%x",
 					dev->state, laddr);
 	}
-
+	/* ADSP SSR scenario, need to disconnect pipe before connecting */
+	if (dev->use_rx_msgqs == MSM_MSGQ_DOWN) {
+		struct msm_slim_endp *endpoint = &dev->rx_msgq;
+		sps_disconnect(endpoint->sps);
+		sps_free_endpoint(endpoint->sps);
+		dev->use_rx_msgqs = MSM_MSGQ_RESET;
+	}
 	/*
 	 * ADSP power collapse case (OR SSR), where HW was reset
 	 * BAM programming will happen when capability message is received
@@ -911,6 +917,8 @@
 
 	ngd_slim_enable(dev, false);
 	/* disconnect BAM pipes */
+	if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
+		dev->use_rx_msgqs = MSM_MSGQ_DOWN;
 	msm_slim_sps_exit(dev, false);
 	mutex_lock(&ctrl->m_ctrl);
 	/* device up should be called again after SSR */
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index 3e19f9b..30341e2 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -581,7 +581,7 @@
 
 void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg)
 {
-	if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED) {
+	if (dev->use_rx_msgqs >= MSM_MSGQ_ENABLED) {
 		struct msm_slim_endp *endpoint = &dev->rx_msgq;
 		struct sps_connect *config = &endpoint->config;
 		struct sps_mem_buffer *descr = &config->desc;
@@ -590,10 +590,12 @@
 		memset(&sps_event, 0x00, sizeof(sps_event));
 		msm_slim_sps_mem_free(dev, mem);
 		sps_register_event(endpoint->sps, &sps_event);
-		sps_disconnect(endpoint->sps);
+		if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED) {
+			sps_disconnect(endpoint->sps);
+			msm_slim_free_endpoint(endpoint);
+			dev->use_rx_msgqs = MSM_MSGQ_RESET;
+		}
 		msm_slim_sps_mem_free(dev, descr);
-		msm_slim_free_endpoint(endpoint);
-		dev->use_rx_msgqs = MSM_MSGQ_RESET;
 	}
 	if (dereg) {
 		sps_deregister_bam_device(dev->bam.hdl);
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 6e329b3..6ff3f19 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -159,6 +159,7 @@
 	MSM_MSGQ_DISABLED,
 	MSM_MSGQ_RESET,
 	MSM_MSGQ_ENABLED,
+	MSM_MSGQ_DOWN,
 };
 
 struct msm_slim_sps_bam {
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index 67e0181..837ac21 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.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
@@ -243,6 +243,17 @@
 }
 EXPORT_SYMBOL(tsens_get_temp);
 
+int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors)
+{
+	if (!tmdev)
+		return -ENODEV;
+
+	*tsens_num_sensors = tmdev->tsens_num_sensor;
+
+	return 0;
+}
+EXPORT_SYMBOL(tsens_get_max_sensor_num);
+
 static int tsens_tz_get_mode(struct thermal_zone_device *thermal,
 			      enum thermal_device_mode *mode)
 {
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index ee80975..9ba954a 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -1504,11 +1504,10 @@
 	},
 };
 
-static int __init tsens_tm_init_driver(void)
+int __init tsens_tm_init_driver(void)
 {
 	return platform_driver_register(&tsens_tm_driver);
 }
-arch_initcall(tsens_tm_init_driver);
 
 static int __init tsens_thermal_register(void)
 {
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 8806004..867e218 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -1920,6 +1920,22 @@
 	return IRQ_HANDLED;
 }
 
+/*
+ * Find UART device port using its port index value.
+ */
+struct uart_port *msm_hs_get_uart_port(int port_index)
+{
+	int i;
+
+	for (i = 0; i < UARTDM_NR; i++) {
+		if (q_uart_port[i].uport.line == port_index)
+			return &q_uart_port[i].uport;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(msm_hs_get_uart_port);
+
 /* request to turn off uart clock once pending TX is flushed */
 void msm_hs_request_clock_off(struct uart_port *uport) {
 	unsigned long flags;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 435ef3b..f83794c 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -2434,10 +2434,14 @@
 					dev_err(&pdev->dev, "irqreq IDINT failed\n");
 					goto disable_hs_ldo;
 				}
+
 				local_irq_save(flags);
 				/* Update initial ID state */
-				msm->id_state = msm->ext_xceiv.id =
+				msm->id_state =
 					!!irq_read_line(msm->pmic_id_irq);
+				if (msm->id_state == DWC3_ID_GROUND)
+					queue_work(system_nrt_wq,
+							&msm->id_work);
 				local_irq_restore(flags);
 				enable_irq_wake(msm->pmic_id_irq);
 			}
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e0255ce..6fca910 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -66,7 +66,8 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/msm_hsusb.h>
-
+#include <linux/tracepoint.h>
+#include <mach/usb_trace.h>
 #include "ci13xxx_udc.h"
 
 /* Turns on streaming. overrides CI13XXX_DISABLE_STREAMING */
@@ -139,6 +140,21 @@
 	return n ? n-1 : 32;
 }
 
+struct ci13xxx_ebi_err_entry {
+	u32 *usb_req_buf;
+	u32 usb_req_length;
+	u32 ep_info;
+	struct ci13xxx_ebi_err_entry *next;
+};
+
+struct ci13xxx_ebi_err_data {
+	u32 ebi_err_addr;
+	u32 apkt0;
+	u32 apkt1;
+	struct ci13xxx_ebi_err_entry *ebi_err_entry;
+};
+static struct ci13xxx_ebi_err_data *ebi_err_data;
+
 /******************************************************************************
  * HW block
  *****************************************************************************/
@@ -1738,6 +1754,72 @@
 	return 0;
 }
 
+static void dump_usb_info(void *ignore, unsigned int ebi_addr,
+	unsigned int ebi_apacket0, unsigned int ebi_apacket1)
+{
+	struct ci13xxx *udc = _udc;
+	unsigned long flags;
+	struct list_head   *ptr = NULL;
+	struct ci13xxx_req *req = NULL;
+	struct ci13xxx_ep *mEp;
+	unsigned i;
+	struct ci13xxx_ebi_err_entry *temp_dump;
+	static int count;
+	u32 epdir = 0;
+
+	if (count)
+		return;
+	count++;
+
+	pr_info("%s: USB EBI error detected\n", __func__);
+
+	ebi_err_data = kmalloc(sizeof(struct ci13xxx_ebi_err_data),
+				 GFP_ATOMIC);
+	if (!ebi_err_data) {
+		pr_err("%s: memory alloc failed for ebi_err_data\n", __func__);
+		return;
+	}
+
+	ebi_err_data->ebi_err_entry = kmalloc(
+					sizeof(struct ci13xxx_ebi_err_entry),
+					GFP_ATOMIC);
+	if (!ebi_err_data->ebi_err_entry) {
+		kfree(ebi_err_data);
+		pr_err("%s: memory alloc failed for ebi_err_entry\n", __func__);
+		return;
+	}
+
+	ebi_err_data->ebi_err_addr = ebi_addr;
+	ebi_err_data->apkt0 = ebi_apacket0;
+	ebi_err_data->apkt1 = ebi_apacket1;
+
+	temp_dump = ebi_err_data->ebi_err_entry;
+	pr_info("\n DUMPING USB Requests Information\n");
+	spin_lock_irqsave(udc->lock, flags);
+	for (i = 0; i < hw_ep_max; i++) {
+		list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue) {
+			mEp = &udc->ci13xxx_ep[i];
+			req = list_entry(ptr, struct ci13xxx_req, queue);
+
+			temp_dump->usb_req_buf = req->req.buf;
+			temp_dump->usb_req_length = req->req.length;
+			epdir = mEp->dir;
+			temp_dump->ep_info = mEp->num | (epdir << 15);
+
+			temp_dump->next = kmalloc(
+					  sizeof(struct ci13xxx_ebi_err_entry),
+					  GFP_ATOMIC);
+			if (!temp_dump->next) {
+				pr_err("%s: memory alloc failed\n", __func__);
+				spin_unlock_irqrestore(udc->lock, flags);
+				return;
+			}
+			temp_dump = temp_dump->next;
+		}
+	}
+	spin_unlock_irqrestore(udc->lock, flags);
+}
+
 /******************************************************************************
  * UTIL block
  *****************************************************************************/
@@ -3692,6 +3774,11 @@
 	pm_runtime_no_callbacks(&udc->gadget.dev);
 	pm_runtime_enable(&udc->gadget.dev);
 
+	retval = register_trace_usb_daytona_invalid_access(dump_usb_info,
+								NULL);
+	if (retval)
+		pr_err("Registering trace failed\n");
+
 	_udc = udc;
 	return retval;
 
@@ -3725,11 +3812,17 @@
 static void udc_remove(void)
 {
 	struct ci13xxx *udc = _udc;
+	int retval;
 
 	if (udc == NULL) {
 		err("EINVAL");
 		return;
 	}
+	retval = unregister_trace_usb_daytona_invalid_access(dump_usb_info,
+									NULL);
+	if (retval)
+		pr_err("Unregistering trace failed\n");
+
 	usb_del_gadget_udc(&udc->gadget);
 
 	if (udc->transceiver) {
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index e415a95..e8d7489 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -3273,10 +3273,10 @@
 		pr_debug("pipe->flags 0x%x\n", pipe->flags);
 		if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) {
 			mfd->mem_hid &= ~BIT(ION_IOMMU_HEAP_ID);
-			mfd->mem_hid |= ION_SECURE;
+			mfd->mem_hid |= ION_FLAG_SECURE;
 		} else {
 			mfd->mem_hid |= BIT(ION_IOMMU_HEAP_ID);
-			mfd->mem_hid &= ~ION_SECURE;
+			mfd->mem_hid &= ~ION_FLAG_SECURE;
 		}
 	}
 
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 2423de5..f8b7f2f 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -2314,7 +2314,7 @@
 					pr_err("ion_map_iommu() read failed\n");
 					return -ENOMEM;
 				}
-				if (mfd->mem_hid & ION_SECURE) {
+				if (mfd->mem_hid & ION_FLAG_SECURE) {
 					if (ion_phys(mfd->iclient, buf->ihdl,
 						&addr, (size_t *)&len)) {
 						pr_err("%s:%d: ion_phys map failed\n",
@@ -2377,7 +2377,7 @@
 	if (!IS_ERR_OR_NULL(mfd->iclient)) {
 		if (!IS_ERR_OR_NULL(buf->ihdl)) {
 			if (mdp_iommu_split_domain) {
-				if (!(mfd->mem_hid & ION_SECURE))
+				if (!(mfd->mem_hid & ION_FLAG_SECURE))
 					ion_unmap_iommu(mfd->iclient, buf->ihdl,
 						DISPLAY_WRITE_DOMAIN, GEN_POOL);
 				ion_unmap_iommu(mfd->iclient, buf->ihdl,
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index fd680e6..2c58e49 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -28,8 +28,9 @@
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_tx.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_util.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_edid.o
-obj-$(CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334) += mhl_sii8334.o mhl_msc.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_hdcp.o
+obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_cec.o
+obj-$(CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334) += mhl_sii8334.o mhl_msc.o
 
 obj-$(CONFIG_FB_MSM_MDSS_WRITEBACK) += mdss_wb.o
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_cec.c b/drivers/video/msm/mdss/mdss_hdmi_cec.c
new file mode 100644
index 0000000..694fcde
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_hdmi_cec.c
@@ -0,0 +1,949 @@
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <mach/board.h>
+
+#include "mdss_hdmi_cec.h"
+
+#define CEC_STATUS_WR_ERROR	BIT(0)
+#define CEC_STATUS_WR_DONE	BIT(1)
+
+/* Reference: HDMI 1.4a Specification section 7.1 */
+#define RETRANSMIT_MAX_NUM	5
+
+/*
+ * Ref. HDMI 1.4a: Supplement-1 CEC Section 6, 7
+ */
+struct hdmi_cec_msg {
+	u8 sender_id;
+	u8 recvr_id;
+	u8 opcode;
+	u8 operand[15];
+	u8 frame_size;
+	u8 retransmit;
+};
+
+struct hdmi_cec_msg_node {
+	struct hdmi_cec_msg msg;
+	struct list_head list;
+};
+
+struct hdmi_cec_ctrl {
+	bool cec_enabled;
+	bool compliance_response_enabled;
+	bool cec_engine_configed;
+
+	u8 cec_logical_addr;
+	u32 cec_msg_wr_status;
+
+	spinlock_t lock;
+	struct list_head msg_head;
+	struct work_struct cec_read_work;
+	struct completion cec_msg_wr_done;
+	struct hdmi_cec_init_data init_data;
+};
+
+static int hdmi_cec_msg_send(struct hdmi_cec_ctrl *cec_ctrl,
+	struct hdmi_cec_msg *msg);
+
+static void hdmi_cec_dump_msg(struct hdmi_cec_ctrl *cec_ctrl,
+	struct hdmi_cec_msg *msg)
+{
+	int i;
+	unsigned long flags;
+
+	if (!cec_ctrl || !msg) {
+		DEV_ERR("%pS->%s: invalid input\n",
+			__builtin_return_address(0), __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	DEV_DBG("=================%pS dump start =====================\n",
+		__builtin_return_address(0));
+
+	DEV_DBG("sender_id     : %d", msg->sender_id);
+	DEV_DBG("recvr_id      : %d", msg->recvr_id);
+
+	if (msg->frame_size < 2) {
+		DEV_DBG("polling message");
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+		return;
+	}
+
+	DEV_DBG("opcode        : %02x", msg->opcode);
+	for (i = 0; i < msg->frame_size - 2; i++)
+		DEV_DBG("operand(%2d) : %02x", i + 1, msg->operand[i]);
+
+	DEV_DBG("=================%pS dump end =====================\n",
+		__builtin_return_address(0));
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+} /* hdmi_cec_dump_msg */
+
+static inline void hdmi_cec_write_logical_addr(struct hdmi_cec_ctrl *cec_ctrl,
+	u8 addr)
+{
+	if (!cec_ctrl || !cec_ctrl->init_data.io) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return;
+	}
+
+	DSS_REG_W(cec_ctrl->init_data.io, HDMI_CEC_ADDR, addr & 0xF);
+} /* hdmi_cec_write_logical_addr */
+
+static void hdmi_cec_disable(struct hdmi_cec_ctrl *cec_ctrl)
+{
+	u32 reg_val;
+	unsigned long flags;
+	struct dss_io_data *io = NULL;
+	struct hdmi_cec_msg_node *msg_node, *tmp;
+
+	if (!cec_ctrl || !cec_ctrl->init_data.io) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return;
+	}
+
+	io = cec_ctrl->init_data.io;
+
+	/* Disable Engine */
+	DSS_REG_W(io, HDMI_CEC_CTRL, 0);
+
+	/* Disable CEC interrupts */
+	reg_val = DSS_REG_R(io, HDMI_CEC_INT);
+	DSS_REG_W(io, HDMI_CEC_INT, reg_val & !BIT(1) & !BIT(3) & !BIT(7));
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	list_for_each_entry_safe(msg_node, tmp, &cec_ctrl->msg_head, list) {
+		list_del(&msg_node->list);
+		kfree(msg_node);
+	}
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+} /* hdmi_cec_disable */
+
+static void hdmi_cec_enable(struct hdmi_cec_ctrl *cec_ctrl)
+{
+	struct dss_io_data *io = NULL;
+
+	if (!cec_ctrl || !cec_ctrl->init_data.io) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return;
+	}
+
+	io = cec_ctrl->init_data.io;
+
+	INIT_LIST_HEAD(&cec_ctrl->msg_head);
+
+	/* Enable CEC interrupts */
+	DSS_REG_W(io, HDMI_CEC_INT, BIT(1) | BIT(3) | BIT(7));
+
+	/* Enable Engine */
+	DSS_REG_W(io, HDMI_CEC_CTRL, BIT(0));
+} /* hdmi_cec_enable */
+
+static int hdmi_cec_send_abort_opcode(struct hdmi_cec_ctrl *cec_ctrl,
+	struct hdmi_cec_msg *in_msg, u8 reason_operand)
+{
+	int i = 0;
+	struct hdmi_cec_msg out_msg;
+
+	if (!cec_ctrl || !in_msg) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	out_msg.sender_id = 0x4;
+	out_msg.recvr_id = in_msg->sender_id;
+	out_msg.opcode = 0x0; /* opcode for feature abort */
+	out_msg.operand[i++] = in_msg->opcode;
+	out_msg.operand[i++] = reason_operand;
+	out_msg.frame_size = i + 2;
+
+	return hdmi_cec_msg_send(cec_ctrl, &out_msg);
+} /* hdmi_cec_send_abort_opcode */
+
+static int hdmi_cec_msg_parser(struct hdmi_cec_ctrl *cec_ctrl,
+	struct hdmi_cec_msg *in_msg)
+{
+	int rc = 0, i = 0;
+	struct hdmi_cec_msg out_msg;
+
+	if (!cec_ctrl || !in_msg) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	DEV_DBG("%s: in_msg->opcode = 0x%x\n", __func__, in_msg->opcode);
+	switch (in_msg->opcode) {
+	case 0x64:
+		/* Set OSD String */
+		DEV_INFO("%s: Recvd OSD Str=[0x%x]\n", __func__,
+			in_msg->operand[3]);
+		break;
+	case 0x83:
+		/* Give Phy Addr */
+		DEV_INFO("%s: Recvd a Give Phy Addr cmd\n", __func__);
+
+		out_msg.sender_id = 0x4;
+		out_msg.recvr_id = 0xF; /* Broadcast */
+		out_msg.opcode = 0x84;
+		out_msg.operand[i++] = 0x10;
+		out_msg.operand[i++] = 0x0;
+		out_msg.operand[i++] = 0x04;
+		out_msg.frame_size = i + 2;
+
+		rc = hdmi_cec_msg_send(cec_ctrl, &out_msg);
+		break;
+	case 0xFF:
+		/* Abort */
+		DEV_INFO("%s: Recvd an abort cmd.\n", __func__);
+
+		/* reason = "Refused" */
+		rc = hdmi_cec_send_abort_opcode(cec_ctrl, in_msg, 0x04);
+		break;
+	case 0x46:
+		/* Give OSD name */
+		DEV_INFO("%s: Recvd 'Give OSD name' cmd.\n", __func__);
+
+		out_msg.sender_id = 0x4;
+		out_msg.recvr_id = in_msg->sender_id;
+		out_msg.opcode = 0x47; /* OSD Name */
+		/* Display control byte */
+		out_msg.operand[i++] = 0x0;
+		out_msg.operand[i++] = 'H';
+		out_msg.operand[i++] = 'e';
+		out_msg.operand[i++] = 'l';
+		out_msg.operand[i++] = 'l';
+		out_msg.operand[i++] = 'o';
+		out_msg.operand[i++] = ' ';
+		out_msg.operand[i++] = 'W';
+		out_msg.operand[i++] = 'o';
+		out_msg.operand[i++] = 'r';
+		out_msg.operand[i++] = 'l';
+		out_msg.operand[i++] = 'd';
+		out_msg.frame_size = i + 2;
+
+		rc = hdmi_cec_msg_send(cec_ctrl, &out_msg);
+		break;
+	case 0x8F:
+		/* Give Device Power status */
+		DEV_INFO("%s: Recvd a Power status message\n", __func__);
+
+		out_msg.sender_id = 0x4;
+		out_msg.recvr_id = in_msg->sender_id;
+		out_msg.opcode = 0x90; /* OSD String */
+		out_msg.operand[i++] = 'H';
+		out_msg.operand[i++] = 'e';
+		out_msg.operand[i++] = 'l';
+		out_msg.operand[i++] = 'l';
+		out_msg.operand[i++] = 'o';
+		out_msg.operand[i++] = ' ';
+		out_msg.operand[i++] = 'W';
+		out_msg.operand[i++] = 'o';
+		out_msg.operand[i++] = 'r';
+		out_msg.operand[i++] = 'l';
+		out_msg.operand[i++] = 'd';
+		out_msg.frame_size = i + 2;
+
+		rc = hdmi_cec_msg_send(cec_ctrl, &out_msg);
+		break;
+	case 0x80:
+		/* Routing Change cmd */
+	case 0x86:
+		/* Set Stream Path */
+		DEV_INFO("%s: Recvd Set Stream or Routing Change cmd\n",
+			__func__);
+
+		out_msg.sender_id = 0x4;
+		out_msg.recvr_id = 0xF; /* broadcast this message */
+		out_msg.opcode = 0x82; /* Active Source */
+		out_msg.operand[i++] = 0x10;
+		out_msg.operand[i++] = 0x0;
+		out_msg.frame_size = i + 2;
+
+		rc = hdmi_cec_msg_send(cec_ctrl, &out_msg);
+
+		/* todo: check if need to wait for msg response from sink */
+
+		/* sending <Image View On> message */
+		memset(&out_msg, 0x0, sizeof(struct hdmi_cec_msg));
+		i = 0;
+		out_msg.sender_id = 0x4;
+		out_msg.recvr_id = in_msg->sender_id;
+		out_msg.opcode = 0x04; /* opcode for Image View On */
+		out_msg.frame_size = i + 2;
+
+		rc = hdmi_cec_msg_send(cec_ctrl, &out_msg);
+		break;
+	case 0x44:
+		/* User Control Pressed */
+		DEV_INFO("%s: User Control Pressed\n", __func__);
+		break;
+	case 0x45:
+		/* User Control Released */
+		DEV_INFO("%s: User Control Released\n", __func__);
+		break;
+	default:
+		DEV_INFO("%s: Recvd an unknown cmd = [%u]\n", __func__,
+			in_msg->opcode);
+
+		/* reason = "Unrecognized opcode" */
+		rc = hdmi_cec_send_abort_opcode(cec_ctrl, in_msg, 0x0);
+		break;
+	}
+
+	return rc;
+} /* hdmi_cec_msg_parser */
+
+static int hdmi_cec_msg_send(struct hdmi_cec_ctrl *cec_ctrl,
+	struct hdmi_cec_msg *msg)
+{
+	int i, line_check_retry = 10;
+	u32 frame_retransmit = RETRANSMIT_MAX_NUM;
+	bool frame_type;
+	unsigned long flags;
+	struct dss_io_data *io = NULL;
+
+	if (!cec_ctrl || !cec_ctrl->init_data.io || !msg) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = cec_ctrl->init_data.io;
+
+	INIT_COMPLETION(cec_ctrl->cec_msg_wr_done);
+	cec_ctrl->cec_msg_wr_status = 0;
+	frame_type = (msg->recvr_id == 15 ? BIT(0) : 0);
+	if (msg->retransmit > 0 && msg->retransmit < RETRANSMIT_MAX_NUM)
+		frame_retransmit = msg->retransmit;
+
+	/* toggle cec in order to flush out bad hw state, if any */
+	DSS_REG_W(io, HDMI_CEC_CTRL, 0);
+	DSS_REG_W(io, HDMI_CEC_CTRL, BIT(0));
+
+	frame_retransmit = (frame_retransmit & 0xF) << 4;
+	DSS_REG_W(io, HDMI_CEC_RETRANSMIT, BIT(0) | frame_retransmit);
+
+	/* header block */
+	DSS_REG_W_ND(io, HDMI_CEC_WR_DATA,
+		(((msg->sender_id << 4) | msg->recvr_id) << 8) | frame_type);
+
+	/* data block 0 : opcode */
+	DSS_REG_W_ND(io, HDMI_CEC_WR_DATA,
+		((msg->frame_size < 2 ? 0 : msg->opcode) << 8) | frame_type);
+
+	/* data block 1-14 : operand 0-13 */
+	for (i = 0; i < msg->frame_size - 2; i++)
+		DSS_REG_W_ND(io, HDMI_CEC_WR_DATA,
+			(msg->operand[i] << 8) | frame_type);
+
+	while ((DSS_REG_R(io, HDMI_CEC_STATUS) & BIT(0)) &&
+		line_check_retry--) {
+		DEV_DBG("%s: CEC line is busy(%d)\n", __func__,
+			line_check_retry);
+		schedule();
+	}
+
+	if (!line_check_retry && (DSS_REG_R(io, HDMI_CEC_STATUS) & BIT(0))) {
+		DEV_ERR("%s: CEC line is busy. Retry\n", __func__);
+		return -EAGAIN;
+	}
+
+	/* start transmission */
+	DSS_REG_W(io, HDMI_CEC_CTRL, BIT(0) | BIT(1) |
+		((msg->frame_size & 0x1F) << 4) | BIT(9));
+
+	if (!wait_for_completion_interruptible_timeout(
+		&cec_ctrl->cec_msg_wr_done, HZ)) {
+		DEV_ERR("%s: timedout", __func__);
+		hdmi_cec_dump_msg(cec_ctrl, msg);
+		return -ETIMEDOUT;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	if (cec_ctrl->cec_msg_wr_status == CEC_STATUS_WR_ERROR)
+		DEV_ERR("%s: msg write failed.\n", __func__);
+	else
+		DEV_DBG("%s: CEC write frame done (frame len=%d)", __func__,
+			msg->frame_size);
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+	hdmi_cec_dump_msg(cec_ctrl, msg);
+
+	return 0;
+} /* hdmi_cec_msg_send */
+
+static void hdmi_cec_msg_recv(struct work_struct *work)
+{
+	int i;
+	u32 data;
+	unsigned long flags;
+	struct hdmi_cec_ctrl *cec_ctrl = NULL;
+	struct dss_io_data *io = NULL;
+	struct hdmi_cec_msg_node *msg_node = NULL;
+
+	cec_ctrl = container_of(work, struct hdmi_cec_ctrl, cec_read_work);
+	if (!cec_ctrl || !cec_ctrl->cec_enabled || !cec_ctrl->init_data.io) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = cec_ctrl->init_data.io;
+
+	msg_node = kzalloc(sizeof(*msg_node), GFP_KERNEL);
+	if (!msg_node) {
+		DEV_ERR("%s: FAILED: out of memory\n", __func__);
+		return;
+	}
+
+	data = DSS_REG_R(io, HDMI_CEC_RD_DATA);
+
+	msg_node->msg.recvr_id   = (data & 0x000F);
+	msg_node->msg.sender_id  = (data & 0x00F0) >> 4;
+	msg_node->msg.frame_size = (data & 0x1F00) >> 8;
+	DEV_DBG("%s: Recvd init=[%u] dest=[%u] size=[%u]\n", __func__,
+		msg_node->msg.sender_id, msg_node->msg.recvr_id,
+		msg_node->msg.frame_size);
+
+	if (msg_node->msg.frame_size < 1) {
+		DEV_ERR("%s: invalid message (frame length = %d)",
+			__func__, msg_node->msg.frame_size);
+		kfree(msg_node);
+		return;
+	} else if (msg_node->msg.frame_size == 1) {
+		DEV_DBG("%s: polling message (dest[%x] <- init[%x])", __func__,
+			msg_node->msg.recvr_id, msg_node->msg.sender_id);
+		kfree(msg_node);
+		return;
+	}
+
+	/* data block 0 : opcode */
+	data = DSS_REG_R_ND(io, HDMI_CEC_RD_DATA);
+	msg_node->msg.opcode = data & 0xFF;
+
+	/* data block 1-14 : operand 0-13 */
+	for (i = 0; i < msg_node->msg.frame_size - 2; i++) {
+		data = DSS_REG_R_ND(io, HDMI_CEC_RD_DATA);
+		msg_node->msg.operand[i] = data & 0xFF;
+	}
+
+	for (; i < 14; i++)
+		msg_node->msg.operand[i] = 0;
+
+	DEV_DBG("%s: CEC read frame done\n", __func__);
+	hdmi_cec_dump_msg(cec_ctrl, &msg_node->msg);
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	if (cec_ctrl->compliance_response_enabled) {
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+		if (hdmi_cec_msg_parser(cec_ctrl, &msg_node->msg) != 0) {
+			DEV_ERR("%s: cec_msg_parser fail. Sending abort msg\n",
+				__func__);
+			/* reason = "Unrecognized opcode" */
+			hdmi_cec_send_abort_opcode(cec_ctrl,
+				&msg_node->msg, 0x0);
+		}
+		kfree(msg_node);
+	} else {
+		list_add_tail(&msg_node->list, &cec_ctrl->msg_head);
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+		/* wake-up sysfs read_msg context */
+		sysfs_notify(cec_ctrl->init_data.sysfs_kobj, "cec", "rd_msg");
+	}
+} /* hdmi_cec_msg_recv*/
+
+static ssize_t hdmi_rda_cec_enable(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	unsigned long flags;
+	struct hdmi_cec_ctrl *cec_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_CEC);
+
+	if (!cec_ctrl || !cec_ctrl->init_data.io) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EPERM;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	if (cec_ctrl->cec_enabled && cec_ctrl->cec_engine_configed) {
+		DEV_DBG("%s: cec is enabled\n", __func__);
+		ret = snprintf(buf, PAGE_SIZE, "%d\n", 1);
+	} else if (cec_ctrl->cec_enabled && !cec_ctrl->cec_engine_configed) {
+		DEV_ERR("%s: CEC will be enabled when HDMI mirroring is on\n",
+			__func__);
+		ret = -EPERM;
+	} else {
+		DEV_DBG("%s: cec is disabled\n", __func__);
+		ret = snprintf(buf, PAGE_SIZE, "%d\n", 0);
+	}
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	return ret;
+} /* hdmi_rda_cec_enable */
+
+static ssize_t hdmi_wta_cec_enable(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int val;
+	bool cec_en;
+	unsigned long flags;
+	ssize_t ret = strnlen(buf, PAGE_SIZE);
+	struct hdmi_cec_ctrl *cec_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_CEC);
+
+	if (!cec_ctrl) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EPERM;
+	}
+
+	if (kstrtoint(buf, 10, &val)) {
+		DEV_ERR("%s: kstrtoint failed.\n", __func__);
+		return -EPERM;
+	}
+	cec_en = (val == 1) ? true : false;
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	if (cec_ctrl->cec_enabled == cec_en) {
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+		DEV_INFO("%s: cec is already %s\n", __func__,
+			cec_en ? "enabled" : "disabled");
+		return ret;
+	}
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	if (!cec_en) {
+		spin_lock_irqsave(&cec_ctrl->lock, flags);
+		if (!cec_ctrl->cec_engine_configed) {
+			DEV_DBG("%s: hdmi is already off. disable cec\n",
+				__func__);
+			cec_ctrl->cec_enabled = false;
+			spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+			return ret;
+		}
+		cec_ctrl->cec_enabled = false;
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+		hdmi_cec_disable(cec_ctrl);
+		return ret;
+	} else {
+		spin_lock_irqsave(&cec_ctrl->lock, flags);
+		if (!cec_ctrl->cec_engine_configed) {
+			DEV_DBG("%s: CEC will be enabled on mirroring\n",
+				__func__);
+			cec_ctrl->cec_enabled = true;
+			spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+			return ret;
+		}
+		cec_ctrl->cec_enabled = true;
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+		hdmi_cec_enable(cec_ctrl);
+
+		return ret;
+	}
+} /* hdmi_wta_cec_enable */
+
+static ssize_t hdmi_rda_cec_enable_compliance(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	unsigned long flags;
+	ssize_t ret;
+	struct hdmi_cec_ctrl *cec_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_CEC);
+
+	if (!cec_ctrl) {
+		DEV_ERR("%s: Invalid cec_ctrl\n", __func__);
+		return -EPERM;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n",
+		cec_ctrl->compliance_response_enabled);
+
+	cec_ctrl->cec_logical_addr = 0x4;
+	hdmi_cec_write_logical_addr(cec_ctrl, cec_ctrl->cec_logical_addr);
+
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	return ret;
+} /* hdmi_rda_cec_enable_compliance */
+
+static ssize_t hdmi_wta_cec_enable_compliance(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int val;
+	unsigned long flags;
+	ssize_t ret = strnlen(buf, PAGE_SIZE);
+	struct hdmi_cec_ctrl *cec_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_CEC);
+
+	if (!cec_ctrl) {
+		DEV_ERR("%s: Invalid cec_ctrl\n", __func__);
+		return -EPERM;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	if (cec_ctrl->cec_enabled && cec_ctrl->cec_engine_configed) {
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+		DEV_ERR("%s: Cannot en/dis compliance when CEC session is on\n",
+			__func__);
+		return -EPERM;
+	} else {
+		if (kstrtoint(buf, 10, &val)) {
+			DEV_ERR("%s: kstrtoint failed.\n", __func__);
+			return -EPERM;
+		}
+		cec_ctrl->compliance_response_enabled =
+			(val == 1) ? true : false;
+	}
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	return ret;
+} /* hdmi_wta_cec_enable_compliance */
+
+static ssize_t hdmi_rda_cec_logical_addr(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	unsigned long flags;
+	ssize_t ret = strnlen(buf, PAGE_SIZE);
+	struct hdmi_cec_ctrl *cec_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_CEC);
+
+	if (!cec_ctrl) {
+		DEV_ERR("%s: Invalid cec_ctrl\n", __func__);
+		return -EPERM;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", cec_ctrl->cec_logical_addr);
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	return ret;
+} /* hdmi_rda_cec_logical_addr */
+
+static ssize_t hdmi_wta_cec_logical_addr(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int logical_addr;
+	unsigned long flags;
+	ssize_t ret = strnlen(buf, PAGE_SIZE);
+	struct hdmi_cec_ctrl *cec_ctrl =
+	 hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_CEC);
+
+	if (!cec_ctrl) {
+		DEV_ERR("%s: Invalid cec_ctrl\n", __func__);
+		return -EPERM;
+	}
+
+	if (kstrtoint(buf, 10, &logical_addr)) {
+		DEV_ERR("%s: kstrtoint failed\n", __func__);
+		return -EPERM;
+	}
+
+	if (logical_addr < 0 || logical_addr > 15) {
+		DEV_ERR("%s: Invalid logical address\n", __func__);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	cec_ctrl->cec_logical_addr = (u8)logical_addr;
+	if (cec_ctrl->cec_enabled && cec_ctrl->cec_engine_configed)
+		hdmi_cec_write_logical_addr(cec_ctrl,
+			cec_ctrl->cec_logical_addr);
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	return ret;
+} /* hdmi_wta_cec_logical_addr */
+
+static ssize_t hdmi_rda_cec_msg(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	int i = 0;
+	unsigned long flags;
+	struct hdmi_cec_msg_node *msg_node, *tmp;
+	struct hdmi_cec_ctrl *cec_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_CEC);
+
+	if (!cec_ctrl) {
+		DEV_ERR("%s: Invalid cec_ctrl\n", __func__);
+		return -EPERM;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+
+	if (cec_ctrl->compliance_response_enabled) {
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+		DEV_ERR("%s: Read is disabled coz compliance response is on\n",
+			__func__);
+		return -EPERM;
+	}
+
+	if (list_empty_careful(&cec_ctrl->msg_head)) {
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+		DEV_ERR("%s: CEC message queue is empty\n", __func__);
+		return -EPERM;
+	}
+
+	list_for_each_entry_safe(msg_node, tmp, &cec_ctrl->msg_head, list) {
+		if ((i+1) * sizeof(struct hdmi_cec_msg) > PAGE_SIZE) {
+			DEV_DBG("%s: Overflowing PAGE_SIZE.\n", __func__);
+			break;
+		}
+
+		memcpy(buf + (i * sizeof(struct hdmi_cec_msg)), &msg_node->msg,
+			sizeof(struct hdmi_cec_msg));
+		list_del(&msg_node->list);
+		kfree(msg_node);
+		i++;
+	}
+
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	return i * sizeof(struct hdmi_cec_msg);
+} /* hdmi_rda_cec_msg */
+
+static ssize_t hdmi_wta_cec_msg(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int rc;
+	unsigned long flags;
+	struct hdmi_cec_msg *msg = (struct hdmi_cec_msg *)buf;
+	struct hdmi_cec_ctrl *cec_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_CEC);
+
+	if (!cec_ctrl) {
+		DEV_ERR("%s: Invalid cec_ctrl\n", __func__);
+		return -EPERM;
+	}
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	if (cec_ctrl->compliance_response_enabled) {
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+		DEV_ERR("%s: Write disabled coz compliance response is on.\n",
+			__func__);
+		return -EPERM;
+	}
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	rc = hdmi_cec_msg_send(cec_ctrl, msg);
+	if (rc) {
+		DEV_ERR("%s: hdmi_cec_msg_send failed\n", __func__);
+		return rc;
+	} else {
+		return sizeof(struct hdmi_cec_msg);
+	}
+} /* hdmi_wta_cec_msg */
+
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, hdmi_rda_cec_enable,
+	hdmi_wta_cec_enable);
+static DEVICE_ATTR(enable_compliance, S_IRUGO | S_IWUSR,
+	hdmi_rda_cec_enable_compliance, hdmi_wta_cec_enable_compliance);
+static DEVICE_ATTR(logical_addr, S_IRUGO | S_IWUSR,
+	hdmi_rda_cec_logical_addr, hdmi_wta_cec_logical_addr);
+static DEVICE_ATTR(rd_msg, S_IRUGO, hdmi_rda_cec_msg,	NULL);
+static DEVICE_ATTR(wr_msg, S_IWUSR, NULL, hdmi_wta_cec_msg);
+
+static struct attribute *hdmi_cec_fs_attrs[] = {
+	&dev_attr_enable.attr,
+	&dev_attr_enable_compliance.attr,
+	&dev_attr_logical_addr.attr,
+	&dev_attr_rd_msg.attr,
+	&dev_attr_wr_msg.attr,
+	NULL,
+};
+
+static struct attribute_group hdmi_cec_fs_attr_group = {
+	.name = "cec",
+	.attrs = hdmi_cec_fs_attrs,
+};
+
+int hdmi_cec_isr(void *input)
+{
+	int rc = 0;
+	u32 cec_intr, cec_status;
+	unsigned long flags;
+	struct dss_io_data *io = NULL;
+	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input;
+
+	if (!cec_ctrl || !cec_ctrl->init_data.io) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EPERM;
+	}
+
+	io = cec_ctrl->init_data.io;
+
+	if (!cec_ctrl->cec_enabled)
+		return 0;
+
+	cec_intr = DSS_REG_R_ND(io, HDMI_CEC_INT);
+	DEV_DBG("%s: cec interrupt status is [0x%x]\n", __func__, cec_intr);
+
+	cec_status = DSS_REG_R_ND(io, HDMI_CEC_STATUS);
+	DEV_DBG("%s: cec status is [0x%x]\n", __func__, cec_status);
+
+	if ((cec_intr & BIT(0)) && (cec_intr & BIT(1))) {
+		DEV_DBG("%s: CEC_IRQ_FRAME_WR_DONE\n", __func__);
+		DSS_REG_W(io, HDMI_CEC_INT, cec_intr | BIT(0));
+
+		spin_lock_irqsave(&cec_ctrl->lock, flags);
+		cec_ctrl->cec_msg_wr_status |= CEC_STATUS_WR_DONE;
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+		if (!completion_done(&cec_ctrl->cec_msg_wr_done))
+			complete_all(&cec_ctrl->cec_msg_wr_done);
+	}
+
+	if ((cec_intr & BIT(2)) && (cec_intr & BIT(3))) {
+		DEV_DBG("%s: CEC_IRQ_FRAME_ERROR\n", __func__);
+		DSS_REG_W(io, HDMI_CEC_INT, cec_intr | BIT(2));
+
+		spin_lock_irqsave(&cec_ctrl->lock, flags);
+		cec_ctrl->cec_msg_wr_status |= CEC_STATUS_WR_ERROR;
+		spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+		if (!completion_done(&cec_ctrl->cec_msg_wr_done))
+			complete_all(&cec_ctrl->cec_msg_wr_done);
+	}
+
+	if ((cec_intr & BIT(6)) && (cec_intr & BIT(7))) {
+		DEV_DBG("%s: CEC_IRQ_FRAME_RD_DONE\n", __func__);
+
+		DSS_REG_W(io, HDMI_CEC_INT, cec_intr | BIT(6));
+		queue_work(cec_ctrl->init_data.workq, &cec_ctrl->cec_read_work);
+	}
+
+	return rc;
+} /* hdmi_cec_isr */
+
+int hdmi_cec_deconfig(void *input)
+{
+	unsigned long flags;
+	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input;
+
+	if (!cec_ctrl) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EPERM;
+	}
+
+	hdmi_cec_disable(cec_ctrl);
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	cec_ctrl->cec_engine_configed = false;
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	return 0;
+} /* hdmi_cec_deconfig */
+
+int hdmi_cec_config(void *input)
+{
+	unsigned long flags;
+	u32 hdmi_hw_version;
+	struct dss_io_data *io = NULL;
+	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input;
+
+	if (!cec_ctrl || !cec_ctrl->init_data.io) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EPERM;
+	}
+
+	io = cec_ctrl->init_data.io;
+
+	/* 19.2Mhz * 0.00005 us = 950 = 0x3B6 */
+	DSS_REG_W(io, HDMI_CEC_REFTIMER, (0x3B6 & 0xFFF) | BIT(16));
+
+	hdmi_hw_version = DSS_REG_R(io, HDMI_VERSION);
+	if (hdmi_hw_version == 0x30000001) {
+		DSS_REG_W(io, HDMI_CEC_RD_RANGE, 0x30AB9888);
+		DSS_REG_W(io, HDMI_CEC_WR_RANGE, 0x888AA888);
+
+		DSS_REG_W(io, HDMI_CEC_RD_START_RANGE, 0x88888888);
+		DSS_REG_W(io, HDMI_CEC_RD_TOTAL_RANGE, 0x99);
+		DSS_REG_W(io, HDMI_CEC_COMPL_CTL, 0xF);
+		DSS_REG_W(io, HDMI_CEC_WR_CHECK_CONFIG, 0x4);
+	} else {
+		DEV_INFO("%s: CEC is not supported on %d HDMI HW version.\n",
+			__func__, hdmi_hw_version);
+		return -EPERM;
+	}
+
+	DSS_REG_W(io, HDMI_CEC_RD_FILTER, BIT(0) | (0x7FF << 4));
+	DSS_REG_W(io, HDMI_CEC_TIME, BIT(0) | ((7 * 0x30) << 7));
+
+	if (cec_ctrl->cec_enabled)
+		hdmi_cec_enable(cec_ctrl);
+
+	spin_lock_irqsave(&cec_ctrl->lock, flags);
+	cec_ctrl->cec_engine_configed = true;
+	spin_unlock_irqrestore(&cec_ctrl->lock, flags);
+
+	return 0;
+} /* hdmi_cec_config */
+
+void hdmi_cec_deinit(void *input)
+{
+	struct hdmi_cec_msg_node *msg_node, *tmp;
+	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input;
+
+	if (cec_ctrl) {
+		list_for_each_entry_safe(msg_node, tmp, &cec_ctrl->msg_head,
+					list) {
+			list_del(&msg_node->list);
+			kfree(msg_node);
+		}
+
+		sysfs_remove_group(cec_ctrl->init_data.sysfs_kobj,
+			&hdmi_cec_fs_attr_group);
+
+		kfree(cec_ctrl);
+	}
+} /* hdmi_cec_deinit */
+
+void *hdmi_cec_init(struct hdmi_cec_init_data *init_data)
+{
+	struct hdmi_cec_ctrl *cec_ctrl = NULL;
+
+	if (!init_data) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		goto error;
+	}
+
+	cec_ctrl = kzalloc(sizeof(*cec_ctrl), GFP_KERNEL);
+	if (!cec_ctrl) {
+		DEV_ERR("%s: FAILED: out of memory\n", __func__);
+		goto error;
+	}
+
+	cec_ctrl->init_data = *init_data;
+
+	if (sysfs_create_group(init_data->sysfs_kobj,
+				&hdmi_cec_fs_attr_group)) {
+		DEV_ERR("%s: cec sysfs group creation failed\n", __func__);
+		goto error;
+	}
+
+	spin_lock_init(&cec_ctrl->lock);
+	INIT_LIST_HEAD(&cec_ctrl->msg_head);
+	INIT_WORK(&cec_ctrl->cec_read_work, hdmi_cec_msg_recv);
+	init_completion(&cec_ctrl->cec_msg_wr_done);
+
+	goto exit;
+
+error:
+	kfree(cec_ctrl);
+	cec_ctrl = NULL;
+exit:
+	return (void *)cec_ctrl;
+} /* hdmi_cec_init */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_cec.h b/drivers/video/msm/mdss/mdss_hdmi_cec.h
new file mode 100644
index 0000000..a554507
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_hdmi_cec.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2010-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 __MDSS_HDMI_CEC_H__
+#define __MDSS_HDMI_CEC_H__
+
+#include "mdss_hdmi_util.h"
+
+struct hdmi_cec_init_data {
+	struct workqueue_struct *workq;
+	struct kobject *sysfs_kobj;
+	struct dss_io_data *io;
+};
+
+int hdmi_cec_deconfig(void *cec_ctrl);
+int hdmi_cec_config(void *cec_ctrl);
+int hdmi_cec_isr(void *cec_ctrl);
+void hdmi_cec_deinit(void *cec_ctrl);
+void *hdmi_cec_init(struct hdmi_cec_init_data *init_data);
+#endif /* __MDSS_HDMI_CEC_H__ */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 66936e5..e28a4e9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -26,9 +26,10 @@
 
 #include "mdss_debug.h"
 #include "mdss_fb.h"
-#include "mdss_hdmi_tx.h"
+#include "mdss_hdmi_cec.h"
 #include "mdss_hdmi_edid.h"
 #include "mdss_hdmi_hdcp.h"
+#include "mdss_hdmi_tx.h"
 #include "mdss.h"
 #include "mdss_panel.h"
 #include "mdss_hdmi_mhl.h"
@@ -644,12 +645,14 @@
 {
 	struct hdmi_edid_init_data edid_init_data;
 	struct hdmi_hdcp_init_data hdcp_init_data;
+	struct hdmi_cec_init_data cec_init_data;
 
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
 
+	/* Initialize EDID feature */
 	edid_init_data.io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	edid_init_data.mutex = &hdmi_ctrl->mutex;
 	edid_init_data.sysfs_kobj = hdmi_ctrl->kobj;
@@ -688,6 +691,17 @@
 
 		DEV_DBG("%s: HDCP feature initialized\n", __func__);
 	}
+
+	/* Initialize CEC feature */
+	cec_init_data.io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	cec_init_data.sysfs_kobj = hdmi_ctrl->kobj;
+	cec_init_data.workq = hdmi_ctrl->workq;
+
+	hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC] =
+		hdmi_cec_init(&cec_init_data);
+	if (!hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC])
+		DEV_WARN("%s: hdmi_cec_init failed\n", __func__);
+
 	return 0;
 } /* hdmi_tx_init_features */
 
@@ -2169,6 +2183,8 @@
 		hdmi_ctrl->hpd_off_pending = false;
 	}
 
+	hdmi_cec_deconfig(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
+
 	mutex_lock(&hdmi_ctrl->mutex);
 	hdmi_ctrl->panel_power_on = false;
 	mutex_unlock(&hdmi_ctrl->mutex);
@@ -2253,10 +2269,12 @@
 
 	mutex_lock(&hdmi_ctrl->mutex);
 	hdmi_ctrl->panel_power_on = true;
+	mutex_unlock(&hdmi_ctrl->mutex);
+
+	hdmi_cec_config(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
 
 	if (hdmi_ctrl->hpd_state) {
 		DEV_DBG("%s: Turning HDMI on\n", __func__);
-		mutex_unlock(&hdmi_ctrl->mutex);
 		rc = hdmi_tx_start(hdmi_ctrl);
 		if (rc) {
 			DEV_ERR("%s: hdmi_tx_start failed. rc=%d\n",
@@ -2264,8 +2282,6 @@
 			hdmi_tx_power_off(panel_data);
 			return rc;
 		}
-	} else {
-		mutex_unlock(&hdmi_ctrl->mutex);
 	}
 
 	dss_reg_dump(io->base, io->len, "HDMI-ON: ", REG_DUMP);
@@ -2345,6 +2361,10 @@
 
 		hdmi_ctrl->hpd_initialized = true;
 
+		DEV_INFO("%s: HDMI HW version = 0x%x\n", __func__,
+			DSS_REG_R_ND(&hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO],
+				HDMI_VERSION));
+
 		/* set timeout to 4.1ms (max) for hardware debounce */
 		reg_val = DSS_REG_R(io, HDMI_HPD_CTRL) | 0x1FFF;
 
@@ -2415,12 +2435,15 @@
 		queue_work(hdmi_ctrl->workq, &hdmi_ctrl->hpd_int_work);
 	}
 
-	if (hdmi_ddc_isr(&hdmi_ctrl->ddc_ctrl) < 0)
+	if (hdmi_ddc_isr(&hdmi_ctrl->ddc_ctrl))
 		DEV_ERR("%s: hdmi_ddc_isr failed\n", __func__);
 
+	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC])
+		if (hdmi_cec_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]))
+			DEV_ERR("%s: hdmi_cec_isr failed\n", __func__);
+
 	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP])
-		if (hdmi_hdcp_isr(
-			hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]) < 0)
+		if (hdmi_hdcp_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]))
 			DEV_ERR("%s: hdmi_hdcp_isr failed\n", __func__);
 
 	return IRQ_HANDLED;
@@ -2433,13 +2456,20 @@
 		return;
 	}
 
+	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]) {
+		hdmi_cec_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
+		hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC] = NULL;
+	}
+
 	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]) {
 		hdmi_hdcp_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]);
 		hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP] = NULL;
 	}
 
-	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID])
+	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) {
 		hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
+		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] = NULL;
+	}
 
 	switch_dev_unregister(&hdmi_ctrl->audio_sdev);
 	switch_dev_unregister(&hdmi_ctrl->sdev);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index cf42346..e99e549 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -201,6 +201,11 @@
 #define HDMI_TPG_INITIAL_VALUE           (0x00000354)
 #define HDMI_TPG_BLK_WHT_PATTERN_FRAMES  (0x00000358)
 #define HDMI_TPG_RGB_MAPPING             (0x0000035C)
+#define HDMI_CEC_COMPL_CTL               (0x00000360)
+#define HDMI_CEC_RD_START_RANGE          (0x00000364)
+#define HDMI_CEC_RD_TOTAL_RANGE          (0x00000368)
+#define HDMI_CEC_RD_ERR_RESP_LO          (0x0000036C)
+#define HDMI_CEC_WR_CHECK_CONFIG         (0x00000370)
 
 /* HDMI PHY Registers */
 #define HDMI_PHY_ANA_CFG0                (0x00000000)
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 1ced200..fa53656 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -986,6 +986,19 @@
 	if (ret) {
 		pr_warn("error powering off intf ctl=%d\n", ctl->num);
 	} else {
+		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, 0);
+		if (sctl)
+			mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_TOP, 0);
+
+		if (ctl->mixer_left) {
+			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(
+					ctl->mixer_left->num), 0);
+		}
+		if (ctl->mixer_right) {
+			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(
+					ctl->mixer_right->num), 0);
+		}
+
 		ctl->power_on = false;
 		ctl->play_cnt = 0;
 		ctl->clk_rate = 0;
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 5c15d9a..f5d7947 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -800,9 +800,9 @@
 	if (resource_context.vidc_platform_data->enable_ion) {
 		if (res_trk_check_for_sec_session()) {
 			if (resource_context.res_mem_type != DDL_FW_MEM)
-				flags |= ION_SECURE;
+				flags |= ION_FLAG_SECURE;
 			else if (res_trk_is_cp_enabled())
-				flags |= ION_SECURE;
+				flags |= ION_FLAG_SECURE;
 		}
 	}
 	return flags;
diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h
index 2ad1ab2..1e65a5f 100644
--- a/include/drm/kgsl_drm.h
+++ b/include/drm/kgsl_drm.h
@@ -21,6 +21,10 @@
 #define DRM_KGSL_GEM_CREATE_FD 0x0E
 #define DRM_KGSL_GEM_GET_ION_FD 0x0F
 #define DRM_KGSL_GEM_CREATE_FROM_ION 0x10
+#define DRM_KGSL_GEM_SET_GLOCK_HANDLES_INFO 0x11
+#define DRM_KGSL_GEM_GET_GLOCK_HANDLES_INFO 0x12
+#define DRM_KGSL_GEM_GET_BUFCOUNT 0x13
+
 
 #define DRM_IOCTL_KGSL_GEM_CREATE \
 DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE, struct drm_kgsl_gem_create)
@@ -57,6 +61,10 @@
 DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_BUFCOUNT, \
 	 struct drm_kgsl_gem_bufcount)
 
+#define DRM_IOCTL_KGSL_GEM_GET_BUFCOUNT \
+DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_BUFCOUNT, \
+	 struct drm_kgsl_gem_bufcount)
+
 #define DRM_IOCTL_KGSL_GEM_SET_ACTIVE \
 DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_ACTIVE, \
 	 struct drm_kgsl_gem_active)
@@ -85,6 +93,16 @@
 DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FROM_ION, \
 struct drm_kgsl_gem_create_from_ion)
 
+#define DRM_IOCTL_KGSL_GEM_SET_GLOCK_HANDLES_INFO \
+DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_GLOCK_HANDLES_INFO, \
+struct drm_kgsl_gem_glockinfo)
+
+#define DRM_IOCTL_KGSL_GEM_GET_GLOCK_HANDLES_INFO \
+DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_GLOCK_HANDLES_INFO, \
+struct drm_kgsl_gem_glockinfo)
+
+
+
 /* Maximum number of sub buffers per GEM object */
 #define DRM_KGSL_GEM_MAX_BUFFERS 3
 
@@ -167,6 +185,11 @@
 	uint32_t gpuaddr[DRM_KGSL_GEM_MAX_BUFFERS];
 };
 
+struct drm_kgsl_gem_glockinfo {
+	uint32_t handle;
+	int glockhandle[DRM_KGSL_GEM_MAX_BUFFERS];
+};
+
 struct drm_kgsl_gem_bufcount {
 	uint32_t handle;
 	uint32_t bufcount;
diff --git a/include/linux/genlock.h b/include/linux/genlock.h
index 587c49d..e233662 100644
--- a/include/linux/genlock.h
+++ b/include/linux/genlock.h
@@ -8,6 +8,7 @@
 
 struct genlock_handle *genlock_get_handle(void);
 struct genlock_handle *genlock_get_handle_fd(int fd);
+int genlock_get_fd_handle(struct genlock_handle *handle);
 void genlock_put_handle(struct genlock_handle *handle);
 struct genlock *genlock_create_lock(struct genlock_handle *);
 struct genlock *genlock_attach_lock(struct genlock_handle *, int fd);
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 67b5e6c..88ad9a0 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -29,10 +29,6 @@
  * @ION_HEAP_TYPE_CARVEOUT:	 memory allocated from a prereserved
  * 				 carveout heap, allocations are physically
  * 				 contiguous
- * @ION_HEAP_TYPE_IOMMU: IOMMU memory
- * @ION_HEAP_TYPE_CP:	 memory allocated from a prereserved
- *				carveout heap, allocations are physically
- *				contiguous. Used for content protection.
  * @ION_HEAP_END:		helper for iterating over heaps
  */
 enum ion_heap_type {
@@ -104,11 +100,6 @@
  * struct ion_platform_data - array of platform heaps passed from board file
  * @has_outer_cache:    set to 1 if outer cache is used, 0 otherwise.
  * @nr:    number of structures in the array
- * @request_region: function to be called when the number of allocations goes
- *						from 0 -> 1
- * @release_region: function to be called when the number of allocations goes
- *						from 1 -> 0
- * @setup_region:   function to be called upon ion registration
  * @heaps: array of platform_heap structions
  *
  * Provided by the board file in the form of platform data to a platform device.
@@ -116,9 +107,6 @@
 struct ion_platform_data {
 	unsigned int has_outer_cache;
 	int nr;
-	int (*request_region)(void *);
-	int (*release_region)(void *);
-	void *(*setup_region)(void);
 	struct ion_platform_heap *heaps;
 };
 
@@ -145,17 +133,6 @@
 				     unsigned int heap_mask, const char *name);
 
 /**
- *  msm_ion_client_create - allocate a client using the ion_device specified in
- *				drivers/gpu/ion/msm/msm_ion.c
- *
- * heap_mask and name are the same as ion_client_create, return values
- * are the same as ion_client_create.
- */
-
-struct ion_client *msm_ion_client_create(unsigned int heap_mask,
-					const char *name);
-
-/**
  * ion_client_destroy() -  free's a client and all it's handles
  * @client:	the client
  *
@@ -257,124 +234,6 @@
  */
 struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd);
 
-/**
- * ion_handle_get_flags - get the flags for a given handle
- *
- * @client - client who allocated the handle
- * @handle - handle to get the flags
- * @flags - pointer to store the flags
- *
- * Gets the current flags for a handle. These flags indicate various options
- * of the buffer (caching, security, etc.)
- */
-int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
-				unsigned long *flags);
-
-
-/**
- * ion_map_iommu - map the given handle into an iommu
- *
- * @client - client who allocated the handle
- * @handle - handle to map
- * @domain_num - domain number to map to
- * @partition_num - partition number to allocate iova from
- * @align - alignment for the iova
- * @iova_length - length of iova to map. If the iova length is
- *		greater than the handle length, the remaining
- *		address space will be mapped to a dummy buffer.
- * @iova - pointer to store the iova address
- * @buffer_size - pointer to store the size of the buffer
- * @flags - flags for options to map
- * @iommu_flags - flags specific to the iommu.
- *
- * Maps the handle into the iova space specified via domain number. Iova
- * will be allocated from the partition specified via partition_num.
- * Returns 0 on success, negative value on error.
- */
-int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
-			int domain_num, int partition_num, unsigned long align,
-			unsigned long iova_length, unsigned long *iova,
-			unsigned long *buffer_size,
-			unsigned long flags, unsigned long iommu_flags);
-
-
-/**
- * ion_handle_get_size - get the allocated size of a given handle
- *
- * @client - client who allocated the handle
- * @handle - handle to get the size
- * @size - pointer to store the size
- *
- * gives the allocated size of a handle. returns 0 on success, negative
- * value on error
- *
- * NOTE: This is intended to be used only to get a size to pass to map_iommu.
- * You should *NOT* rely on this for any other usage.
- */
-
-int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
-			unsigned long *size);
-
-/**
- * ion_unmap_iommu - unmap the handle from an iommu
- *
- * @client - client who allocated the handle
- * @handle - handle to unmap
- * @domain_num - domain to unmap from
- * @partition_num - partition to unmap from
- *
- * Decrement the reference count on the iommu mapping. If the count is
- * 0, the mapping will be removed from the iommu.
- */
-void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
-			int domain_num, int partition_num);
-
-
-/**
- * ion_secure_heap - secure a heap
- *
- * @client - a client that has allocated from the heap heap_id
- * @heap_id - heap id to secure.
- * @version - version of content protection
- * @data - extra data needed for protection
- *
- * Secure a heap
- * Returns 0 on success
- */
-int ion_secure_heap(struct ion_device *dev, int heap_id, int version,
-			void *data);
-
-/**
- * ion_unsecure_heap - un-secure a heap
- *
- * @client - a client that has allocated from the heap heap_id
- * @heap_id - heap id to un-secure.
- * @version - version of content protection
- * @data - extra data needed for protection
- *
- * Un-secure a heap
- * Returns 0 on success
- */
-int ion_unsecure_heap(struct ion_device *dev, int heap_id, int version,
-			void *data);
-
-/**
- * msm_ion_do_cache_op - do cache operations.
- *
- * @client - pointer to ION client.
- * @handle - pointer to buffer handle.
- * @vaddr -  virtual address to operate on.
- * @len - Length of data to do cache operation on.
- * @cmd - Cache operation to perform:
- *		ION_IOC_CLEAN_CACHES
- *		ION_IOC_INV_CACHES
- *		ION_IOC_CLEAN_INV_CACHES
- *
- * Returns 0 on success
- */
-int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
-			void *vaddr, unsigned long len, unsigned int cmd);
-
 #else
 static inline void ion_reserve(struct ion_platform_data *data)
 {
@@ -387,12 +246,6 @@
 	return ERR_PTR(-ENODEV);
 }
 
-static inline struct ion_client *msm_ion_client_create(unsigned int heap_mask,
-					const char *name)
-{
-	return ERR_PTR(-ENODEV);
-}
-
 static inline void ion_client_destroy(struct ion_client *client) { }
 
 static inline struct ion_handle *ion_alloc(struct ion_client *client,
@@ -444,54 +297,6 @@
 	return -ENODEV;
 }
 
-static inline int ion_map_iommu(struct ion_client *client,
-			struct ion_handle *handle, int domain_num,
-			int partition_num, unsigned long align,
-			unsigned long iova_length, unsigned long *iova,
-			unsigned long *buffer_size,
-			unsigned long flags,
-			unsigned long iommu_flags)
-{
-	return -ENODEV;
-}
-
-static inline int ion_handle_get_size(struct ion_client *client,
-				struct ion_handle *handle, unsigned long *size)
-{
-	return -ENODEV;
-}
-
-static inline void ion_unmap_iommu(struct ion_client *client,
-			struct ion_handle *handle, int domain_num,
-			int partition_num)
-{
-	return;
-}
-
-static inline int ion_secure_heap(struct ion_device *dev, int heap_id,
-					int version, void *data)
-{
-	return -ENODEV;
-
-}
-
-static inline int ion_unsecure_heap(struct ion_device *dev, int heap_id,
-					int version, void *data)
-{
-	return -ENODEV;
-}
-
-static inline void ion_mark_dangling_buffers_locked(struct ion_device *dev)
-{
-}
-
-static inline int msm_ion_do_cache_op(struct ion_client *client,
-			struct ion_handle *handle, void *vaddr,
-			unsigned long len, unsigned int cmd)
-{
-	return -ENODEV;
-}
-
 #endif /* CONFIG_ION */
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/mfd/pm8xxx/batterydata-lib.h
index f27ceca..df9569b 100644
--- a/include/linux/mfd/pm8xxx/batterydata-lib.h
+++ b/include/linux/mfd/pm8xxx/batterydata-lib.h
@@ -91,6 +91,8 @@
  *			compensate for battery capacitance.
  * @rbatt_capacitve_mohm: the resistance to be added to compensate for
  *				battery capacitance
+ * @flat_ocv_threshold_uv: the voltage where the battery's discharge curve
+ *				starts flattening out.
  */
 
 struct bms_battery_data {
@@ -103,6 +105,7 @@
 	int			default_rbatt_mohm;
 	int			delta_rbatt_mohm;
 	int			rbatt_capacitive_mohm;
+	int			flat_ocv_threshold_uv;
 };
 
 #if defined(CONFIG_PM8921_BMS) || \
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 37c935d..396fcd8 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -38,7 +38,7 @@
 	ION_MM_FIRMWARE_HEAP_ID = 29,
 	ION_SYSTEM_HEAP_ID = 30,
 
-	ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_SECURE flag */
+	ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_FLAG_SECURE flag */
 };
 
 enum ion_fixed_position {
@@ -194,9 +194,138 @@
 
 #ifdef CONFIG_ION
 /**
+ *  msm_ion_client_create - allocate a client using the ion_device specified in
+ *				drivers/gpu/ion/msm/msm_ion.c
+ *
+ * heap_mask and name are the same as ion_client_create, return values
+ * are the same as ion_client_create.
+ */
+
+struct ion_client *msm_ion_client_create(unsigned int heap_mask,
+					const char *name);
+
+/**
+ * ion_handle_get_flags - get the flags for a given handle
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to get the flags
+ * @flags - pointer to store the flags
+ *
+ * Gets the current flags for a handle. These flags indicate various options
+ * of the buffer (caching, security, etc.)
+ */
+int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
+				unsigned long *flags);
+
+
+/**
+ * ion_map_iommu - map the given handle into an iommu
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to map
+ * @domain_num - domain number to map to
+ * @partition_num - partition number to allocate iova from
+ * @align - alignment for the iova
+ * @iova_length - length of iova to map. If the iova length is
+ *		greater than the handle length, the remaining
+ *		address space will be mapped to a dummy buffer.
+ * @iova - pointer to store the iova address
+ * @buffer_size - pointer to store the size of the buffer
+ * @flags - flags for options to map
+ * @iommu_flags - flags specific to the iommu.
+ *
+ * Maps the handle into the iova space specified via domain number. Iova
+ * will be allocated from the partition specified via partition_num.
+ * Returns 0 on success, negative value on error.
+ */
+int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
+			int domain_num, int partition_num, unsigned long align,
+			unsigned long iova_length, unsigned long *iova,
+			unsigned long *buffer_size,
+			unsigned long flags, unsigned long iommu_flags);
+
+
+/**
+ * ion_handle_get_size - get the allocated size of a given handle
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to get the size
+ * @size - pointer to store the size
+ *
+ * gives the allocated size of a handle. returns 0 on success, negative
+ * value on error
+ *
+ * NOTE: This is intended to be used only to get a size to pass to map_iommu.
+ * You should *NOT* rely on this for any other usage.
+ */
+
+int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
+			unsigned long *size);
+
+/**
+ * ion_unmap_iommu - unmap the handle from an iommu
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to unmap
+ * @domain_num - domain to unmap from
+ * @partition_num - partition to unmap from
+ *
+ * Decrement the reference count on the iommu mapping. If the count is
+ * 0, the mapping will be removed from the iommu.
+ */
+void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
+			int domain_num, int partition_num);
+
+
+/**
+ * ion_secure_heap - secure a heap
+ *
+ * @client - a client that has allocated from the heap heap_id
+ * @heap_id - heap id to secure.
+ * @version - version of content protection
+ * @data - extra data needed for protection
+ *
+ * Secure a heap
+ * Returns 0 on success
+ */
+int ion_secure_heap(struct ion_device *dev, int heap_id, int version,
+			void *data);
+
+/**
+ * ion_unsecure_heap - un-secure a heap
+ *
+ * @client - a client that has allocated from the heap heap_id
+ * @heap_id - heap id to un-secure.
+ * @version - version of content protection
+ * @data - extra data needed for protection
+ *
+ * Un-secure a heap
+ * Returns 0 on success
+ */
+int ion_unsecure_heap(struct ion_device *dev, int heap_id, int version,
+			void *data);
+
+/**
+ * msm_ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @vaddr -  virtual address to operate on.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ *		ION_IOC_CLEAN_CACHES
+ *		ION_IOC_INV_CACHES
+ *		ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+			void *vaddr, unsigned long len, unsigned int cmd);
+
+/**
  * msm_ion_secure_heap - secure a heap. Wrapper around ion_secure_heap.
  *
-  * @heap_id - heap id to secure.
+ * @heap_id - heap id to secure.
  *
  * Secure a heap
  * Returns 0 on success
@@ -257,6 +386,60 @@
 int msm_ion_unsecure_buffer(struct ion_client *client,
 				struct ion_handle *handle);
 #else
+static inline struct ion_client *msm_ion_client_create(unsigned int heap_mask,
+					const char *name)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline int ion_map_iommu(struct ion_client *client,
+			struct ion_handle *handle, int domain_num,
+			int partition_num, unsigned long align,
+			unsigned long iova_length, unsigned long *iova,
+			unsigned long *buffer_size,
+			unsigned long flags,
+			unsigned long iommu_flags)
+{
+	return -ENODEV;
+}
+
+static inline int ion_handle_get_size(struct ion_client *client,
+				struct ion_handle *handle, unsigned long *size)
+{
+	return -ENODEV;
+}
+
+static inline void ion_unmap_iommu(struct ion_client *client,
+			struct ion_handle *handle, int domain_num,
+			int partition_num)
+{
+	return;
+}
+
+static inline int ion_secure_heap(struct ion_device *dev, int heap_id,
+					int version, void *data)
+{
+	return -ENODEV;
+
+}
+
+static inline int ion_unsecure_heap(struct ion_device *dev, int heap_id,
+					int version, void *data)
+{
+	return -ENODEV;
+}
+
+static inline void ion_mark_dangling_buffers_locked(struct ion_device *dev)
+{
+}
+
+static inline int msm_ion_do_cache_op(struct ion_client *client,
+			struct ion_handle *handle, void *vaddr,
+			unsigned long len, unsigned int cmd)
+{
+	return -ENODEV;
+}
+
 static inline int msm_ion_secure_heap(int heap_id)
 {
 	return -ENODEV;
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index e40f301..757f1dc 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -41,5 +41,18 @@
 
 int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp);
 int msm_tsens_early_init(struct tsens_platform_data *pdata);
+
+#if defined(CONFIG_THERMAL_TSENS8974)
+int __init tsens_tm_init_driver(void);
+#else
+static inline int __init tsens_tm_init_driver(void)
+{ return -ENXIO; }
+#endif
+
+#if defined(CONFIG_THERMAL_TSENS8974) || defined(CONFIG_THERMAL_TSENS8960)
 int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors);
+#else
+static inline int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors)
+{ return -ENXIO; }
+#endif
 #endif /*MSM_TSENS_H */
diff --git a/include/media/Kbuild b/include/media/Kbuild
index 16786a9..3992250 100644
--- a/include/media/Kbuild
+++ b/include/media/Kbuild
@@ -1,4 +1,5 @@
 header-y += tavarua.h
+header-y += radio-iris-commands.h
 
 header-y += msm_camera.h
 header-y += vcap_fmt.h
diff --git a/include/media/radio-iris-commands.h b/include/media/radio-iris-commands.h
new file mode 100644
index 0000000..d41baa9
--- /dev/null
+++ b/include/media/radio-iris-commands.h
@@ -0,0 +1,105 @@
+#ifndef __RADIO_IRIS_COMMANDS_H
+#define __RADIO_IRIS_COMMANDS_H
+
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/atomic.h>
+
+enum v4l2_cid_private_iris_t {
+	V4L2_CID_PRIVATE_IRIS_SRCHMODE = (0x08000000 + 1),
+	V4L2_CID_PRIVATE_IRIS_SCANDWELL,
+	V4L2_CID_PRIVATE_IRIS_SRCHON,
+	V4L2_CID_PRIVATE_IRIS_STATE,
+	V4L2_CID_PRIVATE_IRIS_TRANSMIT_MODE,
+	V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK,
+	V4L2_CID_PRIVATE_IRIS_REGION,
+	V4L2_CID_PRIVATE_IRIS_SIGNAL_TH,
+	V4L2_CID_PRIVATE_IRIS_SRCH_PTY,
+	V4L2_CID_PRIVATE_IRIS_SRCH_PI,
+	V4L2_CID_PRIVATE_IRIS_SRCH_CNT,
+	V4L2_CID_PRIVATE_IRIS_EMPHASIS,
+	V4L2_CID_PRIVATE_IRIS_RDS_STD,
+	V4L2_CID_PRIVATE_IRIS_SPACING,
+	V4L2_CID_PRIVATE_IRIS_RDSON,
+	V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC,
+	V4L2_CID_PRIVATE_IRIS_LP_MODE,
+	V4L2_CID_PRIVATE_IRIS_ANTENNA,
+	V4L2_CID_PRIVATE_IRIS_RDSD_BUF,
+	V4L2_CID_PRIVATE_IRIS_PSALL,  /*0x8000014*/
+
+	/*v4l2 Tx controls*/
+	V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT,
+	V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_PS_NAME,
+	V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_RT,
+	V4L2_CID_PRIVATE_IRIS_IOVERC,
+	V4L2_CID_PRIVATE_IRIS_INTDET,
+	V4L2_CID_PRIVATE_IRIS_MPX_DCC,
+	V4L2_CID_PRIVATE_IRIS_AF_JUMP,
+	V4L2_CID_PRIVATE_IRIS_RSSI_DELTA,
+	V4L2_CID_PRIVATE_IRIS_HLSI, /*0x800001d*/
+
+	/*Diagnostic commands*/
+	V4L2_CID_PRIVATE_IRIS_SOFT_MUTE,
+	V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR,
+	V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN,
+	V4L2_CID_PRIVATE_IRIS_RIVA_PEEK,
+	V4L2_CID_PRIVATE_IRIS_RIVA_POKE,
+	V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR,
+	V4L2_CID_PRIVATE_IRIS_SSBI_PEEK,
+	V4L2_CID_PRIVATE_IRIS_SSBI_POKE,
+	V4L2_CID_PRIVATE_IRIS_TX_TONE,
+	V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS,
+	V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER, /* 0x8000028 */
+	V4L2_CID_PRIVATE_IRIS_SET_AUDIO_PATH, /* TAVARUA specific command */
+	V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION,
+	V4L2_CID_PRIVATE_IRIS_SRCH_ALGORITHM, /* TAVARUA specific command */
+	V4L2_CID_PRIVATE_IRIS_GET_SINR,
+	V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD,
+	V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD,
+	V4L2_CID_PRIVATE_SINR_THRESHOLD,
+	V4L2_CID_PRIVATE_SINR_SAMPLES,
+	V4L2_CID_PRIVATE_SPUR_FREQ,
+	V4L2_CID_PRIVATE_SPUR_FREQ_RMSSI,
+	V4L2_CID_PRIVATE_SPUR_SELECTION,
+	V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE,
+	V4L2_CID_PRIVATE_VALID_CHANNEL,
+	V4L2_CID_PRIVATE_AF_RMSSI_TH,
+	V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES,
+	V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH,
+	V4L2_CID_PRIVATE_SRCHALGOTYPE,
+	V4L2_CID_PRIVATE_CF0TH12,
+	V4L2_CID_PRIVATE_SINRFIRSTSTAGE,
+	V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE,
+
+	/*using private CIDs under userclass*/
+	V4L2_CID_PRIVATE_IRIS_READ_DEFAULT = 0x00980928,
+	V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT,
+	V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION,
+};
+
+enum iris_evt_t {
+	IRIS_EVT_RADIO_READY,
+	IRIS_EVT_TUNE_SUCC,
+	IRIS_EVT_SEEK_COMPLETE,
+	IRIS_EVT_SCAN_NEXT,
+	IRIS_EVT_NEW_RAW_RDS,
+	IRIS_EVT_NEW_RT_RDS,
+	IRIS_EVT_NEW_PS_RDS,
+	IRIS_EVT_ERROR,
+	IRIS_EVT_BELOW_TH,
+	IRIS_EVT_ABOVE_TH,
+	IRIS_EVT_STEREO,
+	IRIS_EVT_MONO,
+	IRIS_EVT_RDS_AVAIL,
+	IRIS_EVT_RDS_NOT_AVAIL,
+	IRIS_EVT_NEW_SRCH_LIST,
+	IRIS_EVT_NEW_AF_LIST,
+	IRIS_EVT_TXRDSDAT,
+	IRIS_EVT_TXRDSDONE,
+	IRIS_EVT_RADIO_DISABLED,
+	IRIS_EVT_NEW_ODA,
+	IRIS_EVT_NEW_RT_PLUS,
+	IRIS_EVT_NEW_ERT,
+};
+#endif /* __RADIO_IRIS_COMMANDS_H */
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 84789f1..53602c5 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
  *
  * This file is based on include/net/bluetooth/hci_core.h
  *
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/atomic.h>
+#include "radio-iris-commands.h"
 
 /* ---- HCI Packet structures ---- */
 #define RADIO_HCI_COMMAND_HDR_SIZE sizeof(struct radio_hci_command_hdr)
@@ -621,104 +622,6 @@
 	FM_CALIB
 };
 
-enum v4l2_cid_private_iris_t {
-	V4L2_CID_PRIVATE_IRIS_SRCHMODE = (0x08000000 + 1),
-	V4L2_CID_PRIVATE_IRIS_SCANDWELL,
-	V4L2_CID_PRIVATE_IRIS_SRCHON,
-	V4L2_CID_PRIVATE_IRIS_STATE,
-	V4L2_CID_PRIVATE_IRIS_TRANSMIT_MODE,
-	V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK,
-	V4L2_CID_PRIVATE_IRIS_REGION,
-	V4L2_CID_PRIVATE_IRIS_SIGNAL_TH,
-	V4L2_CID_PRIVATE_IRIS_SRCH_PTY,
-	V4L2_CID_PRIVATE_IRIS_SRCH_PI,
-	V4L2_CID_PRIVATE_IRIS_SRCH_CNT,
-	V4L2_CID_PRIVATE_IRIS_EMPHASIS,
-	V4L2_CID_PRIVATE_IRIS_RDS_STD,
-	V4L2_CID_PRIVATE_IRIS_SPACING,
-	V4L2_CID_PRIVATE_IRIS_RDSON,
-	V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC,
-	V4L2_CID_PRIVATE_IRIS_LP_MODE,
-	V4L2_CID_PRIVATE_IRIS_ANTENNA,
-	V4L2_CID_PRIVATE_IRIS_RDSD_BUF,
-	V4L2_CID_PRIVATE_IRIS_PSALL,  /*0x8000014*/
-
-	/*v4l2 Tx controls*/
-	V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT,
-	V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_PS_NAME,
-	V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_RT,
-	V4L2_CID_PRIVATE_IRIS_IOVERC,
-	V4L2_CID_PRIVATE_IRIS_INTDET,
-	V4L2_CID_PRIVATE_IRIS_MPX_DCC,
-	V4L2_CID_PRIVATE_IRIS_AF_JUMP,
-	V4L2_CID_PRIVATE_IRIS_RSSI_DELTA,
-	V4L2_CID_PRIVATE_IRIS_HLSI, /*0x800001d*/
-
-	/*Diagnostic commands*/
-	V4L2_CID_PRIVATE_IRIS_SOFT_MUTE,
-	V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR,
-	V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN,
-	V4L2_CID_PRIVATE_IRIS_RIVA_PEEK,
-	V4L2_CID_PRIVATE_IRIS_RIVA_POKE,
-	V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR,
-	V4L2_CID_PRIVATE_IRIS_SSBI_PEEK,
-	V4L2_CID_PRIVATE_IRIS_SSBI_POKE,
-	V4L2_CID_PRIVATE_IRIS_TX_TONE,
-	V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS,
-	V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER, /* 0x8000028 */
-	V4L2_CID_PRIVATE_IRIS_SET_AUDIO_PATH, /* TAVARUA specific command */
-	V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION,
-	V4L2_CID_PRIVATE_IRIS_SRCH_ALGORITHM, /* TAVARUA specific command */
-	V4L2_CID_PRIVATE_IRIS_GET_SINR,
-	V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD,
-	V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD,
-	V4L2_CID_PRIVATE_SINR_THRESHOLD,
-	V4L2_CID_PRIVATE_SINR_SAMPLES,
-	V4L2_CID_PRIVATE_SPUR_FREQ,
-	V4L2_CID_PRIVATE_SPUR_FREQ_RMSSI,
-	V4L2_CID_PRIVATE_SPUR_SELECTION,
-	V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE,
-	V4L2_CID_PRIVATE_VALID_CHANNEL,
-	V4L2_CID_PRIVATE_AF_RMSSI_TH,
-	V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES,
-	V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH,
-	V4L2_CID_PRIVATE_SRCHALGOTYPE,
-	V4L2_CID_PRIVATE_CF0TH12,
-	V4L2_CID_PRIVATE_SINRFIRSTSTAGE,
-	V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE,
-
-
-	/*using private CIDs under userclass*/
-	V4L2_CID_PRIVATE_IRIS_READ_DEFAULT = 0x00980928,
-	V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT,
-	V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION,
-};
-
-
-enum iris_evt_t {
-	IRIS_EVT_RADIO_READY,
-	IRIS_EVT_TUNE_SUCC,
-	IRIS_EVT_SEEK_COMPLETE,
-	IRIS_EVT_SCAN_NEXT,
-	IRIS_EVT_NEW_RAW_RDS,
-	IRIS_EVT_NEW_RT_RDS,
-	IRIS_EVT_NEW_PS_RDS,
-	IRIS_EVT_ERROR,
-	IRIS_EVT_BELOW_TH,
-	IRIS_EVT_ABOVE_TH,
-	IRIS_EVT_STEREO,
-	IRIS_EVT_MONO,
-	IRIS_EVT_RDS_AVAIL,
-	IRIS_EVT_RDS_NOT_AVAIL,
-	IRIS_EVT_NEW_SRCH_LIST,
-	IRIS_EVT_NEW_AF_LIST,
-	IRIS_EVT_TXRDSDAT,
-	IRIS_EVT_TXRDSDONE,
-	IRIS_EVT_RADIO_DISABLED,
-	IRIS_EVT_NEW_ODA,
-	IRIS_EVT_NEW_RT_PLUS,
-	IRIS_EVT_NEW_ERT,
-};
 enum emphasis_type {
 	FM_RX_EMP75 = 0x0,
 	FM_RX_EMP50 = 0x1
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index edd656c..e6a2e35 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -224,10 +224,13 @@
 		raw_spin_unlock(&base->cpu_base->lock);
 		raw_spin_lock(&new_base->cpu_base->lock);
 
-		if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) {
-			cpu = this_cpu;
+		this_cpu = smp_processor_id();
+
+		if (cpu != this_cpu && (hrtimer_check_target(timer, new_base)
+			|| !cpu_online(cpu))) {
 			raw_spin_unlock(&new_base->cpu_base->lock);
 			raw_spin_lock(&base->cpu_base->lock);
+			cpu = smp_processor_id();
 			timer->base = base;
 			goto again;
 		}
diff --git a/mm/dmapool.c b/mm/dmapool.c
index c5ab33b..da1b0f0 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -50,7 +50,6 @@
 	size_t allocation;
 	size_t boundary;
 	char name[32];
-	wait_queue_head_t waitq;
 	struct list_head pools;
 };
 
@@ -62,8 +61,6 @@
 	unsigned int offset;
 };
 
-#define	POOL_TIMEOUT_JIFFIES	((100 /* msec */ * HZ) / 1000)
-
 static DEFINE_MUTEX(pools_lock);
 
 static ssize_t
@@ -172,7 +169,6 @@
 	retval->size = size;
 	retval->boundary = boundary;
 	retval->allocation = allocation;
-	init_waitqueue_head(&retval->waitq);
 
 	if (dev) {
 		int ret;
@@ -227,7 +223,6 @@
 		memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
 #endif
 		pool_initialise_page(pool, page);
-		list_add(&page->page_list, &pool->page_list);
 		page->in_use = 0;
 		page->offset = 0;
 	} else {
@@ -315,30 +310,21 @@
 	might_sleep_if(mem_flags & __GFP_WAIT);
 
 	spin_lock_irqsave(&pool->lock, flags);
- restart:
 	list_for_each_entry(page, &pool->page_list, page_list) {
 		if (page->offset < pool->allocation)
 			goto ready;
 	}
-	page = pool_alloc_page(pool, GFP_ATOMIC);
-	if (!page) {
-		if (mem_flags & __GFP_WAIT) {
-			DECLARE_WAITQUEUE(wait, current);
 
-			__set_current_state(TASK_UNINTERRUPTIBLE);
-			__add_wait_queue(&pool->waitq, &wait);
-			spin_unlock_irqrestore(&pool->lock, flags);
+	/* pool_alloc_page() might sleep, so temporarily drop &pool->lock */
+	spin_unlock_irqrestore(&pool->lock, flags);
 
-			schedule_timeout(POOL_TIMEOUT_JIFFIES);
+	page = pool_alloc_page(pool, mem_flags);
+	if (!page)
+		return NULL;
 
-			spin_lock_irqsave(&pool->lock, flags);
-			__remove_wait_queue(&pool->waitq, &wait);
-			goto restart;
-		}
-		retval = NULL;
-		goto done;
-	}
+	spin_lock_irqsave(&pool->lock, flags);
 
+	list_add(&page->page_list, &pool->page_list);
  ready:
 	page->in_use++;
 	offset = page->offset;
@@ -348,7 +334,6 @@
 #ifdef	DMAPOOL_DEBUG
 	memset(retval, POOL_POISON_ALLOCATED, pool->size);
 #endif
- done:
 	spin_unlock_irqrestore(&pool->lock, flags);
 	return retval;
 }
@@ -435,8 +420,6 @@
 	page->in_use--;
 	*(int *)vaddr = page->offset;
 	page->offset = offset;
-	if (waitqueue_active(&pool->waitq))
-		wake_up_locked(&pool->waitq);
 	/*
 	 * Resist a temptation to do
 	 *    if (!is_page_busy(page)) pool_free_page(pool, page);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d6dd07a..69b9521 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1128,7 +1128,7 @@
 #ifdef CONFIG_CMA
 	if (migratetype == MIGRATE_MOVABLE && !zone->cma_alloc)
 		page = __rmqueue_smallest(zone, order, MIGRATE_CMA);
-	else
+	if (!page)
 #endif
 retry_reserve :
 		page = __rmqueue_smallest(zone, order, migratetype);
diff --git a/mm/readahead.c b/mm/readahead.c
index cbcbb02..728a7a3 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -261,6 +261,8 @@
 
 /*
  * Set the initial window size, round to next power of 2 and square
+ * Small size is not dependant on max value - only a one-page read is regarded
+ * as small.
  * for small size, x 4 for medium, and x 2 for large
  * for 128k (32 page) max ra
  * 1-8 page = 32k initial, > 8 page = 128k initial
@@ -269,7 +271,7 @@
 {
 	unsigned long newsize = roundup_pow_of_two(size);
 
-	if (newsize <= max / 32)
+	if (newsize <= 1)
 		newsize = newsize * 4;
 	else if (newsize <= max / 4)
 		newsize = newsize * 2;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index ca8cfaa..fd3e0dc 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -1662,7 +1662,7 @@
 	int i;
 	int ret;
 	int num_anc_slots;
-	struct anc_header *anc_head;
+	struct wcd9xxx_anc_header *anc_head;
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
 	u32 anc_writes_size = 0;
 	int anc_size_remaining;
@@ -1683,16 +1683,18 @@
 			return -ENODEV;
 		}
 
-		if (fw->size < sizeof(struct anc_header)) {
+		if (fw->size < sizeof(struct wcd9xxx_anc_header)) {
 			dev_err(codec->dev, "Not enough data\n");
 			release_firmware(fw);
 			return -ENOMEM;
 		}
 
 		/* First number is the number of register writes */
-		anc_head = (struct anc_header *)(fw->data);
-		anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
-		anc_size_remaining = fw->size - sizeof(struct anc_header);
+		anc_head = (struct wcd9xxx_anc_header *)(fw->data);
+		anc_ptr = (u32 *)((u32)fw->data +
+				  sizeof(struct wcd9xxx_anc_header));
+		anc_size_remaining = fw->size -
+				     sizeof(struct wcd9xxx_anc_header);
 		num_anc_slots = anc_head->num_anc_slots;
 
 		if (tapan->anc_slot >= num_anc_slots) {
@@ -4226,7 +4228,12 @@
 		return ret;
 	}
 
-	/* TODO: wcd9xxx_mbhc_init to enable mbhc */
+	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec,
+				WCD9XXX_MBHC_VERSION_TAPAN);
+	if (ret) {
+		pr_err("%s: mbhc init failed %d\n", __func__, ret);
+		return ret;
+	}
 
 	tapan->codec = codec;
 	for (i = 0; i < COMPANDER_MAX; i++) {
diff --git a/sound/soc/codecs/wcd9306.h b/sound/soc/codecs/wcd9306.h
index 61d47b5..fdd62d1 100644
--- a/sound/soc/codecs/wcd9306.h
+++ b/sound/soc/codecs/wcd9306.h
@@ -71,11 +71,6 @@
 	TAPAN_TX_MAX,
 };
 
-struct anc_header {
-	u32 reserved[3];
-	u32 num_anc_slots;
-};
-
 extern int tapan_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
 			     bool dapm);
 extern int tapan_hs_detect(struct snd_soc_codec *codec,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 8f63250..cc1e8eb 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -2855,7 +2855,7 @@
 	int i;
 	int ret;
 	int num_anc_slots;
-	struct anc_header *anc_head;
+	struct wcd9xxx_anc_header *anc_head;
 	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
 	u32 anc_writes_size = 0;
 	int anc_size_remaining;
@@ -2878,16 +2878,18 @@
 			return -ENODEV;
 		}
 
-		if (fw->size < sizeof(struct anc_header)) {
+		if (fw->size < sizeof(struct wcd9xxx_anc_header)) {
 			dev_err(codec->dev, "Not enough data\n");
 			release_firmware(fw);
 			return -ENOMEM;
 		}
 
 		/* First number is the number of register writes */
-		anc_head = (struct anc_header *)(fw->data);
-		anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
-		anc_size_remaining = fw->size - sizeof(struct anc_header);
+		anc_head = (struct wcd9xxx_anc_header *)(fw->data);
+		anc_ptr = (u32 *)((u32)fw->data +
+				  sizeof(struct wcd9xxx_anc_header));
+		anc_size_remaining = fw->size -
+				     sizeof(struct wcd9xxx_anc_header);
 		num_anc_slots = anc_head->num_anc_slots;
 
 		if (taiko->anc_slot >= num_anc_slots) {
@@ -4308,7 +4310,7 @@
 			.rate_max = 192000,
 			.rate_min = 8000,
 			.channels_min = 1,
-			.channels_max = 4,
+			.channels_max = 5,
 		},
 		.ops = &taiko_dai_ops,
 	},
@@ -5831,7 +5833,8 @@
 	taiko_init_slim_slave_cfg(codec);
 
 	wcd9xxx_mbhc_deinit(&taiko->mbhc);
-	ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec);
+	ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
+				WCD9XXX_MBHC_VERSION_TAIKO);
 	if (ret)
 		pr_err("%s: mbhc init failed %d\n", __func__, ret);
 	else
@@ -5991,7 +5994,8 @@
 	wcd9xxx_clsh_init(&taiko->clsh_d, &taiko->resmgr);
 
 	/* init and start mbhc */
-	ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec);
+	ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
+				WCD9XXX_MBHC_VERSION_TAIKO);
 	if (ret) {
 		pr_err("%s: mbhc init failed %d\n", __func__, ret);
 		return ret;
diff --git a/sound/soc/codecs/wcd9320.h b/sound/soc/codecs/wcd9320.h
index 36310e5..a4dbd7a 100644
--- a/sound/soc/codecs/wcd9320.h
+++ b/sound/soc/codecs/wcd9320.h
@@ -90,11 +90,6 @@
 	TAIKO_TX_MAX,
 };
 
-struct anc_header {
-	u32 reserved[3];
-	u32 num_anc_slots;
-};
-
 struct mad_audio_header {
 	u32 reserved[3];
 	u32 num_reg_cfg;
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index dc00ec6..6bc581c 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -55,6 +55,10 @@
 	struct wcd9xxx_resmgr *resmgr;
 };
 
+struct wcd9xxx_anc_header {
+	u32 reserved[3];
+	u32 num_anc_slots;
+};
 
 enum wcd9xxx_buck_volt {
 	WCD9XXX_CDC_BUCK_UNSUPPORTED = 0,
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index cbfff1c..aacc9df 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 #include "wcd9320.h"
+#include "wcd9306.h"
 #include "wcd9xxx-mbhc.h"
 #include "wcd9xxx-resmgr.h"
 
@@ -92,6 +93,9 @@
 
 #define WCD9XXX_USLEEP_RANGE_MARGIN_US 1000
 
+#define WCD9XXX_IRQ_MBHC_JACK_SWITCH_TAIKO 28
+#define WCD9XXX_IRQ_MBHC_JACK_SWITCH_TAPAN 21
+
 static bool detect_use_vddio_switch;
 
 struct wcd9xxx_mbhc_detect {
@@ -140,6 +144,64 @@
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, on << 2);
 }
 
+static int wcd9xxx_enable_mux_bias_block(struct snd_soc_codec *codec,
+					 struct wcd9xxx_mbhc *mbhc)
+{
+	switch (mbhc->mbhc_version) {
+	case WCD9XXX_MBHC_VERSION_TAIKO:
+		snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+				    0x80, 0x80);
+		break;
+	case WCD9XXX_MBHC_VERSION_TAPAN:
+		snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+				    0x80, 0x00);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int wcd9xxx_put_cfilt_fast_mode(struct snd_soc_codec *codec,
+				       struct wcd9xxx_mbhc *mbhc)
+{
+	switch (mbhc->mbhc_version) {
+	case WCD9XXX_MBHC_VERSION_TAIKO:
+		snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
+				    0x70, 0x00);
+		break;
+	case WCD9XXX_MBHC_VERSION_TAPAN:
+		snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
+				    0x70, 0x70);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int wcd9xxx_codec_specific_cal_setup(struct snd_soc_codec *codec,
+					    struct wcd9xxx_mbhc *mbhc)
+{
+	switch (mbhc->mbhc_version) {
+	case WCD9XXX_MBHC_VERSION_TAIKO:
+		snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
+				    0x04, 0x04);
+		break;
+	case WCD9XXX_MBHC_VERSION_TAPAN:
+		snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
+				    0x0C, 0x04);
+		snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0xE0, 0xE0);
+		/* Make sure the calibration is ON */
+		snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_val,
+				    0x02, 0x02);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 /* called under codec_resource_lock acquisition */
 static void wcd9xxx_pause_hs_polling(struct wcd9xxx_mbhc *mbhc)
 {
@@ -161,17 +223,24 @@
 {
 	struct snd_soc_codec *codec = mbhc->codec;
 	int mbhc_state = mbhc->mbhc_state;
+	int ret;
 
 	pr_debug("%s: enter\n", __func__);
 	if (!mbhc->polling_active) {
 		pr_debug("Polling is not active, do not start polling\n");
 		return;
 	}
-	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x84);
+
+	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x04);
+	ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
+	if (ret) {
+		pr_err("%s: Error returned, ret: %d\n", __func__, ret);
+		return;
+	}
 
 	if (!mbhc->no_mic_headset_override &&
 	    mbhc_state == MBHC_STATE_POTENTIAL) {
-		pr_debug("%s recovering MBHC state macine\n", __func__);
+		pr_debug("%s recovering MBHC state machine\n", __func__);
 		mbhc->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
 		/* set to max button press threshold */
 		snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B2_CTL, 0x7F);
@@ -347,33 +416,65 @@
 		      (mbhc->mbhc_data.v_brl >> 8) & 0xFF);
 }
 
-static void wcd9xxx_codec_switch_cfilt_mode(struct wcd9xxx_mbhc *mbhc,
+static int wcd9xxx_codec_switch_cfilt_mode(struct wcd9xxx_mbhc *mbhc,
 					    bool fast)
 {
 	struct snd_soc_codec *codec = mbhc->codec;
 	u8 reg_mode_val, cur_mode_val;
 
-	if (fast)
-		reg_mode_val = WCD9XXX_CFILT_FAST_MODE;
-	else
-		reg_mode_val = WCD9XXX_CFILT_SLOW_MODE;
+	switch (mbhc->mbhc_version) {
+	case WCD9XXX_MBHC_VERSION_TAIKO:
+		if (fast)
+			reg_mode_val = WCD9XXX_CFILT_FAST_MODE;
+		else
+			reg_mode_val = WCD9XXX_CFILT_SLOW_MODE;
 
-	cur_mode_val =
-	    snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl) & 0x40;
+		cur_mode_val =
+		    snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl) & 0x40;
 
-	if (cur_mode_val != reg_mode_val) {
-		if (mbhc->polling_active)
-			wcd9xxx_pause_hs_polling(mbhc);
-		snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40,
-				    reg_mode_val);
-		if (mbhc->polling_active)
-			wcd9xxx_start_hs_polling(mbhc);
-		pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
-			cur_mode_val, reg_mode_val);
-	} else {
-		pr_debug("%s: CFILT Value is already %x\n",
-			__func__, cur_mode_val);
+		if (cur_mode_val != reg_mode_val) {
+			if (mbhc->polling_active)
+				wcd9xxx_pause_hs_polling(mbhc);
+			snd_soc_update_bits(codec,
+					    mbhc->mbhc_bias_regs.cfilt_ctl,
+					    0x40, reg_mode_val);
+			if (mbhc->polling_active)
+				wcd9xxx_start_hs_polling(mbhc);
+			pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
+				cur_mode_val, reg_mode_val);
+		} else {
+			pr_debug("%s: CFILT Value is already %x\n",
+				 __func__, cur_mode_val);
+		}
+		break;
+	case WCD9XXX_MBHC_VERSION_TAPAN:
+		if (fast)
+			reg_mode_val = WCD9XXX_CFILT_EXT_PRCHG_EN;
+		else
+			reg_mode_val = WCD9XXX_CFILT_EXT_PRCHG_DSBL;
+
+		cur_mode_val =
+		    snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl) & 0x70;
+
+		if (cur_mode_val != reg_mode_val) {
+			if (mbhc->polling_active)
+				wcd9xxx_pause_hs_polling(mbhc);
+			snd_soc_update_bits(codec,
+					    mbhc->mbhc_bias_regs.cfilt_ctl,
+					    0x70, reg_mode_val);
+			if (mbhc->polling_active)
+				wcd9xxx_start_hs_polling(mbhc);
+			pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
+				cur_mode_val, reg_mode_val);
+		} else {
+			pr_debug("%s: CFILT Value is already %x\n",
+				__func__, cur_mode_val);
+		}
+		break;
+	default:
+		return -EINVAL;
 	}
+	return 0;
 }
 
 static void wcd9xxx_jack_report(struct wcd9xxx_mbhc *mbhc,
@@ -838,6 +939,7 @@
 	struct snd_soc_codec *codec = mbhc->codec;
 	short bias_value;
 	u8 cfilt_mode;
+	int ret;
 
 	WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
 
@@ -858,10 +960,14 @@
 
 	/* Make sure CFILT is in fast mode, save current mode */
 	cfilt_mode = snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl);
-	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00);
-
+	ret = wcd9xxx_put_cfilt_fast_mode(codec, mbhc);
+	if (ret)
+		goto gen_err;
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
-	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x84);
+	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x04);
+	ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
+	if (ret)
+		goto gen_err;
 
 	snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0x80, 0x80);
 	snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0x1F, 0x1C);
@@ -878,11 +984,14 @@
 
 	/* don't flip override */
 	bias_value = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
-	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40,
-			    cfilt_mode);
+	snd_soc_write(codec, mbhc->mbhc_bias_regs.cfilt_ctl, cfilt_mode);
 	snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
 
 	return bias_value;
+
+gen_err:
+	pr_err("%s: Error returned, ret: %d\n", __func__, ret);
+	return ret;
 }
 
 static void wcd9xxx_shutdown_hs_removal_detect(struct wcd9xxx_mbhc *mbhc)
@@ -1273,8 +1382,9 @@
 					    0);
 	}
 
-	snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc, 0x3,
-			    mbhc->mbhc_cfg->micbias);
+	if (mbhc->resmgr->reg_addr->micb_4_mbhc)
+		snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc,
+				    0x3, mbhc->mbhc_cfg->micbias);
 
 	wcd9xxx_enable_irq(mbhc->resmgr->core, WCD9XXX_IRQ_MBHC_INSERTION);
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
@@ -2580,6 +2690,7 @@
 {
 	u8 cfilt_mode;
 	u16 reg0, reg1;
+	int ret;
 	struct snd_soc_codec *codec = mbhc->codec;
 
 	pr_debug("%s: enter\n", __func__);
@@ -2596,8 +2707,9 @@
 	 * Need to restore defaults once calculation is done.
 	 */
 	cfilt_mode = snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl);
-	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
-
+	ret = wcd9xxx_put_cfilt_fast_mode(codec, mbhc);
+	if (ret)
+		goto gen_err;
 	/*
 	 * Micbias, CFILT, LDOH, MBHC MUX mode settings
 	 * to perform ADC calibration
@@ -2607,8 +2719,9 @@
 	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
 	snd_soc_update_bits(codec, WCD9XXX_A_LDO_H_MODE_1, 0x60, 0x60);
 	snd_soc_write(codec, WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0x78);
-	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
-
+	ret = wcd9xxx_codec_specific_cal_setup(codec, mbhc);
+	if (ret)
+		goto gen_err;
 	/* Pull down micbias to ground */
 	reg0 = snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg);
 	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 1, 1);
@@ -2616,7 +2729,10 @@
 	reg1 = snd_soc_read(codec, WCD9XXX_A_MAD_ANA_CTRL);
 	snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4, 1 << 0);
 	/* Connect the MUX to micbias */
-	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x82);
+	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x02);
+	ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
+	if (ret)
+		goto gen_err;
 	usleep_range(WCD9XXX_MUX_SWITCH_READY_WAIT_US,
 		     WCD9XXX_MUX_SWITCH_READY_WAIT_US +
 		     WCD9XXX_USLEEP_RANGE_MARGIN_US);
@@ -2635,7 +2751,10 @@
 	/* DCE measurment for MB voltage */
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
-	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x82);
+	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x02);
+	ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
+	if (ret)
+		goto gen_err;
 	usleep_range(100, 100);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x04);
 	usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce);
@@ -2645,7 +2764,10 @@
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
-	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x82);
+	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x02);
+	ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
+	if (ret)
+		goto gen_err;
 	usleep_range(100, 100);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02);
 	usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta);
@@ -2653,16 +2775,20 @@
 
 	/* Restore default settings. */
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
-	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40,
-			    cfilt_mode);
-
-	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x84);
+	snd_soc_write(codec, mbhc->mbhc_bias_regs.cfilt_ctl, cfilt_mode);
+	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x04);
+	ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
+	if (ret)
+		goto gen_err;
 	usleep_range(100, 100);
 
 	wcd9xxx_enable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
 	wcd9xxx_turn_onoff_rel_detection(codec, true);
 
 	pr_debug("%s: leave\n", __func__);
+
+gen_err:
+	pr_err("%s: Error returned, ret: %d\n", __func__, ret);
 }
 
 static void wcd9xxx_mbhc_setup(struct wcd9xxx_mbhc *mbhc)
@@ -2702,8 +2828,9 @@
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x78,
 			    btn_det->mbhc_nsc << 3);
 
-	snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc, 0x03,
-			    MBHC_MICBIAS2);
+	if (mbhc->resmgr->reg_addr->micb_4_mbhc)
+		snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc,
+				    0x03, MBHC_MICBIAS2);
 
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
 
@@ -2720,6 +2847,7 @@
 {
 	int ret = 0;
 	void *core = mbhc->resmgr->core;
+	int jack_irq;
 
 	if (mbhc->mbhc_cfg->gpio) {
 		ret = request_threaded_irq(mbhc->mbhc_cfg->gpio_irq, NULL,
@@ -2741,13 +2869,25 @@
 		/* Enable HPHL_10K_SW */
 		snd_soc_update_bits(mbhc->codec, WCD9XXX_A_RX_HPH_OCP_CTL,
 				    1 << 1, 1 << 1);
-		ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_JACK_SWITCH,
+
+		switch (mbhc->mbhc_version) {
+		case WCD9XXX_MBHC_VERSION_TAIKO:
+			jack_irq = WCD9XXX_IRQ_MBHC_JACK_SWITCH_TAIKO;
+			break;
+		case WCD9XXX_MBHC_VERSION_TAPAN:
+			jack_irq = WCD9XXX_IRQ_MBHC_JACK_SWITCH_TAPAN;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		ret = wcd9xxx_request_irq(core, jack_irq,
 					  wcd9xxx_mech_plug_detect_irq,
 					  "Jack Detect",
 					  mbhc);
 		if (ret)
 			pr_err("%s: Failed to request insert detect irq %d\n",
-			       __func__, WCD9XXX_IRQ_MBHC_JACK_SWITCH);
+				__func__, jack_irq);
 	}
 
 	return ret;
@@ -2977,7 +3117,7 @@
 int wcd9xxx_mbhc_start(struct wcd9xxx_mbhc *mbhc,
 		       struct wcd9xxx_mbhc_config *mbhc_cfg)
 {
-	int rc = 0;
+	int rc;
 	struct snd_soc_codec *codec = mbhc->codec;
 
 	pr_debug("%s: enter\n", __func__);
@@ -3001,10 +3141,10 @@
 	wcd9xxx_get_mbhc_micbias_regs(mbhc, &mbhc->mbhc_bias_regs);
 
 	/* Put CFILT in fast mode by default */
-	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
-			    0x40, WCD9XXX_CFILT_FAST_MODE);
-
-	if (!mbhc->mbhc_cfg->read_fw_bin)
+	rc = wcd9xxx_put_cfilt_fast_mode(codec, mbhc);
+	if (rc)
+		pr_err("%s: Error returned, ret: %d\n", __func__, rc);
+	else if (!mbhc->mbhc_cfg->read_fw_bin)
 		rc = wcd9xxx_init_and_calibrate(mbhc);
 	else
 		schedule_delayed_work(&mbhc->mbhc_firmware_dwork,
@@ -3211,7 +3351,7 @@
 			 * Switch CFILT to slow mode if MBHC CFILT is being
 			 * used.
 			 */
-			wcd9xxx_codec_switch_cfilt_mode(mbhc, false);
+			ret = wcd9xxx_codec_switch_cfilt_mode(mbhc, false);
 		break;
 	case WCD9XXX_EVENT_POST_CFILT_1_OFF:
 	case WCD9XXX_EVENT_POST_CFILT_2_OFF:
@@ -3222,7 +3362,7 @@
 			 * Switch CFILT to fast mode if MBHC CFILT is not
 			 * used anymore.
 			 */
-			wcd9xxx_codec_switch_cfilt_mode(mbhc, true);
+			ret = wcd9xxx_codec_switch_cfilt_mode(mbhc, true);
 		break;
 	/* System resume */
 	case WCD9XXX_EVENT_POST_RESUME:
@@ -3244,7 +3384,7 @@
 
 	pr_debug("%s: leave\n", __func__);
 
-	return 0;
+	return ret;
 }
 
 /*
@@ -3253,7 +3393,7 @@
  * NOTE: mbhc->mbhc_cfg is not YET configure so shouldn't be used
  */
 int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
-		      struct snd_soc_codec *codec)
+		      struct snd_soc_codec *codec, int version)
 {
 	int ret;
 	void *core;
@@ -3276,6 +3416,7 @@
 	mbhc->codec = codec;
 	mbhc->resmgr = resmgr;
 	mbhc->resmgr->mbhc = mbhc;
+	mbhc->mbhc_version = version;
 
 	if (mbhc->headset_jack.jack == NULL) {
 		ret = snd_soc_jack_new(codec, "Headset Jack", WCD9XXX_JACK_MASK,
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index fb1dfdc..300e34e 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.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
@@ -16,6 +16,8 @@
 
 #define WCD9XXX_CFILT_FAST_MODE 0x00
 #define WCD9XXX_CFILT_SLOW_MODE 0x40
+#define WCD9XXX_CFILT_EXT_PRCHG_EN 0x70
+#define WCD9XXX_CFILT_EXT_PRCHG_DSBL 0x40
 
 struct mbhc_micbias_regs {
 	u16 cfilt_val;
@@ -51,6 +53,12 @@
 	s16 v_inval_ins_high;
 };
 
+enum wcd9xxx_mbhc_version {
+	WCD9XXX_MBHC_VERSION_UNKNOWN = 0,
+	WCD9XXX_MBHC_VERSION_TAIKO,
+	WCD9XXX_MBHC_VERSION_TAPAN,
+};
+
 enum wcd9xxx_mbhc_plug_type {
 	PLUG_TYPE_INVALID = -1,
 	PLUG_TYPE_NONE,
@@ -243,6 +251,8 @@
 
 	struct notifier_block nblock;
 
+	enum wcd9xxx_mbhc_version mbhc_version;
+
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_poke;
 	struct dentry *debugfs_mbhc;
@@ -307,7 +317,7 @@
 int wcd9xxx_mbhc_start(struct wcd9xxx_mbhc *mbhc,
 		       struct wcd9xxx_mbhc_config *mbhc_cfg);
 int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
-		      struct snd_soc_codec *codec);
+		      struct snd_soc_codec *codec, int version);
 void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
 void *wcd9xxx_mbhc_cal_btn_det_mp(
 			    const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 7381677..d973c17 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -1805,7 +1805,7 @@
 		SNDRV_PCM_RATE_192000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		.channels_min = 1,
-		.channels_max = 4,
+		.channels_max = 5,
 		.rate_min =     8000,
 		.rate_max =	192000,
 	},
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index ba054bd..95c5cd7 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -24,6 +24,7 @@
 #include <sound/pcm.h>
 #include <sound/initval.h>
 #include <sound/control.h>
+#include <sound/pcm_params.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 
@@ -470,8 +471,8 @@
 		return -EPERM;
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
 			prtd->audio_client,
-			runtime->hw.period_bytes_min,
-			runtime->hw.periods_max);
+			params_period_bytes(params),
+			params_periods(params));
 	if (ret < 0) {
 		pr_err("Audio Start: Buffer Allocation failed \
 					rc = %d\n", ret);
@@ -488,7 +489,7 @@
 	dma_buf->private_data = NULL;
 	dma_buf->area = buf[0].data;
 	dma_buf->addr =  buf[0].phys;
-	dma_buf->bytes = runtime->hw.buffer_bytes_max;
+	dma_buf->bytes = params_period_bytes(params) * params_periods(params);
 	if (!dma_buf->area)
 		return -ENOMEM;
 
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index b97d9dc..08731f6 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -56,7 +56,7 @@
 	.mclk_rate = TAPAN_EXT_CLK_RATE,
 	.gpio = 0,
 	.gpio_irq = 0,
-	.gpio_level_insert = 1,
+	.gpio_level_insert = 0,
 	.detect_extn_cable = true,
 	.insert_detect = true,
 	.swap_gnd_mic = NULL,
@@ -402,11 +402,8 @@
 
 	/* start mbhc */
 	mbhc_cfg.calibration = def_tapan_mbhc_cal();
-	if (mbhc_cfg.calibration) {
-		pr_info("%s: WCD9306: Headset detection disabled\n",
-				__func__);
-	}
-
+	if (mbhc_cfg.calibration)
+		err = tapan_hs_detect(codec, &mbhc_cfg);
 	else
 		err = -ENOMEM;
 
@@ -439,8 +436,8 @@
 	S(t_ldoh, 100);
 	S(t_bg_fast_settle, 100);
 	S(t_shutdown_plug_rem, 255);
-	S(mbhc_nsa, 4);
-	S(mbhc_navg, 4);
+	S(mbhc_nsa, 2);
+	S(mbhc_navg, 128);
 #undef S
 #define S(X, Y) ((WCD9XXX_MBHC_CAL_PLUG_DET_PTR(tapan_cal)->X) = (Y))
 	S(mic_current, TAPAN_PID_MIC_5_UA);
@@ -451,13 +448,13 @@
 #undef S
 #define S(X, Y) ((WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(tapan_cal)->X) = (Y))
 	S(v_no_mic, 30);
-	S(v_hs_max, 2400);
+	S(v_hs_max, 1650);
 #undef S
 #define S(X, Y) ((WCD9XXX_MBHC_CAL_BTN_DET_PTR(tapan_cal)->X) = (Y))
 	S(c[0], 62);
 	S(c[1], 124);
 	S(nc, 1);
-	S(n_meas, 3);
+	S(n_meas, 5);
 	S(mbhc_nsc, 11);
 	S(n_btn_meas, 1);
 	S(n_btn_con, 2);
@@ -487,13 +484,13 @@
 	btn_high[7] = 330;
 	n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_READY);
 	n_ready[0] = 80;
-	n_ready[1] = 68;
+	n_ready[1] = 12;
 	n_cic = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_CIC);
 	n_cic[0] = 60;
 	n_cic[1] = 47;
 	gain = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_GAIN);
 	gain[0] = 11;
-	gain[1] = 9;
+	gain[1] = 14;
 
 	return tapan_cal;
 }
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 9ff968f..8affc09 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -193,6 +193,7 @@
 static int msm_btsco_ch = 1;
 static int msm_hdmi_rx_ch = 2;
 static int slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
+static int msm_proxy_rx_ch = 2;
 
 static struct mutex cdc_mclk_mutex;
 static struct q_clkdiv *codec_clk;
@@ -584,12 +585,15 @@
 
 static const char *const spk_function[] = {"Off", "On"};
 static const char *const slim0_rx_ch_text[] = {"One", "Two"};
-static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four",
+						"Five"};
 static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
 					"Six", "Seven", "Eight"};
 static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE"};
 static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
 					"KHZ_192"};
+static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
+	"Five",	"Six", "Seven", "Eight"};
 
 static const char *const btsco_rate_text[] = {"8000", "16000"};
 static const struct soc_enum msm_btsco_enum[] = {
@@ -854,6 +858,23 @@
 	}
 	return 0;
 }
+static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
+						msm_proxy_rx_ch);
+	ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
+	return 0;
+}
+
+static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
+	pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
+						msm_proxy_rx_ch);
+	return 1;
+}
 
 static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
@@ -870,15 +891,31 @@
 	return 0;
 }
 
-static int msm_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-			struct snd_pcm_hw_params *params)
+static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
 {
 	struct snd_interval *rate = hw_param_interval(params,
-	SNDRV_PCM_HW_PARAM_RATE);
+					SNDRV_PCM_HW_PARAM_RATE);
 
-	pr_debug("%s()\n", __func__);
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
+
+	if (channels->max < 2)
+		channels->min = channels->max = 2;
+	channels->min = channels->max = msm_proxy_rx_ch;
 	rate->min = rate->max = 48000;
+	return 0;
+}
 
+static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	rate->min = rate->max = 48000;
 	return 0;
 }
 
@@ -1146,10 +1183,11 @@
 static const struct soc_enum msm_snd_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, spk_function),
 	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
-	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+	SOC_ENUM_SINGLE_EXT(5, slim0_tx_ch_text),
 	SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
 	SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
 	SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
+	SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1169,6 +1207,8 @@
 			slim0_rx_sample_rate_get, slim0_rx_sample_rate_put),
 	SOC_ENUM_EXT("HDMI_RX Bit Format", msm_snd_enum[4],
 			hdmi_rx_bit_format_get, hdmi_rx_bit_format_put),
+	SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[6],
+			msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
 };
 
 static bool msm8974_swap_gnd_mic(struct snd_soc_codec *codec)
@@ -1809,7 +1849,7 @@
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
-		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
 		.ignore_suspend = 1,
@@ -1823,7 +1863,7 @@
 		.codec_dai_name = "msm-stub-tx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
-		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
 		.ignore_suspend = 1,
 	},
 	/* HDMI Hostless */
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 96da2f1..a2e0b87 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -1043,7 +1043,7 @@
 		goto done;
 	}
 
-	if (size <= 0) {
+	if ((size <= 0) || (size > sizeof(data))) {
 		pr_err("%s: Invalid size sent to driver: %d\n",
 			__func__, size);
 		result = -EFAULT;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index 96ddcf6..2a64ae2 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -32,16 +32,22 @@
 #include <linux/memory_alloc.h>
 #include "msm-pcm-afe-v2.h"
 
-#define MIN_PERIOD_SIZE (128 * 2)
-#define MAX_PERIOD_SIZE (128 * 2 * 2 * 6)
-#define MAX_NUM_PERIODS 384
-#define MIN_NUM_PERIODS 32
-static struct snd_pcm_hardware msm_afe_hardware = {
-	.info =			(SNDRV_PCM_INFO_MMAP |
+#define MIN_PLAYBACK_PERIOD_SIZE (128 * 2)
+#define MAX_PLAYBACK_PERIOD_SIZE (128 * 2 * 2 * 6)
+#define MIN_PLAYBACK_NUM_PERIODS (32)
+#define MAX_PLAYBACK_NUM_PERIODS (384)
+
+#define MIN_CAPTURE_PERIOD_SIZE (128 * 2 * 4)
+#define MAX_CAPTURE_PERIOD_SIZE (128 * 2 * 2 * 6 * 4)
+#define MIN_CAPTURE_NUM_PERIODS (32)
+#define MAX_CAPTURE_NUM_PERIODS (384)
+
+static struct snd_pcm_hardware msm_afe_hardware_playback = {
+	.info =                 (SNDRV_PCM_INFO_MMAP |
 				SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_INTERLEAVED),
-	.formats =              SNDRV_PCM_FMTBIT_S16_LE |
+	.formats =              SNDRV_PCM_FMTBIT_S16_LE|
 				SNDRV_PCM_FMTBIT_S24_LE,
 	.rates =                (SNDRV_PCM_RATE_8000 |
 				SNDRV_PCM_RATE_16000 |
@@ -50,13 +56,39 @@
 	.rate_max =             48000,
 	.channels_min =         1,
 	.channels_max =         6,
-	.buffer_bytes_max =     MAX_PERIOD_SIZE * MIN_NUM_PERIODS,
-	.period_bytes_min =     MIN_PERIOD_SIZE,
-	.period_bytes_max =     MAX_PERIOD_SIZE,
-	.periods_min =          MIN_NUM_PERIODS,
-	.periods_max =          MAX_NUM_PERIODS,
+	.buffer_bytes_max =     MAX_PLAYBACK_PERIOD_SIZE *
+				MIN_PLAYBACK_NUM_PERIODS,
+	.period_bytes_min =     MIN_PLAYBACK_PERIOD_SIZE,
+	.period_bytes_max =     MAX_PLAYBACK_PERIOD_SIZE,
+	.periods_min =          MIN_PLAYBACK_NUM_PERIODS,
+	.periods_max =          MAX_PLAYBACK_NUM_PERIODS,
 	.fifo_size =            0,
 };
+
+static struct snd_pcm_hardware msm_afe_hardware_capture = {
+	.info =                 (SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				SNDRV_PCM_INFO_MMAP_VALID |
+				SNDRV_PCM_INFO_INTERLEAVED),
+	.formats =              SNDRV_PCM_FMTBIT_S16_LE|
+				SNDRV_PCM_FMTBIT_S24_LE,
+	.rates =                (SNDRV_PCM_RATE_8000 |
+				SNDRV_PCM_RATE_16000 |
+				SNDRV_PCM_RATE_48000),
+	.rate_min =             8000,
+	.rate_max =             48000,
+	.channels_min =         1,
+	.channels_max =         6,
+	.buffer_bytes_max =     MAX_CAPTURE_PERIOD_SIZE *
+				MIN_CAPTURE_NUM_PERIODS,
+	.period_bytes_min =     MIN_CAPTURE_PERIOD_SIZE,
+	.period_bytes_max =     MAX_CAPTURE_PERIOD_SIZE,
+	.periods_min =          MIN_CAPTURE_NUM_PERIODS,
+	.periods_max =          MAX_CAPTURE_NUM_PERIODS,
+	.fifo_size =            0,
+};
+
+
 static enum hrtimer_restart afe_hrtimer_callback(struct hrtimer *hrt);
 static enum hrtimer_restart afe_hrtimer_rec_callback(struct hrtimer *hrt);
 
@@ -130,6 +162,8 @@
 	struct snd_pcm_substream *substream = NULL;
 	struct snd_pcm_runtime *runtime = NULL;
 	uint16_t event;
+	uint64_t period_bytes;
+	uint64_t bytes_one_sec;
 
 	if (prtd == NULL)
 		return;
@@ -143,12 +177,28 @@
 			switch (event) {
 			case AFE_EVENT_RTPORT_START: {
 				prtd->dsp_cnt = 0;
-				prtd->poll_time = ((unsigned long)((
-						snd_pcm_lib_period_bytes
-						(prtd->substream) *
-						1000 * 1000)/
-						(runtime->rate *
-						runtime->channels * 2)));
+				/* Calculate poll time.
+				 * Split steps to avoid overflow.
+				 * Poll time-time corresponding to one period
+				 * in bytes.
+				 * (Samplerate * channelcount * format) =
+				 * bytes in 1 sec.
+				 * Poll time =
+				 *	(period bytes / bytes in one sec) *
+				 *	 1000000 micro seconds.
+				 * Multiplication by 1000000 is done in two
+				 * steps to keep the accuracy of poll time.
+				 */
+				period_bytes = ((uint64_t)(
+					(snd_pcm_lib_period_bytes(
+						prtd->substream)) *
+						1000));
+				bytes_one_sec =
+					(runtime->rate * runtime->channels * 2);
+				bytes_one_sec =
+					div_u64(bytes_one_sec, 1000);
+				prtd->poll_time =
+					div_u64(period_bytes, bytes_one_sec);
 				pr_debug("prtd->poll_time: %d",
 						prtd->poll_time);
 				break;
@@ -197,6 +247,8 @@
 	struct snd_pcm_substream *substream = NULL;
 	struct snd_pcm_runtime *runtime = NULL;
 	uint16_t event;
+	uint64_t period_bytes;
+	uint64_t bytes_one_sec;
 
 	if (prtd == NULL)
 		return;
@@ -210,11 +262,22 @@
 		switch (event) {
 		case AFE_EVENT_RTPORT_START: {
 			prtd->dsp_cnt = 0;
-			prtd->poll_time = ((unsigned long)((
-				snd_pcm_lib_period_bytes(prtd->substream)
-					* 1000 * 1000)/(runtime->rate
-					* runtime->channels * 2)));
-			pr_debug("prtd->poll_time : %d", prtd->poll_time);
+			/* Calculate poll time. Split steps to avoid overflow.
+			 * Poll time-time corresponding to one period in bytes.
+			 * (Samplerate * channelcount * format)=bytes in 1 sec.
+			 * Poll time =  (period bytes / bytes in one sec) *
+			 * 1000000 micro seconds.
+			 * Multiplication by 1000000 is done in two steps to
+			 * keep the accuracy of poll time.
+			 */
+			period_bytes = ((uint64_t)(
+				(snd_pcm_lib_period_bytes(prtd->substream)) *
+				 1000));
+			bytes_one_sec = (runtime->rate * runtime->channels * 2);
+			bytes_one_sec = div_u64(bytes_one_sec , 1000);
+			prtd->poll_time =
+				div_u64(period_bytes, bytes_one_sec);
+			pr_debug("prtd->poll_time : %d\n", prtd->poll_time);
 			break;
 		}
 		case AFE_EVENT_RTPORT_STOP:
@@ -326,7 +389,11 @@
 
 	mutex_lock(&prtd->lock);
 
-	runtime->hw = msm_afe_hardware;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		runtime->hw = msm_afe_hardware_playback;
+	else
+		runtime->hw = msm_afe_hardware_capture;
+
 	prtd->substream = substream;
 	runtime->private_data = prtd;
 	prtd->audio_client = q6afe_audio_client_alloc(prtd);
@@ -355,6 +422,18 @@
 	if (ret < 0)
 		pr_err("snd_pcm_hw_constraint_integer failed\n");
 
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		ret = snd_pcm_hw_constraint_minmax(runtime,
+			SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+			MIN_CAPTURE_NUM_PERIODS * MIN_CAPTURE_PERIOD_SIZE,
+			MAX_CAPTURE_NUM_PERIODS * MAX_CAPTURE_PERIOD_SIZE);
+
+		if (ret < 0) {
+			pr_err("constraint for buffer bytes min max ret = %d\n",
+			      ret);
+		}
+	}
+
 	return 0;
 }
 
@@ -497,10 +576,18 @@
 		dir = IN;
 	else
 		dir = OUT;
+
 	rc = q6afe_audio_client_buf_alloc_contiguous(dir,
-			prtd->audio_client,
-			runtime->hw.period_bytes_min,
-			runtime->hw.periods_max);
+		prtd->audio_client,
+		(params_buffer_bytes(params) / params_periods(params)),
+		params_periods(params));
+	pr_debug("params_buffer_bytes(params) = %d\n",
+			(params_buffer_bytes(params)));
+	pr_debug("params_periods(params) = %d\n",
+			(params_periods(params)));
+	pr_debug("params_periodsize(params) = %d\n",
+		(params_buffer_bytes(params) / params_periods(params)));
+
 	if (rc < 0) {
 		pr_err("Audio Start: Buffer Allocation failed rc = %d\n", rc);
 		mutex_unlock(&prtd->lock);
@@ -519,14 +606,18 @@
 	dma_buf->private_data = NULL;
 	dma_buf->area = buf[0].data;
 	dma_buf->addr = buf[0].phys;
-	dma_buf->bytes = runtime->hw.buffer_bytes_max;
+
+	dma_buf->bytes = params_buffer_bytes(params);
+
 	if (!dma_buf->area) {
 		pr_err("%s:MSM AFE physical memory allocation failed\n",
 							__func__);
 		mutex_unlock(&prtd->lock);
 		return -ENOMEM;
 	}
-	memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max);
+
+	memset(dma_buf->area, 0,  params_buffer_bytes(params));
+
 	prtd->dma_addr = (u32) dma_buf->addr;
 
 	mutex_unlock(&prtd->lock);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index c8de460..a163f6a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -24,6 +24,7 @@
 #include <sound/pcm.h>
 #include <sound/initval.h>
 #include <sound/control.h>
+#include <sound/pcm_params.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 
@@ -493,8 +494,8 @@
 		return -EPERM;
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
 			prtd->audio_client,
-			runtime->hw.period_bytes_min,
-			runtime->hw.periods_max);
+			params_period_bytes(params),
+			params_periods(params));
 	if (ret < 0) {
 		pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
 						ret);
@@ -511,7 +512,7 @@
 	dma_buf->private_data = NULL;
 	dma_buf->area = buf[0].data;
 	dma_buf->addr =  buf[0].phys;
-	dma_buf->bytes = runtime->hw.buffer_bytes_max;
+	dma_buf->bytes = params_period_bytes(params) * params_periods(params);
 	if (!dma_buf->area)
 		return -ENOMEM;
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 4df66d0..25bb72f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -472,6 +472,7 @@
 
 	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);
+	voc_set_tty_mode(voc_get_session_id(VOLTE_SESSION_NAME), tty_mode);
 
 	return 0;
 }
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 09d6a0f..9d6896e 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -944,7 +944,7 @@
 
 	i = port_id - SLIMBUS_0_RX;
 	if (i < 0 || i > ARRAY_SIZE(afe_ports_mad_type)) {
-		pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
+		pr_debug("%s: Non Slimbus port_id 0x%x\n", __func__, port_id);
 		return MAD_HW_NONE;
 	}
 	return (enum afe_mad_type) atomic_read(&afe_ports_mad_type[i]);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index fffd0b3..c2b824f 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2866,6 +2866,7 @@
 		if (buf_node->buf_addr_lsw == buf_add) {
 			list_del(&buf_node->list);
 			kfree(buf_node);
+			break;
 		}
 	}
 	rc = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index a417b26..80bc4f9 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -4116,6 +4116,11 @@
 			if (v != NULL)
 				v->voc_state = VOC_ERROR;
 
+			session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+			v = voice_get_session(session_id);
+			if (v != NULL)
+				v->voc_state = VOC_ERROR;
+
 			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
 			v = voice_get_session(session_id);
 			if (v != NULL)
@@ -4250,6 +4255,11 @@
 			if (v != NULL)
 				v->voc_state = VOC_ERROR;
 
+			session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+			v = voice_get_session(session_id);
+			if (v != NULL)
+				v->voc_state = VOC_ERROR;
+
 			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
 			v = voice_get_session(session_id);
 			if (v != NULL)
@@ -4515,6 +4525,11 @@
 			if (v != NULL)
 				v->voc_state = VOC_ERROR;
 
+			session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+			v = voice_get_session(session_id);
+			if (v != NULL)
+				v->voc_state = VOC_ERROR;
+
 			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
 			v = voice_get_session(session_id);
 			if (v != NULL)