Merge "kernel: rng: Add IOCTL support to disable bus bandwidth"
diff --git a/Documentation/arm/msm/msm_sharedmem.txt b/Documentation/arm/msm/msm_sharedmem.txt
new file mode 100644
index 0000000..d9c939e
--- /dev/null
+++ b/Documentation/arm/msm/msm_sharedmem.txt
@@ -0,0 +1,115 @@
+Introduction
+============
+
+This is a new platform driver for newly introduced UIO devices
+to facilitate clients in Userspace.
+
+Hardware description
+====================
+This driver does not implement any specific hardware driver.
+
+Software description
+====================
+
+Design
+======
+
+The goal of this driver is to ensure there is no security lapse in the
+Userspace clients' functionality. This new driver uses the existing
+UIO framework to facilitate the clients to be able to memory map their
+respective allotted shared memory address in the client's address space.
+
+				  |
+    Userspace			  |		Kernel space
+ +--------------+	+---------------+	+---------------+
+ |   Client	|	|  Shared	|	|  shrdmem_uio	|
+ |		<------->    Memory	<------->  driver	|
+ +--------------+	+---------------+	+---------------+
+				  |
+				  |
+
+The shared memory (a transport buffer) address is unique for each
+individual client and is made available to the driver via device tree.
+
+For a given client the probe would be called once in the shrdmem_uio driver.
+This driver would parse the device tree and register a new UIO device with kernel
+available under /dev/uioX (where X would start from zero, being serially
+incremented for the next UIO device probed)
+
+The client in Userspace would be able to access the respective UIO device
+under the sysfs entry(/sys/class/uio/uioX) upon verifying the name and version
+of the device under this sysfs node. Once verified it could access the physical
+address under /sys/class/uio/uioX/maps/map0/addr
+
+The client would request for memory mapping which would be taken care of in the
+kernel space by the UIO framework. No explicit mmap() implementation required by
+the shrdmem_uio driver.
+
+Power Management
+================
+Does not implement any power management.
+
+SMP/multi-core
+==============
+
+The platform driver would be loaded/probed once per client.
+DTS files will be looked up for shared memory addresses and sizes for all the clients.
+The UIO char device will be created under /dev/uioX.
+
+This being one time activity for a given client it does not require SMP/multi-core safety.
+
+Security
+========
+
+The devices (/dev/uioX) would have permission checks for restricted access
+
+Performance
+===========
+
+None.
+
+Interface
+=========
+
+This driver does not export any APIs for kernel.
+Android user space can access the shared memory by mmaping it.
+
+Driver parameters
+=================
+
+None.
+
+Config options
+==============
+
+None.
+
+Dependencies
+============
+
+The only dependency is the kernel device tree files for the
+Userspace client details.
+
+User space utilities
+====================
+This driver communicates with the following user space clients/utilities:
+
+Remote File System:
+ - Based on Qualcomm Messaging Interface (QMI)
+ - This service enables the modules on the MSM modem processor to
+   read data from and write data to the embedded multimedia card (eMMC),
+   which is solely controlled by the applications processor.
+
+Remote File System Access (QMI_RFSA):
+ - Based on Qualcomm Messaging Interface (QMI)
+ - This service provides access from the Hexagon processor to a High-Level
+   Operating Sytem (HLOS) file system
+Other
+=====
+
+None.
+
+Known issues
+============
+
+None.
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
index d9a0d59..f969e2f 100644
--- a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
+++ b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
@@ -40,6 +40,8 @@
 - qcom,saw2-spm-cmd-wfi: The WFI command sequence
 - qcom,saw2-spm-cmd-ret: The Retention command sequence
 - qcom,saw2-spm-cmd-spc: The Standalone PC command sequence
+- qcom,saw2-spm-cmd-pc-no-rpm: The Power Collapse command sequence where APPS
+	proc won't inform the RPM.
 - qcom,saw2-spm-cmd-pc: The Power Collapse command sequence
 - qcom,saw2-spm-cmd-gdhs: L2 GDHS command sequence
 - qcom,L2-spm-is-apcs-master: Boolean indicates if the target uses L2 SAW to
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 5425c92..7d8fe0a 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -93,6 +93,16 @@
 					set, the charger ovp status is monitored in software.
 - qcom,ext-ovp-present			Indicates if an external OVP exists which reduces the
 					overall input resistance of the charge path.
+- qcom,ibat-calibration-enabled		Indicates if ibat calibration is enabled. This is
+					required for devices which have a ibat trim error
+					causing ibatmax to go out of spec.
+- qcom,power-stage-reduced		Indicates if power stage workaround is enabled. This work
+					around reduces the power stage segments while charging
+					under high load during low battery voltages. It's for
+					improving IADC accuracy while board has a bad layout.
+- qcom,use-external-rsense		A boolean that controls whether BMS will use
+					an external sensor resistor instead of the default
+					RDS of the batfet.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
diff --git a/Documentation/devicetree/bindings/uio/msm_sharedmem.txt b/Documentation/devicetree/bindings/uio/msm_sharedmem.txt
new file mode 100644
index 0000000..5af50da
--- /dev/null
+++ b/Documentation/devicetree/bindings/uio/msm_sharedmem.txt
@@ -0,0 +1,13 @@
+msm_sharedmem provides the shared memory addresses for various clients in user-space
+
+Required properties:
+- compatible:		Must be "qcom,sharedmem-uio"
+- reg : The address and size of the shared memory. The address/sizes may vary.
+- reg-names : indicates various client-names.
+
+Example:
+	msm_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0dc80000 0x00180000>,
+		reg-names = "rmtfs";
+	};
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index e7eae76..714311e 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -86,6 +86,11 @@
 	for detection of dp line transition during VDD minimization.
 - qcom,hsusb-otg-dmsehv-int: If present, indicates mpm interrupt to be configured
 	for detection of dm line transition during VDD minimization.
+- qcom,ahb-async-bridge-bypass: If present, indicates that enable AHB2AHB By Pass
+	mode with device controller for better throughput. With this mode, USB Core
+	runs using PNOC clock and synchronous to it. Hence it is must to have proper
+	"qcom,msm_bus,vectors" to have high bus frequency. User shouldn't try to
+	enable this feature without proper bus voting.
 
 Example HSUSB OTG controller device node :
 	usb@f9690000 {
@@ -176,12 +181,19 @@
 - qcom,android-usb-cdrom : if this property is present then device creates
   a new LUN as CD-ROM
 - qcom,android-usb-internal-ums : if this property is present then device
-  creates a new LUN as internal usb mass storage
+  creates a new LUN as internal usb mass storage.
+- qcom,streaming-func : add list of usb function name. If mention usb function
+  is being enable as part of USB composition, streaming mode is enable with
+  usb device controller to get better throughput. NOTE: Inverted CRC and
+  turnaround timeout is observed on enabling streaming. Hence it is required
+  to see these errors and number of erros on enabling this at USB level to make
+  final decision to enable this feature or not.
 Example Android USB device node :
 	android_usb@fc42b0c8 {
 		compatible = "qcom,android-usb";
 		reg = <0xfc42b0c8 0xc8>;
 		qcom,android-usb-swfi-latency = <1>;
+		qcom,streaming-func = "rndis","mtp";
 	};
 
 
diff --git a/arch/arm/boot/dts/apq8026-v1-cdp.dts b/arch/arm/boot/dts/apq8026-v1-cdp.dts
index d7e283b..b9ec6f9 100644
--- a/arch/arm/boot/dts/apq8026-v1-cdp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-cdp.dts
@@ -13,7 +13,7 @@
 
 /dts-v1/;
 /include/ "apq8026-v1.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-720p-cdp.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026 CDP";
diff --git a/arch/arm/boot/dts/apq8026-v1-mtp.dts b/arch/arm/boot/dts/apq8026-v1-mtp.dts
index d24875c..c2fc72c 100644
--- a/arch/arm/boot/dts/apq8026-v1-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-mtp.dts
@@ -13,7 +13,7 @@
 
 /dts-v1/;
 /include/ "apq8026-v1.dtsi"
-/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-720p-mtp.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026 MTP";
diff --git a/arch/arm/boot/dts/apq8026-v1-xpm.dts b/arch/arm/boot/dts/apq8026-v1-xpm.dts
index f69511b..b435018 100644
--- a/arch/arm/boot/dts/apq8026-v1-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v1-xpm.dts
@@ -13,7 +13,7 @@
 
 /dts-v1/;
 /include/ "apq8026-v1.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-720p-cdp.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026 XPM";
diff --git a/arch/arm/boot/dts/apq8026-v2-cdp.dts b/arch/arm/boot/dts/apq8026-v2-1080p-cdp.dts
similarity index 91%
copy from arch/arm/boot/dts/apq8026-v2-cdp.dts
copy to arch/arm/boot/dts/apq8026-v2-1080p-cdp.dts
index cb68779..5294628 100644
--- a/arch/arm/boot/dts/apq8026-v2-cdp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-1080p-cdp.dts
@@ -13,10 +13,10 @@
 
 /dts-v1/;
 /include/ "apq8026-v2.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-1080p-cdp.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026v2 CDP";
 	compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
-	qcom,board-id = <1 0>;
+	qcom,board-id = <1 2>;
 };
diff --git a/arch/arm/boot/dts/apq8026-v2-mtp.dts b/arch/arm/boot/dts/apq8026-v2-1080p-mtp.dts
similarity index 91%
copy from arch/arm/boot/dts/apq8026-v2-mtp.dts
copy to arch/arm/boot/dts/apq8026-v2-1080p-mtp.dts
index 40856c8..0ea98f5 100644
--- a/arch/arm/boot/dts/apq8026-v2-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-1080p-mtp.dts
@@ -13,10 +13,10 @@
 
 /dts-v1/;
 /include/ "apq8026-v2.dtsi"
-/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-1080p-mtp.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026v2 MTP";
 	compatible = "qcom,apq8026-mtp", "qcom,apq8026", "qcom,mtp";
-	qcom,board-id = <8 0>;
+	qcom,board-id = <8 2>;
 };
diff --git a/arch/arm/boot/dts/apq8026-v2-cdp.dts b/arch/arm/boot/dts/apq8026-v2-720p-cdp.dts
similarity index 95%
rename from arch/arm/boot/dts/apq8026-v2-cdp.dts
rename to arch/arm/boot/dts/apq8026-v2-720p-cdp.dts
index cb68779..cb2226a 100644
--- a/arch/arm/boot/dts/apq8026-v2-cdp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-720p-cdp.dts
@@ -13,7 +13,7 @@
 
 /dts-v1/;
 /include/ "apq8026-v2.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-720p-cdp.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026v2 CDP";
diff --git a/arch/arm/boot/dts/apq8026-v2-mtp.dts b/arch/arm/boot/dts/apq8026-v2-720p-mtp.dts
similarity index 95%
rename from arch/arm/boot/dts/apq8026-v2-mtp.dts
rename to arch/arm/boot/dts/apq8026-v2-720p-mtp.dts
index 40856c8..439b3d7 100644
--- a/arch/arm/boot/dts/apq8026-v2-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-720p-mtp.dts
@@ -13,7 +13,7 @@
 
 /dts-v1/;
 /include/ "apq8026-v2.dtsi"
-/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-720p-mtp.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026v2 MTP";
diff --git a/arch/arm/boot/dts/apq8026-v2-xpm.dts b/arch/arm/boot/dts/apq8026-v2-xpm.dts
index 324516d..3133424 100644
--- a/arch/arm/boot/dts/apq8026-v2-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v2-xpm.dts
@@ -13,7 +13,7 @@
 
 /dts-v1/;
 /include/ "apq8026-v2.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-720p-cdp.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026v2 XPM";
diff --git a/arch/arm/boot/dts/batterydata-qrd-4v2-2200mah.dtsi b/arch/arm/boot/dts/batterydata-qrd-4v2-2200mah.dtsi
new file mode 100644
index 0000000..53aa781
--- /dev/null
+++ b/arch/arm/boot/dts/batterydata-qrd-4v2-2200mah.dtsi
@@ -0,0 +1,105 @@
+/* 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.
+ */
+
+qcom,qrd-4v2-2200mah-data {
+	qcom,default-rbatt-mohm = <163>;
+	qcom,max-voltage-uv = <4200>;
+	qcom,fcc-mah = <2200>;
+	qcom,rbatt-capacitive-mohm = <0>;
+	qcom,v-cutoff-uv = <3400000>;
+	qcom,chg-term-ua = <100000>;
+	qcom,batt-id-kohm = <10>;
+	qcom,flat-ocv-threshold-uv = <3800000>;
+
+	qcom,fcc-temp-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-data = <2167 2179 2234 2178 2164>;
+	};
+
+	qcom,pc-temp-ocv-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-row-legend = <100 95 90 85 80>,
+				<75 70 65 60 55>,
+				<50 45 40 35 30>,
+				<25 20 15 10 9>,
+				<8 7 6 5 4>,
+				<3 2 1 0>;
+		qcom,lut-data = <4188 4184 4199 4176 4170>,
+				<4109 4124 4145 4124 4118>,
+				<4051 4082 4097 4077 4072>,
+				<3963 4024 4055 4034 4029>,
+				<3920 3971 4002 3993 3989>,
+				<3880 3932 3963 3957 3952>,
+				<3846 3892 3920 3913 3910>,
+				<3822 3859 3881 3873 3871>,
+				<3805 3834 3851 3845 3844>,
+				<3790 3813 3828 3823 3822>,
+				<3777 3796 3808 3805 3803>,
+				<3764 3784 3792 3790 3788>,
+				<3750 3775 3778 3777 3774>,
+				<3736 3766 3766 3761 3751>,
+				<3721 3752 3755 3745 3732>,
+				<3704 3733 3737 3729 3716>,
+				<3684 3707 3713 3707 3694>,
+				<3655 3686 3688 3682 3672>,
+				<3598 3661 3677 3671 3659>,
+				<3585 3655 3673 3669 3656>,
+				<3571 3644 3664 3663 3650>,
+				<3551 3626 3643 3648 3631>,
+				<3523 3598 3609 3618 3600>,
+				<3489 3561 3565 3578 3561>,
+				<3445 3514 3510 3529 3512>,
+				<3389 3453 3440 3468 3450>,
+				<3313 3372 3345 3386 3366>,
+				<3207 3252 3209 3262 3239>,
+				<3000 3000 3000 3000 3000>;
+	};
+
+	qcom,rbatt-sf-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-row-legend = <100 95 90 85 80>,
+				<75 70 65 60 55>,
+				<50 45 40 35 30>,
+				<25 20 15 10 9>,
+				<8 7 6 5 4>,
+				<3 2 1 0>;
+		qcom,lut-data = <1371 224 100 79 74>,
+				<1358 242 100 80 74>,
+				<1358 242 103 80 74>,
+				<1195 257 107 82 75>,
+				<1171 256 112 84 77>,
+				<1149 250 119 89 79>,
+				<1144 232 114 90 79>,
+				<1150 225 101 83 76>,
+				<1175 227 98 81 76>,
+				<1210 232 98 82 76>,
+				<1260 236 98 82 77>,
+				<1329 242 100 84 77>,
+				<1421 251 100 86 79>,
+				<1536 263 101 81 76>,
+				<1671 280 100 80 74>,
+				<1830 304 100 81 75>,
+				<2036 338 101 82 76>,
+				<2326 443 103 82 76>,
+				<2788 708 112 88 79>,
+				<2890 747 115 90 80>,
+				<2755 676 117 89 79>,
+				<2750 716 118 87 78>,
+				<2916 765 119 87 79>,
+				<3336 833 123 89 80>,
+				<4214 920 133 92 81>,
+				<5615 1031 151 96 83>,
+				<7923 1188 192 104 89>,
+				<13252 1886 585 137 122>,
+				<43764 20050 47711 3680 16847>;
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
index 7e63014..8f94502 100755
--- a/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
@@ -124,7 +124,7 @@
 		qcom,mdss-dsi-panel-timings = [97 23 17 00 4B 53 1C 27 27 03 04 00];
 		qcom,mdss-dsi-t-clk-post = <0x04>;
 		qcom,mdss-dsi-t-clk-pre = <0x1b>;
-		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-min-level = <26>;
 		qcom,mdss-dsi-bl-max-level = <255>;
 		qcom,mdss-dsi-dma-trigger = <4>;
 		qcom,mdss-dsi-mdp-trigger = <0>;
diff --git a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
index 9477c56..393419b 100644
--- a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
@@ -256,7 +256,7 @@
 		qcom,mdss-dsi-panel-timings = [8B 1F 14 00 45 4A 19 23 23 03 04 00];
 		qcom,mdss-dsi-t-clk-post = <0x04>;
 		qcom,mdss-dsi-t-clk-pre = <0x1b>;
-		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-min-level = <26>;
 		qcom,mdss-dsi-bl-max-level = <255>;
 		qcom,mdss-dsi-dma-trigger = <4>;
 		qcom,mdss-dsi-mdp-trigger = <0>;
diff --git a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
index bb8389f..b510e6b 100644
--- a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
@@ -30,9 +30,9 @@
 		qcom,mdss-dsi-h-back-porch = <24>;
 		qcom,mdss-dsi-h-pulse-width = <14>;
 		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <15>;
-		qcom,mdss-dsi-v-front-porch = <12>;
-		qcom,mdss-dsi-v-pulse-width = <10>;
+		qcom,mdss-dsi-v-back-porch = <14>;
+		qcom,mdss-dsi-v-front-porch = <11>;
+		qcom,mdss-dsi-v-pulse-width = <2>;
 		qcom,mdss-dsi-h-left-border = <0>;
 		qcom,mdss-dsi-h-right-border = <0>;
 		qcom,mdss-dsi-v-top-border = <0>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index b540063..0678559 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -209,7 +209,9 @@
 		qcom,resume-soc = <99>;
 		qcom,tchg-mins = <150>;
 		qcom,chg-vadc = <&pm8941_vadc>;
+		qcom,chg-iadc = <&pm8941_iadc>;
 		qcom,chg-adc_tm = <&pm8941_adc_tm>;
+		qcom,ibat-calibration-enabled;
 
 		qcom,chgr@1000 {
 			status = "disabled";
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-1080p-cdp.dtsi
similarity index 91%
copy from arch/arm/boot/dts/msm8226-cdp.dtsi
copy to arch/arm/boot/dts/msm8226-1080p-cdp.dtsi
index 3ebe225..bb66538 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-1080p-cdp.dtsi
@@ -27,13 +27,37 @@
 			vcc_i2c-supply = <&pm8226_lvs1>;
 			synaptics,reset-gpio = <&msmgpio 16 0x00>;
 			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
-			synaptics,button-map = <139 102 158>;
+			synaptics,display-coords = <0 0 1079 1919>;
 			synaptics,i2c-pull-up;
 			synaptics,power-down;
 			synaptics,disable-gpios;
 		};
 	};
 
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "synaptics_rmi4_i2c";
+		qcom,disp-maxx = <1079>;
+		qcom,disp-maxy = <1919>;
+		qcom,panel-maxx = <1079>;
+		qcom,panel-maxy = <2084>;
+		qcom,key-codes = <158 139 102 217>;
+	};
+
+	i2c@f9925000 { /* BLSP1 QUP3 */
+		nfc-nci@0e {
+			compatible = "qcom,nfc-nci";
+			reg = <0x0e>;
+			qcom,irq-gpio = <&msmgpio 21 0x00>;
+			qcom,dis-gpio = <&msmgpio 20 0x00>;
+			qcom,clk-src = "BBCLK2";
+			qcom,clk-en-gpio = <&msmgpio 0 0x00>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <21 0>;
+			qcom,clk-gpio = <&pm8226_gpios 3 0>;
+		};
+	};
+
 	gpio_keys {
 		compatible = "gpio-keys";
 		input-name = "gpio-keys";
@@ -370,6 +394,11 @@
 	};
 
 	gpio@c200 { /* GPIO 3 */
+		qcom,mode = <0>;		/* QPNP_PIN_MODE_DIG_IN */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;
 	};
 
 	gpio@c300 { /* GPIO 4 */
@@ -464,9 +493,10 @@
 };
 
 &mdss_dsi0 {
-	qcom,dsi-pref-prim-pan = <&dsi_nt35590_720_vid>;
+	qcom,dsi-pref-prim-pan = <&dsi_jdi_1080_vid>;
+	qcom,platform-enable-gpio = <&msmgpio 109 0>;
 };
 
-&dsi_nt35590_720_vid {
+&dsi_jdi_1080_vid {
 	qcom,cont-splash-enabled;
 };
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-1080p-mtp.dtsi
similarity index 96%
copy from arch/arm/boot/dts/msm8226-mtp.dtsi
copy to arch/arm/boot/dts/msm8226-1080p-mtp.dtsi
index a4bd8fd..31624de 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-1080p-mtp.dtsi
@@ -27,13 +27,23 @@
 			vcc_i2c-supply = <&pm8226_lvs1>;
 			synaptics,reset-gpio = <&msmgpio 16 0x00>;
 			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
-			synaptics,button-map = <139 102 158>;
+			synaptics,display-coords = <0 0 1079 1919>;
 			synaptics,i2c-pull-up;
 			synaptics,power-down;
 			synaptics,disable-gpios;
 		};
 	};
 
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "synaptics_rmi4_i2c";
+		qcom,disp-maxx = <1079>;
+		qcom,disp-maxy = <1919>;
+		qcom,panel-maxx = <1079>;
+		qcom,panel-maxy = <2084>;
+		qcom,key-codes = <158 139 102 217>;
+	};
+
 	i2c@f9925000 { /* BLSP1 QUP3 */
 		nfc-nci@0e {
 			compatible = "qcom,nfc-nci";
@@ -476,12 +486,12 @@
 
 &pm8226_bms {
 	status = "ok";
+	qcom,battery-data = <&mtp_batterydata>;
 	qcom,enable-fcc-learning;
 	qcom,min-fcc-learning-soc = <20>;
 	qcom,min-fcc-ocv-pc = <30>;
 	qcom,min-fcc-learning-samples = <5>;
 	qcom,fcc-resolution = <10>;
-	qcom,battery-data = <&mtp_batterydata>;
 };
 
 &pm8226_chg {
@@ -497,13 +507,13 @@
 
 &mdss_mdp {
 	qcom,mdss-pref-prim-intf = "dsi";
-	batfet-supply = <&pm8226_chg_batif>;
 };
 
 &mdss_dsi0 {
-	qcom,dsi-pref-prim-pan = <&dsi_nt35590_720_vid>;
+	qcom,dsi-pref-prim-pan = <&dsi_jdi_1080_vid>;
+	qcom,platform-enable-gpio = <&msmgpio 109 0>;
 };
 
-&dsi_nt35590_720_vid {
+&dsi_jdi_1080_vid {
 	qcom,cont-splash-enabled;
 };
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-720p-cdp.dtsi
similarity index 99%
rename from arch/arm/boot/dts/msm8226-cdp.dtsi
rename to arch/arm/boot/dts/msm8226-720p-cdp.dtsi
index 3ebe225..9a1eb36 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-720p-cdp.dtsi
@@ -28,6 +28,7 @@
 			synaptics,reset-gpio = <&msmgpio 16 0x00>;
 			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
+			synaptics,fw-image-name = "PR1468813.img";
 			synaptics,i2c-pull-up;
 			synaptics,power-down;
 			synaptics,disable-gpios;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-720p-mtp.dtsi
similarity index 99%
rename from arch/arm/boot/dts/msm8226-mtp.dtsi
rename to arch/arm/boot/dts/msm8226-720p-mtp.dtsi
index a4bd8fd..7f4f8fc 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-720p-mtp.dtsi
@@ -28,6 +28,7 @@
 			synaptics,reset-gpio = <&msmgpio 16 0x00>;
 			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
+			synaptics,fw-image-name = "PR1468813.img";
 			synaptics,i2c-pull-up;
 			synaptics,power-down;
 			synaptics,disable-gpios;
diff --git a/arch/arm/boot/dts/msm8226-mdss-panels.dtsi b/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
index eeec175..0731a9a 100644
--- a/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
@@ -16,3 +16,4 @@
 /include/ "dsi-panel-nt35596-1080p-video.dtsi"
 /include/ "dsi-panel-nt35590-720p-cmd.dtsi"
 /include/ "dsi-panel-ssd2080m-720p-video.dtsi"
+/include/ "dsi-panel-jdi-1080p-video.dtsi"
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 3e2507ff..e2891d1 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -36,7 +36,7 @@
 		qcom,mdss-wb-off = <0x00011100 0x00013100>;
 		qcom,mdss-intf-off = <0x00000000 0x00021300>;
 		qcom,mdss-rot-block-size = <64>;
-		qcom,mdss-smp-mb-per-pipe = <2>;
+		qcom,mdss-smp-mb-per-pipe = <4>;
 		vdd-cx-supply = <&pm8226_s1_corner>;
 
 		qcom,vbif-settings = <0x004 0x00000001>,
diff --git a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
index 76bd262..2e32ac4 100755
--- a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
@@ -85,25 +85,25 @@
 			goodix,button-map= <158 102 139>;
 			goodix,product-id = "915";
 			goodix,cfg-data0 = [
-				41 D0 02 00 05 05 35 01 01 0F
-				2D 06 50 32 03 05 00 00 00 00
-				00 00 05 18 1A 1E 14 8C 0E 0E
-				3F 3D 2A 09 00 00 00 99 04 1D
-				00 00 00 00 00 00 00 00 00 00
-				00 32 6E 94 D5 01 05 00 00 04
-				CE 36 00 B5 3F 00 9E 4A 00 8B
-				57 00 7C 65 00 7C 10 38 68 00
-				56 50 35 66 66 27 00 00 00 00
+				41 D0 02 00 05 05 35 11 01 0F
+				2D 06 50 32 03 02 00 00 00 00
+				00 00 05 18 1A 1E 14 8C 2E 0E
+				59 5B B2 04 00 00 00 99 03 11
+				00 1C 00 00 00 00 00 00 00 00
+				00 53 A6 94 C5 01 05 00 00 08
+				7F 59 00 71 66 00 64 75 00 58
+				87 00 4E 9B 00 4E 10 38 68 00
+				56 45 30 66 66 27 00 00 00 00
 				00 00 00 00 00 00 00 00 00 00
 				00 00 00 00 00 00 00 00 00 00
 				00 00 02 04 06 08 0A 0C 0E 10
-				12 14 16 18 1A 1C 00 00 00 00
-				00 00 00 00 00 00 00 00 00 00
-				00 00 00 02 04 06 08 0A 0C 0F
+				12 14 16 18 1A 1C FF FF FF FF
+				FF FF FF FF FF FF FF FF FF FF
+				FF FF 00 02 04 06 08 0A 0C 0F
 				10 12 13 14 16 18 1C 1D 1E 1F
-				20 21 22 24 26 28 29 2A 00 00
-				00 FF FF FF FF FF FF FF FF FF
-				FF FF FF FF A3 01];
+				20 21 22 24 26 28 29 2A FF FF
+				FF FF FF FF FF FF FF FF FF FF
+				FF FF FF FF 03 01];
 			goodix,cfg-data1 = [
 				41 D0 02 00 05 05 35 01 01 C3
 				2D 06 55 32 03 03 00 00 00 00
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index eac0bb6..7ff97f6 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -28,6 +28,7 @@
 			synaptics,reset-gpio = <&msmgpio 16 0x00>;
 			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
+			synaptics,fw-image-name = "PR1468813.img";
 			synaptics,i2c-pull-up;
 			synaptics,power-down;
 			synaptics,disable-gpios;
diff --git a/arch/arm/boot/dts/msm8226-v1-cdp.dts b/arch/arm/boot/dts/msm8226-v1-cdp.dts
index e426a97..4b8cafd 100644
--- a/arch/arm/boot/dts/msm8226-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v1-cdp.dts
@@ -12,7 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-720p-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 CDP";
diff --git a/arch/arm/boot/dts/msm8226-v1-mtp.dts b/arch/arm/boot/dts/msm8226-v1-mtp.dts
index 08d7cec..a1e78b7 100644
--- a/arch/arm/boot/dts/msm8226-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v1-mtp.dts
@@ -12,7 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
-/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-720p-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 MTP";
diff --git a/arch/arm/boot/dts/msm8226-v2-cdp.dts b/arch/arm/boot/dts/msm8226-v2-1080p-cdp.dts
similarity index 92%
copy from arch/arm/boot/dts/msm8226-v2-cdp.dts
copy to arch/arm/boot/dts/msm8226-v2-1080p-cdp.dts
index 3302d26..77cc08c 100644
--- a/arch/arm/boot/dts/msm8226-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-1080p-cdp.dts
@@ -12,13 +12,13 @@
 
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-1080p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 CDP";
 	compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
-	qcom,board-id = <1 0>;
+	qcom,board-id = <1 2>;
 };
 
 &hsic_host {
diff --git a/arch/arm/boot/dts/msm8226-v2-mtp.dts b/arch/arm/boot/dts/msm8226-v2-1080p-mtp.dts
similarity index 92%
copy from arch/arm/boot/dts/msm8226-v2-mtp.dts
copy to arch/arm/boot/dts/msm8226-v2-1080p-mtp.dts
index 6034107..b12a77d 100644
--- a/arch/arm/boot/dts/msm8226-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-1080p-mtp.dts
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
-/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-1080p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 MTP";
 	compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
-	qcom,board-id = <8 0>;
+	qcom,board-id = <8 2>;
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-cdp.dts b/arch/arm/boot/dts/msm8226-v2-720p-cdp.dts
similarity index 95%
rename from arch/arm/boot/dts/msm8226-v2-cdp.dts
rename to arch/arm/boot/dts/msm8226-v2-720p-cdp.dts
index 3302d26..966ae2b 100644
--- a/arch/arm/boot/dts/msm8226-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-720p-cdp.dts
@@ -12,7 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-720p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8226-v2-mtp.dts b/arch/arm/boot/dts/msm8226-v2-720p-mtp.dts
similarity index 95%
rename from arch/arm/boot/dts/msm8226-v2-mtp.dts
rename to arch/arm/boot/dts/msm8226-v2-720p-mtp.dts
index 6034107..0768b75 100644
--- a/arch/arm/boot/dts/msm8226-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-720p-mtp.dts
@@ -12,7 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
-/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-720p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index abe5ff3..906e4a8 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -39,7 +39,7 @@
 
 		qsecom_mem: qsecom_region {
 			linux,contiguous-region;
-			reg = <0 0x780000>;
+			reg = <0 0xd00000>;
 			label = "qsecom_mem";
 		};
 	};
@@ -216,6 +216,13 @@
 		reg = <0xf991f000 0x1000>;
 		interrupts = <0 109 0>;
 		status = "disabled";
+
+		qcom,msm-bus,name = "blsp1_uart2";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<86 512 0 0>,
+				<86 512 500 800>;
 	};
 
 	serial@f995e000 {
@@ -283,6 +290,7 @@
 		qcom,hsusb-otg-otg-control = <2>;
 		qcom,hsusb-otg-disable-reset;
 		qcom,dp-manual-pullup;
+		qcom,ahb-async-bridge-bypass;
 
 		qcom,msm-bus,name = "usb";
 		qcom,msm-bus,num-cases = <3>;
@@ -297,6 +305,7 @@
 		compatible = "qcom,android-usb";
 		reg = <0xfe8050c8 0xc8>;
 		qcom,android-usb-swfi-latency = <1>;
+		qcom,streaming-func = "rndis";
 	};
 
 	hsic_host: hsic@f9a00000 {
@@ -720,6 +729,24 @@
 		compatible = "qcom,bcl";
 	};
 
+	rmtfs_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd80000 0x00180000>;
+		reg-names = "rmtfs";
+	};
+
+	dsp_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd60000 0x00020000>;
+		reg-names = "rfsa_dsp";
+	};
+
+	mdm_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd60000 0x00020000>;
+		reg-names = "rfsa_mdm";
+	};
+
 	sdcc1: qcom,sdcc@f9824000 {
 		cell-index = <1>; /* SDC1 eMMC slot */
 		compatible = "qcom,msm-sdcc";
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 71748ea..92d1a77 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -102,6 +102,10 @@
 		linux,default-trigger = "flashlight-trigger";
 	};
 
+	qcom,wdt@f9017000 {
+		qcom,bark-time = <13000>;
+	};
+
 	gpio_keys {
                 compatible = "gpio-keys";
                 input-name = "gpio-keys";
@@ -309,6 +313,7 @@
 
 	qcom,chgr@1000 {
 		status = "ok";
+		qcom,tchg-mins = <250>;
 	};
 
 	qcom,buck@1100 {
diff --git a/arch/arm/boot/dts/msm8610-rumi.dts b/arch/arm/boot/dts/msm8610-rumi.dts
index 7f06485..c22b4f28 100644
--- a/arch/arm/boot/dts/msm8610-rumi.dts
+++ b/arch/arm/boot/dts/msm8610-rumi.dts
@@ -17,7 +17,7 @@
 / {
 	model = "Qualcomm MSM 8610 Rumi";
 	compatible = "qcom,msm8610-rumi", "qcom,msm8610", "qcom,rumi";
-	qcom,msm-id = <147 15 0>;
+	qcom,board-id = <15 0>;
 };
 
 &soc {
diff --git a/arch/arm/boot/dts/msm8610-sim.dts b/arch/arm/boot/dts/msm8610-sim.dts
index 33176b9..531ee4b 100644
--- a/arch/arm/boot/dts/msm8610-sim.dts
+++ b/arch/arm/boot/dts/msm8610-sim.dts
@@ -17,7 +17,7 @@
 / {
 	model = "Qualcomm MSM 8610 Simulator";
 	compatible = "qcom,msm8610-sim", "qcom,msm8610", "qcom,sim";
-	qcom,msm-id = <147 16 0>;
+	qcom,board-id = <16 0>;
 };
 
 &soc {
diff --git a/arch/arm/boot/dts/msm8610-v1-cdp.dts b/arch/arm/boot/dts/msm8610-v1-cdp.dts
index beb3976..5a70379 100644
--- a/arch/arm/boot/dts/msm8610-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-v1-cdp.dts
@@ -19,8 +19,7 @@
 / {
 	model = "Qualcomm MSM 8610 CDP";
 	compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
-	qcom,msm-id = <147 1 0>, <165 1 0>, <161 1 0>, <162 1 0>,
-		      <163 1 0>, <164 1 0>, <166 1 0>;
+	qcom,board-id = <1 0>;
 };
 
 
diff --git a/arch/arm/boot/dts/msm8610-v1-mtp.dts b/arch/arm/boot/dts/msm8610-v1-mtp.dts
index 82992a3..c8c8d09 100644
--- a/arch/arm/boot/dts/msm8610-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-v1-mtp.dts
@@ -19,8 +19,7 @@
 / {
 	model = "Qualcomm MSM 8610 MTP";
 	compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
-	qcom,msm-id = <147 8 0>, <165 8 0>, <161 8 0>, <162 8 0>,
-		      <163 8 0>, <164 8 0>, <166 8 0>;
+	qcom,board-id = <8 0>;
 };
 
 
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index 6296692..62aa0f4 100644
--- a/arch/arm/boot/dts/msm8610-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
@@ -56,10 +56,10 @@
 		qcom,saw2-spm-dly= <0x3c102800>;
 		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
 	};
 
 	qcom,spm@f90b9000 {
@@ -99,6 +99,9 @@
 		qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
 				11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
 				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+		qcom,saw2-spm-cmd-pc-no-rpm = [00 32 b0 10 e0 d0 6b c0 42 f0
+				11 03 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
 		qcom,L2-spm-is-apcs-master;
 	};
 
@@ -125,28 +128,29 @@
 			qcom,latency-us = <500>;
 			qcom,ss-power = <410>;
 			qcom,energy-overhead = <603400>;
-			qcom,time-overhead = <1200>;
+			qcom,time-overhead = <1410>;
 		};
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "pc";
-			qcom,l2 = "l2_cache_retention";
-			qcom,latency-us = <520>;
-			qcom,ss-power = <460>;
-			qcom,energy-overhead = <704900>;
-			qcom,time-overhead = <1300>;
+			qcom,l2 = "l2_cache_pc_no_rpm";
+			qcom,latency-us = <1000>;
+			qcom,ss-power = <315>;
+			qcom,energy-overhead = <1027150>;
+			qcom,time-overhead = <2400>;
 		};
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_pc";
-			qcom,latency-us = <11700>;
+			qcom,latency-us = <12700>;
 			qcom,ss-power = <315>;
 			qcom,energy-overhead = <1027150>;
 			qcom,time-overhead = <2400>;
 		};
+
 	};
 
 	qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
index 4a08f3f..de48f1f 100644
--- a/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
@@ -33,3 +33,10 @@
 &dsi_hx8389b_qhd_vid {
 	qcom,cont-splash-enabled;
 };
+&soc {
+	i2c@f9925000 {
+		fsl@1c {
+			fsl,sensors-position = <7>;
+		};
+	};
+};
\ No newline at end of file
diff --git a/arch/arm/boot/dts/msm8610-v2-cdp.dts b/arch/arm/boot/dts/msm8610-v2-cdp.dts
index a6d1d9c..447161f 100644
--- a/arch/arm/boot/dts/msm8610-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-v2-cdp.dts
@@ -19,8 +19,7 @@
 / {
 	model = "Qualcomm MSM 8610v2 CDP";
 	compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
-	qcom,msm-id = <147 1 0x10001>, <165 1 0x10001>, <161 1 0x10001>, <162 1 0x10001>,
-		      <163 1 0x10001>, <164 1 0x10001>, <166 1 0x10001>;
+	qcom,board-id = <1 0>;
 };
 
 
diff --git a/arch/arm/boot/dts/msm8610-v2-mtp.dts b/arch/arm/boot/dts/msm8610-v2-mtp.dts
index 405a775..77f5276 100644
--- a/arch/arm/boot/dts/msm8610-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-v2-mtp.dts
@@ -19,8 +19,7 @@
 / {
 	model = "Qualcomm MSM 8610v2 MTP";
 	compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
-	qcom,msm-id = <147 8 0x10001>, <165 8 0x10001>, <161 8 0x10001>, <162 8 0x10001>,
-		      <163 8 0x10001>, <164 8 0x10001>, <166 8 0x10001>;
+	qcom,board-id = <8 0>;
 };
 
 
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index 6c7f2f6..e401f7a 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -56,10 +56,10 @@
 		qcom,saw2-spm-dly= <0x3c102800>;
 		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
 	};
 
 	qcom,spm@f90b9000 {
@@ -101,6 +101,9 @@
 		qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
 				11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
 				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+		qcom,saw2-spm-cmd-pc-no-rpm = [00 32 b0 10 e0 d0 6b c0 42 f0
+				11 03 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
 		qcom,L2-spm-is-apcs-master;
 	};
 
@@ -134,17 +137,27 @@
 			reg = <0x2>;
 			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_gdhs";
-			qcom,latency-us = <10700>;
-			qcom,ss-power = <325>;
-			qcom,energy-overhead = <441250>;
-			qcom,time-overhead = <1020>;
+			qcom,latency-us = <11700>;
+			qcom,ss-power = <372>;
+			qcom,energy-overhead = <738750>;
+			qcom,time-overhead = <1410>;
 		};
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
+			qcom,l2 = "l2_cache_pc_no_rpm";
+			qcom,latency-us = <1000>;
+			qcom,ss-power = <315>;
+			qcom,energy-overhead = <1027150>;
+			qcom,time-overhead = <2400>;
+		};
+
+		qcom,lpm-level@4 {
+			reg = <0x4>;
+			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_pc";
-			qcom,latency-us = <11700>;
+			qcom,latency-us = <12700>;
 			qcom,ss-power = <315>;
 			qcom,energy-overhead = <1027150>;
 			qcom,time-overhead = <2400>;
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
index 4735554..2547148 100644
--- a/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
@@ -56,3 +56,26 @@
 &dsi_hx8389b_qhd_vid {
 	qcom,cont-splash-enabled;
 };
+
+&soc {
+	i2c@f9925000 {
+		fsl@1c {
+			fsl,sensors-position = <7>;
+		};
+	};
+};
+
+&qrd_batterydata {
+	qcom,rpull-up-kohm = <100>;
+	qcom,vref-batt-therm = <1800000>;
+
+	/include/ "batterydata-qrd-4v2-2200mah.dtsi"
+};
+
+&pm8110_bms {
+	qcom,battery-data = <&qrd_batterydata>;
+};
+
+&pm8110_chg {
+	qcom,battery-data = <&qrd_batterydata>;
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 133757a..0281e45 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -239,6 +239,7 @@
 		qcom,hsusb-otg-otg-control = <2>;
 		qcom,hsusb-otg-disable-reset;
 		qcom,dp-manual-pullup;
+		qcom,ahb-async-bridge-bypass;
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
@@ -253,6 +254,25 @@
 		compatible = "qcom,android-usb";
 		reg = <0xfe8050c8 0xc8>;
 		qcom,android-usb-swfi-latency = <1>;
+		qcom,streaming-func = "rndis";
+	};
+
+	rmtfs_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0dc80000 0x00180000>;
+		reg-names = "rmtfs";
+	};
+
+	dsp_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0dc60000 0x00020000>;
+		reg-names = "rfsa_dsp";
+	};
+
+	mdm_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0dc60000 0x00020000>;
+		reg-names = "rfsa_mdm";
 	};
 
 	sdcc1: qcom,sdcc@f9824000 {
@@ -422,7 +442,6 @@
 		compatible = "qcom,rpm-smd";
 		rpm-channel-name = "rpm_requests";
 		rpm-channel-type = <15>; /* SMD_APPS_RPM */
-		rpm-standalone;
 	};
 
 	qcom,bcl {
diff --git a/arch/arm/boot/dts/msm8926-cdp.dts b/arch/arm/boot/dts/msm8926-1080p-cdp.dts
similarity index 93%
copy from arch/arm/boot/dts/msm8926-cdp.dts
copy to arch/arm/boot/dts/msm8926-1080p-cdp.dts
index d6e70e6..33e484a 100644
--- a/arch/arm/boot/dts/msm8926-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-1080p-cdp.dts
@@ -13,13 +13,13 @@
 
 /dts-v1/;
 /include/ "msm8926.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-1080p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926 CDP";
 	compatible = "qcom,msm8926-cdp", "qcom,msm8926", "qcom,cdp";
-	qcom,board-id = <1 0>;
+	qcom,board-id = <1 2>;
 };
 
 &pm8226_chg {
diff --git a/arch/arm/boot/dts/msm8926-mtp.dts b/arch/arm/boot/dts/msm8926-1080p-mtp.dts
similarity index 92%
copy from arch/arm/boot/dts/msm8926-mtp.dts
copy to arch/arm/boot/dts/msm8926-1080p-mtp.dts
index 624781b..c1217a2 100644
--- a/arch/arm/boot/dts/msm8926-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-1080p-mtp.dts
@@ -13,11 +13,11 @@
 
 /dts-v1/;
 /include/ "msm8926.dtsi"
-/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-1080p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926 MTP";
 	compatible = "qcom,msm8926-mtp", "qcom,msm8926", "qcom,mtp";
-	qcom,board-id = <8 0>;
+	qcom,board-id = <8 2>;
 };
diff --git a/arch/arm/boot/dts/msm8926-cdp.dts b/arch/arm/boot/dts/msm8926-720p-cdp.dts
similarity index 96%
rename from arch/arm/boot/dts/msm8926-cdp.dts
rename to arch/arm/boot/dts/msm8926-720p-cdp.dts
index d6e70e6..80bb5e6 100644
--- a/arch/arm/boot/dts/msm8926-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-720p-cdp.dts
@@ -13,7 +13,7 @@
 
 /dts-v1/;
 /include/ "msm8926.dtsi"
-/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-720p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8926-mtp.dts b/arch/arm/boot/dts/msm8926-720p-mtp.dts
similarity index 95%
rename from arch/arm/boot/dts/msm8926-mtp.dts
rename to arch/arm/boot/dts/msm8926-720p-mtp.dts
index 624781b..32301fd 100644
--- a/arch/arm/boot/dts/msm8926-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-720p-mtp.dts
@@ -13,7 +13,7 @@
 
 /dts-v1/;
 /include/ "msm8926.dtsi"
-/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-720p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8926-qrd-skug.dts b/arch/arm/boot/dts/msm8926-qrd-skug.dts
index 6d907ef..15a2d58 100644
--- a/arch/arm/boot/dts/msm8926-qrd-skug.dts
+++ b/arch/arm/boot/dts/msm8926-qrd-skug.dts
@@ -61,8 +61,8 @@
 			focaltech,fw-name = "ft_8926_qrd_fw.bin";
 			focaltech,fw-delay-aa-ms = <30>;
 			focaltech,fw-delay-55-ms = <30>;
-			focaltech,fw-upgrade-id1 = <0x79>;
-			focaltech,fw-upgrade-id2 = <0x08>;
+			focaltech,fw-upgrade-id1 = <0x11>;
+			focaltech,fw-upgrade-id2 = <0x11>;
 			focaltech,fw-delay-readid-ms = <10>;
 			focaltech,fw-delay-era-flsh-ms = <2000>;
 			focaltech,fw-auto-cal;
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index 0115d89..e850c55 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -208,10 +208,26 @@
 			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 34>,  /* APCC_qgicL2ErrorIrptReq */
+			<0xff 35>,  /* WDT_barkInt */
+			<0xff 40>,  /* qtimer_phy_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
 			<0xff 59>,  /* mss_to_apps_irq(2) */
 			<0xff 60>,  /* mss_to_apps_irq(3) */
+			<0xff 74>,  /* osmmu_CIrpt[1] */
+			<0xff 75>,  /* osmmu_CIrpt[0] */
+			<0xff 77>,  /* osmmu_CIrpt[0] */
+			<0xff 78>,  /* osmmu_CIrpt[0] */
+			<0xff 79>,  /* osmmu_CIrpt[0] */
+			<0xff 94>,  /* osmmu_CIrpt[0] */
+			<0xff 99>,  /* msm_iommu_pmon_nonsecure_irq */
+			<0xff 102>,  /* osmmu_CIrpt[1] */
+			<0xff 109>,  /* ocmem_dm_nonsec_irq */
+			<0xff 126>,  /* bam_irq[0] */
+			<0xff 155>,  /* sdcc_irq[0] */
+			<0xff 163>,  /* usb30_ee1_irq */
+			<0xff 170>,  /* sdcc_pwr_cmd_irq */
 			<0xff 173>, /* o_wcss_apss_smd_hi */
 			<0xff 174>, /* o_wcss_apss_smd_med */
 			<0xff 175>, /* o_wcss_apss_smd_low */
@@ -230,6 +246,7 @@
 			<0xff 195>, /* lpass_irq_out_apcs(7) */
 			<0xff 196>, /* lpass_irq_out_apcs(8) */
 			<0xff 197>, /* lpass_irq_out_apcs(9) */
+			<0xff 198>, /* coresight-tmc-etr interrupt */
 			<0xff 200>, /* rpm_ipc(4) */
 			<0xff 201>, /* rpm_ipc(5) */
 			<0xff 202>, /* rpm_ipc(6) */
@@ -238,7 +255,10 @@
 			<0xff 205>, /* rpm_ipc(25) */
 			<0xff 206>, /* rpm_ipc(26) */
 			<0xff 207>, /* rpm_ipc(27) */
-			<0xff 240>; /* summary_irq_kpss */
+			<0xff 240>, /* summary_irq_kpss */
+			<0xff 268>, /* bam_irq[1] */
+			<0xff 270>, /* bam_irq[0] */
+			<0xff 271>; /* bam_irq[0] */
 
 		qcom,gpio-parent = <&msmgpio>;
 		qcom,gpio-map = <3  102>,
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 8836975..eb3a48f 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -215,6 +215,9 @@
 			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 34>,  /* APCC_qgicL2ErrorIrptReq */
+			<0xff 35>,  /* WDT_barkInt */
+			<0xff 40>,  /* qtimer_phy_irq */
 			<0xff 56>,  /* modem_watchdog */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
@@ -222,8 +225,21 @@
 			<0xff 60>,  /* mss_to_apps_irq(3) */
 			<0xff 61>,  /* mss_a2_bam_irq */
 			<0xff 70>,  /* iommu_pmon_nonsecure_irq */
+			<0xff 74>,  /* osmmu_CIrpt[1] */
+			<0xff 75>,  /* osmmu_CIrpt[0] */
+			<0xff 77>,  /* osmmu_CIrpt[0] */
+			<0xff 78>,  /* osmmu_CIrpt[0] */
+			<0xff 79>,  /* osmmu_CIrpt[0] */
+			<0xff 94>,  /* osmmu_CIrpt[0] */
 			<0xff 97>,  /* iommu_nonsecure_irq */
+			<0xff 99>,  /* msm_iommu_pmon_nonsecure_irq */
+			<0xff 102>,  /* osmmu_CIrpt[1] */
 			<0xff 105>, /* iommu_pmon_nonsecure_irq */
+			<0xff 109>,  /* ocmem_dm_nonsec_irq */
+			<0xff 126>,  /* bam_irq[0] */
+			<0xff 155>,  /* sdcc_irq[0] */
+			<0xff 163>,  /* usb30_ee1_irq */
+			<0xff 170>,  /* sdcc_pwr_cmd_irq */
 			<0xff 173>, /* o_wcss_apss_smd_hi */
 			<0xff 174>, /* o_wcss_apss_smd_med */
 			<0xff 175>, /* o_wcss_apss_smd_low */
@@ -231,7 +247,6 @@
 			<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
 			<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
 			<0xff 179>, /* o_wcss_apss_asic_intr */
-
 			<0xff 181>, /* wcnss watchdog */
 			<0xff 188>, /* lpass_irq_out_apcs(0) */
 			<0xff 189>, /* lpass_irq_out_apcs(1) */
@@ -243,6 +258,7 @@
 			<0xff 195>, /* lpass_irq_out_apcs(7) */
 			<0xff 196>, /* lpass_irq_out_apcs(8) */
 			<0xff 197>, /* lpass_irq_out_apcs(9) */
+			<0xff 198>, /* coresight-tmc-etr interrupt */
 			<0xff 200>, /* rpm_ipc(4) */
 			<0xff 201>, /* rpm_ipc(5) */
 			<0xff 202>, /* rpm_ipc(6) */
@@ -252,7 +268,10 @@
 			<0xff 206>, /* rpm_ipc(26) */
 			<0xff 207>, /* rpm_ipc(27) */
 			<0xff 211>, /* usb_dwc3_otg */
-			<0xff 240>; /* summary_irq_kpss */
+			<0xff 240>, /* summary_irq_kpss */
+			<0xff 268>, /* bam_irq[1] */
+			<0xff 270>, /* bam_irq[0] */
+			<0xff 271>; /* bam_irq[0] */
 
 		qcom,gpio-parent = <&msmgpio>;
 		qcom,gpio-map = <3  102>,
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index e612df7..69e2529 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -283,6 +283,24 @@
 				<87 512 60000 960000>;
 	};
 
+	rmtfs_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd80000 0x00180000>;
+		reg-names = "rmtfs";
+	};
+
+	dsp_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd60000 0x00020000>;
+		reg-names = "rfsa_dsp";
+	};
+
+	mdm_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd60000 0x00020000>;
+		reg-names = "rfsa_mdm";
+	};
+
 	sdcc1: qcom,sdcc@f9824000 {
 		cell-index = <1>; /* SDC1 eMMC slot */
 		compatible = "qcom,msm-sdcc";
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
index 9e1f83f..5769446 100644
--- a/arch/arm/boot/dts/msm8974pro-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -205,6 +205,9 @@
 			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 34>,  /* APCC_qgicL2ErrorIrptReq */
+			<0xff 35>,  /* WDT_barkInt */
+			<0xff 40>,  /* qtimer_phy_irq */
 			<0xff 56>,  /* modem_watchdog */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
@@ -212,8 +215,21 @@
 			<0xff 60>,  /* mss_to_apps_irq(3) */
 			<0xff 61>,  /* mss_a2_bam_irq */
 			<0xff 70>,  /* iommu_pmon_nonsecure_irq */
+			<0xff 74>,  /* osmmu_CIrpt[1] */
+			<0xff 75>,  /* osmmu_CIrpt[0] */
+			<0xff 77>,  /* osmmu_CIrpt[0] */
+			<0xff 78>,  /* osmmu_CIrpt[0] */
+			<0xff 79>,  /* osmmu_CIrpt[0] */
+			<0xff 94>,  /* osmmu_CIrpt[0] */
 			<0xff 97>,  /* iommu_nonsecure_irq */
+			<0xff 99>,  /* msm_iommu_pmon_nonsecure_irq */
+			<0xff 102>,  /* osmmu_CIrpt[1] */
 			<0xff 105>, /* iommu_pmon_nonsecure_irq */
+			<0xff 109>,  /* ocmem_dm_nonsec_irq */
+			<0xff 126>,  /* bam_irq[0] */
+			<0xff 155>,  /* sdcc_irq[0] */
+			<0xff 163>,  /* usb30_ee1_irq */
+			<0xff 170>,  /* sdcc_pwr_cmd_irq */
 			<0xff 173>, /* o_wcss_apss_smd_hi */
 			<0xff 174>, /* o_wcss_apss_smd_med */
 			<0xff 175>, /* o_wcss_apss_smd_low */
@@ -233,6 +249,7 @@
 			<0xff 195>, /* lpass_irq_out_apcs(7) */
 			<0xff 196>, /* lpass_irq_out_apcs(8) */
 			<0xff 197>, /* lpass_irq_out_apcs(9) */
+			<0xff 198>, /* coresight-tmc-etr interrupt */
 			<0xff 200>, /* rpm_ipc(4) */
 			<0xff 201>, /* rpm_ipc(5) */
 			<0xff 202>, /* rpm_ipc(6) */
@@ -242,7 +259,10 @@
 			<0xff 206>, /* rpm_ipc(26) */
 			<0xff 207>, /* rpm_ipc(27) */
 			<0xff 211>, /* usb_dwc3_otg */
-			<0xff 240>; /* summary_irq_kpss */
+			<0xff 240>, /* summary_irq_kpss */
+			<0xff 268>, /* bam_irq[1] */
+			<0xff 270>, /* bam_irq[0] */
+			<0xff 271>; /* bam_irq[0] */
 
 		qcom,gpio-parent = <&msmgpio>;
 		qcom,gpio-map = <3  102>,
diff --git a/arch/arm/boot/dts/msm8974pro-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
index 0f37584..2c06c3c 100644
--- a/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
@@ -38,18 +38,22 @@
 
 &krait0_vreg {
 		regulator-max-microvolt = <1120000>;
+		qcom,ldo-delta-voltage = <25000>;
 };
 
 &krait1_vreg {
 		regulator-max-microvolt = <1120000>;
+		qcom,ldo-delta-voltage = <25000>;
 };
 
 &krait2_vreg {
 		regulator-max-microvolt = <1120000>;
+		qcom,ldo-delta-voltage = <25000>;
 };
 
 &krait3_vreg {
 		regulator-max-microvolt = <1120000>;
+		qcom,ldo-delta-voltage = <25000>;
 };
 
 &tspp {
diff --git a/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
index df00f8a..00e3b8b 100644
--- a/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
@@ -494,7 +494,7 @@
 			qcom,retention-voltage = <675000>;
 			qcom,ldo-default-voltage = <750000>;
 			qcom,ldo-threshold-voltage = <850000>;
-			qcom,ldo-delta-voltage = <50000>;
+			qcom,ldo-delta-voltage = <25000>;
 			qcom,cpu-num = <0>;
 		};
 
@@ -510,7 +510,7 @@
 			qcom,retention-voltage = <675000>;
 			qcom,ldo-default-voltage = <750000>;
 			qcom,ldo-threshold-voltage = <850000>;
-			qcom,ldo-delta-voltage = <50000>;
+			qcom,ldo-delta-voltage = <25000>;
 			qcom,cpu-num = <1>;
 		};
 
@@ -526,7 +526,7 @@
 			qcom,retention-voltage = <675000>;
 			qcom,ldo-default-voltage = <750000>;
 			qcom,ldo-threshold-voltage = <850000>;
-			qcom,ldo-delta-voltage = <50000>;
+			qcom,ldo-delta-voltage = <25000>;
 			qcom,cpu-num = <2>;
 		};
 
@@ -542,7 +542,7 @@
 			qcom,retention-voltage = <675000>;
 			qcom,ldo-default-voltage = <750000>;
 			qcom,ldo-threshold-voltage = <850000>;
-			qcom,ldo-delta-voltage = <50000>;
+			qcom,ldo-delta-voltage = <25000>;
 			qcom,cpu-num = <3>;
 		};
 	};
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index a492561..6c55566 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -65,6 +65,24 @@
 		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
 	};
 
+	rmtfs_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd80000 0x00180000>;
+		reg-names = "rmtfs";
+	};
+
+	dsp_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd60000 0x00020000>;
+		reg-names = "rfsa_dsp";
+	};
+
+	mdm_sharedmem {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x0fd60000 0x00020000>;
+		reg-names = "rfsa_mdm";
+	};
+
 	sdcc1: qcom,sdcc@f9824000 {
 		cell-index = <1>; /* SDC1 eMMC slot */
 		compatible = "qcom,msm-sdcc";
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 7d7bf46..c5aa51a 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -25,6 +25,7 @@
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
 CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
 CONFIG_KPROBES=y
@@ -269,6 +270,7 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
+CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
@@ -395,6 +397,8 @@
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
 CONFIG_RTC_DRV_QPNP=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index c1f2ca2..f4ee78d 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -271,6 +271,7 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
+CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
@@ -421,6 +422,8 @@
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
 CONFIG_RTC_DRV_QPNP=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index efdd8de..8366a41 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -79,7 +79,6 @@
 CONFIG_ARM_ARCH_TIMER=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
 CONFIG_COMPACTION=y
 CONFIG_CC_STACKPROTECTOR=y
 CONFIG_ENABLE_VMALLOC_SAVING=y
@@ -247,6 +246,7 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
+CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
@@ -355,7 +355,11 @@
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
 CONFIG_RTC_DRV_QPNP=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
 CONFIG_STAGING=y
+CONFIG_ZRAM=y
+CONFIG_ZSMALLOC=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_ASHMEM=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index c140a46..02db2f2 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -80,7 +80,6 @@
 CONFIG_ARM_ARCH_TIMER=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
 CONFIG_COMPACTION=y
 CONFIG_CC_STACKPROTECTOR=y
 CONFIG_ENABLE_VMALLOC_SAVING=y
@@ -249,6 +248,7 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
+CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
@@ -379,7 +379,11 @@
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
 CONFIG_RTC_DRV_QPNP=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
 CONFIG_STAGING=y
+CONFIG_ZRAM=y
+CONFIG_ZSMALLOC=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_ASHMEM=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index fb05a08..07bb88c 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -298,6 +298,7 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
+CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
@@ -435,6 +436,8 @@
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
 CONFIG_RTC_DRV_QPNP=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 8f6f52f..82bbdb7 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -306,6 +306,7 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
+CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
@@ -443,6 +444,8 @@
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
 CONFIG_RTC_DRV_QPNP=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index e000e5e..edb73b4 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -440,12 +440,18 @@
 		 */
 		thumb = handler & 1;
 
+#if __LINUX_ARM_ARCH__ >= 7
+		/*
+		 * Clear the If-Then Thumb-2 execution state
+		 * ARM spec requires this to be all 000s in ARM mode
+		 * Snapdragon S4/Krait misbehaves on a Thumb=>ARM
+		 * signal transition without this.
+		 */
+		cpsr &= ~PSR_IT_MASK;
+#endif
+
 		if (thumb) {
 			cpsr |= PSR_T_BIT;
-#if __LINUX_ARM_ARCH__ >= 7
-			/* clear the If-Then Thumb-2 execution state */
-			cpsr &= ~PSR_IT_MASK;
-#endif
 		} else
 			cpsr &= ~PSR_T_BIT;
 	}
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
index 650d592..94b0650 100644
--- a/arch/arm/lib/memset.S
+++ b/arch/arm/lib/memset.S
@@ -14,27 +14,15 @@
 
 	.text
 	.align	5
-	.word	0
-
-1:	subs	r2, r2, #4		@ 1 do we have enough
-	blt	5f			@ 1 bytes to align with?
-	cmp	r3, #2			@ 1
-	strltb	r1, [r0], #1		@ 1
-	strleb	r1, [r0], #1		@ 1
-	strb	r1, [r0], #1		@ 1
-	add	r2, r2, r3		@ 1 (r2 = r2 - (4 - r3))
-/*
- * The pointer is now aligned and the length is adjusted.  Try doing the
- * memset again.
- */
 
 ENTRY(memset)
 	ands	r3, r0, #3		@ 1 unaligned?
-	bne	1b			@ 1
+	mov	ip, r0			@ preserve r0 as return value
+	bne	6f			@ 1
 /*
- * we know that the pointer in r0 is aligned to a word boundary.
+ * we know that the pointer in ip is aligned to a word boundary.
  */
-	orr	r1, r1, r1, lsl #8
+1:	orr	r1, r1, r1, lsl #8
 	orr	r1, r1, r1, lsl #16
 	mov	r3, r1
 	cmp	r2, #16
@@ -43,29 +31,28 @@
 #if ! CALGN(1)+0
 
 /*
- * We need an extra register for this loop - save the return address and
- * use the LR
+ * We need 2 extra registers for this loop - use r8 and the LR
  */
-	str	lr, [sp, #-4]!
-	mov	ip, r1
+	stmfd	sp!, {r8, lr}
+	mov	r8, r1
 	mov	lr, r1
 
 2:	subs	r2, r2, #64
-	stmgeia	r0!, {r1, r3, ip, lr}	@ 64 bytes at a time.
-	stmgeia	r0!, {r1, r3, ip, lr}
-	stmgeia	r0!, {r1, r3, ip, lr}
-	stmgeia	r0!, {r1, r3, ip, lr}
+	stmgeia	ip!, {r1, r3, r8, lr}	@ 64 bytes at a time.
+	stmgeia	ip!, {r1, r3, r8, lr}
+	stmgeia	ip!, {r1, r3, r8, lr}
+	stmgeia	ip!, {r1, r3, r8, lr}
 	bgt	2b
-	ldmeqfd	sp!, {pc}		@ Now <64 bytes to go.
+	ldmeqfd	sp!, {r8, pc}		@ Now <64 bytes to go.
 /*
  * No need to correct the count; we're only testing bits from now on
  */
 	tst	r2, #32
-	stmneia	r0!, {r1, r3, ip, lr}
-	stmneia	r0!, {r1, r3, ip, lr}
+	stmneia	ip!, {r1, r3, r8, lr}
+	stmneia	ip!, {r1, r3, r8, lr}
 	tst	r2, #16
-	stmneia	r0!, {r1, r3, ip, lr}
-	ldr	lr, [sp], #4
+	stmneia	ip!, {r1, r3, r8, lr}
+	ldmfd	sp!, {r8, lr}
 
 #else
 
@@ -74,54 +61,63 @@
  * whole cache lines at once.
  */
 
-	stmfd	sp!, {r4-r7, lr}
+	stmfd	sp!, {r4-r8, lr}
 	mov	r4, r1
 	mov	r5, r1
 	mov	r6, r1
 	mov	r7, r1
-	mov	ip, r1
+	mov	r8, r1
 	mov	lr, r1
 
 	cmp	r2, #96
-	tstgt	r0, #31
+	tstgt	ip, #31
 	ble	3f
 
-	and	ip, r0, #31
-	rsb	ip, ip, #32
-	sub	r2, r2, ip
-	movs	ip, ip, lsl #(32 - 4)
-	stmcsia	r0!, {r4, r5, r6, r7}
-	stmmiia	r0!, {r4, r5}
-	tst	ip, #(1 << 30)
-	mov	ip, r1
-	strne	r1, [r0], #4
+	and	r8, ip, #31
+	rsb	r8, r8, #32
+	sub	r2, r2, r8
+	movs	r8, r8, lsl #(32 - 4)
+	stmcsia	ip!, {r4, r5, r6, r7}
+	stmmiia	ip!, {r4, r5}
+	tst	r8, #(1 << 30)
+	mov	r8, r1
+	strne	r1, [ip], #4
 
 3:	subs	r2, r2, #64
-	stmgeia	r0!, {r1, r3-r7, ip, lr}
-	stmgeia	r0!, {r1, r3-r7, ip, lr}
+	stmgeia	ip!, {r1, r3-r8, lr}
+	stmgeia	ip!, {r1, r3-r8, lr}
 	bgt	3b
-	ldmeqfd	sp!, {r4-r7, pc}
+	ldmeqfd	sp!, {r4-r8, pc}
 
 	tst	r2, #32
-	stmneia	r0!, {r1, r3-r7, ip, lr}
+	stmneia	ip!, {r1, r3-r8, lr}
 	tst	r2, #16
-	stmneia	r0!, {r4-r7}
-	ldmfd	sp!, {r4-r7, lr}
+	stmneia	ip!, {r4-r7}
+	ldmfd	sp!, {r4-r8, lr}
 
 #endif
 
 4:	tst	r2, #8
-	stmneia	r0!, {r1, r3}
+	stmneia	ip!, {r1, r3}
 	tst	r2, #4
-	strne	r1, [r0], #4
+	strne	r1, [ip], #4
 /*
  * When we get here, we've got less than 4 bytes to zero.  We
  * may have an unaligned pointer as well.
  */
 5:	tst	r2, #2
-	strneb	r1, [r0], #1
-	strneb	r1, [r0], #1
+	strneb	r1, [ip], #1
+	strneb	r1, [ip], #1
 	tst	r2, #1
-	strneb	r1, [r0], #1
+	strneb	r1, [ip], #1
 	mov	pc, lr
+
+6:	subs	r2, r2, #4		@ 1 do we have enough
+	blt	5b			@ 1 bytes to align with?
+	cmp	r3, #2			@ 1
+	strltb	r1, [ip], #1		@ 1
+	strleb	r1, [ip], #1		@ 1
+	strb	r1, [ip], #1		@ 1
+	add	r2, r2, r3		@ 1 (r2 = r2 - (4 - r3))
+	b	1b
 ENDPROC(memset)
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 552ed16..83c1d4c 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -99,28 +99,34 @@
 
 # MSM8226
    zreladdr-$(CONFIG_ARCH_MSM8226)	:= 0x00008000
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-sim.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-fluid.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-cdp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-mtp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-evt.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-dvt.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-cdp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-mtp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-evt.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-dvt.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-cdp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-mtp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-qrd.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-qrd-skug.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-skuf.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-skuf.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-xpm.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-cdp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-mtp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-xpm.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-cdp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-sim.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-fluid.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-evt.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-dvt.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-720p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-1080p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-720p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-1080p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-evt.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-dvt.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-720p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-1080p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-720p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-1080p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-qrd.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-qrd-skug.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-skuf.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-skuf.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-xpm.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-xpm.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-720p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-1080p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-720p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-1080p-mtp.dtb
 
 # FSM9XXX
    zreladdr-$(CONFIG_ARCH_FSM9XXX)	:= 0x10008000
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 60be20a..5117949 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -95,159 +95,7 @@
 	},
 };
 
-static struct msm_bus_paths bw_level_tbl_v1[] __initdata = {
-	[0] =  BW_MBPS(600), /* At least  75 MHz on bus. */
-	[1] =  BW_MBPS(800), /* At least 100 MHz on bus. */
-	[2] = BW_MBPS(1200), /* At least 150 MHz on bus. */
-	[3] = BW_MBPS(1600), /* At least 200 MHz on bus. */
-	[4] = BW_MBPS(2224), /* At least 278 MHz on bus. */
-	[5] = BW_MBPS(3200), /* At least 400 MHz on bus. */
-	[6] = BW_MBPS(4448), /* At least 556 MHz on bus. */
-	[7] = BW_MBPS(6400), /* At least 800 MHz on bus. */
-};
-
-static struct l2_level l2_freq_tbl_v1[] __initdata = {
-	[0]  = { {  300000, PLL_0, 0,   0 }, LVL_LOW,   950000, 0 },
-	[1]  = { {  345600, HFPLL, 2,  36 }, LVL_NOM,   950000, 1 },
-	[2]  = { {  422400, HFPLL, 2,  44 }, LVL_NOM,   950000, 1 },
-	[3]  = { {  499200, HFPLL, 2,  52 }, LVL_NOM,   950000, 2 },
-	[4]  = { {  576000, HFPLL, 1,  30 }, LVL_NOM,   950000, 3 },
-	[5]  = { {  652800, HFPLL, 1,  34 }, LVL_NOM,   950000, 3 },
-	[6]  = { {  729600, HFPLL, 1,  38 }, LVL_NOM,   950000, 3 },
-	[7]  = { {  806400, HFPLL, 1,  42 }, LVL_HIGH, 1050000, 4 },
-	[8]  = { {  883200, HFPLL, 1,  46 }, LVL_HIGH, 1050000, 4 },
-	[9]  = { {  960000, HFPLL, 1,  50 }, LVL_HIGH, 1050000, 4 },
-	[10] = { { 1036800, HFPLL, 1,  54 }, LVL_HIGH, 1050000, 5 },
-	[11] = { { 1113600, HFPLL, 1,  58 }, LVL_HIGH, 1050000, 5 },
-	[12] = { { 1190400, HFPLL, 1,  62 }, LVL_HIGH, 1050000, 6 },
-	[13] = { { 1267200, HFPLL, 1,  66 }, LVL_HIGH, 1050000, 6 },
-	[14] = { { 1344000, HFPLL, 1,  70 }, LVL_HIGH, 1050000, 7 },
-	[15] = { { 1420800, HFPLL, 1,  74 }, LVL_HIGH, 1050000, 7 },
-	[16] = { { 1497600, HFPLL, 1,  78 }, LVL_HIGH, 1050000, 7 },
-	{ }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 208 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 229 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 252 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 275 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 298 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 321 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 346 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 371 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 397 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 423 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 450 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 477 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 506 },
-	{ 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 208 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 229 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 252 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 275 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 298 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 321 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 346 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 371 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 397 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 423 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 450 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 477 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 506 },
-	{ 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 208 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 229 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 252 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 275 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 298 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 321 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 346 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 371 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 397 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 423 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 450 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 477 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 506 },
-	{ 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 208 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 229 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 252 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 275 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 298 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 321 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 346 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 371 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 397 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 423 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 450 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 477 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 506 },
-	{ 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),  825000,  73 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),  825000,  85 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),  825000, 104 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),  825000, 124 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),  825000, 144 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),  825000, 165 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),  825000, 186 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10), 825000, 208 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10), 825000, 229 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10), 825000, 252 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10), 825000, 275 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 298 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 321 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 346 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12), 885000, 371 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 397 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 423 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 450 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 477 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 950000, 506 },
-	{ 0, { 0 } }
-};
-
-static struct msm_bus_paths bw_level_tbl_v2[] __initdata = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
 	[0] =  BW_MBPS(600), /* At least  75 MHz on bus. */
 	[1] =  BW_MBPS(800), /* At least 100 MHz on bus. */
 	[2] = BW_MBPS(1200), /* At least 150 MHz on bus. */
@@ -259,7 +107,7 @@
 	[8] = BW_MBPS(7448), /* At least 931 MHz on bus. */
 };
 
-static struct l2_level l2_freq_tbl_v2[] __initdata = {
+static struct l2_level l2_freq_tbl[] __initdata = {
 	[0]  = { {  300000, PLL_0, 0,   0 }, LVL_LOW,   950000, 0 },
 	[1]  = { {  345600, HFPLL, 2,  36 }, LVL_LOW,   950000, 1 },
 	[2]  = { {  422400, HFPLL, 2,  44 }, LVL_LOW,   950000, 2 },
@@ -2440,15 +2288,6 @@
 	{ 0, { 0 } }
 };
 
-static struct pvs_table pvs_v1[NUM_PVS_REVS][NUM_SPEED_BINS][NUM_PVS] __initdata = {
-	/* 8974v1 1.7GHz Parts */
-	[0][0][0] = { acpu_freq_tbl_v1_pvs0, sizeof(acpu_freq_tbl_v1_pvs0) },
-	[0][0][1] = { acpu_freq_tbl_v1_pvs1, sizeof(acpu_freq_tbl_v1_pvs1) },
-	[0][0][2] = { acpu_freq_tbl_v1_pvs2, sizeof(acpu_freq_tbl_v1_pvs2) },
-	[0][0][3] = { acpu_freq_tbl_v1_pvs3, sizeof(acpu_freq_tbl_v1_pvs3) },
-	[0][0][4] = { acpu_freq_tbl_v1_pvs4, sizeof(acpu_freq_tbl_v1_pvs4) },
-};
-
 static struct pvs_table pvs_v2[NUM_PVS_REVS][NUM_SPEED_BINS][NUM_PVS] __initdata = {
 	/* 8974v2 2.0GHz Parts */
 	[0][0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
@@ -2560,8 +2399,8 @@
 };
 
 static struct msm_bus_scale_pdata bus_scale_data __initdata = {
-	.usecase = bw_level_tbl_v2,
-	.num_usecases = ARRAY_SIZE(bw_level_tbl_v2),
+	.usecase = bw_level_tbl,
+	.num_usecases = ARRAY_SIZE(bw_level_tbl),
 	.active_only = 1,
 	.name = "acpuclk-8974",
 };
@@ -2570,68 +2409,23 @@
 	.scalable = scalable,
 	.scalable_size = sizeof(scalable),
 	.hfpll_data = &hfpll_data,
-	.pvs_tables = pvs_v2,
-	.l2_freq_tbl = l2_freq_tbl_v2,
-	.l2_freq_tbl_size = sizeof(l2_freq_tbl_v2),
+	.l2_freq_tbl = l2_freq_tbl,
+	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
 	.pte_efuse_phys = 0xFC4B80B0,
 	.get_bin_info = get_krait_bin_format_b,
 	.stby_khz = 300000,
 };
 
-static void __init apply_pro_bringup_workaround(void)
-{
-	acpuclk_8974_params.pvs_tables = pvs_pro;
-}
-
-static void __init apply_v1_l2_workaround(void)
-{
-	static struct l2_level resticted_l2_tbl[] __initdata = {
-		[0] = { {  300000, PLL_0, 0,   0 }, LVL_LOW,  1050000, 0 },
-		[1] = { { 1497600, HFPLL, 1,  78 }, LVL_HIGH, 1050000, 7 },
-		{ }
-	};
-	struct acpu_level *l;
-	int s, p, r;
-
-	for (r = 0; r < NUM_PVS_REVS; r++)
-		for (s = 0; s < NUM_SPEED_BINS; s++)
-			for (p = 0; p < NUM_PVS; p++) {
-				l = pvs_v1[r][s][p].table;
-				for (; l && l->speed.khz; l++)
-					l->l2_level = l->l2_level > 5 ? 1 : 0;
-			}
-
-	acpuclk_8974_params.l2_freq_tbl = resticted_l2_tbl;
-	acpuclk_8974_params.l2_freq_tbl_size = sizeof(resticted_l2_tbl);
-}
-
 #define cpu_is_msm8974pro() (cpu_is_msm8974pro_aa() || cpu_is_msm8974pro_ab() \
 			     || cpu_is_msm8974pro_ac())
 
 static int __init acpuclk_8974_probe(struct platform_device *pdev)
 {
-	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1
-	    && cpu_is_msm8974()) {
-		acpuclk_8974_params.pvs_tables = pvs_v1;
-		acpuclk_8974_params.l2_freq_tbl = l2_freq_tbl_v1;
-		bus_scale_data.usecase = bw_level_tbl_v1;
-		bus_scale_data.num_usecases = ARRAY_SIZE(bw_level_tbl_v1);
-		acpuclk_8974_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_v1);
-
-		/*
-		 * 8974 hardware revisions older than v1.2 may experience L2
-		 * parity errors when running at some performance points between
-		 * 300MHz and 1497.6MHz (non-inclusive), or when vdd_mx is less
-		 * than 1.05V. Restrict L2 operation to safe performance points
-		 * on these devices.
-		 */
-		if (SOCINFO_VERSION_MINOR(socinfo_get_version()) < 2)
-			apply_v1_l2_workaround();
-	}
-
 	if (cpu_is_msm8974pro())
-		apply_pro_bringup_workaround();
+		acpuclk_8974_params.pvs_tables = pvs_pro;
+	else
+		acpuclk_8974_params.pvs_tables = pvs_v2;
 
 	return acpuclk_krait_init(&pdev->dev, &acpuclk_8974_params);
 }
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index cf3fac0..c5b1deb 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -761,15 +761,22 @@
 	}
 
 	/*
-	 * Increment the L2 HFPLL regulator refcount if _this_ CPU's frequency
-	 * requires a corresponding target L2 frequency that needs the L2 to
-	 * run off of an HFPLL.
+	 * Vote for the L2 HFPLL regulators if _this_ CPU's frequency requires
+	 * a corresponding target L2 frequency that needs the L2 an HFPLL.
 	 */
-	if (drv.l2_freq_tbl[acpu_level->l2_level].speed.src == HFPLL)
-		l2_vreg_count++;
+	if (drv.l2_freq_tbl[acpu_level->l2_level].speed.src == HFPLL) {
+		ret = enable_l2_regulators();
+		if (ret) {
+			dev_err(drv.dev, "enable_l2_regulators() failed (%d)\n",
+				ret);
+			goto err_l2_regs;
+		}
+	}
 
 	return 0;
 
+err_l2_regs:
+	regulator_disable(sc->vreg[VREG_CORE].reg);
 err_core_conf:
 	regulator_put(sc->vreg[VREG_CORE].reg);
 err_core_get:
@@ -901,7 +908,7 @@
 			ret = -ENODEV;
 			goto err_table;
 		}
-		dev_dbg(drv.dev, "CPU%d is running at an unknown rate. Defaulting to %lu KHz.\n",
+		dev_warn(drv.dev, "CPU%d is running at an unknown rate. Defaulting to %lu KHz.\n",
 			cpu, acpu_level->speed.khz);
 	} else {
 		dev_dbg(drv.dev, "CPU%d is running at %lu KHz\n", cpu,
@@ -1208,7 +1215,7 @@
 	l2_level = find_cur_l2_level();
 	if (!l2_level) {
 		l2_level = drv.l2_freq_tbl;
-		dev_dbg(drv.dev, "L2 is running at an unknown rate. Defaulting to %lu KHz.\n",
+		dev_warn(drv.dev, "L2 is running at an unknown rate. Defaulting to %lu KHz.\n",
 			l2_level->speed.khz);
 	} else {
 		dev_dbg(drv.dev, "L2 is running at %lu KHz\n",
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 34e23d1..9767746 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -185,7 +185,14 @@
 
 static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
 	{
-		.gpio = 25,
+		.gpio = 25,		/* LCD Reset */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &lcd_rst_act_cfg,
+			[GPIOMUX_SUSPENDED] = &lcd_rst_sus_cfg,
+		},
+	},
+	{
+		.gpio = 109,		/* LCD Enable */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &lcd_rst_act_cfg,
 			[GPIOMUX_SUSPENDED] = &lcd_rst_sus_cfg,
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 80a957f..7b13bbc 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -108,6 +108,11 @@
 	msm_thermal_device_init();
 }
 
+static struct of_dev_auxdata msm_hsic_host_adata[] = {
+	OF_DEV_AUXDATA("qcom,hsic-host", 0xF9A00000, "msm_hsic_host", NULL),
+	{}
+};
+
 static struct of_dev_auxdata msm8974_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
 			"msm_otg", NULL),
@@ -148,6 +153,8 @@
 			"qcrypto.0", NULL),
 	OF_DEV_AUXDATA("qcom,hsic-host", 0xF9A00000, \
 			"msm_hsic_host", NULL),
+	OF_DEV_AUXDATA("qcom,hsic-smsc-hub", 0, "msm_smsc_hub",
+			msm_hsic_host_adata),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index a883e39..da0e500 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -694,6 +694,7 @@
 	F_GCC(  56000000,      gpll0,   1,    7,   75),
 	F_GCC(  58982400,      gpll0,   1, 1536, 15625),
 	F_GCC(  60000000,      gpll0,  10,    0,    0),
+	F_GCC(  63160000,      gpll0, 9.5,    0,    0),
 	F_END
 };
 
@@ -1278,6 +1279,7 @@
 	.en_mask = BIT(5),
 	.base = &virt_bases[GCC_BASE],
 	.c = {
+		.parent = &ce1_clk_src.c,
 		.dbg_name = "gcc_ce1_clk",
 		.ops = &clk_ops_vote,
 		CLK_INIT(gcc_ce1_clk.c),
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 45a6b89..5e312aa 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -676,6 +676,7 @@
 	F(  960000, gcc_xo, 10, 1, 2),
 	F( 4800000, gcc_xo,  4, 0, 0),
 	F( 9600000, gcc_xo,  2, 0, 0),
+	F(12000000,  gpll0, 10, 1, 5),
 	F(15000000,  gpll0, 10, 1, 4),
 	F(19200000, gcc_xo,  1, 0, 0),
 	F(25000000,  gpll0, 12, 1, 2),
@@ -782,6 +783,7 @@
 	F(56000000,  gpll0,    1,    7,    75),
 	F(58982400,  gpll0,    1, 1536, 15625),
 	F(60000000,  gpll0,   10,    0,     0),
+	F(63160000,  gpll0,  9.5,    0,     0),
 	F_END,
 };
 
@@ -1283,6 +1285,7 @@
 	.en_mask = BIT(5),
 	.base = &virt_bases[GCC_BASE],
 	.c = {
+		.parent = &ce1_clk_src.c,
 		.dbg_name = "gcc_ce1_clk",
 		.ops = &clk_ops_vote,
 		CLK_INIT(gcc_ce1_clk.c),
@@ -3040,10 +3043,12 @@
 		"fda00c00.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_clk", csi0phytimer_clk.c,
 		"fda00c00.qcom,csiphy"),
+	CLK_LOOKUP("csi_ahb_clk", csi_ahb_clk.c, "fda00c00.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_src_clk", csi1phytimer_clk_src.c,
 		"fda01000.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_clk", csi1phytimer_clk.c,
 		"fda01000.qcom,csiphy"),
+	CLK_LOOKUP("csi_ahb_clk", csi_ahb_clk.c,  "fda01000.qcom,csiphy"),
 
 	/* CSID clocks */
 	CLK_LOOKUP("csi_clk", csi0_clk.c, "fda00000.qcom,csid"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 03fcb25..c95726f 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -2200,6 +2200,7 @@
 	.en_mask = BIT(5),
 	.base = &virt_bases[GCC_BASE],
 	.c = {
+		.parent = &ce1_clk_src.c,
 		.dbg_name = "gcc_ce1_clk",
 		.ops = &clk_ops_vote,
 		CLK_INIT(gcc_ce1_clk.c),
@@ -2236,6 +2237,7 @@
 	.en_mask = BIT(2),
 	.base = &virt_bases[GCC_BASE],
 	.c = {
+		.parent = &ce2_clk_src.c,
 		.dbg_name = "gcc_ce2_clk",
 		.ops = &clk_ops_vote,
 		CLK_INIT(gcc_ce2_clk.c),
diff --git a/arch/arm/mach-msm/clock-krypton.c b/arch/arm/mach-msm/clock-krypton.c
index 176dc32..2b529b0 100644
--- a/arch/arm/mach-msm/clock-krypton.c
+++ b/arch/arm/mach-msm/clock-krypton.c
@@ -515,6 +515,7 @@
 	F(  56000000,      gpll0,    1,    7,    75),
 	F(  58982400,      gpll0,    1, 1536, 15625),
 	F(  60000000,      gpll0,   10,    0,     0),
+	F(  63160000,      gpll0,  9.5,    0,     0),
 	F_END
 };
 
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index 7c06268..c480e56 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -112,8 +112,8 @@
 			continue;
 
 		state = &msm_cpuidle_driver.states[state_count];
-		snprintf(state->name, CPUIDLE_NAME_LEN, cstate->name);
-		snprintf(state->desc, CPUIDLE_DESC_LEN, cstate->desc);
+		snprintf(state->name, CPUIDLE_NAME_LEN, "%s", cstate->name);
+		snprintf(state->desc, CPUIDLE_DESC_LEN, "%s", cstate->desc);
 		state->flags = 0;
 		state->exit_latency = 0;
 		state->power_usage = 0;
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index f8a32b4..2956bd6 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -180,6 +180,7 @@
 	mov	r2, #1
 	and	r1, r2, r1, ASR #30 /* Check if the cache is write back */
 	orr	r1, r0, r1
+	and	r1, r1, #1
 	cmp	r1, #1
 	bne	skip
 	bl	v7_flush_dcache_all
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
index ff3da11..3973044 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
@@ -30,6 +30,7 @@
 		bool down_mix);
 	int (*get_audio_edid_blk) (struct platform_device *pdev,
 		struct msm_hdmi_audio_edid_blk *blk);
+	int (*hdmi_cable_status) (struct platform_device *pdev, u32 vote);
 };
 
 int msm_hdmi_register_audio_codec(struct platform_device *pdev,
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 20a5249..1d5e0d9 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -553,7 +553,8 @@
 	ida_simple_remove(&domain_nums, data->domain_num);
 
 	for (i = 0; i < data->npools; ++i)
-		gen_pool_destroy(data->pools[i].gpool);
+		if (data->pools[i].gpool)
+			gen_pool_destroy(data->pools[i].gpool);
 
 	kfree(data->pools);
 	kfree(data);
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index bdda546..5aa6c93 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -589,17 +589,24 @@
 };
 
 static const struct proto_ops msm_ipc_proto_ops = {
-	.owner		= THIS_MODULE,
 	.family         = AF_MSM_IPC,
+	.owner		= THIS_MODULE,
+	.release        = msm_ipc_router_close,
 	.bind		= msm_ipc_router_bind,
 	.connect	= sock_no_connect,
+	.socketpair	= sock_no_socketpair,
+	.accept		= sock_no_accept,
+	.getname	= sock_no_getname,
+	.poll           = msm_ipc_router_poll,
+	.ioctl          = msm_ipc_router_ioctl,
+	.listen		= sock_no_listen,
+	.shutdown	= sock_no_shutdown,
+	.setsockopt     = sock_no_setsockopt,
+	.getsockopt     = sock_no_getsockopt,
 	.sendmsg	= msm_ipc_router_sendmsg,
 	.recvmsg	= msm_ipc_router_recvmsg,
-	.ioctl		= msm_ipc_router_ioctl,
-	.poll		= msm_ipc_router_poll,
-	.setsockopt	= sock_no_setsockopt,
-	.getsockopt	= sock_no_getsockopt,
-	.release	= msm_ipc_router_close,
+	.mmap		= sock_no_mmap,
+	.sendpage	= sock_no_sendpage,
 };
 
 static struct proto msm_ipc_proto = {
diff --git a/arch/arm/mach-msm/pil-msa.c b/arch/arm/mach-msm/pil-msa.c
index 3a26af9..76afe6c 100644
--- a/arch/arm/mach-msm/pil-msa.c
+++ b/arch/arm/mach-msm/pil-msa.c
@@ -233,18 +233,17 @@
 	if (drv->self_auth) {
 		ret = pil_msa_wait_for_mba_ready(drv);
 		if (ret)
-			goto err_auth;
+			goto err_q6v5_reset;
 	}
 
 	drv->is_booted = true;
 
 	return 0;
 
-err_auth:
-	pil_q6v5_shutdown(pil);
 err_q6v5_reset:
 	pil_msa_pbl_disable_clks(drv);
 err_clks:
+	writel_relaxed(1, drv->restart_reg);
 	pil_msa_pbl_power_down(drv);
 err_power:
 	return ret;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c b/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c
deleted file mode 100644
index 8aacb56..0000000
--- a/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c
+++ /dev/null
@@ -1,1731 +0,0 @@
-/* Copyright (c) 2010-2012, 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/module.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/msm_audio.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <mach/qdsp6v2/audio_dev_ctl.h>
-#include <mach/debug_mm.h>
-#include <mach/qdsp6v2/q6voice.h>
-#include <sound/apr_audio.h>
-#include <sound/q6adm.h>
-
-#ifndef MAX
-#define  MAX(x, y) (((x) > (y)) ? (x) : (y))
-#endif
-
-
-static DEFINE_MUTEX(session_lock);
-static struct workqueue_struct *msm_reset_device_work_queue;
-static void reset_device_work(struct work_struct *work);
-static DECLARE_WORK(msm_reset_device_work, reset_device_work);
-
-struct audio_dev_ctrl_state {
-	struct msm_snddev_info *devs[AUDIO_DEV_CTL_MAX_DEV];
-	u32 num_dev;
-	atomic_t opened;
-	struct msm_snddev_info *voice_rx_dev;
-	struct msm_snddev_info *voice_tx_dev;
-	wait_queue_head_t      wait;
-};
-
-static struct audio_dev_ctrl_state audio_dev_ctrl;
-struct event_listner event;
-
-struct session_freq {
-	int freq;
-	int evt;
-};
-
-struct audio_routing_info {
-	unsigned short mixer_mask[MAX_SESSIONS];
-	unsigned short audrec_mixer_mask[MAX_SESSIONS];
-	struct session_freq dec_freq[MAX_SESSIONS];
-	struct session_freq enc_freq[MAX_SESSIONS];
-	unsigned int copp_list[MAX_SESSIONS][AFE_MAX_PORTS];
-	int voice_tx_dev_id;
-	int voice_rx_dev_id;
-	int voice_tx_sample_rate;
-	int voice_rx_sample_rate;
-	signed int voice_tx_vol;
-	signed int voice_rx_vol;
-	int tx_mute;
-	int rx_mute;
-	int voice_state;
-	struct mutex copp_list_mutex;
-	struct mutex adm_mutex;
-};
-
-static struct audio_routing_info routing_info;
-
-struct audio_copp_topology {
-	struct mutex lock;
-	int session_cnt;
-	int session_id[MAX_SESSIONS];
-	int topolog_id[MAX_SESSIONS];
-};
-static struct audio_copp_topology adm_tx_topology_tbl;
-
-int msm_reset_all_device(void)
-{
-	int rc = 0;
-	int dev_id = 0;
-	struct msm_snddev_info *dev_info = NULL;
-
-	for (dev_id = 0; dev_id < audio_dev_ctrl.num_dev; dev_id++) {
-		dev_info = audio_dev_ctrl_find_dev(dev_id);
-		if (IS_ERR(dev_info)) {
-			pr_err("%s:pass invalid dev_id\n", __func__);
-			rc = PTR_ERR(dev_info);
-			return rc;
-		}
-		if (!dev_info->opened)
-			continue;
-		pr_debug("%s:Resetting device %d active on COPP %d"
-			"with  %lld as routing\n", __func__,
-				dev_id, dev_info->copp_id, dev_info->sessions);
-		broadcast_event(AUDDEV_EVT_REL_PENDING,
-					dev_id,
-					SESSION_IGNORE);
-		rc = dev_info->dev_ops.close(dev_info);
-		if (rc < 0) {
-			pr_err("%s:Snd device failed close!\n", __func__);
-			return rc;
-		} else {
-			dev_info->opened = 0;
-			broadcast_event(AUDDEV_EVT_DEV_RLS,
-				dev_id,
-				SESSION_IGNORE);
-
-			if (dev_info->copp_id == VOICE_PLAYBACK_TX)
-				voice_start_playback(0);
-		}
-		dev_info->sessions = 0;
-	}
-	msm_clear_all_session();
-	return 0;
-}
-EXPORT_SYMBOL(msm_reset_all_device);
-
-static void reset_device_work(struct work_struct *work)
-{
-	msm_reset_all_device();
-}
-
-int reset_device(void)
-{
-	queue_work(msm_reset_device_work_queue, &msm_reset_device_work);
-	return 0;
-}
-EXPORT_SYMBOL(reset_device);
-
-int msm_set_copp_id(int session_id, int copp_id)
-{
-	int rc = 0;
-	int index;
-
-	if (session_id < 1 || session_id > 8)
-		return -EINVAL;
-	if (afe_validate_port(copp_id) < 0)
-		return -EINVAL;
-
-	index = afe_get_port_index(copp_id);
-	if (index < 0 || index > AFE_MAX_PORTS)
-		return -EINVAL;
-	pr_debug("%s: session[%d] copp_id[%d] index[%d]\n", __func__,
-			session_id, copp_id, index);
-	mutex_lock(&routing_info.copp_list_mutex);
-	if (routing_info.copp_list[session_id][index] == COPP_IGNORE)
-		routing_info.copp_list[session_id][index] = copp_id;
-	mutex_unlock(&routing_info.copp_list_mutex);
-
-	return rc;
-}
-EXPORT_SYMBOL(msm_set_copp_id);
-
-int msm_clear_copp_id(int session_id, int copp_id)
-{
-	int rc = 0;
-	int index = afe_get_port_index(copp_id);
-
-	if (session_id < 1 || session_id > 8)
-		return -EINVAL;
-	pr_debug("%s: session[%d] copp_id[%d] index[%d]\n", __func__,
-			session_id, copp_id, index);
-	mutex_lock(&routing_info.copp_list_mutex);
-	if (routing_info.copp_list[session_id][index] == copp_id)
-		routing_info.copp_list[session_id][index] = COPP_IGNORE;
-#ifdef CONFIG_MSM8X60_RTAC
-	rtac_remove_adm_device(copp_id, session_id);
-#endif
-	mutex_unlock(&routing_info.copp_list_mutex);
-
-	return rc;
-}
-EXPORT_SYMBOL(msm_clear_copp_id);
-
-int msm_clear_session_id(int session_id)
-{
-	int rc = 0;
-	int i = 0;
-	if (session_id < 1 || session_id > 8)
-		return -EINVAL;
-	pr_debug("%s: session[%d]\n", __func__, session_id);
-	mutex_lock(&routing_info.adm_mutex);
-	mutex_lock(&routing_info.copp_list_mutex);
-	for (i = 0; i < AFE_MAX_PORTS; i++) {
-		if (routing_info.copp_list[session_id][i] != COPP_IGNORE) {
-			rc = adm_close(routing_info.copp_list[session_id][i]);
-			if (rc < 0) {
-				pr_err("%s: adm close fail port[%d] rc[%d]\n",
-					__func__,
-					routing_info.copp_list[session_id][i],
-					rc);
-				continue;
-			}
-#ifdef CONFIG_MSM8X60_RTAC
-			rtac_remove_adm_device(
-			routing_info.copp_list[session_id][i], session_id);
-#endif
-			routing_info.copp_list[session_id][i] = COPP_IGNORE;
-			rc = 0;
-		}
-	}
-	mutex_unlock(&routing_info.copp_list_mutex);
-	mutex_unlock(&routing_info.adm_mutex);
-
-	return rc;
-}
-EXPORT_SYMBOL(msm_clear_session_id);
-
-int msm_clear_all_session()
-{
-	int rc = 0;
-	int i = 0, j = 0;
-	pr_info("%s:\n", __func__);
-	mutex_lock(&routing_info.adm_mutex);
-	mutex_lock(&routing_info.copp_list_mutex);
-	for (j = 1; j < MAX_SESSIONS; j++) {
-		for (i = 0; i < AFE_MAX_PORTS; i++) {
-			if (routing_info.copp_list[j][i] != COPP_IGNORE) {
-				rc = adm_close(
-					routing_info.copp_list[j][i]);
-				if (rc < 0) {
-					pr_err("%s: adm close fail copp[%d]"
-					"session[%d] rc[%d]\n",
-					__func__,
-					routing_info.copp_list[j][i],
-					j, rc);
-					continue;
-				}
-				routing_info.copp_list[j][i] = COPP_IGNORE;
-				rc = 0;
-			}
-		}
-	}
-	mutex_unlock(&routing_info.copp_list_mutex);
-	mutex_unlock(&routing_info.adm_mutex);
-	return rc;
-}
-EXPORT_SYMBOL(msm_clear_all_session);
-
-int msm_get_voice_state(void)
-{
-	pr_debug("voice state %d\n", routing_info.voice_state);
-	return routing_info.voice_state;
-}
-EXPORT_SYMBOL(msm_get_voice_state);
-
-int msm_set_voice_mute(int dir, int mute, u32 session_id)
-{
-	pr_debug("dir %x mute %x\n", dir, mute);
-	if (dir == DIR_TX) {
-		routing_info.tx_mute = mute;
-		broadcast_event(AUDDEV_EVT_DEVICE_VOL_MUTE_CHG,
-			routing_info.voice_tx_dev_id, session_id);
-	} else
-		return -EPERM;
-	return 0;
-}
-EXPORT_SYMBOL(msm_set_voice_mute);
-
-int msm_set_voice_vol(int dir, s32 volume, u32 session_id)
-{
-	if (dir == DIR_TX) {
-		routing_info.voice_tx_vol = volume;
-		broadcast_event(AUDDEV_EVT_DEVICE_VOL_MUTE_CHG,
-					routing_info.voice_tx_dev_id,
-					session_id);
-	} else if (dir == DIR_RX) {
-		routing_info.voice_rx_vol = volume;
-		broadcast_event(AUDDEV_EVT_DEVICE_VOL_MUTE_CHG,
-					routing_info.voice_rx_dev_id,
-					session_id);
-	} else
-		return -EINVAL;
-	return 0;
-}
-EXPORT_SYMBOL(msm_set_voice_vol);
-
-void msm_snddev_register(struct msm_snddev_info *dev_info)
-{
-	mutex_lock(&session_lock);
-	if (audio_dev_ctrl.num_dev < AUDIO_DEV_CTL_MAX_DEV) {
-		audio_dev_ctrl.devs[audio_dev_ctrl.num_dev] = dev_info;
-		/* roughly 0 DB for digital gain
-		 * If default gain is not desirable, it is expected that
-		 * application sets desired gain before activating sound
-		 * device
-		 */
-		dev_info->dev_volume = 75;
-		dev_info->sessions = 0x0;
-		dev_info->usage_count = 0;
-		audio_dev_ctrl.num_dev++;
-	} else
-		pr_err("%s: device registry max out\n", __func__);
-	mutex_unlock(&session_lock);
-}
-EXPORT_SYMBOL(msm_snddev_register);
-
-int msm_snddev_devcount(void)
-{
-	return audio_dev_ctrl.num_dev;
-}
-EXPORT_SYMBOL(msm_snddev_devcount);
-
-int msm_snddev_query(int dev_id)
-{
-	if (dev_id <= audio_dev_ctrl.num_dev)
-			return 0;
-	return -ENODEV;
-}
-EXPORT_SYMBOL(msm_snddev_query);
-
-int msm_snddev_is_set(int popp_id, int copp_id)
-{
-	return routing_info.mixer_mask[popp_id] & (0x1 << copp_id);
-}
-EXPORT_SYMBOL(msm_snddev_is_set);
-
-unsigned short msm_snddev_route_enc(int enc_id)
-{
-	if (enc_id >= MAX_SESSIONS)
-		return -EINVAL;
-	return routing_info.audrec_mixer_mask[enc_id];
-}
-EXPORT_SYMBOL(msm_snddev_route_enc);
-
-unsigned short msm_snddev_route_dec(int popp_id)
-{
-	if (popp_id >= MAX_SESSIONS)
-		return -EINVAL;
-	return routing_info.mixer_mask[popp_id];
-}
-EXPORT_SYMBOL(msm_snddev_route_dec);
-
-/*To check one->many case*/
-int msm_check_multicopp_per_stream(int session_id,
-				struct route_payload *payload)
-{
-	int i = 0;
-	int flag = 0;
-	pr_debug("%s: session_id=%d\n", __func__, session_id);
-	mutex_lock(&routing_info.copp_list_mutex);
-	for (i = 0; i < AFE_MAX_PORTS; i++) {
-		if (routing_info.copp_list[session_id][i] == COPP_IGNORE)
-			continue;
-		else {
-			pr_debug("Device enabled\n");
-			payload->copp_ids[flag++] =
-				routing_info.copp_list[session_id][i];
-		}
-	}
-	mutex_unlock(&routing_info.copp_list_mutex);
-	if (flag > 1) {
-		pr_debug("Multiple copp per stream case num_copps=%d\n", flag);
-	} else {
-		pr_debug("Stream routed to single copp\n");
-	}
-	payload->num_copps = flag;
-	return flag;
-}
-
-int msm_snddev_set_dec(int popp_id, int copp_id, int set,
-					int rate, int mode)
-{
-	int rc = 0, i = 0, num_copps;
-	struct route_payload payload;
-
-	if ((popp_id >= MAX_SESSIONS) || (popp_id <= 0)) {
-		pr_err("%s: Invalid session id %d\n", __func__, popp_id);
-		return 0;
-	}
-
-	mutex_lock(&routing_info.adm_mutex);
-	if (set) {
-		rc = adm_open(copp_id, ADM_PATH_PLAYBACK, rate, mode,
-			DEFAULT_COPP_TOPOLOGY);
-		if (rc < 0) {
-			pr_err("%s: adm open fail rc[%d]\n", __func__, rc);
-			rc = -EINVAL;
-			mutex_unlock(&routing_info.adm_mutex);
-			return rc;
-		}
-		msm_set_copp_id(popp_id, copp_id);
-		pr_debug("%s:Session id=%d copp_id=%d\n",
-			__func__, popp_id, copp_id);
-		memset(payload.copp_ids, COPP_IGNORE,
-				(sizeof(unsigned int) * AFE_MAX_PORTS));
-		num_copps = msm_check_multicopp_per_stream(popp_id, &payload);
-		/* Multiple streams per copp is handled, one stream at a time */
-		rc = adm_matrix_map(popp_id, ADM_PATH_PLAYBACK, num_copps,
-					payload.copp_ids, copp_id);
-		if (rc < 0) {
-			pr_err("%s: matrix map failed rc[%d]\n",
-				__func__, rc);
-			adm_close(copp_id);
-			rc = -EINVAL;
-			mutex_unlock(&routing_info.adm_mutex);
-			return rc;
-		}
-#ifdef CONFIG_MSM8X60_RTAC
-		for (i = 0; i < num_copps; i++)
-			rtac_add_adm_device(payload.copp_ids[i], popp_id);
-#endif
-	} else {
-		for (i = 0; i < AFE_MAX_PORTS; i++) {
-			if (routing_info.copp_list[popp_id][i] == copp_id) {
-				rc = adm_close(copp_id);
-				if (rc < 0) {
-					pr_err("%s: adm close fail copp[%d]"
-						"rc[%d]\n",
-						__func__, copp_id, rc);
-					rc = -EINVAL;
-					mutex_unlock(&routing_info.adm_mutex);
-					return rc;
-				}
-				msm_clear_copp_id(popp_id, copp_id);
-				break;
-			}
-		}
-	}
-
-	if (copp_id == VOICE_PLAYBACK_TX) {
-		/* Signal uplink playback. */
-		rc = voice_start_playback(set);
-	}
-	mutex_unlock(&routing_info.adm_mutex);
-	return rc;
-}
-EXPORT_SYMBOL(msm_snddev_set_dec);
-
-
-static int check_tx_copp_topology(int session_id)
-{
-	int cnt;
-	int ret_val = -ENOENT;
-
-	cnt = adm_tx_topology_tbl.session_cnt;
-	if (cnt) {
-		do {
-			if (adm_tx_topology_tbl.session_id[cnt-1]
-				== session_id)
-				ret_val = cnt-1;
-		} while (--cnt);
-	}
-
-	return ret_val;
-}
-
-static int add_to_tx_topology_lists(int session_id, int topology)
-{
-	int idx = 0, tbl_idx;
-	int ret_val = -ENOSPC;
-
-	mutex_lock(&adm_tx_topology_tbl.lock);
-
-	tbl_idx = check_tx_copp_topology(session_id);
-	if (tbl_idx == -ENOENT) {
-		while (adm_tx_topology_tbl.session_id[idx++])
-			;
-		tbl_idx = idx-1;
-	}
-
-	if (tbl_idx < MAX_SESSIONS) {
-		adm_tx_topology_tbl.session_id[tbl_idx] = session_id;
-		adm_tx_topology_tbl.topolog_id[tbl_idx] = topology;
-		adm_tx_topology_tbl.session_cnt++;
-
-		ret_val = 0;
-	}
-	mutex_unlock(&adm_tx_topology_tbl.lock);
-	return ret_val;
-}
-
-static void remove_from_tx_topology_lists(int session_id)
-{
-	int tbl_idx;
-
-	mutex_lock(&adm_tx_topology_tbl.lock);
-	tbl_idx = check_tx_copp_topology(session_id);
-	if (tbl_idx != -ENOENT) {
-
-		adm_tx_topology_tbl.session_cnt--;
-		adm_tx_topology_tbl.session_id[tbl_idx] = 0;
-		adm_tx_topology_tbl.topolog_id[tbl_idx] = 0;
-	}
-	mutex_unlock(&adm_tx_topology_tbl.lock);
-}
-
-int auddev_cfg_tx_copp_topology(int session_id, int cfg)
-{
-	int ret = 0;
-
-	if (cfg == DEFAULT_COPP_TOPOLOGY)
-		remove_from_tx_topology_lists(session_id);
-	else {
-		switch (cfg) {
-		case VPM_TX_SM_ECNS_COPP_TOPOLOGY:
-		case VPM_TX_DM_FLUENCE_COPP_TOPOLOGY:
-			ret = add_to_tx_topology_lists(session_id, cfg);
-			break;
-
-		default:
-			ret = -ENODEV;
-			break;
-		}
-	}
-	return ret;
-}
-
-int msm_snddev_set_enc(int popp_id, int copp_id, int set,
-					int rate, int mode)
-{
-	int topology;
-	int tbl_idx;
-	int rc = 0, i = 0;
-	mutex_lock(&routing_info.adm_mutex);
-	if (set) {
-		mutex_lock(&adm_tx_topology_tbl.lock);
-		tbl_idx = check_tx_copp_topology(popp_id);
-		if (tbl_idx == -ENOENT)
-			topology = DEFAULT_COPP_TOPOLOGY;
-		else {
-			topology = adm_tx_topology_tbl.topolog_id[tbl_idx];
-			rate = 16000;
-		}
-		mutex_unlock(&adm_tx_topology_tbl.lock);
-		rc = adm_open(copp_id, ADM_PATH_LIVE_REC, rate, mode, topology);
-		if (rc < 0) {
-			pr_err("%s: adm open fail rc[%d]\n", __func__, rc);
-			rc = -EINVAL;
-			goto fail_cmd;
-		}
-
-		rc = adm_matrix_map(popp_id, ADM_PATH_LIVE_REC, 1,
-					(unsigned int *)&copp_id, copp_id);
-		if (rc < 0) {
-			pr_err("%s: matrix map failed rc[%d]\n", __func__, rc);
-			adm_close(copp_id);
-			rc = -EINVAL;
-			goto fail_cmd;
-		}
-		msm_set_copp_id(popp_id, copp_id);
-#ifdef CONFIG_MSM8X60_RTAC
-	rtac_add_adm_device(copp_id, popp_id);
-#endif
-
-	} else {
-		for (i = 0; i < AFE_MAX_PORTS; i++) {
-			if (routing_info.copp_list[popp_id][i] == copp_id) {
-				rc = adm_close(copp_id);
-				if (rc < 0) {
-					pr_err("%s: adm close fail copp[%d]"
-					"rc[%d]\n",
-							__func__, copp_id, rc);
-					rc = -EINVAL;
-					goto fail_cmd;
-				}
-				msm_clear_copp_id(popp_id, copp_id);
-				break;
-			}
-		}
-	}
-fail_cmd:
-	mutex_unlock(&routing_info.adm_mutex);
-	return rc;
-}
-EXPORT_SYMBOL(msm_snddev_set_enc);
-
-int msm_device_is_voice(int dev_id)
-{
-	if ((dev_id == routing_info.voice_rx_dev_id)
-		|| (dev_id == routing_info.voice_tx_dev_id))
-		return 0;
-	else
-		return -EINVAL;
-}
-EXPORT_SYMBOL(msm_device_is_voice);
-
-int msm_set_voc_route(struct msm_snddev_info *dev_info,
-			int stream_type, int dev_id)
-{
-	int rc = 0;
-	u64 session_mask = 0;
-
-	mutex_lock(&session_lock);
-	switch (stream_type) {
-	case AUDIO_ROUTE_STREAM_VOICE_RX:
-		if (audio_dev_ctrl.voice_rx_dev)
-			audio_dev_ctrl.voice_rx_dev->sessions &= ~0xFFFF;
-
-		if (!(dev_info->capability & SNDDEV_CAP_RX) |
-		    !(dev_info->capability & SNDDEV_CAP_VOICE)) {
-			rc = -EINVAL;
-			break;
-		}
-		audio_dev_ctrl.voice_rx_dev = dev_info;
-		if (audio_dev_ctrl.voice_rx_dev) {
-			session_mask =
-				((u64)0x1) << (MAX_BIT_PER_CLIENT * \
-				((int)AUDDEV_CLNT_VOC-1));
-			audio_dev_ctrl.voice_rx_dev->sessions |=
-				session_mask;
-		}
-		routing_info.voice_rx_dev_id = dev_id;
-		break;
-	case AUDIO_ROUTE_STREAM_VOICE_TX:
-		if (audio_dev_ctrl.voice_tx_dev)
-			audio_dev_ctrl.voice_tx_dev->sessions &= ~0xFFFF;
-
-		if (!(dev_info->capability & SNDDEV_CAP_TX) |
-		    !(dev_info->capability & SNDDEV_CAP_VOICE)) {
-			rc = -EINVAL;
-			break;
-		}
-
-		audio_dev_ctrl.voice_tx_dev = dev_info;
-		if (audio_dev_ctrl.voice_rx_dev) {
-			session_mask =
-				((u64)0x1) << (MAX_BIT_PER_CLIENT * \
-					((int)AUDDEV_CLNT_VOC-1));
-			audio_dev_ctrl.voice_tx_dev->sessions |=
-				session_mask;
-		}
-		routing_info.voice_tx_dev_id = dev_id;
-		break;
-	default:
-		rc = -EINVAL;
-	}
-	mutex_unlock(&session_lock);
-	return rc;
-}
-EXPORT_SYMBOL(msm_set_voc_route);
-
-void msm_release_voc_thread(void)
-{
-	wake_up(&audio_dev_ctrl.wait);
-}
-EXPORT_SYMBOL(msm_release_voc_thread);
-
-int msm_snddev_get_enc_freq(session_id)
-{
-	return routing_info.enc_freq[session_id].freq;
-}
-EXPORT_SYMBOL(msm_snddev_get_enc_freq);
-
-int msm_get_voc_freq(int *tx_freq, int *rx_freq)
-{
-	*tx_freq = routing_info.voice_tx_sample_rate;
-	*rx_freq = routing_info.voice_rx_sample_rate;
-	return 0;
-}
-EXPORT_SYMBOL(msm_get_voc_freq);
-
-int msm_get_voc_route(u32 *rx_id, u32 *tx_id)
-{
-	int rc = 0;
-
-	if (!rx_id || !tx_id)
-		return -EINVAL;
-
-	mutex_lock(&session_lock);
-	if (!audio_dev_ctrl.voice_rx_dev || !audio_dev_ctrl.voice_tx_dev) {
-		rc = -ENODEV;
-		mutex_unlock(&session_lock);
-		return rc;
-	}
-
-	*rx_id = audio_dev_ctrl.voice_rx_dev->acdb_id;
-	*tx_id = audio_dev_ctrl.voice_tx_dev->acdb_id;
-
-	mutex_unlock(&session_lock);
-
-	return rc;
-}
-EXPORT_SYMBOL(msm_get_voc_route);
-
-struct msm_snddev_info *audio_dev_ctrl_find_dev(u32 dev_id)
-{
-	struct msm_snddev_info *info;
-
-	if ((audio_dev_ctrl.num_dev - 1) < dev_id) {
-		info = ERR_PTR(-ENODEV);
-		goto error;
-	}
-
-	info = audio_dev_ctrl.devs[dev_id];
-error:
-	return info;
-
-}
-EXPORT_SYMBOL(audio_dev_ctrl_find_dev);
-
-int snddev_voice_set_volume(int vol, int path)
-{
-	if (audio_dev_ctrl.voice_rx_dev
-		&& audio_dev_ctrl.voice_tx_dev) {
-		if (path)
-			audio_dev_ctrl.voice_tx_dev->dev_volume = vol;
-		else
-			audio_dev_ctrl.voice_rx_dev->dev_volume = vol;
-	} else
-		return -ENODEV;
-	return 0;
-}
-EXPORT_SYMBOL(snddev_voice_set_volume);
-
-static int audio_dev_ctrl_get_devices(struct audio_dev_ctrl_state *dev_ctrl,
-				      void __user *arg)
-{
-	int rc = 0;
-	u32 index;
-	struct msm_snd_device_list work_list;
-	struct msm_snd_device_info *work_tbl;
-
-	if (copy_from_user(&work_list, arg, sizeof(work_list))) {
-		rc = -EFAULT;
-		goto error;
-	}
-
-	if (work_list.num_dev > dev_ctrl->num_dev) {
-		rc = -EINVAL;
-		goto error;
-	}
-
-	work_tbl = kmalloc(work_list.num_dev *
-		sizeof(struct msm_snd_device_info), GFP_KERNEL);
-	if (!work_tbl) {
-		rc = -ENOMEM;
-		goto error;
-	}
-
-	for (index = 0; index < dev_ctrl->num_dev; index++) {
-		work_tbl[index].dev_id = index;
-		work_tbl[index].dev_cap = dev_ctrl->devs[index]->capability;
-		strlcpy(work_tbl[index].dev_name, dev_ctrl->devs[index]->name,
-		64);
-	}
-
-	if (copy_to_user((void *) (work_list.list), work_tbl,
-		 work_list.num_dev * sizeof(struct msm_snd_device_info)))
-		rc = -EFAULT;
-	kfree(work_tbl);
-error:
-	return rc;
-}
-
-
-int auddev_register_evt_listner(u32 evt_id, u32 clnt_type, u32 clnt_id,
-		void (*listner)(u32 evt_id,
-			union auddev_evt_data *evt_payload,
-			void *private_data),
-		void *private_data)
-{
-	int rc;
-	struct msm_snd_evt_listner *callback = NULL;
-	struct msm_snd_evt_listner *new_cb;
-
-	new_cb = kzalloc(sizeof(struct msm_snd_evt_listner), GFP_KERNEL);
-	if (!new_cb) {
-		pr_err("No memory to add new listener node\n");
-		return -ENOMEM;
-	}
-
-	mutex_lock(&session_lock);
-	new_cb->cb_next = NULL;
-	new_cb->auddev_evt_listener = listner;
-	new_cb->evt_id = evt_id;
-	new_cb->clnt_type = clnt_type;
-	new_cb->clnt_id = clnt_id;
-	new_cb->private_data = private_data;
-	if (event.cb == NULL) {
-		event.cb = new_cb;
-		new_cb->cb_prev = NULL;
-	} else {
-		callback = event.cb;
-		for (; ;) {
-			if (callback->cb_next == NULL)
-				break;
-			else {
-				callback = callback->cb_next;
-				continue;
-			}
-		}
-		callback->cb_next = new_cb;
-		new_cb->cb_prev = callback;
-	}
-	event.num_listner++;
-	mutex_unlock(&session_lock);
-	rc = 0;
-	return rc;
-}
-EXPORT_SYMBOL(auddev_register_evt_listner);
-
-int auddev_unregister_evt_listner(u32 clnt_type, u32 clnt_id)
-{
-	struct msm_snd_evt_listner *callback = event.cb;
-	struct msm_snddev_info *info;
-	u64 session_mask = 0;
-	int i = 0;
-
-	mutex_lock(&session_lock);
-	while (callback != NULL) {
-		if ((callback->clnt_type == clnt_type)
-			&& (callback->clnt_id == clnt_id))
-			break;
-		 callback = callback->cb_next;
-	}
-	if (callback == NULL) {
-		mutex_unlock(&session_lock);
-		return -EINVAL;
-	}
-
-	if ((callback->cb_next == NULL) && (callback->cb_prev == NULL))
-		event.cb = NULL;
-	else if (callback->cb_next == NULL)
-		callback->cb_prev->cb_next = NULL;
-	else if (callback->cb_prev == NULL) {
-		callback->cb_next->cb_prev = NULL;
-		event.cb = callback->cb_next;
-	} else {
-		callback->cb_prev->cb_next = callback->cb_next;
-		callback->cb_next->cb_prev = callback->cb_prev;
-	}
-	kfree(callback);
-
-	session_mask = (((u64)0x1) << clnt_id) << (MAX_BIT_PER_CLIENT * \
-				((int)clnt_type-1));
-	for (i = 0; i < audio_dev_ctrl.num_dev; i++) {
-		info = audio_dev_ctrl.devs[i];
-		info->sessions &= ~session_mask;
-	}
-	mutex_unlock(&session_lock);
-	return 0;
-}
-EXPORT_SYMBOL(auddev_unregister_evt_listner);
-
-int msm_snddev_withdraw_freq(u32 session_id, u32 capability, u32 clnt_type)
-{
-	int i = 0;
-	struct msm_snddev_info *info;
-	u64 session_mask = 0;
-
-	if ((clnt_type == AUDDEV_CLNT_VOC) && (session_id != 0))
-		return -EINVAL;
-	if ((clnt_type == AUDDEV_CLNT_DEC)
-			&& (session_id >= MAX_SESSIONS))
-		return -EINVAL;
-	if ((clnt_type == AUDDEV_CLNT_ENC)
-			&& (session_id >= MAX_SESSIONS))
-		return -EINVAL;
-
-	session_mask = (((u64)0x1) << session_id) << (MAX_BIT_PER_CLIENT * \
-				((int)clnt_type-1));
-
-	for (i = 0; i < audio_dev_ctrl.num_dev; i++) {
-		info = audio_dev_ctrl.devs[i];
-		if ((info->sessions & session_mask)
-			&& (info->capability & capability)) {
-			if (!(info->sessions & ~(session_mask)))
-				info->set_sample_rate = 0;
-		}
-	}
-	if (clnt_type == AUDDEV_CLNT_DEC)
-		routing_info.dec_freq[session_id].freq
-					= 0;
-	else if (clnt_type == AUDDEV_CLNT_ENC)
-		routing_info.enc_freq[session_id].freq
-					= 0;
-	else if (capability == SNDDEV_CAP_TX)
-		routing_info.voice_tx_sample_rate = 0;
-	else
-		routing_info.voice_rx_sample_rate = 48000;
-	return 0;
-}
-
-int msm_snddev_request_freq(int *freq, u32 session_id,
-			u32 capability, u32 clnt_type)
-{
-	int i = 0;
-	int rc = 0;
-	struct msm_snddev_info *info;
-	u32 set_freq;
-	u64 session_mask = 0;
-	u64 clnt_type_mask = 0;
-
-	pr_debug(": clnt_type 0x%08x\n", clnt_type);
-
-	if ((clnt_type == AUDDEV_CLNT_VOC) && (session_id != 0))
-		return -EINVAL;
-	if ((clnt_type == AUDDEV_CLNT_DEC)
-			&& (session_id >= MAX_SESSIONS))
-		return -EINVAL;
-	if ((clnt_type == AUDDEV_CLNT_ENC)
-			&& (session_id >= MAX_SESSIONS))
-		return -EINVAL;
-	session_mask = (((u64)0x1) << session_id) << (MAX_BIT_PER_CLIENT * \
-				((int)clnt_type-1));
-	clnt_type_mask = (0xFFFF << (MAX_BIT_PER_CLIENT * (clnt_type-1)));
-	if (!(*freq == 8000) && !(*freq == 11025) &&
-		!(*freq == 12000) && !(*freq == 16000) &&
-		!(*freq == 22050) && !(*freq == 24000) &&
-		!(*freq == 32000) && !(*freq == 44100) &&
-		!(*freq == 48000))
-		return -EINVAL;
-
-	for (i = 0; i < audio_dev_ctrl.num_dev; i++) {
-		info = audio_dev_ctrl.devs[i];
-		if ((info->sessions & session_mask)
-			&& (info->capability & capability)) {
-			rc = 0;
-			if ((info->sessions & ~clnt_type_mask)
-				&& ((*freq != 8000) && (*freq != 16000)
-					&& (*freq != 48000))) {
-				if (clnt_type == AUDDEV_CLNT_ENC) {
-					routing_info.enc_freq[session_id].freq
-							= 0;
-					return -EPERM;
-				} else if (clnt_type == AUDDEV_CLNT_DEC) {
-					routing_info.dec_freq[session_id].freq
-							= 0;
-					return -EPERM;
-				}
-			}
-			if (*freq == info->set_sample_rate) {
-				rc = info->set_sample_rate;
-				continue;
-			}
-			set_freq = MAX(*freq, info->set_sample_rate);
-
-
-			if (clnt_type == AUDDEV_CLNT_DEC) {
-				routing_info.dec_freq[session_id].evt = 1;
-				routing_info.dec_freq[session_id].freq
-						= set_freq;
-			} else if (clnt_type == AUDDEV_CLNT_ENC) {
-				routing_info.enc_freq[session_id].evt = 1;
-				routing_info.enc_freq[session_id].freq
-						= set_freq;
-			} else if (capability == SNDDEV_CAP_TX)
-				routing_info.voice_tx_sample_rate = set_freq;
-
-			rc = set_freq;
-			info->set_sample_rate = set_freq;
-			*freq = info->set_sample_rate;
-
-			if (info->opened) {
-				broadcast_event(AUDDEV_EVT_FREQ_CHG, i,
-							SESSION_IGNORE);
-				set_freq = info->dev_ops.set_freq(info,
-								set_freq);
-				broadcast_event(AUDDEV_EVT_DEV_RDY, i,
-							SESSION_IGNORE);
-			}
-		}
-		pr_debug("info->set_sample_rate = %d\n", info->set_sample_rate);
-		pr_debug("routing_info.enc_freq.freq = %d\n",
-					routing_info.enc_freq[session_id].freq);
-	}
-	return rc;
-}
-EXPORT_SYMBOL(msm_snddev_request_freq);
-
-int msm_snddev_enable_sidetone(u32 dev_id, u32 enable, uint16_t gain)
-{
-	int rc;
-	struct msm_snddev_info *dev_info;
-
-	pr_debug("dev_id %d enable %d\n", dev_id, enable);
-
-	dev_info = audio_dev_ctrl_find_dev(dev_id);
-
-	if (IS_ERR(dev_info)) {
-		pr_err("bad dev_id %d\n", dev_id);
-		rc = -EINVAL;
-	} else if (!dev_info->dev_ops.enable_sidetone) {
-		pr_debug("dev %d no sidetone support\n", dev_id);
-		rc = -EPERM;
-	} else
-		rc = dev_info->dev_ops.enable_sidetone(dev_info, enable, gain);
-
-	return rc;
-}
-EXPORT_SYMBOL(msm_snddev_enable_sidetone);
-
-int msm_enable_incall_recording(int popp_id, int rec_mode, int rate,
-				int channel_mode)
-{
-	int rc = 0;
-	unsigned int port_id[2];
-	port_id[0] = VOICE_RECORD_TX;
-	port_id[1] = VOICE_RECORD_RX;
-
-	pr_debug("%s: popp_id %d, rec_mode %d, rate %d, channel_mode %d\n",
-		 __func__, popp_id, rec_mode, rate, channel_mode);
-
-	mutex_lock(&routing_info.adm_mutex);
-
-	if (rec_mode == VOC_REC_UPLINK) {
-		rc = afe_start_pseudo_port(port_id[0]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in Tx pseudo port start\n",
-			       __func__, rc);
-
-			goto fail_cmd;
-		}
-
-		rc = adm_open(port_id[0], ADM_PATH_LIVE_REC, rate, channel_mode,
-				DEFAULT_COPP_TOPOLOGY);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM open %d\n",
-			       __func__, rc, port_id[0]);
-
-			goto fail_cmd;
-		}
-
-		rc = adm_matrix_map(popp_id, ADM_PATH_LIVE_REC, 1,
-				&port_id[0], port_id[0]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM matrix map %d\n",
-			       __func__, rc, port_id[0]);
-
-			goto fail_cmd;
-		}
-
-		msm_set_copp_id(popp_id, port_id[0]);
-
-	} else if (rec_mode == VOC_REC_DOWNLINK) {
-		rc = afe_start_pseudo_port(port_id[1]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in Rx pseudo port start\n",
-			       __func__, rc);
-
-			goto fail_cmd;
-		}
-
-		rc = adm_open(port_id[1], ADM_PATH_LIVE_REC, rate, channel_mode,
-				DEFAULT_COPP_TOPOLOGY);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM open %d\n",
-			       __func__, rc, port_id[1]);
-
-			goto fail_cmd;
-		}
-
-		rc = adm_matrix_map(popp_id, ADM_PATH_LIVE_REC, 1,
-				&port_id[1], port_id[1]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM matrix map %d\n",
-			       __func__, rc, port_id[1]);
-
-			goto fail_cmd;
-		}
-
-		msm_set_copp_id(popp_id, port_id[1]);
-
-	} else if (rec_mode == VOC_REC_BOTH) {
-		rc = afe_start_pseudo_port(port_id[0]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in Tx pseudo port start\n",
-			       __func__, rc);
-
-			goto fail_cmd;
-		}
-
-		rc = adm_open(port_id[0], ADM_PATH_LIVE_REC, rate, channel_mode,
-				DEFAULT_COPP_TOPOLOGY);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM open %d\n",
-			       __func__, rc, port_id[0]);
-
-			goto fail_cmd;
-		}
-
-		msm_set_copp_id(popp_id, port_id[0]);
-
-		rc = afe_start_pseudo_port(port_id[1]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in Rx pseudo port start\n",
-			       __func__, rc);
-
-			goto fail_cmd;
-		}
-
-		rc = adm_open(port_id[1], ADM_PATH_LIVE_REC, rate, channel_mode,
-				DEFAULT_COPP_TOPOLOGY);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM open %d\n",
-			       __func__, rc, port_id[0]);
-
-			goto fail_cmd;
-		}
-
-		rc = adm_matrix_map(popp_id, ADM_PATH_LIVE_REC, 2,
-				&port_id[0], port_id[1]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM matrix map\n",
-			       __func__, rc);
-
-			goto fail_cmd;
-		}
-
-		msm_set_copp_id(popp_id, port_id[1]);
-	} else {
-		pr_err("%s Unknown rec_mode %d\n", __func__, rec_mode);
-
-		goto fail_cmd;
-	}
-
-	rc = voice_start_record(rec_mode, 1);
-
-fail_cmd:
-	mutex_unlock(&routing_info.adm_mutex);
-	return rc;
-}
-
-int msm_disable_incall_recording(uint32_t popp_id, uint32_t rec_mode)
-{
-	int rc = 0;
-	uint32_t port_id[2];
-	port_id[0] = VOICE_RECORD_TX;
-	port_id[1] = VOICE_RECORD_RX;
-
-	pr_debug("%s: popp_id %d, rec_mode %d\n", __func__, popp_id, rec_mode);
-
-	mutex_lock(&routing_info.adm_mutex);
-
-	rc = voice_start_record(rec_mode, 0);
-	if (rc < 0) {
-		pr_err("%s: Error %d stopping record\n", __func__, rc);
-
-		goto fail_cmd;
-	}
-
-	if (rec_mode == VOC_REC_UPLINK) {
-		rc = adm_close(port_id[0]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM close %d\n",
-			       __func__, rc, port_id[0]);
-
-			goto fail_cmd;
-		}
-
-		msm_clear_copp_id(popp_id, port_id[0]);
-
-		rc = afe_stop_pseudo_port(port_id[0]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in Tx pseudo port stop\n",
-			       __func__, rc);
-			goto fail_cmd;
-		}
-
-	} else if (rec_mode == VOC_REC_DOWNLINK) {
-		rc = adm_close(port_id[1]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM close %d\n",
-			       __func__, rc, port_id[1]);
-
-			goto fail_cmd;
-		}
-
-		msm_clear_copp_id(popp_id, port_id[1]);
-
-		rc = afe_stop_pseudo_port(port_id[1]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in Rx pseudo port stop\n",
-			       __func__, rc);
-			goto fail_cmd;
-		}
-	} else if (rec_mode == VOC_REC_BOTH) {
-		rc = adm_close(port_id[0]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM close %d\n",
-			       __func__, rc, port_id[0]);
-
-			goto fail_cmd;
-		}
-
-		msm_clear_copp_id(popp_id, port_id[0]);
-
-		rc = afe_stop_pseudo_port(port_id[0]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in Tx pseudo port stop\n",
-			       __func__, rc);
-			goto fail_cmd;
-		}
-
-		rc = adm_close(port_id[1]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in ADM close %d\n",
-			       __func__, rc, port_id[1]);
-
-			goto fail_cmd;
-		}
-
-		msm_clear_copp_id(popp_id, port_id[1]);
-
-		rc = afe_stop_pseudo_port(port_id[1]);
-		if (rc < 0) {
-			pr_err("%s: Error %d in Rx pseudo port stop\n",
-			       __func__, rc);
-			goto fail_cmd;
-		}
-	} else {
-		pr_err("%s Unknown rec_mode %d\n", __func__, rec_mode);
-
-		goto fail_cmd;
-	}
-
-fail_cmd:
-	mutex_unlock(&routing_info.adm_mutex);
-	return rc;
-}
-
-static long audio_dev_ctrl_ioctl(struct file *file,
-	unsigned int cmd, unsigned long arg)
-{
-	int rc = 0;
-	struct audio_dev_ctrl_state *dev_ctrl = file->private_data;
-
-	mutex_lock(&session_lock);
-	switch (cmd) {
-	case AUDIO_GET_NUM_SND_DEVICE:
-		rc = put_user(dev_ctrl->num_dev, (uint32_t __user *) arg);
-		break;
-	case AUDIO_GET_SND_DEVICES:
-		rc = audio_dev_ctrl_get_devices(dev_ctrl, (void __user *) arg);
-		break;
-	case AUDIO_ENABLE_SND_DEVICE: {
-		struct msm_snddev_info *dev_info;
-		u32 dev_id;
-
-		if (get_user(dev_id, (u32 __user *) arg)) {
-			rc = -EFAULT;
-			break;
-		}
-		dev_info = audio_dev_ctrl_find_dev(dev_id);
-		if (IS_ERR(dev_info))
-			rc = PTR_ERR(dev_info);
-		else {
-			rc = dev_info->dev_ops.open(dev_info);
-			if (!rc)
-				dev_info->opened = 1;
-			wake_up(&audio_dev_ctrl.wait);
-		}
-		break;
-
-	}
-
-	case AUDIO_DISABLE_SND_DEVICE: {
-		struct msm_snddev_info *dev_info;
-		u32 dev_id;
-
-		if (get_user(dev_id, (u32 __user *) arg)) {
-			rc = -EFAULT;
-			break;
-		}
-		dev_info = audio_dev_ctrl_find_dev(dev_id);
-		if (IS_ERR(dev_info))
-			rc = PTR_ERR(dev_info);
-		else {
-			rc = dev_info->dev_ops.close(dev_info);
-			dev_info->opened = 0;
-		}
-		break;
-	}
-
-	case AUDIO_ROUTE_STREAM: {
-		struct msm_audio_route_config route_cfg;
-		struct msm_snddev_info *dev_info;
-
-		if (copy_from_user(&route_cfg, (void __user *) arg,
-			sizeof(struct msm_audio_route_config))) {
-			rc = -EFAULT;
-			break;
-		}
-		pr_debug("%s: route cfg %d %d type\n", __func__,
-		route_cfg.dev_id, route_cfg.stream_type);
-		dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id);
-		if (IS_ERR(dev_info)) {
-			pr_err("%s: pass invalid dev_id\n", __func__);
-			rc = PTR_ERR(dev_info);
-			break;
-		}
-
-		switch (route_cfg.stream_type) {
-
-		case AUDIO_ROUTE_STREAM_VOICE_RX:
-			if (!(dev_info->capability & SNDDEV_CAP_RX) |
-			    !(dev_info->capability & SNDDEV_CAP_VOICE)) {
-				rc = -EINVAL;
-				break;
-			}
-			dev_ctrl->voice_rx_dev = dev_info;
-			break;
-		case AUDIO_ROUTE_STREAM_VOICE_TX:
-			if (!(dev_info->capability & SNDDEV_CAP_TX) |
-			    !(dev_info->capability & SNDDEV_CAP_VOICE)) {
-				rc = -EINVAL;
-				break;
-			}
-			dev_ctrl->voice_tx_dev = dev_info;
-			break;
-		}
-		break;
-	}
-
-	default:
-		rc = -EINVAL;
-	}
-	mutex_unlock(&session_lock);
-	return rc;
-}
-
-static int audio_dev_ctrl_open(struct inode *inode, struct file *file)
-{
-	pr_debug("open audio_dev_ctrl\n");
-	atomic_inc(&audio_dev_ctrl.opened);
-	file->private_data = &audio_dev_ctrl;
-	return 0;
-}
-
-static int audio_dev_ctrl_release(struct inode *inode, struct file *file)
-{
-	pr_debug("release audio_dev_ctrl\n");
-	atomic_dec(&audio_dev_ctrl.opened);
-	return 0;
-}
-
-static const struct file_operations audio_dev_ctrl_fops = {
-	.owner = THIS_MODULE,
-	.open = audio_dev_ctrl_open,
-	.release = audio_dev_ctrl_release,
-	.unlocked_ioctl = audio_dev_ctrl_ioctl,
-};
-
-
-struct miscdevice audio_dev_ctrl_misc = {
-	.minor	= MISC_DYNAMIC_MINOR,
-	.name	= "msm_audio_dev_ctrl",
-	.fops	= &audio_dev_ctrl_fops,
-};
-
-/* session id is 64 bit routing mask per device
- * 0-15 for voice clients
- * 16-31 for Decoder clients
- * 32-47 for Encoder clients
- * 48-63 Do not care
- */
-void broadcast_event(u32 evt_id, u32 dev_id, u64 session_id)
-{
-	int clnt_id = 0, i;
-	union auddev_evt_data *evt_payload;
-	struct msm_snd_evt_listner *callback;
-	struct msm_snddev_info *dev_info = NULL;
-	u64 session_mask = 0;
-	static int pending_sent;
-
-	pr_debug(": evt_id = %d\n", evt_id);
-
-	if ((evt_id != AUDDEV_EVT_START_VOICE)
-		&& (evt_id != AUDDEV_EVT_END_VOICE)
-		&& (evt_id != AUDDEV_EVT_STREAM_VOL_CHG)
-		&& (evt_id != AUDDEV_EVT_VOICE_STATE_CHG)) {
-		dev_info = audio_dev_ctrl_find_dev(dev_id);
-		if (IS_ERR(dev_info)) {
-			pr_err("%s: pass invalid dev_id(%d)\n",
-					 __func__, dev_id);
-			return;
-		}
-	}
-
-	if (event.cb != NULL)
-		callback = event.cb;
-	else
-		return;
-	mutex_lock(&session_lock);
-
-	if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG)
-		routing_info.voice_state = dev_id;
-
-	evt_payload = kzalloc(sizeof(union auddev_evt_data),
-			GFP_KERNEL);
-
-	if (evt_payload == NULL) {
-		pr_err("broadcast_event: cannot allocate memory\n");
-		mutex_unlock(&session_lock);
-		return;
-	}
-	for (; ;) {
-		if (!(evt_id & callback->evt_id)) {
-			if (callback->cb_next == NULL)
-				break;
-			else {
-				callback = callback->cb_next;
-				continue;
-			}
-		}
-		clnt_id = callback->clnt_id;
-		memset(evt_payload, 0, sizeof(union auddev_evt_data));
-
-		if ((evt_id == AUDDEV_EVT_START_VOICE)
-			|| (evt_id == AUDDEV_EVT_END_VOICE)
-			|| evt_id == AUDDEV_EVT_DEVICE_VOL_MUTE_CHG)
-			goto skip_check;
-		if (callback->clnt_type == AUDDEV_CLNT_AUDIOCAL)
-			goto aud_cal;
-
-		session_mask = (((u64)0x1) << clnt_id)
-				<< (MAX_BIT_PER_CLIENT * \
-				((int)callback->clnt_type-1));
-
-		if ((evt_id == AUDDEV_EVT_STREAM_VOL_CHG) || \
-			(evt_id == AUDDEV_EVT_VOICE_STATE_CHG)) {
-			pr_debug("AUDDEV_EVT_STREAM_VOL_CHG or\
-				AUDDEV_EVT_VOICE_STATE_CHG\n");
-			goto volume_strm;
-		}
-
-		pr_debug("dev_info->sessions = %llu\n", dev_info->sessions);
-
-		if ((!session_id && !(dev_info->sessions & session_mask)) ||
-			(session_id && ((dev_info->sessions & session_mask) !=
-						session_id))) {
-			if (callback->cb_next == NULL)
-				break;
-			else {
-				callback = callback->cb_next;
-				continue;
-			}
-		}
-		if (evt_id == AUDDEV_EVT_DEV_CHG_VOICE)
-			goto voc_events;
-
-volume_strm:
-		if (callback->clnt_type == AUDDEV_CLNT_DEC) {
-			pr_debug("AUDDEV_CLNT_DEC\n");
-			if (evt_id == AUDDEV_EVT_STREAM_VOL_CHG) {
-				pr_debug("clnt_id = %d, session_id = %llu\n",
-					clnt_id, session_id);
-				if (session_mask != session_id)
-					goto sent_dec;
-				else
-					evt_payload->session_vol =
-						msm_vol_ctl.volume;
-			} else if (evt_id == AUDDEV_EVT_FREQ_CHG) {
-				if (routing_info.dec_freq[clnt_id].evt) {
-					routing_info.dec_freq[clnt_id].evt
-							= 0;
-					goto sent_dec;
-				} else if (routing_info.dec_freq[clnt_id].freq
-					== dev_info->set_sample_rate)
-					goto sent_dec;
-				else {
-					evt_payload->freq_info.sample_rate
-						= dev_info->set_sample_rate;
-					evt_payload->freq_info.dev_type
-						= dev_info->capability;
-					evt_payload->freq_info.acdb_dev_id
-						= dev_info->acdb_id;
-				}
-			} else if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG)
-				evt_payload->voice_state =
-					routing_info.voice_state;
-			else
-				evt_payload->routing_id = dev_info->copp_id;
-			callback->auddev_evt_listener(
-					evt_id,
-					evt_payload,
-					callback->private_data);
-sent_dec:
-			if ((evt_id != AUDDEV_EVT_STREAM_VOL_CHG) &&
-				(evt_id != AUDDEV_EVT_VOICE_STATE_CHG))
-				routing_info.dec_freq[clnt_id].freq
-						= dev_info->set_sample_rate;
-
-			if (callback->cb_next == NULL)
-				break;
-			else {
-				callback = callback->cb_next;
-				continue;
-			}
-		}
-		if (callback->clnt_type == AUDDEV_CLNT_ENC) {
-			pr_debug("AUDDEV_CLNT_ENC\n");
-			if (evt_id == AUDDEV_EVT_FREQ_CHG) {
-				if (routing_info.enc_freq[clnt_id].evt) {
-					routing_info.enc_freq[clnt_id].evt
-							= 0;
-					goto sent_enc;
-				 } else {
-					evt_payload->freq_info.sample_rate
-						= dev_info->set_sample_rate;
-					evt_payload->freq_info.dev_type
-						= dev_info->capability;
-					evt_payload->freq_info.acdb_dev_id
-						= dev_info->acdb_id;
-				}
-			} else if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG)
-				evt_payload->voice_state =
-					routing_info.voice_state;
-			else
-				evt_payload->routing_id = dev_info->copp_id;
-			callback->auddev_evt_listener(
-					evt_id,
-					evt_payload,
-					callback->private_data);
-sent_enc:
-			if (callback->cb_next == NULL)
-					break;
-			else {
-				callback = callback->cb_next;
-				continue;
-			}
-		}
-aud_cal:
-		if (callback->clnt_type == AUDDEV_CLNT_AUDIOCAL) {
-			pr_debug("AUDDEV_CLNT_AUDIOCAL\n");
-			if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG)
-				evt_payload->voice_state =
-					routing_info.voice_state;
-			else if (!dev_info->sessions)
-				goto sent_aud_cal;
-			else {
-				evt_payload->audcal_info.dev_id =
-						dev_info->copp_id;
-				evt_payload->audcal_info.acdb_id =
-						dev_info->acdb_id;
-				evt_payload->audcal_info.dev_type =
-					(dev_info->capability & SNDDEV_CAP_TX) ?
-					SNDDEV_CAP_TX : SNDDEV_CAP_RX;
-				evt_payload->audcal_info.sample_rate =
-					dev_info->set_sample_rate ?
-					dev_info->set_sample_rate :
-					dev_info->sample_rate;
-			}
-			callback->auddev_evt_listener(
-				evt_id,
-				evt_payload,
-				callback->private_data);
-
-sent_aud_cal:
-			if (callback->cb_next == NULL)
-				break;
-			else {
-				callback = callback->cb_next;
-				continue;
-			}
-		}
-skip_check:
-voc_events:
-		if (callback->clnt_type == AUDDEV_CLNT_VOC) {
-			pr_debug("AUDDEV_CLNT_VOC\n");
-			if (evt_id == AUDDEV_EVT_DEV_RLS) {
-				if (!pending_sent)
-					goto sent_voc;
-				else
-					pending_sent = 0;
-			}
-			if (evt_id == AUDDEV_EVT_REL_PENDING)
-				pending_sent = 1;
-
-			if (evt_id == AUDDEV_EVT_DEVICE_VOL_MUTE_CHG) {
-				evt_payload->voc_vm_info.voice_session_id =
-								session_id;
-
-				if (dev_info->capability & SNDDEV_CAP_TX) {
-					evt_payload->voc_vm_info.dev_type =
-						SNDDEV_CAP_TX;
-					evt_payload->voc_vm_info.acdb_dev_id =
-						dev_info->acdb_id;
-					evt_payload->
-					voc_vm_info.dev_vm_val.mute =
-						routing_info.tx_mute;
-				} else {
-					evt_payload->voc_vm_info.dev_type =
-						SNDDEV_CAP_RX;
-					evt_payload->voc_vm_info.acdb_dev_id =
-						dev_info->acdb_id;
-					evt_payload->
-					voc_vm_info.dev_vm_val.vol =
-						routing_info.voice_rx_vol;
-				}
-			} else if ((evt_id == AUDDEV_EVT_START_VOICE)
-					|| (evt_id == AUDDEV_EVT_END_VOICE)) {
-				memset(evt_payload, 0,
-					sizeof(union auddev_evt_data));
-
-				evt_payload->voice_session_id = session_id;
-			} else if (evt_id == AUDDEV_EVT_FREQ_CHG) {
-				if (routing_info.voice_tx_sample_rate
-						!= dev_info->set_sample_rate) {
-					routing_info.voice_tx_sample_rate
-						= dev_info->set_sample_rate;
-					evt_payload->freq_info.sample_rate
-						= dev_info->set_sample_rate;
-					evt_payload->freq_info.dev_type
-						= dev_info->capability;
-					evt_payload->freq_info.acdb_dev_id
-						= dev_info->acdb_id;
-				} else
-					goto sent_voc;
-			} else if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG)
-				evt_payload->voice_state =
-						routing_info.voice_state;
-			else {
-				evt_payload->voc_devinfo.dev_type =
-					(dev_info->capability & SNDDEV_CAP_TX) ?
-					SNDDEV_CAP_TX : SNDDEV_CAP_RX;
-				evt_payload->voc_devinfo.acdb_dev_id =
-					dev_info->acdb_id;
-				evt_payload->voc_devinfo.dev_port_id =
-					dev_info->copp_id;
-				evt_payload->voc_devinfo.dev_sample =
-					dev_info->set_sample_rate ?
-					dev_info->set_sample_rate :
-					dev_info->sample_rate;
-				evt_payload->voc_devinfo.dev_id = dev_id;
-				if (dev_info->capability & SNDDEV_CAP_RX) {
-					for (i = 0; i < VOC_RX_VOL_ARRAY_NUM;
-						i++) {
-						evt_payload->
-						voc_devinfo.max_rx_vol[i] =
-						dev_info->max_voc_rx_vol[i];
-						evt_payload
-						->voc_devinfo.min_rx_vol[i] =
-						dev_info->min_voc_rx_vol[i];
-					}
-				}
-			}
-			callback->auddev_evt_listener(
-				evt_id,
-				evt_payload,
-				callback->private_data);
-			if (evt_id == AUDDEV_EVT_DEV_RLS)
-				dev_info->sessions &= ~(0xFFFF);
-sent_voc:
-			if (callback->cb_next == NULL)
-				break;
-			else {
-				callback = callback->cb_next;
-				continue;
-			}
-		}
-	}
-	kfree(evt_payload);
-	mutex_unlock(&session_lock);
-}
-EXPORT_SYMBOL(broadcast_event);
-
-
-void mixer_post_event(u32 evt_id, u32 id)
-{
-
-	pr_debug("evt_id = %d\n", evt_id);
-	switch (evt_id) {
-	case AUDDEV_EVT_DEV_CHG_VOICE: /* Called from Voice_route */
-		broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, id, SESSION_IGNORE);
-		break;
-	case AUDDEV_EVT_DEV_RDY:
-		broadcast_event(AUDDEV_EVT_DEV_RDY, id, SESSION_IGNORE);
-		break;
-	case AUDDEV_EVT_DEV_RLS:
-		broadcast_event(AUDDEV_EVT_DEV_RLS, id, SESSION_IGNORE);
-		break;
-	case AUDDEV_EVT_REL_PENDING:
-		broadcast_event(AUDDEV_EVT_REL_PENDING, id, SESSION_IGNORE);
-		break;
-	case AUDDEV_EVT_DEVICE_VOL_MUTE_CHG:
-		broadcast_event(AUDDEV_EVT_DEVICE_VOL_MUTE_CHG, id,
-							SESSION_IGNORE);
-		break;
-	case AUDDEV_EVT_STREAM_VOL_CHG:
-		broadcast_event(AUDDEV_EVT_STREAM_VOL_CHG, id,
-							SESSION_IGNORE);
-		break;
-	case AUDDEV_EVT_START_VOICE:
-		broadcast_event(AUDDEV_EVT_START_VOICE,
-				id, SESSION_IGNORE);
-		break;
-	case AUDDEV_EVT_END_VOICE:
-		broadcast_event(AUDDEV_EVT_END_VOICE,
-				id, SESSION_IGNORE);
-		break;
-	case AUDDEV_EVT_FREQ_CHG:
-		broadcast_event(AUDDEV_EVT_FREQ_CHG, id, SESSION_IGNORE);
-		break;
-	default:
-		break;
-	}
-}
-EXPORT_SYMBOL(mixer_post_event);
-
-static int __init audio_dev_ctrl_init(void)
-{
-	init_waitqueue_head(&audio_dev_ctrl.wait);
-
-	event.cb = NULL;
-	msm_reset_device_work_queue = create_workqueue("reset_device");
-	if (msm_reset_device_work_queue == NULL)
-		return -ENOMEM;
-	atomic_set(&audio_dev_ctrl.opened, 0);
-	audio_dev_ctrl.num_dev = 0;
-	audio_dev_ctrl.voice_tx_dev = NULL;
-	audio_dev_ctrl.voice_rx_dev = NULL;
-	routing_info.voice_state = VOICE_STATE_INVALID;
-
-	mutex_init(&adm_tx_topology_tbl.lock);
-	mutex_init(&routing_info.copp_list_mutex);
-	mutex_init(&routing_info.adm_mutex);
-
-	memset(routing_info.copp_list, COPP_IGNORE,
-		(sizeof(unsigned int) * MAX_SESSIONS * AFE_MAX_PORTS));
-	return misc_register(&audio_dev_ctrl_misc);
-}
-
-static void __exit audio_dev_ctrl_exit(void)
-{
-	destroy_workqueue(msm_reset_device_work_queue);
-}
-module_init(audio_dev_ctrl_init);
-module_exit(audio_dev_ctrl_exit);
-
-MODULE_DESCRIPTION("MSM 8K Audio Device Control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index a1463bc..5fa7b1b 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -179,6 +179,16 @@
 			pr_err("%s[%p]: pause cmd failed rc=%d\n",
 				__func__, audio, rc);
 
+		if (rc == 0) {
+			/* Send suspend only if pause was successful */
+			rc = q6asm_cmd(audio->ac, CMD_SUSPEND);
+			if (rc < 0)
+				pr_err("%s[%p]: suspend cmd failed rc=%d\n",
+					__func__, audio, rc);
+		} else
+			pr_err("%s[%p]: not sending suspend since pause failed\n",
+				__func__, audio);
+
 	} else
 		pr_err("%s[%p]: Driver not enabled\n", __func__, audio);
 	return rc;
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
index 0a50bcc..2d375ac 100644
--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -269,6 +269,7 @@
 	} else {
 		ion_phys_addr_t phys_addr;
 		size_t phys_len;
+		size_t va_len = 0;
 		pr_debug("%s: page is NULL\n", __func__);
 
 		ret = ion_phys(ab->client, ab->handle, &phys_addr, &phys_len);
@@ -282,6 +283,12 @@
 			vma, (unsigned int)vma->vm_start,
 			(unsigned int)vma->vm_end, vma->vm_pgoff,
 			(unsigned long int)vma->vm_page_prot);
+		va_len = vma->vm_end - vma->vm_start;
+		if ((offset > phys_len) || (va_len > phys_len-offset)) {
+			pr_err("wrong offset size %ld, lens= %d, va_len=%d\n",
+				offset, phys_len, va_len);
+			return -EINVAL;
+		}
 		ret =  remap_pfn_range(vma, vma->vm_start,
 				__phys_to_pfn(phys_addr) + vma->vm_pgoff,
 				vma->vm_end - vma->vm_start,
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_in.c b/arch/arm/mach-msm/qdsp6v2/pcm_in.c
index 0db4894..cf7548d 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_in.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2009 Google, Inc.
  * Copyright (C) 2009 HTC Corporation
- * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-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
@@ -256,6 +256,7 @@
 	}
 	case AUDIO_GET_CONFIG: {
 		struct msm_audio_config config;
+		memset(&config, 0, sizeof(config));
 		config.buffer_size = pcm->buffer_size;
 		config.buffer_count = pcm->buffer_count;
 		config.sample_rate = pcm->sample_rate;
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c b/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c
index 5faee21..f7bf1ae 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c
@@ -1,5 +1,5 @@
 
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -475,6 +475,7 @@
 	}
 	case AUDIO_GET_CONFIG: {
 		struct msm_audio_config config;
+		memset(&config, 0, sizeof(config));
 		config.buffer_size = pcm->buffer_size;
 		config.buffer_count = pcm->buffer_count;
 		config.sample_rate = pcm->sample_rate;
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 923e647..faf774f 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -1266,14 +1266,16 @@
 {
 	struct device *dev = &pdev->dev;
 	struct rpm_regulator *reg;
+	struct rpm_vreg *rpm_vreg;
 
 	reg = platform_get_drvdata(pdev);
 	if (reg) {
-		rpm_vreg_lock(reg->rpm_vreg);
+		rpm_vreg = reg->rpm_vreg;
+		rpm_vreg_lock(rpm_vreg);
 		regulator_unregister(reg->rdev);
 		list_del(&reg->list);
 		kfree(reg);
-		rpm_vreg_unlock(reg->rpm_vreg);
+		rpm_vreg_unlock(rpm_vreg);
 	} else {
 		dev_err(dev, "%s: drvdata missing\n", __func__);
 		return -EINVAL;
diff --git a/arch/arm/mach-msm/sensors_adsp.c b/arch/arm/mach-msm/sensors_adsp.c
index fab10b8..ad19e16 100644
--- a/arch/arm/mach-msm/sensors_adsp.c
+++ b/arch/arm/mach-msm/sensors_adsp.c
@@ -38,6 +38,7 @@
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
 
+#define CLASS_NAME	"ssc"
 #define DRV_NAME	"sensors"
 #define DRV_VERSION	"1.00"
 
@@ -1079,7 +1080,7 @@
 static int sensors_adsp_probe(struct platform_device *pdev)
 {
 	int ret = 0;
-	sns_ctl.dev_class = class_create(THIS_MODULE, DRV_NAME);
+	sns_ctl.dev_class = class_create(THIS_MODULE, CLASS_NAME);
 	if (sns_ctl.dev_class == NULL) {
 		pr_err("%s: class_create fail.\n", __func__);
 		goto res_err;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 110ab87..cb9697d 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -3243,7 +3243,7 @@
  */
 void smd_set_edge_subsys_name(uint32_t edge, const char *subsys_name)
 {
-	if (edge <= ARRAY_SIZE(edge_to_pids))
+	if (edge < ARRAY_SIZE(edge_to_pids))
 		strlcpy(edge_to_pids[edge].subsys_name,
 			subsys_name, SMD_MAX_CH_NAME_LEN);
 	else
@@ -3258,7 +3258,7 @@
  */
 void smd_set_edge_initialized(uint32_t edge)
 {
-	if (edge <= ARRAY_SIZE(edge_to_pids))
+	if (edge < ARRAY_SIZE(edge_to_pids))
 		edge_to_pids[edge].initialized = true;
 	else
 		pr_err("%s: Invalid edge type[%d]\n", __func__, edge);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 8af3890..4b68e66 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -1080,7 +1080,7 @@
 			msm_get_image_crm_version, msm_set_image_crm_version);
 
 static struct device_attribute select_image =
-	__ATTR(select_image, S_IRUGO | S_IWUGO,
+	__ATTR(select_image, S_IRUGO | S_IWUSR,
 			msm_get_image_number, msm_select_image);
 
 static struct sysdev_class soc_sysdev_class = {
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 34ae4e6..ac6ccf3b 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -885,8 +885,9 @@
 		   MLM(VMALLOC_START, VMALLOC_END),
 		   MLM(PAGE_OFFSET, (unsigned long)high_memory));
 #endif
-#ifdef CONFIG_HIGHMEM
+
 	printk(KERN_NOTICE
+#ifdef CONFIG_HIGHMEM
 		   "    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #endif
 #ifdef CONFIG_MODULES
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 1d12b07..9a1a2eb 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -85,6 +85,7 @@
 	}
 #ifdef CONFIG_SMP
 	thread->vfpstate.hard.cpu = NR_CPUS;
+	vfp_current_hw_state[cpu] = NULL;
 #endif
 }
 
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
index c5f9021..fbf4eeb 100644
--- a/arch/sparc/mm/init_32.c
+++ b/arch/sparc/mm/init_32.c
@@ -77,7 +77,7 @@
 	printk("Mem-info:\n");
 	show_free_areas(filter);
 	printk("Free swap:       %6ldkB\n",
-	       nr_swap_pages << (PAGE_SHIFT-10));
+	       get_nr_swap_pages() << (PAGE_SHIFT-10));
 	printk("%ld pages of RAM\n", totalram_pages);
 	printk("%ld free pages\n", nr_free_pages());
 #if 0 /* undefined pgtable_cache_size, pgd_cache_size */
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
index 2410aa8..ea7dd38 100644
--- a/arch/tile/mm/pgtable.c
+++ b/arch/tile/mm/pgtable.c
@@ -61,7 +61,7 @@
 	       global_page_state(NR_PAGETABLE),
 	       global_page_state(NR_BOUNCE),
 	       global_page_state(NR_FILE_PAGES),
-	       nr_swap_pages);
+	       get_nr_swap_pages());
 
 	for_each_zone(zone) {
 		unsigned long flags, order, total = 0, largest_order = -1;
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e2864ec..02d76fc 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -650,14 +650,13 @@
           different function.
 
 config MSM_ADSPRPC
-        tristate "Qualcomm ADSP RPC driver"
-        depends on MSM_AUDIO_QDSP6 || MSM_AUDIO_QDSP6V2
-        default m
-        help
-          Provides a communication mechanism that allows for clients to
-          make remote method invocations across processor boundary to
-          applications DSP processor. Say M if you want to enable this
-          module.
+	tristate "Qualcomm ADSP RPC driver"
+	depends on MSM_AUDIO_QDSP6 || MSM_AUDIO_QDSP6V2
+	help
+	  Provides a communication mechanism that allows for clients to
+	  make remote method invocations across processor boundary to
+	  applications DSP processor. Say M if you want to enable this
+	  module.
 
 config MMC_GENERIC_CSDIO
 	tristate "Generic sdio driver"
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 4507f80..921b80c 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -33,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/of.h>
 #include <linux/iommu.h>
+#include <linux/kref.h>
 
 #ifndef ION_ADSPRPC_HEAP_ID
 #define ION_ADSPRPC_HEAP_ID ION_AUDIO_HEAP_ID
@@ -152,9 +153,11 @@
 	struct class *class;
 	struct device *dev;
 	struct fastrpc_smmu smmu;
+	struct mutex smd_mutex;
 	dev_t dev_no;
 	spinlock_t wrlock;
 	spinlock_t hlock;
+	struct kref kref;
 	struct hlist_head htbl[RPC_HASH_SZ];
 };
 
@@ -661,6 +664,7 @@
 		spin_lock_init(&me->hlock);
 		spin_lock_init(&me->wrlock);
 		init_completion(&me->work);
+		mutex_init(&me->smd_mutex);
 		for (i = 0; i < RPC_HASH_SZ; ++i)
 			INIT_HLIST_HEAD(&me->htbl[i]);
 		VERIFY(err, 0 == context_list_ctor(&me->clst, SZ_4K));
@@ -687,23 +691,10 @@
 			if (me->smmu.domain_id >= 0)
 				me->smmu.enabled = enabled;
 		}
-		VERIFY(err, 0 == smd_named_open_on_edge(FASTRPC_SMD_GUID,
-						SMD_APPS_QDSP, &me->chan,
-						me, smd_event_handler));
-		if (err)
-			goto smd_bail;
-		VERIFY(err, 0 != wait_for_completion_timeout(&me->work,
-							RPC_TIMEOUT));
-		if (err)
-			goto completion_bail;
 	}
 
 	return 0;
 
-completion_bail:
-	smd_close(me->chan);
-smd_bail:
-	ion_client_destroy(me->iclient);
 ion_bail:
 	context_list_dtor(&me->clst);
 context_list_bail:
@@ -1087,9 +1078,22 @@
 	return;
 }
 
+static void fastrpc_channel_close(struct kref *kref)
+{
+	struct fastrpc_apps *me = &gfa;
+
+	smd_close(me->chan);
+	me->chan = 0;
+	mutex_unlock(&me->smd_mutex);
+	pr_info("'closed /dev/%s c %d 0'\n", DEVICE_NAME,
+						MAJOR(me->dev_no));
+}
+
 static int fastrpc_device_release(struct inode *inode, struct file *file)
 {
 	struct file_data *fdata = (struct file_data *)file->private_data;
+	struct fastrpc_apps *me = &gfa;
+
 	(void)fastrpc_release_current_dsp_process();
 	cleanup_current_dev();
 	if (fdata) {
@@ -1102,6 +1106,8 @@
 			kfree(map);
 		}
 		kfree(fdata);
+		kref_put_mutex(&me->kref, fastrpc_channel_close,
+				&me->smd_mutex);
 	}
 	return 0;
 }
@@ -1109,6 +1115,25 @@
 static int fastrpc_device_open(struct inode *inode, struct file *filp)
 {
 	int err = 0;
+	struct fastrpc_apps *me = &gfa;
+
+	mutex_lock(&me->smd_mutex);
+	if (kref_get_unless_zero(&me->kref) == 0) {
+		VERIFY(err, 0 == smd_named_open_on_edge(FASTRPC_SMD_GUID,
+						SMD_APPS_QDSP, &me->chan,
+						me, smd_event_handler));
+		if (err)
+			goto smd_bail;
+		VERIFY(err, 0 != wait_for_completion_timeout(&me->work,
+							RPC_TIMEOUT));
+		if (err)
+			goto completion_bail;
+		kref_init(&me->kref);
+		pr_info("'opened /dev/%s c %d 0'\n", DEVICE_NAME,
+						MAJOR(me->dev_no));
+	}
+	mutex_unlock(&me->smd_mutex);
+
 	filp->private_data = 0;
 	if (0 != try_module_get(THIS_MODULE)) {
 		struct file_data *fdata = 0;
@@ -1130,10 +1155,19 @@
 		if (err) {
 			cleanup_current_dev();
 			kfree(fdata);
+			kref_put_mutex(&me->kref, fastrpc_channel_close,
+					&me->smd_mutex);
 		}
 		module_put(THIS_MODULE);
 	}
 	return err;
+
+completion_bail:
+	smd_close(me->chan);
+	me->chan = 0;
+smd_bail:
+	mutex_unlock(&me->smd_mutex);
+	return err;
 }
 
 
@@ -1242,7 +1276,7 @@
 	VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), 1));
 	if (err)
 		goto cdev_init_bail;
-	me->class = class_create(THIS_MODULE, "chardrv");
+	me->class = class_create(THIS_MODULE, "fastrpc");
 	VERIFY(err, !IS_ERR(me->class));
 	if (err)
 		goto class_create_bail;
@@ -1251,7 +1285,6 @@
 	VERIFY(err, !IS_ERR(me->dev));
 	if (err)
 		goto device_create_bail;
-	pr_info("'created /dev/%s c %d 0'\n", DEVICE_NAME, MAJOR(me->dev_no));
 
 	return 0;
 
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 69e6250..c28b3bd 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -229,83 +229,90 @@
 static void diag_disable_log_mask(void)
 {
 	int i = 0;
-	struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
+	struct diag_log_mask_t *log_item = NULL;
 
-	pr_debug("diag: disable log masks\n");
-	mutex_lock(&driver->diagchar_mutex);
-	for (i = 0; i < MAX_EQUIP_ID; i++) {
-		pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
-		if (!(parse_ptr->equip_id)) /* Reached a null entry */
-			break;
-		memset(driver->log_masks + parse_ptr->index, 0,
-			    (parse_ptr->num_items + 7)/8);
-		parse_ptr++;
-	}
+	mutex_lock(&driver->log_mask_mutex);
+	log_item = (struct diag_log_mask_t *)driver->log_masks;
+	for (i = 0; i < MAX_EQUIP_ID; i++, log_item++)
+		memset(log_item->ptr, 0, MAX_ITEMS_PER_EQUIP_ID);
+
 	driver->log_status = DIAG_CTRL_MASK_ALL_DISABLED;
-	mutex_unlock(&driver->diagchar_mutex);
+	mutex_unlock(&driver->log_mask_mutex);
 }
 
-int chk_equip_id_and_mask(int equip_id, uint8_t *buf)
+static int copy_log_mask_equip(int equip_id, uint8_t *buf)
 {
-	int i = 0, flag = 0, num_items, offset;
-	unsigned char *ptr_data;
-	struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
+	int i, ret = 0;
+	uint8_t *temp = buf;
+	struct diag_log_mask_t *log_item = NULL;
+	uint32_t mask_size = 0;
 
-	pr_debug("diag: received equip id = %d\n", equip_id);
-	/* Check if this is valid equipment ID */
-	for (i = 0; i < MAX_EQUIP_ID; i++) {
-		if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
-			offset = ptr->index;
-			num_items = ptr->num_items;
-			flag = 1;
+	if (!buf)
+		return ret;
+
+	log_item = (struct diag_log_mask_t *)driver->log_masks;
+	for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
+		if (log_item->equip_id != equip_id)
+			continue;
+		*(int *)temp = log_item->equip_id;
+		temp += sizeof(int);
+		*(int *)(temp) = log_item->num_items;
+		temp += sizeof(int);
+		mask_size = LOG_ITEMS_TO_SIZE(log_item->num_items);
+		if (mask_size > MAX_ITEMS_PER_EQUIP_ID) {
+			pr_err("diag: Invalid length: %d in %s, perimissible: %d",
+				mask_size, __func__, MAX_ITEMS_PER_EQUIP_ID);
 			break;
 		}
-		ptr++;
+		if (mask_size > 0) {
+			memcpy(temp, log_item->ptr, mask_size);
+			/*
+			 * Return the total number of bytes copied = size of
+			 * equip_id (int) + size of num_items (int) + mask_size
+			 */
+			ret = (2 * sizeof(int)) + mask_size;
+		}
+		break;
 	}
-	if (!flag)
-		return -EPERM;
-	ptr_data = driver->log_masks + offset;
-	memcpy(buf, ptr_data, (num_items+7)/8);
-	return 0;
+
+	return ret;
 }
 
 static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
 {
-	uint8_t *temp = buf;
 	int i = 0;
-	unsigned char *ptr_data;
-	int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
-	struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
+	struct diag_log_mask_t *log_item = NULL;
+	uint32_t mask_size = 0;
 
-	pr_debug("diag: received equip id = %d\n", equip_id);
-	mutex_lock(&driver->diagchar_mutex);
-	/* Check if we already know index of this equipment ID */
-	for (i = 0; i < MAX_EQUIP_ID; i++) {
-		if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
-			offset = ptr->index;
-			break;
-		}
-		if ((ptr->equip_id == 0) && (ptr->index == 0)) {
-			/* Reached a null entry */
-			ptr->equip_id = equip_id;
-			ptr->num_items = num_items;
-			ptr->index = driver->log_masks_length;
-			offset = driver->log_masks_length;
-			driver->log_masks_length += ((num_items+7)/8);
-			break;
-		}
-		ptr++;
+	mutex_lock(&driver->log_mask_mutex);
+	driver->log_status = DIAG_CTRL_MASK_INVALID;
+	if (!buf || (equip_id < 0 || equip_id >= MAX_EQUIP_ID) ||
+							num_items < 1) {
+		pr_err("diag: Invalid params in %s, buf: %x equip_id: %d, num_items: %d\n",
+		       __func__, (unsigned int)buf, equip_id, num_items);
+		mutex_unlock(&driver->log_mask_mutex);
+		return;
 	}
-	ptr_data = driver->log_masks + offset;
-	if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
-					 + LOG_MASK_SIZE, (num_items+7)/8)) {
-		memcpy(ptr_data, temp, (num_items+7)/8);
+	mask_size = LOG_ITEMS_TO_SIZE(num_items);
+	if (mask_size > MAX_ITEMS_PER_EQUIP_ID) {
+		pr_err("diag: In %s, Invalid mask_size %d\n", __func__,
+								mask_size);
+		mutex_unlock(&driver->log_mask_mutex);
+		return;
+	}
+
+	log_item = (struct diag_log_mask_t *)driver->log_masks;
+	for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
+		if (log_item->equip_id != equip_id)
+			continue;
+		/* Found the equip id */
+		log_item->num_items = num_items;
+		if (mask_size > 0)
+			memcpy(log_item->ptr, buf, mask_size);
 		driver->log_status = DIAG_CTRL_MASK_VALID;
-	} else {
-		pr_err("diag: Not enough buffer space for LOG_MASK\n");
-		driver->log_status = DIAG_CTRL_MASK_INVALID;
+		break;
 	}
-	mutex_unlock(&driver->diagchar_mutex);
+	mutex_unlock(&driver->log_mask_mutex);
 }
 
 void diag_mask_update_fn(struct work_struct *work)
@@ -335,72 +342,76 @@
 void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
 {
 	void *buf = driver->buf_log_mask_update;
-	int header_size = sizeof(struct diag_ctrl_log_mask);
-	struct mask_info *ptr = (struct mask_info *)driver->log_masks;
-	int i, size, wr_size = -ENOMEM, retry_count = 0;
+	struct diag_log_mask_t *log_item = NULL;
+	struct diag_ctrl_log_mask ctrl_pkt;
+	uint32_t log_mask_size = 0;
+	int wr_size = -ENOMEM, retry_count = 0;
+	int i, header_size, send_once = 0;
 
+	header_size = sizeof(struct diag_ctrl_log_mask);
+	log_item = (struct diag_log_mask_t *)driver->log_masks;
 	mutex_lock(&driver->diag_cntl_mutex);
-	for (i = 0; i < MAX_EQUIP_ID; i++) {
-		size = (ptr->num_items+7)/8;
-		/* reached null entry */
-		if ((ptr->equip_id == 0) && (ptr->index == 0))
-			break;
-		driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
-		driver->log_mask->num_items = ptr->num_items;
-		driver->log_mask->data_len  = 11 + size;
-		driver->log_mask->stream_id = 1; /* 2, if dual stream */
-		driver->log_mask->equip_id = ptr->equip_id;
-		driver->log_mask->status = driver->log_status;
+	for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
+		if (equip_id != i && equip_id != ALL_EQUIP_ID)
+			continue;
+		log_mask_size = LOG_ITEMS_TO_SIZE(log_item->num_items);
+		ctrl_pkt.cmd_type = DIAG_CTRL_MSG_LOG_MASK;
+		ctrl_pkt.data_len = 11 + log_mask_size;
+		ctrl_pkt.stream_id = 1;
+		ctrl_pkt.status = driver->log_status;
 		switch (driver->log_status) {
 		case DIAG_CTRL_MASK_ALL_DISABLED:
-			driver->log_mask->log_mask_size = 0;
+			ctrl_pkt.equip_id = 0;
+			ctrl_pkt.num_items = 0;
+			ctrl_pkt.log_mask_size = 0;
+			send_once = 1;
 			break;
 		case DIAG_CTRL_MASK_ALL_ENABLED:
-			driver->log_mask->log_mask_size = 0;
+			ctrl_pkt.equip_id = 0;
+			ctrl_pkt.num_items = 0;
+			ctrl_pkt.log_mask_size = 0;
+			send_once = 1;
 			break;
 		case DIAG_CTRL_MASK_VALID:
-			driver->log_mask->log_mask_size = size;
+			ctrl_pkt.equip_id = i;
+			ctrl_pkt.num_items = log_item->num_items;
+			ctrl_pkt.log_mask_size = log_mask_size;
+			send_once = 0;
 			break;
 		default:
-			/* Log status is not set or the buffer is corrupted */
 			pr_err("diag: In %s, invalid status %d", __func__,
-							driver->log_status);
-			driver->log_mask->status = DIAG_CTRL_MASK_INVALID;
-		}
-
-		if (driver->log_mask->status == DIAG_CTRL_MASK_INVALID) {
+				 driver->log_status);
 			mutex_unlock(&driver->diag_cntl_mutex);
 			return;
 		}
-		/* send only desired update, NOT ALL */
-		if (equip_id == ALL_EQUIP_ID || equip_id ==
-					 driver->log_mask->equip_id) {
-			memcpy(buf, driver->log_mask, header_size);
-			if (driver->log_status == DIAG_CTRL_MASK_VALID)
-				memcpy(buf + header_size,
-				       driver->log_masks+ptr->index, size);
-			if (ch) {
-				while (retry_count < 3) {
-					wr_size = smd_write(ch, buf,
-							 header_size + size);
-					if (wr_size == -ENOMEM) {
-						retry_count++;
-						usleep_range(10000, 10100);
-					} else
-						break;
-				}
-				if (wr_size != header_size + size)
-					pr_err("diag: log mask update failed %d, tried %d",
-						wr_size, header_size + size);
-				else
-					pr_debug("diag: updated log equip ID %d,len %d\n",
-					driver->log_mask->equip_id,
-					driver->log_mask->log_mask_size);
-			} else
-				pr_err("diag: ch not valid for log update\n");
+		memcpy(buf, &ctrl_pkt, header_size);
+		if (log_mask_size > 0) {
+			memcpy(buf + header_size, log_item->ptr,
+			       log_mask_size);
 		}
-		ptr++;
+
+		if (ch) {
+			while (retry_count < 3) {
+				wr_size = smd_write(ch, buf,
+						header_size + log_mask_size);
+				if (wr_size == -ENOMEM) {
+					retry_count++;
+					usleep_range(10000, 10100);
+				} else
+				break;
+			}
+			if (wr_size != header_size + log_mask_size)
+				pr_err("diag: log mask update failed %d, tried %d",
+					wr_size, header_size + log_mask_size);
+			else
+				pr_debug("diag: updated log equip ID %d,len %d\n",
+					 i, log_mask_size);
+		} else
+			pr_err("diag: ch not valid for log update\n");
+		if (send_once)
+			break;
 	}
+
 	mutex_unlock(&driver->diag_cntl_mutex);
 }
 
@@ -623,7 +634,7 @@
 	int ssid_first, ssid_last, ssid_range;
 	int rt_mask, rt_first_ssid, rt_last_ssid, rt_mask_size;
 	uint8_t *rt_mask_ptr;
-	int equip_id, num_items;
+	int equip_id, copy_len;
 #if defined(CONFIG_DIAG_OVER_USB)
 	int payload_length;
 #endif
@@ -631,7 +642,6 @@
 	/* Set log masks */
 	if (*buf == 0x73 && *(int *)(buf+4) == 3) {
 		buf += 8;
-		/* Read Equip ID and pass as first param below*/
 		diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
 		diag_update_userspace_clients(LOG_MASKS_TYPE);
 #if defined(CONFIG_DIAG_OVER_USB)
@@ -639,7 +649,8 @@
 			driver->apps_rsp_buf[0] = 0x73;
 			*(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
 			*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
-			payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
+			payload_length = 8 +
+					LOG_ITEMS_TO_SIZE(*(int *)(buf + 4));
 			if (payload_length > APPS_BUF_SIZE - 12) {
 				pr_err("diag: log masks: buffer overflow\n");
 				return -EIO;
@@ -663,20 +674,16 @@
 		if (!(driver->smd_data[MODEM_DATA].ch) &&
 						chk_apps_only()) {
 			equip_id = *(int *)(buf + 8);
-			num_items = *(int *)(buf + 12);
 			driver->apps_rsp_buf[0] = 0x73;
 			driver->apps_rsp_buf[1] = 0x0;
 			driver->apps_rsp_buf[2] = 0x0;
 			driver->apps_rsp_buf[3] = 0x0;
 			*(int *)(driver->apps_rsp_buf + 4) = 0x4;
-			if (!chk_equip_id_and_mask(equip_id,
-				driver->apps_rsp_buf+20))
-				*(int *)(driver->apps_rsp_buf + 8) = 0x0;
-			else
-				*(int *)(driver->apps_rsp_buf + 8) = 0x1;
-			*(int *)(driver->apps_rsp_buf + 12) = equip_id;
-			*(int *)(driver->apps_rsp_buf + 16) = num_items;
-			encode_rsp_and_send(20+(num_items+7)/8-1);
+			copy_len = copy_log_mask_equip(equip_id,
+						driver->apps_rsp_buf + 12);
+			*(int *)(driver->apps_rsp_buf + 8) =
+						(copy_len == 0) ? 1 : 0;
+			encode_rsp_and_send(12 + copy_len);
 			return 0;
 		}
 #endif
@@ -858,6 +865,19 @@
 	return  packet_type;
 }
 
+static void diag_log_mask_init(void)
+{
+	struct diag_log_mask_t *log_item = NULL;
+	uint8_t i;
+
+	mutex_init(&driver->log_mask_mutex);
+	log_item = (struct diag_log_mask_t *)driver->log_masks;
+	for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
+		log_item->equip_id = i;
+		log_item->num_items = LOG_GET_ITEM_NUM(log_code_last_tbl[i]);
+	}
+}
+
 void diag_masks_init(void)
 {
 	driver->event_status = DIAG_CTRL_MASK_INVALID;
@@ -936,7 +956,7 @@
 			goto err;
 		kmemleak_not_leak(driver->log_masks);
 	}
-	driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
+	diag_log_mask_init();
 	if (driver->event_masks == NULL) {
 		driver->event_masks = kzalloc(EVENT_MASK_SIZE, GFP_KERNEL);
 		if (driver->event_masks == NULL)
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index c66a4b6..856d4fc 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -15,7 +15,12 @@
 
 #include "diagfwd.h"
 
-int chk_equip_id_and_mask(int equip_id, uint8_t *buf);
+struct diag_log_mask_t {
+	uint8_t equip_id;
+	uint32_t num_items;
+	uint8_t ptr[MAX_ITEMS_PER_EQUIP_ID];
+} __packed;
+
 void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
 void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
 					 int ssid_last, int proc);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9d9d89b..5be77c4 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -82,11 +82,14 @@
  * And there are MSG_MASK_TBL_CNT rows.
  */
 #define MSG_MASK_SIZE		((MAX_SSID_PER_RANGE+3) * 4 * MSG_MASK_TBL_CNT)
-#define LOG_MASK_SIZE 8000
+#define MAX_EQUIP_ID		16
+#define MAX_ITEMS_PER_EQUIP_ID	512
+#define LOG_MASK_ITEM_SIZE	(5 + MAX_ITEMS_PER_EQUIP_ID)
+#define LOG_MASK_SIZE		(MAX_EQUIP_ID * LOG_MASK_ITEM_SIZE)
 #define EVENT_MASK_SIZE 1000
 #define USER_SPACE_DATA 8192
 #define PKT_SIZE 4096
-#define MAX_EQUIP_ID 15
+
 #define DIAG_CTRL_MSG_LOG_MASK	9
 #define DIAG_CTRL_MSG_EVENT_MASK	10
 #define DIAG_CTRL_MSG_F3_MASK	11
@@ -334,6 +337,7 @@
 	struct diag_ctrl_log_mask *log_mask;
 	struct diag_ctrl_msg_mask *msg_mask;
 	struct diag_ctrl_feature_mask *feature_mask;
+	struct mutex log_mask_mutex;
 	/* State for diag forwarding */
 	struct diag_smd_info smd_data[NUM_SMD_DATA_CHANNELS];
 	struct diag_smd_info smd_cntl[NUM_SMD_CONTROL_CHANNELS];
@@ -380,7 +384,6 @@
 	uint8_t msg_status;
 	uint8_t *log_masks;
 	uint8_t log_status;
-	int log_masks_length;
 	uint8_t *event_masks;
 	uint8_t event_status;
 	uint8_t log_on_demand_support;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 19ff6f4..f7c0d24 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1485,26 +1485,25 @@
 		return err;
 	}
 	if (pkt_type == CALLBACK_DATA_TYPE) {
-		if (payload_size > itemsize) {
+		if (payload_size > driver->itemsize) {
 			pr_err("diag: Dropping packet, packet payload size crosses 4KB limit. Current payload size %d\n",
 				payload_size);
 			driver->dropped_count++;
 			return -EBADMSG;
 		}
 
-		mutex_lock(&driver->diagchar_mutex);
 		buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
 		if (!buf_copy) {
 			driver->dropped_count++;
-			mutex_unlock(&driver->diagchar_mutex);
 			return -ENOMEM;
 		}
 
 		err = copy_from_user(buf_copy, buf + 4, payload_size);
 		if (err) {
 			pr_err("diag: copy failed for user space data\n");
-			ret = -EIO;
-			goto fail_free_copy;
+			diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+			buf_copy = NULL;
+			return -EIO;
 		}
 		/* Check for proc_type */
 		remote_proc = diag_get_remote(*(int *)buf_copy);
@@ -1513,7 +1512,9 @@
 			wait_event_interruptible(driver->wait_q,
 				 (driver->in_busy_pktdata == 0));
 			ret = diag_process_apps_pkt(buf_copy, payload_size);
-			goto fail_free_copy;
+			diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+			buf_copy = NULL;
+			return ret;
 		}
 		/* The packet is for the remote processor */
 		token_offset = 4;
@@ -1526,7 +1527,7 @@
 							1 + payload_size);
 		send.terminate = 1;
 
-
+		mutex_lock(&driver->diagchar_mutex);
 		if (!buf_hdlc)
 			buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
 							POOL_TYPE_HDLC);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 2beb143..ba3ecc2 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1294,22 +1294,38 @@
 		driver->apps_rsp_buf[0] = 0x73;
 		*(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
 		*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
-		*(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
-		*(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
-		*(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
-		*(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
-		*(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
-		*(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
-		*(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
-		*(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
-		*(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
-		*(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
-		*(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
-		*(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
-		*(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
-		*(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
-		*(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
-		*(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
+		*(int *)(driver->apps_rsp_buf + 12) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[0]);
+		*(int *)(driver->apps_rsp_buf + 16) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[1]);
+		*(int *)(driver->apps_rsp_buf + 20) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[2]);
+		*(int *)(driver->apps_rsp_buf + 24) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[3]);
+		*(int *)(driver->apps_rsp_buf + 28) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[4]);
+		*(int *)(driver->apps_rsp_buf + 32) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[5]);
+		*(int *)(driver->apps_rsp_buf + 36) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[6]);
+		*(int *)(driver->apps_rsp_buf + 40) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[7]);
+		*(int *)(driver->apps_rsp_buf + 44) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[8]);
+		*(int *)(driver->apps_rsp_buf + 48) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[9]);
+		*(int *)(driver->apps_rsp_buf + 52) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[10]);
+		*(int *)(driver->apps_rsp_buf + 56) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[11]);
+		*(int *)(driver->apps_rsp_buf + 60) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[12]);
+		*(int *)(driver->apps_rsp_buf + 64) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[13]);
+		*(int *)(driver->apps_rsp_buf + 68) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[14]);
+		*(int *)(driver->apps_rsp_buf + 72) =
+				LOG_GET_ITEM_NUM(log_code_last_tbl[15]);
 		encode_rsp_and_send(75);
 		return 0;
 	}
diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c
index 7778477..8037187 100644
--- a/drivers/crypto/msm/qce.c
+++ b/drivers/crypto/msm/qce.c
@@ -1949,6 +1949,12 @@
 	else
 		q_req->cryptlen = areq->cryptlen - authsize;
 
+	if ((q_req->cryptlen > ULONG_MAX - ivsize) ||
+		(q_req->cryptlen + ivsize > ULONG_MAX - areq->assoclen)) {
+		pr_err("Integer overflow on total aead req length.\n");
+		return -EINVAL;
+	}
+
 	totallen = q_req->cryptlen + ivsize + areq->assoclen;
 	pad_len = ALIGN(totallen, ADM_CE_BLOCK_SIZE) - totallen;
 
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 4c05978..a4154c1 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -43,13 +43,17 @@
 #define QCE_MAX_NUM_DSCR    0x500
 #define QCE_SECTOR_SIZE	    0x200
 
-static DEFINE_MUTEX(bam_register_cnt);
+static DEFINE_MUTEX(bam_register_lock);
 struct bam_registration_info {
+	struct list_head qlist;
 	uint32_t handle;
 	uint32_t cnt;
+	uint32_t bam_mem;
+	void __iomem *bam_iobase;
+	bool support_cmd_dscr;
 };
-static struct bam_registration_info bam_registry;
-static bool ce_bam_registered;
+static LIST_HEAD(qce50_bam_list);
+
 /*
  * CE HW device structure.
  * Each engine has an instance of the structure.
@@ -58,11 +62,14 @@
  */
 struct qce_device {
 	struct device *pdev;        /* Handle to platform_device structure */
+	struct bam_registration_info *pbam;
 
 	unsigned char *coh_vmem;    /* Allocated coherent virtual memory */
 	dma_addr_t coh_pmem;	    /* Allocated coherent physical memory */
 	int memsize;				/* Memory allocated */
-	int is_shared;				/* CE HW is shared */
+	uint32_t bam_mem;		/* bam physical address, from DT */
+	uint32_t bam_mem_size;		/* bam io size, from DT */
+	int is_shared;			/* CE HW is shared */
 	bool support_cmd_dscr;
 	bool support_hw_key;
 
@@ -2162,25 +2169,93 @@
 			sps_connect_info->desc.phys_base);
 	sps_free_endpoint(sps_pipe_info);
 }
-/**
- * Initialize SPS HW connected with CE core
- *
- * This function register BAM HW resources with
- * SPS driver and then initialize 2 SPS endpoints
- *
- * This function should only be called once typically
- * during driver probe.
- *
- * @pce_dev - Pointer to qce_device structure
- *
- * @return - 0 if successful else negative value.
- *
- */
-static int qce_sps_init(struct qce_device *pce_dev)
+
+static void qce_sps_release_bam(struct qce_device *pce_dev)
+{
+	struct bam_registration_info *pbam;
+
+	mutex_lock(&bam_register_lock);
+	pbam = pce_dev->pbam;
+	if (pbam == NULL)
+		goto ret;
+
+	pbam->cnt--;
+	if (pbam->cnt > 0)
+		goto ret;
+
+	if (pce_dev->ce_sps.bam_handle) {
+		sps_deregister_bam_device(pce_dev->ce_sps.bam_handle);
+
+		pr_debug("deregister bam handle %x\n",
+					pce_dev->ce_sps.bam_handle);
+		pce_dev->ce_sps.bam_handle = 0;
+	}
+	iounmap(pbam->bam_iobase);
+	pr_debug("delete bam 0x%x\n", pbam->bam_mem);
+	list_del(&pbam->qlist);
+	kfree(pbam);
+
+	pce_dev->pbam = NULL;
+ret:
+	mutex_unlock(&bam_register_lock);
+}
+
+static int qce_sps_get_bam(struct qce_device *pce_dev)
 {
 	int rc = 0;
 	struct sps_bam_props bam = {0};
-	bool register_bam = false;
+	struct bam_registration_info *pbam = NULL;
+	struct bam_registration_info *p;
+	uint32_t bam_cfg = 0 ;
+
+
+	mutex_lock(&bam_register_lock);
+
+	list_for_each_entry(p, &qce50_bam_list, qlist) {
+		if (p->bam_mem == pce_dev->bam_mem) {
+			pbam = p;  /* found */
+			break;
+		}
+	}
+
+	if (pbam) {
+		pr_debug("found bam 0x%x\n", pbam->bam_mem);
+		pbam->cnt++;
+		pce_dev->ce_sps.bam_handle =  pbam->handle;
+		pce_dev->ce_sps.bam_mem = pbam->bam_mem;
+		pce_dev->ce_sps.bam_iobase = pbam->bam_iobase;
+		pce_dev->pbam = pbam;
+		pce_dev->support_cmd_dscr = pbam->support_cmd_dscr;
+		goto ret;
+	}
+
+	pbam = kzalloc(sizeof(struct  bam_registration_info), GFP_KERNEL);
+	if (!pbam) {
+		pr_err("qce50 Memory allocation of bam FAIL, error %ld\n",
+						PTR_ERR(pbam));
+
+		rc = -ENOMEM;
+		goto ret;
+	}
+	pbam->cnt = 1;
+	pbam->bam_mem = pce_dev->bam_mem;
+	pbam->bam_iobase = ioremap_nocache(pce_dev->bam_mem,
+					pce_dev->bam_mem_size);
+	if (!pbam->bam_iobase) {
+		kfree(pbam);
+		rc = -ENOMEM;
+		pr_err("Can not map BAM io memory\n");
+		goto ret;
+	}
+	pce_dev->ce_sps.bam_mem = pbam->bam_mem;
+	pce_dev->ce_sps.bam_iobase = pbam->bam_iobase;
+	pbam->handle = 0;
+	pr_debug("allocate bam 0x%x\n", pbam->bam_mem);
+	bam_cfg = readl_relaxed(pce_dev->ce_sps.bam_iobase +
+					CRYPTO_BAM_CNFG_BITS_REG);
+	pbam->support_cmd_dscr =  (bam_cfg & CRYPTO_BAM_CD_ENABLE_MASK) ?
+					true : false;
+	pce_dev->support_cmd_dscr = pbam->support_cmd_dscr;
 
 	bam.phys_addr = pce_dev->ce_sps.bam_mem;
 	bam.virt_addr = pce_dev->ce_sps.bam_iobase;
@@ -2212,27 +2287,46 @@
 	pr_debug("bam physical base=0x%x\n", (u32)bam.phys_addr);
 	pr_debug("bam virtual base=0x%x\n", (u32)bam.virt_addr);
 
-	mutex_lock(&bam_register_cnt);
-	if (ce_bam_registered == false) {
-		bam_registry.handle = 0;
-		bam_registry.cnt = 0;
+	/* Register CE Peripheral BAM device to SPS driver */
+	rc = sps_register_bam_device(&bam, &pbam->handle);
+	if (rc) {
+		pr_err("sps_register_bam_device() failed! err=%d", rc);
+		rc = -EIO;
+		iounmap(pbam->bam_iobase);
+		kfree(pbam);
+		goto ret;
 	}
-	if ((bam_registry.handle == 0) && (bam_registry.cnt == 0)) {
-		/* Register CE Peripheral BAM device to SPS driver */
-		rc = sps_register_bam_device(&bam, &bam_registry.handle);
-		if (rc) {
-			mutex_unlock(&bam_register_cnt);
-			pr_err("sps_register_bam_device() failed! err=%d", rc);
-			return -EIO;
-		}
-		bam_registry.cnt++;
-		register_bam = true;
-		ce_bam_registered = true;
-	} else {
-		   bam_registry.cnt++;
-	}
-	mutex_unlock(&bam_register_cnt);
-	pce_dev->ce_sps.bam_handle =  bam_registry.handle;
+
+	pce_dev->pbam = pbam;
+	list_add_tail(&pbam->qlist, &qce50_bam_list);
+	pce_dev->ce_sps.bam_handle =  pbam->handle;
+
+ret:
+	mutex_unlock(&bam_register_lock);
+
+	return rc;
+}
+/**
+ * Initialize SPS HW connected with CE core
+ *
+ * This function register BAM HW resources with
+ * SPS driver and then initialize 2 SPS endpoints
+ *
+ * This function should only be called once typically
+ * during driver probe.
+ *
+ * @pce_dev - Pointer to qce_device structure
+ *
+ * @return - 0 if successful else negative value.
+ *
+ */
+static int qce_sps_init(struct qce_device *pce_dev)
+{
+	int rc = 0;
+
+	rc = qce_sps_get_bam(pce_dev);
+	if (rc)
+		return rc;
 	pr_debug("BAM device registered. bam_handle=0x%x",
 		pce_dev->ce_sps.bam_handle);
 
@@ -2253,14 +2347,7 @@
 sps_connect_consumer_err:
 	qce_sps_exit_ep_conn(pce_dev, &pce_dev->ce_sps.producer);
 sps_connect_producer_err:
-	if (register_bam) {
-		mutex_lock(&bam_register_cnt);
-		sps_deregister_bam_device(pce_dev->ce_sps.bam_handle);
-		ce_bam_registered = false;
-		bam_registry.handle = 0;
-		bam_registry.cnt = 0;
-		mutex_unlock(&bam_register_cnt);
-	}
+	qce_sps_release_bam(pce_dev);
 	return rc;
 }
 
@@ -2280,17 +2367,7 @@
 {
 	qce_sps_exit_ep_conn(pce_dev, &pce_dev->ce_sps.consumer);
 	qce_sps_exit_ep_conn(pce_dev, &pce_dev->ce_sps.producer);
-	mutex_lock(&bam_register_cnt);
-	if ((bam_registry.handle != 0) && (bam_registry.cnt == 1)) {
-		sps_deregister_bam_device(pce_dev->ce_sps.bam_handle);
-		bam_registry.cnt = 0;
-		bam_registry.handle = 0;
-	}
-	if ((bam_registry.handle != 0) && (bam_registry.cnt > 1))
-		bam_registry.cnt--;
-	mutex_unlock(&bam_register_cnt);
-
-	iounmap(pce_dev->ce_sps.bam_iobase);
+	qce_sps_release_bam(pce_dev);
 }
 
 static void _aead_sps_producer_callback(struct sps_event_notify *notify)
@@ -4069,22 +4146,15 @@
 	resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 							"crypto-bam-base");
 	if (resource) {
-		pce_dev->ce_sps.bam_mem = resource->start;
-		pce_dev->ce_sps.bam_iobase = ioremap_nocache(resource->start,
-					resource_size(resource));
-		if (!pce_dev->ce_sps.bam_iobase) {
-			rc = -ENOMEM;
-			pr_err("Can not map BAM io memory\n");
-			goto err_getting_bam_info;
-		}
+		pce_dev->bam_mem = resource->start;
+		pce_dev->bam_mem_size = resource_size(resource);
 	} else {
 		pr_err("CRYPTO BAM mem unavailable.\n");
 		rc = -ENODEV;
 		goto err_getting_bam_info;
 	}
-	pr_warn("ce_bam_phy_reg_base=0x%x  ", pce_dev->ce_sps.bam_mem);
-	pr_warn("ce_bam_virt_reg_base=0x%x\n",
-				(uint32_t)pce_dev->ce_sps.bam_iobase);
+	pr_warn("ce_bam_phy_reg_base=0x%x  ", pce_dev->bam_mem);
+
 	resource  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (resource) {
 		pce_dev->ce_sps.bam_irq = resource->start;
@@ -4250,7 +4320,6 @@
 void *qce_open(struct platform_device *pdev, int *rc)
 {
 	struct qce_device *pce_dev;
-	uint32_t bam_cfg = 0 ;
 
 	pce_dev = kzalloc(sizeof(struct qce_device), GFP_KERNEL);
 	if (!pce_dev) {
@@ -4293,15 +4362,9 @@
 	}
 	*rc = 0;
 
-	bam_cfg = readl_relaxed(pce_dev->ce_sps.bam_iobase +
-					CRYPTO_BAM_CNFG_BITS_REG);
-	pce_dev->support_cmd_dscr = (bam_cfg & CRYPTO_BAM_CD_ENABLE_MASK) ?
-								true : false;
 	qce_init_ce_cfg_val(pce_dev);
-	qce_setup_ce_sps_data(pce_dev);
 	qce_sps_init(pce_dev);
-
-
+	qce_setup_ce_sps_data(pce_dev);
 	qce_disable_clk(pce_dev);
 
 	return pce_dev;
@@ -4313,8 +4376,6 @@
 		dma_free_coherent(pce_dev->pdev, pce_dev->memsize,
 			pce_dev->coh_vmem, pce_dev->coh_pmem);
 err_iobase:
-	if (pce_dev->ce_sps.bam_iobase)
-		iounmap(pce_dev->ce_sps.bam_iobase);
 	if (pce_dev->iobase)
 		iounmap(pce_dev->iobase);
 err_pce_dev:
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 81a90fe..4845f11 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1339,7 +1339,7 @@
 				areq->cipher_op_req.vbuf.src[0].len))
 		return -EFAULT;
 
-	k_align_src += areq->cipher_op_req.vbuf.src[0].len;
+	k_align_src += byteoffset + areq->cipher_op_req.vbuf.src[0].len;
 
 	for (i = 1; i < areq->cipher_op_req.entries; i++) {
 		user_src =
@@ -1602,11 +1602,6 @@
 static int qcedev_check_cipher_key(struct qcedev_cipher_op_req *req,
 						struct qcedev_control *podev)
 {
-
-	if (req->encklen < 0) {
-		pr_err("%s: Invalid key size: %d\n", __func__, req->encklen);
-		return -EINVAL;
-	}
 	/* if intending to use HW key make sure key fields are set
 	 * correctly and HW key is indeed supported in target
 	 */
@@ -1701,6 +1696,13 @@
 			goto error;
 		}
 	}
+
+	if (req->data_len < req->byteoffset) {
+		pr_err("%s: req data length %u is less than byteoffset %u\n",
+				__func__, req->data_len, req->byteoffset);
+		goto error;
+	}
+
 	/* Ensure zer ivlen for ECB  mode  */
 	if (req->ivlen > 0) {
 		if ((req->mode == QCEDEV_AES_MODE_ECB) ||
@@ -1716,16 +1718,28 @@
 		}
 	}
 	/* Check for sum of all dst length is equal to data_len  */
-	for (i = 0; (i < QCEDEV_MAX_BUFFERS) && (total < req->data_len); i++)
+	for (i = 0; (i < QCEDEV_MAX_BUFFERS) && (total < req->data_len); i++) {
+		if (req->vbuf.dst[i].len > ULONG_MAX - total) {
+			pr_err("%s: Integer overflow on total req dst vbuf length\n",
+				__func__);
+			goto error;
+		}
 		total += req->vbuf.dst[i].len;
+	}
 	if (total != req->data_len) {
 		pr_err("%s: Total (i=%d) dst(%d) buf size != data_len (%d)\n",
 			__func__, i, total, req->data_len);
 		goto error;
 	}
 	/* Check for sum of all src length is equal to data_len  */
-	for (i = 0, total = 0; i < req->entries; i++)
+	for (i = 0, total = 0; i < req->entries; i++) {
+		if (req->vbuf.src[i].len > ULONG_MAX - total) {
+			pr_err("%s: Integer overflow on total req src vbuf length\n",
+				__func__);
+			goto error;
+		}
 		total += req->vbuf.src[i].len;
+	}
 	if (total != req->data_len) {
 		pr_err("%s: Total src(%d) buf size != data_len (%d)\n",
 			__func__, total, req->data_len);
@@ -1781,8 +1795,15 @@
 	}
 
 	/* Check for sum of all src length is equal to data_len  */
-	for (i = 0, total = 0; i < req->entries; i++)
+	for (i = 0, total = 0; i < req->entries; i++) {
+		if (req->data[i].len > ULONG_MAX - total) {
+			pr_err("%s: Integer overflow on total req buf length\n",
+				__func__);
+			goto sha_error;
+		}
 		total += req->data[i].len;
+	}
+
 	if (total != req->data_len) {
 		pr_err("%s: Total src(%d) buf size != data_len (%d)\n",
 			__func__, total, req->data_len);
@@ -2112,21 +2133,21 @@
 	int len = 0;
 
 	pstat = &_qcedev_stat;
-	len = snprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
+	len = scnprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
 			"\nQualcomm QCE dev driver %d Statistics:\n",
 				id + 1);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   Encryption operation success       : %d\n",
 					pstat->qcedev_enc_success);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   Encryption operation fail   : %d\n",
 					pstat->qcedev_enc_fail);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   Decryption operation success     : %d\n",
 					pstat->qcedev_dec_success);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   Encryption operation fail          : %d\n",
 					pstat->qcedev_dec_fail);
 
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index ae57d6c..6606706 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -409,7 +409,7 @@
 {
 	int i;
 
-	for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg))
+	for (i = 0; nbytes > 0 && sg != NULL; i++, sg = scatterwalk_sg_next(sg))
 		nbytes -= sg->length;
 
 	return i;
@@ -628,98 +628,98 @@
 	int len = 0;
 
 	pstat = &_qcrypto_stat;
-	len = snprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
+	len = scnprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
 			"\nQualcomm crypto accelerator %d Statistics:\n",
 				id + 1);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   ABLK AES CIPHER encryption   : %d\n",
 					pstat->ablk_cipher_aes_enc);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   ABLK AES CIPHER decryption   : %d\n",
 					pstat->ablk_cipher_aes_dec);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   ABLK DES CIPHER encryption   : %d\n",
 					pstat->ablk_cipher_des_enc);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   ABLK DES CIPHER decryption   : %d\n",
 					pstat->ablk_cipher_des_dec);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   ABLK 3DES CIPHER encryption  : %d\n",
 					pstat->ablk_cipher_3des_enc);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   ABLK 3DES CIPHER decryption  : %d\n",
 					pstat->ablk_cipher_3des_dec);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   ABLK CIPHER operation success: %d\n",
 					pstat->ablk_cipher_op_success);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   ABLK CIPHER operation fail   : %d\n",
 					pstat->ablk_cipher_op_fail);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD SHA1-AES encryption      : %d\n",
 					pstat->aead_sha1_aes_enc);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD SHA1-AES decryption      : %d\n",
 					pstat->aead_sha1_aes_dec);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD SHA1-DES encryption      : %d\n",
 					pstat->aead_sha1_des_enc);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD SHA1-DES decryption      : %d\n",
 					pstat->aead_sha1_des_dec);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD SHA1-3DES encryption     : %d\n",
 					pstat->aead_sha1_3des_enc);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD SHA1-3DES decryption     : %d\n",
 					pstat->aead_sha1_3des_dec);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD CCM-AES encryption     : %d\n",
 					pstat->aead_ccm_aes_enc);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD CCM-AES decryption     : %d\n",
 					pstat->aead_ccm_aes_dec);
 
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD operation success       : %d\n",
 					pstat->aead_op_success);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD operation fail          : %d\n",
 					pstat->aead_op_fail);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD bad message             : %d\n",
 					pstat->aead_bad_msg);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA1 digest			 : %d\n",
 					pstat->sha1_digest);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA256 digest		 : %d\n",
 					pstat->sha256_digest);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA  operation fail          : %d\n",
 					pstat->sha_op_fail);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA  operation success          : %d\n",
 					pstat->sha_op_success);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA1 HMAC digest			 : %d\n",
 					pstat->sha1_hmac_digest);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA256 HMAC digest		 : %d\n",
 					pstat->sha256_hmac_digest);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA HMAC operation fail          : %d\n",
 					pstat->sha_hmac_op_fail);
-	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA HMAC operation success          : %d\n",
 					pstat->sha_hmac_op_success);
 	return len;
@@ -1423,8 +1423,20 @@
 
 			rctx->orig_src = req->src;
 			rctx->orig_dst = req->dst;
+
+			if ((MAX_ALIGN_SIZE*2 > ULONG_MAX - req->assoclen) ||
+				((MAX_ALIGN_SIZE*2 + req->assoclen) >
+						ULONG_MAX - qreq.authsize) ||
+				((MAX_ALIGN_SIZE*2 + req->assoclen +
+						qreq.authsize) >
+						ULONG_MAX - req->cryptlen)) {
+				pr_err("Integer overflow on aead req length.\n");
+				return -EINVAL;
+			}
+
 			rctx->data = kzalloc((req->cryptlen + qreq.assoclen +
-					qreq.authsize + 64*2), GFP_ATOMIC);
+					qreq.authsize + MAX_ALIGN_SIZE*2),
+					GFP_ATOMIC);
 			if (rctx->data == NULL) {
 				pr_err("Mem Alloc fail rctx->data, err %ld\n",
 							PTR_ERR(rctx->data));
@@ -1486,6 +1498,16 @@
 			 * include  assoicated data, ciphering data stream,
 			 * generated MAC, and CCM padding.
 			 */
+			if ((MAX_ALIGN_SIZE * 2 > ULONG_MAX - req->assoclen) ||
+				((MAX_ALIGN_SIZE * 2 + req->assoclen) >
+						ULONG_MAX - qreq.ivsize) ||
+				((MAX_ALIGN_SIZE * 2 + req->assoclen
+					+ qreq.ivsize)
+						> ULONG_MAX - req->cryptlen)) {
+				pr_err("Integer overflow on aead req length.\n");
+				return -EINVAL;
+			}
+
 			rctx->data = kzalloc(
 					(req->cryptlen +
 						req->assoclen +
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index b5945da..728e90c 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -772,6 +772,9 @@
 #define SP0_ICL1_MISSES                0x1A
 #define SP_FS_CFLOW_INSTRUCTIONS       0x0C
 
+/* COUNTABLE FOR TSE PERFCOUNTER */
+#define TSE_INPUT_PRIM_NUM             0x0
+
 /* VBIF PERFCOUNTER ENA/CLR values */
 #define VBIF_PERF_CNT_0 BIT(0)
 #define VBIF_PERF_CNT_1 BIT(1)
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 8f48440..0ee54d0 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -362,7 +362,7 @@
 	unsigned int replay_for_snapshot;
 };
 
-#define FT_DETECT_REGS_COUNT 12
+#define FT_DETECT_REGS_COUNT 14
 
 struct log_field {
 	bool show;
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 5778e9e..f316664 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -3863,7 +3863,9 @@
 	 * USP L1 instruction miss request.
 	 * Set SP to count SP_FS_FULL_ALU_INSTRUCTIONS, it
 	 * counts USP flow control instruction execution.
-	 * we will use this to augment our hang detection
+	 * Set TSE to count TSE_INPUT_PRIM_NUM, it counts
+	 * number of input primitives in TSE.
+	 * we will use above countables for our hang detection
 	 */
 	if (adreno_dev->fast_hang_detect) {
 		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
@@ -3878,6 +3880,10 @@
 			SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10],
 			PERFCOUNTER_FLAG_KERNEL);
 		ft_detect_regs[11] = ft_detect_regs[10] + 1;
+		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_TSE,
+			TSE_INPUT_PRIM_NUM, &ft_detect_regs[12],
+			PERFCOUNTER_FLAG_KERNEL);
+		ft_detect_regs[13] = ft_detect_regs[12] + 1;
 	}
 
 	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 6cd1f68..2eb5300 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -59,6 +59,9 @@
 	struct sg_table *table;
 };
 
+static void kgsl_put_process_private(struct kgsl_device *device,
+			 struct kgsl_process_private *private);
+
 static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry);
 
 /**
@@ -409,14 +412,19 @@
  */
 static int
 kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
-				   struct kgsl_process_private *process)
+				   struct kgsl_device_private *dev_priv)
 {
 	int ret;
+	struct kgsl_process_private *process = dev_priv->process_priv;
+	
+	ret = kref_get_unless_zero(&process->refcount);
+	if (!ret)
+		return -EBADF;
 
 	while (1) {
 		if (idr_pre_get(&process->mem_idr, GFP_KERNEL) == 0) {
 			ret = -ENOMEM;
-			goto err;
+			goto err_put_proc_priv;
 		}
 
 		spin_lock(&process->mem_lock);
@@ -427,9 +435,10 @@
 		if (ret == 0)
 			break;
 		else if (ret != -EAGAIN)
-			goto err;
+			goto err_put_proc_priv;
 	}
 	entry->priv = process;
+	entry->dev_priv = dev_priv;
 
 	spin_lock(&process->mem_lock);
 	ret = kgsl_mem_entry_track_gpuaddr(process, entry);
@@ -437,14 +446,17 @@
 		idr_remove(&process->mem_idr, entry->id);
 	spin_unlock(&process->mem_lock);
 	if (ret)
-		goto err;
+		goto err_put_proc_priv;
 	/* map the memory after unlocking if gpuaddr has been assigned */
 	if (entry->memdesc.gpuaddr) {
 		ret = kgsl_mmu_map(process->pagetable, &entry->memdesc);
 		if (ret)
 			kgsl_mem_entry_detach_process(entry);
 	}
-err:
+	return ret;
+
+err_put_proc_priv:
+	kgsl_put_process_private(dev_priv->device, process);
 	return ret;
 }
 
@@ -467,6 +479,7 @@
 
 	entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
 	spin_unlock(&entry->priv->mem_lock);
+	kgsl_put_process_private(entry->dev_priv->device, entry->priv);
 
 	entry->priv = NULL;
 }
@@ -813,11 +826,6 @@
  */
 static void kgsl_destroy_process_private(struct kref *kref)
 {
-
-	struct kgsl_mem_entry *entry = NULL;
-	int next = 0;
-
-
 	struct kgsl_process_private *private = container_of(kref,
 			struct kgsl_process_private, refcount);
 
@@ -841,20 +849,6 @@
 	if (private->debug_root)
 		debugfs_remove_recursive(private->debug_root);
 
-	while (1) {
-		spin_lock(&private->mem_lock);
-		entry = idr_get_next(&private->mem_idr, &next);
-		spin_unlock(&private->mem_lock);
-		if (entry == NULL)
-			break;
-		kgsl_mem_entry_put(entry);
-		/*
-		 * Always start back at the beginning, to
-		 * ensure all entries are removed,
-		 * like list_for_each_entry_safe.
-		 */
-		next = 0;
-	}
 	idr_destroy(&private->mem_idr);
 	kgsl_mmu_putpagetable(private->pagetable);
 
@@ -1004,6 +998,7 @@
 	struct kgsl_process_private *private = dev_priv->process_priv;
 	struct kgsl_device *device = dev_priv->device;
 	struct kgsl_context *context;
+	struct kgsl_mem_entry *entry;
 	int next = 0;
 
 	filep->private_data = NULL;
@@ -1024,6 +1019,25 @@
 
 		next = next + 1;
 	}
+	next = 0;
+	while (1) {
+		spin_lock(&private->mem_lock);
+		entry = idr_get_next(&private->mem_idr, &next);
+		spin_unlock(&private->mem_lock);
+		if (entry == NULL)
+			break;
+		/*
+		 * If the free pending flag is not set it means that user space
+		 * did not free it's reference to this entry, in that case
+		 * free a reference to this entry, other references are from
+		 * within kgsl so they will be freed eventually by kgsl
+		 */
+		if (entry->dev_priv == dev_priv && !entry->pending_free) {
+			entry->pending_free = 1;
+			kgsl_mem_entry_put(entry);
+		}
+		next = next + 1;
+	}
 	/*
 	 * Clean up any to-be-freed entries that belong to this
 	 * process and this device. This is done after the context
@@ -2246,7 +2260,7 @@
 	/* echo back flags */
 	param->flags = entry->memdesc.flags;
 
-	result = kgsl_mem_entry_attach_process(entry, private);
+	result = kgsl_mem_entry_attach_process(entry, dev_priv);
 	if (result)
 		goto error_attach;
 
@@ -2534,7 +2548,7 @@
 	if (result)
 		return result;
 
-	result = kgsl_mem_entry_attach_process(entry, private);
+	result = kgsl_mem_entry_attach_process(entry, dev_priv);
 	if (result != 0)
 		goto err;
 
@@ -2567,7 +2581,7 @@
 	if (result != 0)
 		goto err;
 
-	result = kgsl_mem_entry_attach_process(entry, private);
+	result = kgsl_mem_entry_attach_process(entry, dev_priv);
 	if (result != 0)
 		goto err;
 
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 42d3b3e..3f4dde7 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -197,6 +197,7 @@
 	struct kgsl_process_private *priv;
 	/* Initialized to 0, set to 1 when entry is marked for freeing */
 	int pending_free;
+	struct kgsl_device_private *dev_priv;
 };
 
 #ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
diff --git a/drivers/input/misc/cm36283.c b/drivers/input/misc/cm36283.c
index 17127a8..7d9241b 100644
--- a/drivers/input/misc/cm36283.c
+++ b/drivers/input/misc/cm36283.c
@@ -674,17 +674,9 @@
 {
 	int ret = -EIO;
 	unsigned int delay;
-	
-	mutex_lock(&als_enable_mutex);
 
-	if (lpi->als_enable) {
-		dev_err(&lpi->i2c_client->dev, "%s: already enabled\n",
-			       __func__);
-		ret = 0;
-	} else {
-		ret = control_and_report(lpi, CONTROL_ALS, 1, 0);
-	}
-	
+	mutex_lock(&als_enable_mutex);
+	ret = control_and_report(lpi, CONTROL_ALS, 1, 0);
 	mutex_unlock(&als_enable_mutex);
 
 	delay = atomic_read(&lpi->ls_poll_delay);
@@ -2009,27 +2001,40 @@
 	struct cm36283_info *lpi = lp_info;
 
 	if (lpi->als_enable) {
-		lightsensor_disable(lpi);
+		if (lightsensor_disable(lpi))
+			goto out;
 		lpi->als_enable = 1;
 	}
-	cm36283_power_set(lpi, 0);
+	if (cm36283_power_set(lpi, 0))
+		goto out;
 
 	return 0;
+
+out:
+	dev_err(&lpi->i2c_client->dev, "%s:failed during resume operation.\n",
+			__func__);
+	return -EIO;
 }
 
 static int cm36283_resume(struct device *dev)
 {
 	struct cm36283_info *lpi = lp_info;
 
-	cm36283_power_set(lpi, 1);
+	if (cm36283_power_set(lpi, 1))
+		goto out;
 
 	if (lpi->als_enable) {
-		cm36283_setup(lpi);
-		lightsensor_setup(lpi);
-		psensor_setup(lpi);
-		lightsensor_enable(lpi);
+		ls_initial_cmd(lpi);
+		psensor_initial_cmd(lpi);
+		if (lightsensor_enable(lpi))
+			goto out;
 	}
 	return 0;
+
+out:
+	dev_err(&lpi->i2c_client->dev, "%s:failed during resume operation.\n",
+			__func__);
+	return -EIO;
 }
 #endif
 
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index a325d54..91aa928 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -53,6 +53,7 @@
 #define MMA8X5X_BUF_SIZE	7
 
 #define	MMA_SHUTTEDDOWN		(1 << 31)
+#define MMA_STATE_MASK		(~MMA_SHUTTEDDOWN)
 
 struct sensor_regulator {
 	struct regulator *vreg;
@@ -349,7 +350,7 @@
 	struct input_polled_dev *poll_dev = pdata->poll_dev;
 	struct mma8x5x_data_axis data;
 	mutex_lock(&pdata->data_lock);
-	if (pdata->active == MMA_STANDBY) {
+	if ((pdata->active & MMA_STATE_MASK) == MMA_STANDBY) {
 		poll_dev->poll_interval = POLL_STOP_TIME;
 		/* if standby ,set as 10s to slow the poll. */
 		goto out;
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index f366364..9a4301e 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -717,7 +717,9 @@
 
 		if (r_buf[0] != info.upgrade_id_1
 			|| r_buf[1] != info.upgrade_id_2) {
-			dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
+			dev_err(&client->dev, "Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n",
+				i, r_buf[0], r_buf[1],
+				info.upgrade_id_1, info.upgrade_id_2);
 		} else
 			break;
 	}
@@ -743,6 +745,10 @@
 	else
 		is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
 
+	dev_dbg(&client->dev, "bootloader type=%d, r_buf=0x%x, family_id=0x%x\n",
+		is_5336_new_bootloader, r_buf[0], ts_data->family_id);
+	/* is_5336_new_bootloader = FT_BLOADER_VERSION_GZF; */
+
 	/* erase app and panel paramenter area */
 	w_buf[0] = FT_ERASE_APP_REG;
 	ft5x06_i2c_write(client, w_buf, 1);
@@ -1537,7 +1543,7 @@
 		goto free_reset_gpio;
 	}
 
-	data->family_id = reg_value;
+	data->family_id = pdata->family_id;
 
 	err = request_threaded_irq(client->irq, NULL,
 				   ft5x06_ts_interrupt, pdata->irqflags,
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 70c1307..7282c2e 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -353,7 +353,7 @@
 
 	if (img->is_contain_build_info) {
 		img->firmware_id = extract_uint(data->firmware_id);
-		img->package_id = (data->pkg_id_rev_msb << 8) |
+		img->package_id = (data->pkg_id_msb << 8) |
 				data->pkg_id_lsb;
 		img->package_revision_id = (data->pkg_id_rev_msb << 8) |
 				data->pkg_id_rev_lsb;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index fb1caea..ea0195d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -623,6 +623,12 @@
 		goto reg_cfg_failed;
 	}
 
+	if (!proc_cmd->cmd_len) {
+		pr_err("%s: Passed cmd_len as 0\n", __func__);
+		rc = -EINVAL;
+		goto cfg_data_failed;
+	}
+
 	cfg_data = kzalloc(proc_cmd->cmd_len, GFP_KERNEL);
 	if (!cfg_data) {
 		pr_err("%s: cfg_data alloc failed\n", __func__);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
old mode 100644
new mode 100755
index 89016ec..de098c9
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -200,17 +200,17 @@
 			ispif->base + ISPIF_VFE_m_INTF_CMD_0(i));
 		msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY,
 			ispif->base + ISPIF_VFE_m_INTF_CMD_1(i));
-
+		pr_debug("%s: base %x", __func__, (unsigned int)ispif->base);
 		msm_camera_io_w(0, ispif->base +
 			ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
 		msm_camera_io_w(0, ispif->base +
 			ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1));
 		msm_camera_io_w(0, ispif->base +
-			ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
+			ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 0));
 		msm_camera_io_w(0, ispif->base +
-			ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1));
+			ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 1));
 		msm_camera_io_w(0, ispif->base +
-			ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 2));
+			ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 2));
 
 		msm_camera_io_w(0, ispif->base +
 			ISPIF_VFE_m_PIX_INTF_n_CROP(i, 0));
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index efa3ad0..c79b3a3 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -438,7 +438,7 @@
 static inline int __msm_destroy_session_streams(void *d1, void *d2)
 {
 	struct msm_stream *stream = d1;
-
+	pr_err("%s: Destroyed here due to list is not empty\n", __func__);
 	INIT_LIST_HEAD(&stream->queued_list);
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 154ee87..7520ce5 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -100,6 +100,24 @@
 	return ret;
 }
 
+static void msm_buf_mngr_sd_shutdown(struct msm_buf_mngr_device *buf_mngr_dev)
+{
+	unsigned long flags;
+	struct msm_get_bufs *bufs, *save;
+
+	spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
+	if (!list_empty(&buf_mngr_dev->buf_qhead)) {
+		list_for_each_entry_safe(bufs,
+			save, &buf_mngr_dev->buf_qhead, entry) {
+			pr_err("%s: Delete invalid bufs =%x\n", __func__,
+				(unsigned int)bufs);
+			list_del_init(&bufs->entry);
+			kfree(bufs);
+		}
+	}
+	spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
+}
+
 static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
 	unsigned int cmd, void *arg)
 {
@@ -123,6 +141,9 @@
 	case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
 		rc = msm_buf_mngr_put_buf(buf_mngr_dev, argp);
 		break;
+	case MSM_SD_SHUTDOWN:
+		msm_buf_mngr_sd_shutdown(buf_mngr_dev);
+		break;
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 8fa8f8d..0fbaeca 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -251,6 +251,7 @@
 	unsigned long flags;
 	struct msm_vb2_buffer *msm_vb2;
 	struct msm_stream *stream;
+	struct vb2_buffer *vb2_buf = NULL;
 	int rc = 0;
 
 	stream = msm_get_stream(session_id, stream_id);
@@ -258,6 +259,18 @@
 		return 0;
 	spin_lock_irqsave(&stream->stream_lock, flags);
 	if (vb) {
+		list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
+			vb2_buf = &(msm_vb2->vb2_buf);
+			if (vb2_buf == vb)
+				break;
+		}
+		if (vb2_buf != vb) {
+			pr_err("%s:%d VB buffer is INVALID vb=%x, ses_id=%d, str_id=%d\n",
+				__func__, __LINE__, (unsigned int)vb,
+				session_id, stream_id);
+			rc = -EINVAL;
+			goto out;
+		}
 		msm_vb2 =
 			container_of(vb, struct msm_vb2_buffer, vb2_buf);
 		/* put buf before buf done */
@@ -268,10 +281,11 @@
 		} else
 			rc = -EINVAL;
 	} else {
-		pr_err("%s: VB buffer is null\n", __func__);
+		pr_err("%s:%d VB buffer is NULL for ses_id=%d, str_id=%d\n",
+			__func__, __LINE__, session_id, stream_id);
 		rc = -EINVAL;
 	}
-
+out:
 	spin_unlock_irqrestore(&stream->stream_lock, flags);
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 8b8d23b..69f0a3d 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -57,14 +57,12 @@
 };
 
 struct msm_cpp_timer_t {
-	uint8_t used;
+	atomic_t used;
 	struct msm_cpp_timer_data_t data;
 	struct timer_list cpp_timer;
 };
 
-struct msm_cpp_timer_t cpp_timers[2];
-static int del_timer_idx;
-static int set_timer_idx;
+struct msm_cpp_timer_t cpp_timer;
 
 /* dump the frame command before writing to the hardware */
 #define  MSM_CPP_DUMP_FRM_CMD 0
@@ -596,24 +594,20 @@
 				if (msg_id == MSM_CPP_MSG_ID_FRAME_ACK) {
 					CPP_DBG("Frame done!!\n");
 					/* delete CPP timer */
-					CPP_DBG("delete timer %d.\n",
-						del_timer_idx);
-					timer = &cpp_timers[del_timer_idx];
+					CPP_DBG("delete timer.\n");
+					timer = &cpp_timer;
+					atomic_set(&timer->used, 0);
 					del_timer(&timer->cpp_timer);
-					timer->used = 0;
 					timer->data.processed_frame = NULL;
-					del_timer_idx = 1 - del_timer_idx;
 					msm_cpp_notify_frame_done(cpp_dev);
 				} else if (msg_id ==
 					MSM_CPP_MSG_ID_FRAME_NACK) {
 					pr_err("NACK error from hw!!\n");
-					CPP_DBG("delete timer %d.\n",
-						del_timer_idx);
-					timer = &cpp_timers[del_timer_idx];
+					CPP_DBG("delete timer.\n");
+					timer = &cpp_timer;
+					atomic_set(&timer->used, 0);
 					del_timer(&timer->cpp_timer);
-					timer->used = 0;
 					timer->data.processed_frame = NULL;
-					del_timer_idx = 1 - del_timer_idx;
 					msm_cpp_notify_frame_done(cpp_dev);
 				}
 				i += cmd_len + 2;
@@ -926,35 +920,35 @@
 
 	cpp_dev->cpp_open_cnt--;
 	if (cpp_dev->cpp_open_cnt == 0) {
-		pr_err("%s: irq_status: 0x%x\n", __func__,
+		pr_debug("irq_status: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x4));
-		pr_err("%s: DEBUG_SP: 0x%x\n", __func__,
+		pr_debug("DEBUG_SP: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x40));
-		pr_err("%s: DEBUG_T: 0x%x\n", __func__,
+		pr_debug("DEBUG_T: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x44));
-		pr_err("%s: DEBUG_N: 0x%x\n", __func__,
+		pr_debug("DEBUG_N: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x48));
-		pr_err("%s: DEBUG_R: 0x%x\n", __func__,
+		pr_debug("DEBUG_R: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x4C));
-		pr_err("%s: DEBUG_OPPC: 0x%x\n", __func__,
+		pr_debug("DEBUG_OPPC: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x50));
-		pr_err("%s: DEBUG_MO: 0x%x\n", __func__,
+		pr_debug("DEBUG_MO: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x54));
-		pr_err("%s: DEBUG_TIMER0: 0x%x\n", __func__,
+		pr_debug("DEBUG_TIMER0: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x60));
-		pr_err("%s: DEBUG_TIMER1: 0x%x\n", __func__,
+		pr_debug("DEBUG_TIMER1: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x64));
-		pr_err("%s: DEBUG_GPI: 0x%x\n", __func__,
+		pr_debug("DEBUG_GPI: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x70));
-		pr_err("%s: DEBUG_GPO: 0x%x\n", __func__,
+		pr_debug("DEBUG_GPO: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x74));
-		pr_err("%s: DEBUG_T0: 0x%x\n", __func__,
+		pr_debug("DEBUG_T0: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x80));
-		pr_err("%s: DEBUG_R0: 0x%x\n", __func__,
+		pr_debug("DEBUG_R0: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x84));
-		pr_err("%s: DEBUG_T1: 0x%x\n", __func__,
+		pr_debug("DEBUG_T1: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x88));
-		pr_err("%s: DEBUG_R1: 0x%x\n", __func__,
+		pr_debug("DEBUG_R1: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x8C));
 		msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
 		cpp_deinit_mem(cpp_dev);
@@ -1077,97 +1071,62 @@
 {
 	int ret;
 	uint32_t i = 0;
-	struct msm_cpp_frame_info_t *this_frame =
-		cpp_timers[del_timer_idx].data.processed_frame;
-	struct msm_cpp_frame_info_t *second_frame = NULL;
+	struct msm_cpp_frame_info_t *this_frame = NULL;
 
-	pr_err("cpp_timer_callback called idx:%d. (jiffies=%lu)\n",
-		del_timer_idx, jiffies);
-	if (!work || !this_frame) {
-		pr_err("Invalid work:%p, this_frame:%p, del_idx:%d\n",
-			work, this_frame, del_timer_idx);
+	pr_err("cpp_timer_callback called. (jiffies=%lu)\n",
+		jiffies);
+	if (!work) {
+		pr_err("Invalid work:%p\n", work);
 		return;
 	}
-	pr_err("fatal: cpp_timer expired for identity=0x%x, frame_id=%03d",
-		this_frame->identity, this_frame->frame_id);
-	cpp_timers[del_timer_idx].used = 0;
-	cpp_timers[del_timer_idx].data.processed_frame = NULL;
-	del_timer_idx = 1 - del_timer_idx;
-
-	if (cpp_timers[del_timer_idx].used == 1) {
-		pr_err("deleting cpp_timer %d.\n", del_timer_idx);
-		del_timer(&cpp_timers[del_timer_idx].cpp_timer);
-		cpp_timers[del_timer_idx].used = 0;
-		second_frame = cpp_timers[del_timer_idx].data.processed_frame;
-		cpp_timers[del_timer_idx].data.processed_frame = NULL;
-		del_timer_idx = 1 - del_timer_idx;
+	if (!atomic_read(&cpp_timer.used)) {
+		pr_err("Delayed trigger, IRQ serviced\n");
+		return;
 	}
 
-	disable_irq(cpp_timers[del_timer_idx].data.cpp_dev->irq->start);
+	disable_irq(cpp_timer.data.cpp_dev->irq->start);
 	pr_err("Reloading firmware\n");
-	cpp_load_fw(cpp_timers[del_timer_idx].data.cpp_dev, NULL);
+	cpp_load_fw(cpp_timer.data.cpp_dev, NULL);
 	pr_err("Firmware loading done\n");
-	enable_irq(cpp_timers[del_timer_idx].data.cpp_dev->irq->start);
-	msm_camera_io_w_mb(0x8, cpp_timers[del_timer_idx].data.cpp_dev->base +
+	enable_irq(cpp_timer.data.cpp_dev->irq->start);
+	msm_camera_io_w_mb(0x8, cpp_timer.data.cpp_dev->base +
 		MSM_CPP_MICRO_IRQGEN_MASK);
 	msm_camera_io_w_mb(0xFFFF,
-		cpp_timers[del_timer_idx].data.cpp_dev->base +
+		cpp_timer.data.cpp_dev->base +
 		MSM_CPP_MICRO_IRQGEN_CLR);
 
-	cpp_timers[set_timer_idx].data.processed_frame = this_frame;
-	cpp_timers[set_timer_idx].used = 1;
-	pr_err("ReInstalling cpp_timer %d\n", set_timer_idx);
-	setup_timer(&cpp_timers[set_timer_idx].cpp_timer, cpp_timer_callback,
-		(unsigned long)&cpp_timers[0]);
+	if (!atomic_read(&cpp_timer.used)) {
+		pr_err("Delayed trigger, IRQ serviced\n");
+		return;
+	}
+
+	this_frame = cpp_timer.data.processed_frame;
+	pr_err("ReInstalling cpp_timer\n");
+	setup_timer(&cpp_timer.cpp_timer, cpp_timer_callback,
+		(unsigned long)&cpp_timer);
 	pr_err("Starting timer to fire in %d ms. (jiffies=%lu)\n",
 		CPP_CMD_TIMEOUT_MS, jiffies);
-	ret = mod_timer(&cpp_timers[set_timer_idx].cpp_timer,
+	ret = mod_timer(&cpp_timer.cpp_timer,
 		jiffies + msecs_to_jiffies(CPP_CMD_TIMEOUT_MS));
 	if (ret)
 		pr_err("error in mod_timer\n");
 
-	set_timer_idx = 1 - set_timer_idx;
-	pr_err("Rescheduling for identity=0x%x, frame_id=%03d",
+	pr_err("Rescheduling for identity=0x%x, frame_id=%03d\n",
 		this_frame->identity, this_frame->frame_id);
-	msm_cpp_write(0x6, cpp_timers[set_timer_idx].data.cpp_dev->base);
+	msm_cpp_write(0x6, cpp_timer.data.cpp_dev->base);
 	msm_cpp_dump_frame_cmd(this_frame->cpp_cmd_msg,
 		this_frame->msg_len);
 	for (i = 0; i < this_frame->msg_len; i++)
 		msm_cpp_write(this_frame->cpp_cmd_msg[i],
-			cpp_timers[set_timer_idx].data.cpp_dev->base);
-
-
-	if (second_frame != NULL) {
-		cpp_timers[set_timer_idx].data.processed_frame = second_frame;
-		cpp_timers[set_timer_idx].used = 1;
-		pr_err("ReInstalling cpp_timer %d\n", set_timer_idx);
-		setup_timer(&cpp_timers[set_timer_idx].cpp_timer,
-			cpp_timer_callback, (unsigned long)&cpp_timers[0]);
-		pr_err("Starting timer to fire in %d ms. (jiffies=%lu)\n",
-			CPP_CMD_TIMEOUT_MS, jiffies);
-		ret = mod_timer(&cpp_timers[set_timer_idx].cpp_timer,
-			jiffies + msecs_to_jiffies(CPP_CMD_TIMEOUT_MS));
-		if (ret)
-			pr_err("error in mod_timer\n");
-
-		set_timer_idx = 1 - set_timer_idx;
-		pr_err("Rescheduling for identity=0x%x, frame_id=%03d",
-			second_frame->identity, second_frame->frame_id);
-		msm_cpp_write(0x6,
-			cpp_timers[set_timer_idx].data.cpp_dev->base);
-		msm_cpp_dump_frame_cmd(second_frame->cpp_cmd_msg,
-			second_frame->msg_len);
-		for (i = 0; i < second_frame->msg_len; i++)
-			msm_cpp_write(second_frame->cpp_cmd_msg[i],
-				cpp_timers[set_timer_idx].data.cpp_dev->base);
-	}
+			cpp_timer.data.cpp_dev->base);
+	return;
 }
 
 void cpp_timer_callback(unsigned long data)
 {
 	struct msm_cpp_work_t *work =
-		cpp_timers[set_timer_idx].data.cpp_dev->work;
-	queue_work(cpp_timers[set_timer_idx].data.cpp_dev->timer_wq,
+		cpp_timer.data.cpp_dev->work;
+	queue_work(cpp_timer.data.cpp_dev->timer_wq,
 		(struct work_struct *)work);
 }
 
@@ -1184,21 +1143,19 @@
 		msm_enqueue(&cpp_dev->processing_q,
 					&frame_qcmd->list_frame);
 
-		cpp_timers[set_timer_idx].data.processed_frame = process_frame;
-		cpp_timers[set_timer_idx].used = 1;
+		cpp_timer.data.processed_frame = process_frame;
+		atomic_set(&cpp_timer.used, 1);
 		/* install timer for cpp timeout */
-		CPP_DBG("Installing cpp_timer %d\n", set_timer_idx);
-		setup_timer(&cpp_timers[set_timer_idx].cpp_timer,
-			cpp_timer_callback, (unsigned long)&cpp_timers[0]);
+		CPP_DBG("Installing cpp_timer\n");
+		setup_timer(&cpp_timer.cpp_timer,
+			cpp_timer_callback, (unsigned long)&cpp_timer);
 		CPP_DBG("Starting timer to fire in %d ms. (jiffies=%lu)\n",
 			CPP_CMD_TIMEOUT_MS, jiffies);
-		ret = mod_timer(&cpp_timers[set_timer_idx].cpp_timer,
+		ret = mod_timer(&cpp_timer.cpp_timer,
 			jiffies + msecs_to_jiffies(CPP_CMD_TIMEOUT_MS));
 		if (ret)
 			pr_err("error in mod_timer\n");
 
-		set_timer_idx = 1 - set_timer_idx;
-
 		msm_cpp_write(0x6, cpp_dev->base);
 		msm_cpp_dump_frame_cmd(process_frame->cpp_cmd_msg,
 				process_frame->msg_len);
@@ -1285,8 +1242,8 @@
 
 	in_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
 		&new_frame->input_buffer_info,
-		((new_frame->identity >> 16) & 0xFFFF),
-		(new_frame->identity & 0xFFFF), &in_fd);
+		((new_frame->input_buffer_info.identity >> 16) & 0xFFFF),
+		(new_frame->input_buffer_info.identity & 0xFFFF), &in_fd);
 	if (!in_phyaddr) {
 		pr_err("error gettting input physical address\n");
 		rc = -EINVAL;
@@ -1712,6 +1669,7 @@
 		struct cpp_device *cpp_dev = v4l2_get_subdevdata(sd);
 		struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
 		struct msm_cpp_frame_info_t inst_info;
+		memset(&inst_info, 0, sizeof(struct msm_cpp_frame_info_t));
 		for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) {
 			if (cpp_dev->cpp_subscribe_list[i].vfh == vfh) {
 				inst_info.inst_id = i;
@@ -1890,10 +1848,8 @@
 	INIT_WORK((struct work_struct *)cpp_dev->work, msm_cpp_do_timeout_work);
 	cpp_dev->cpp_open_cnt = 0;
 	cpp_dev->is_firmware_loaded = 0;
-	cpp_timers[0].data.cpp_dev = cpp_dev;
-	cpp_timers[1].data.cpp_dev = cpp_dev;
-	cpp_timers[0].used = 0;
-	cpp_timers[1].used = 0;
+	cpp_timer.data.cpp_dev = cpp_dev;
+	atomic_set(&cpp_timer.used, 0);
 	cpp_dev->fw_name_bin = NULL;
 	return rc;
 ERROR3:
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
old mode 100644
new mode 100755
index 9384a5b..d8608ae
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -177,6 +177,7 @@
 static struct msm_cam_clk_info csiphy_8610_clk_info[] = {
 	{"csiphy_timer_src_clk", 200000000},
 	{"csiphy_timer_clk", -1},
+	{"csi_ahb_clk", -1},
 };
 
 static struct msm_cam_clk_info csiphy_8974_clk_info[] = {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h
index 9f3a81c..a4d7f15 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h
@@ -53,9 +53,11 @@
 	const char *flash_trigger_name[MAX_LED_TRIGGERS];
 	struct led_trigger *flash_trigger[MAX_LED_TRIGGERS];
 	uint32_t flash_op_current[MAX_LED_TRIGGERS];
+	uint32_t flash_max_current[MAX_LED_TRIGGERS];
 	const char *torch_trigger_name;
 	struct led_trigger *torch_trigger;
 	uint32_t torch_op_current;
+	uint32_t torch_max_current;
 	void *data;
 	uint32_t num_sources;
 	enum msm_camera_device_type_t flash_device_type;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
index 01d2c13..699142a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
@@ -51,6 +51,7 @@
 	int rc = 0;
 	struct msm_camera_led_cfg_t *cfg = (struct msm_camera_led_cfg_t *)data;
 	uint32_t i;
+	uint32_t curr_l, max_curr_l;
 	CDBG("called led_state %d\n", cfg->cfgtype);
 
 	if (!fctrl) {
@@ -68,18 +69,38 @@
 		break;
 
 	case MSM_CAMERA_LED_LOW:
-		if (fctrl->torch_trigger)
+		if (fctrl->torch_trigger) {
+			max_curr_l = fctrl->torch_max_current;
+			if (cfg->led_current > 0 &&
+					cfg->led_current < max_curr_l) {
+				curr_l = cfg->led_current;
+			} else {
+				curr_l = fctrl->torch_op_current;
+				pr_err("LED current clamped to %d\n",
+					curr_l);
+			}
 			led_trigger_event(fctrl->torch_trigger,
-				fctrl->torch_op_current);
+				curr_l);
+		}
 		break;
 
 	case MSM_CAMERA_LED_HIGH:
 		if (fctrl->torch_trigger)
 			led_trigger_event(fctrl->torch_trigger, 0);
 		for (i = 0; i < fctrl->num_sources; i++)
-			if (fctrl->flash_trigger[i])
+			if (fctrl->flash_trigger[i]) {
+				max_curr_l = fctrl->flash_max_current[i];
+				if (cfg->led_current > 0 &&
+						cfg->led_current < max_curr_l) {
+					curr_l = cfg->led_current;
+				} else {
+					curr_l = fctrl->flash_op_current[i];
+					pr_err("LED current clamped to %d\n",
+						curr_l);
+				}
 				led_trigger_event(fctrl->flash_trigger[i],
-					fctrl->flash_op_current[i]);
+					curr_l);
+			}
 		break;
 
 	case MSM_CAMERA_LED_INIT:
@@ -116,7 +137,7 @@
 
 static int32_t msm_led_trigger_probe(struct platform_device *pdev)
 {
-	int32_t rc = 0, i = 0;
+	int32_t rc = 0, rc_1 = 0, i = 0;
 	struct device_node *of_node = pdev->dev.of_node;
 	struct device_node *flash_src_node = NULL;
 	uint32_t count = 0;
@@ -181,7 +202,10 @@
 				rc = of_property_read_u32(flash_src_node,
 					"qcom,current",
 					&fctrl.flash_op_current[i]);
-				if (rc < 0) {
+				rc_1 = of_property_read_u32(flash_src_node,
+					"qcom,max-current",
+					&fctrl.flash_max_current[i]);
+				if ((rc < 0) || (rc_1 < 0)) {
 					pr_err("current: read failed\n");
 					of_node_put(flash_src_node);
 					continue;
@@ -229,7 +253,11 @@
 				rc = of_property_read_u32(flash_src_node,
 					"qcom,current",
 					&fctrl.torch_op_current);
-				if (rc < 0) {
+				rc_1 = of_property_read_u32(flash_src_node,
+					"qcom,max-current",
+					&fctrl.torch_max_current);
+
+				if ((rc < 0) || (rc_1 < 0)) {
 					pr_err("current: read failed\n");
 					goto torch_failed;
 				}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/sp1628.c b/drivers/media/platform/msm/camera_v2/sensor/sp1628.c
old mode 100644
new mode 100755
index 82e4b7c..9a422c0
--- a/drivers/media/platform/msm/camera_v2/sensor/sp1628.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/sp1628.c
@@ -866,6 +866,42 @@
 		}
 		break;
 	}
+	case CFG_SET_SATURATION: {
+
+		break;
+	}
+	case CFG_SET_CONTRAST: {
+
+		break;
+	}
+	case CFG_SET_SHARPNESS: {
+
+		break;
+	}
+	case CFG_SET_ISO: {
+
+		break;
+	}
+	case CFG_SET_EXPOSURE_COMPENSATION: {
+
+		break;
+	}
+	case CFG_SET_EFFECT: {
+
+		break;
+	}
+	case CFG_SET_ANTIBANDING: {
+
+		break;
+	}
+	case CFG_SET_BESTSHOT_MODE: {
+
+		break;
+	}
+	case CFG_SET_WHITE_BALANCE: {
+
+		break;
+	}
 	default:
 		rc = -EFAULT;
 		break;
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index abdb039..3fd5d3a 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1183,42 +1183,78 @@
 	callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
 }
 
-void hfi_process_sys_property_info(
-		struct hfi_property_sys_image_version_info_type *pkt)
+static void hfi_process_sys_get_prop_image_version(
+		struct hfi_msg_sys_property_info_packet *pkt)
 {
 	int i = 0;
 	u32 smem_block_size = 0;
 	u8 *smem_table_ptr;
 	char version[256];
+	const u32 version_string_size = 128;
 	const u32 smem_image_index_venus = 14 * 128;
+	u8 *str_image_version;
+	int req_bytes;
 
-	if (!pkt || !pkt->string_size) {
+	req_bytes = pkt->size - sizeof(*pkt);
+	if (req_bytes < version_string_size ||
+			!pkt->rg_property_data[1] ||
+			pkt->num_properties > 1) {
+		dprintk(VIDC_ERR,
+				"hfi_process_sys_get_prop_image_version:bad_pkt: %d",
+				req_bytes);
+		return;
+	}
+	str_image_version = (u8 *)&pkt->rg_property_data[1];
+	/*
+	 * The version string returned by firmware includes null
+	 * characters at the start and in between. Replace the null
+	 * characters with space, to print the version info.
+	 */
+	for (i = 0; i < version_string_size; i++) {
+		if (str_image_version[i] != '\0')
+			version[i] = str_image_version[i];
+		else
+			version[i] = ' ';
+	}
+	version[i] = '\0';
+	dprintk(VIDC_DBG, "F/W version: %s\n", version);
+
+	smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
+			&smem_block_size);
+	if (smem_table_ptr &&
+			((smem_image_index_venus +
+				version_string_size) <= smem_block_size))
+		memcpy(smem_table_ptr + smem_image_index_venus,
+				str_image_version, version_string_size);
+}
+
+static void hfi_process_sys_property_info(
+		struct hfi_msg_sys_property_info_packet *pkt)
+{
+	if (!pkt) {
 		dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
 		return;
 	}
-
-	if (pkt->string_size < sizeof(version)) {
-		/*
-		 * The version string returned by firmware includes null
-		 * characters at the start and in between. Replace the null
-		 * characters with space, to print the version info.
-		 */
-		for (i = 0; i < pkt->string_size; i++) {
-			if (pkt->str_image_version[i] != '\0')
-				version[i] = pkt->str_image_version[i];
-			else
-				version[i] = ' ';
-		}
-		version[i] = '\0';
-		dprintk(VIDC_DBG, "F/W version: %s\n", version);
+	if (pkt->size < sizeof(*pkt)) {
+		dprintk(VIDC_ERR,
+				"hfi_process_sys_property_info: bad_pkt_size\n");
+		return;
+	}
+	if (pkt->num_properties == 0) {
+		dprintk(VIDC_ERR,
+				"hfi_process_sys_property_info: no_properties\n");
+		return;
 	}
 
-	smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
-						&smem_block_size);
-	if (smem_table_ptr &&
-		((smem_image_index_venus + 128) <= smem_block_size))
-		memcpy(smem_table_ptr + smem_image_index_venus,
-			   (u8 *)pkt->str_image_version, 128);
+	switch (pkt->rg_property_data[0]) {
+	case HFI_PROPERTY_SYS_IMAGE_VERSION:
+		hfi_process_sys_get_prop_image_version(pkt);
+		break;
+	default:
+		dprintk(VIDC_ERR,
+				"hfi_process_sys_property_info:unknown_prop_id: %d\n",
+				pkt->rg_property_data[0]);
+	}
 }
 
 u32 hfi_process_msg_packet(
@@ -1263,7 +1299,7 @@
 		break;
 	case HFI_MSG_SYS_PROPERTY_INFO:
 		hfi_process_sys_property_info(
-		   (struct hfi_property_sys_image_version_info_type *)
+		   (struct hfi_msg_sys_property_info_packet *)
 			msg_hdr);
 		break;
 	case HFI_MSG_SYS_SESSION_END_DONE:
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 502d4bc..efa195e 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -1820,7 +1820,7 @@
 int msm_vdec_ctrl_init(struct msm_vidc_inst *inst)
 {
 	int idx = 0;
-	struct v4l2_ctrl_config ctrl_cfg;
+	struct v4l2_ctrl_config ctrl_cfg = {0};
 	int ret_val = 0;
 
 	ret_val = v4l2_ctrl_handler_init(&inst->ctrl_handler, NUM_CTRLS);
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index f9b5519..c0bf32c 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -2662,7 +2662,7 @@
 {
 
 	int idx = 0;
-	struct v4l2_ctrl_config ctrl_cfg;
+	struct v4l2_ctrl_config ctrl_cfg = {0};
 	int ret_val = 0;
 	ret_val = v4l2_ctrl_handler_init(&inst->ctrl_handler, NUM_CTRLS);
 	if (ret_val) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 42460fa..808c283 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -765,6 +765,7 @@
 			mutex_lock(&core->lock);
 			core->state = VIDC_CORE_INVALID;
 			mutex_unlock(&core->lock);
+			mutex_lock(&core->sync_lock);
 			list_for_each_entry(inst, &core->instances,
 					list) {
 				mutex_lock(&inst->lock);
@@ -786,6 +787,7 @@
 				msm_vidc_queue_v4l2_event(inst,
 						V4L2_EVENT_MSM_VIDC_SYS_ERROR);
 			}
+			mutex_unlock(&core->sync_lock);
 		} else {
 			dprintk(VIDC_ERR,
 				"Got SYS_ERR but unable to identify core");
@@ -813,6 +815,7 @@
 	mutex_lock(&core->lock);
 	core->state = VIDC_CORE_INVALID;
 	mutex_unlock(&core->lock);
+	mutex_lock(&core->sync_lock);
 	list_for_each_entry(inst, &core->instances, list) {
 		if (inst) {
 			msm_vidc_queue_v4l2_event(inst,
@@ -834,6 +837,7 @@
 			mutex_unlock(&inst->lock);
 		}
 	}
+	mutex_unlock(&core->sync_lock);
 }
 
 static void handle_session_close(enum command_response cmd, void *data)
@@ -3158,10 +3162,12 @@
 	int num_mbs_per_sec = 0;
 
 	if (inst->state == MSM_VIDC_OPEN_DONE) {
+		mutex_lock(&inst->core->sync_lock);
 		num_mbs_per_sec = msm_comm_get_load(inst->core,
 			MSM_VIDC_DECODER);
 		num_mbs_per_sec += msm_comm_get_load(inst->core,
 			MSM_VIDC_ENCODER);
+		mutex_unlock(&inst->core->sync_lock);
 		if (num_mbs_per_sec > inst->core->resources.max_load) {
 			dprintk(VIDC_ERR,
 				"H/w is overloaded. needed: %d max: %d\n",
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index 7c99ec3..8e91f34 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -560,17 +560,28 @@
 		dprintk(VIDC_ERR, "session_init: failed to create packet");
 		goto err_session_init;
 	}
+	/*
+	 * Add session id to the list entry and then send the apr pkt.
+	 * This will avoid scenarios where apr_send_pkt is taking more
+	 * time and Q6 is returning an ack even before the session id
+	 * gets added to the session list.
+	 */
+	mutex_lock(&dev->session_lock);
+	list_add_tail(&new_session->list, &dev->sess_head);
+	mutex_unlock(&dev->session_lock);
 
 	rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
 	if (rc != apr.hdr.pkt_size) {
 		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
 				__func__, rc);
+		/* Delete the session id as the send pkt is not successful */
+		mutex_lock(&dev->session_lock);
+		list_del(&new_session->list);
+		mutex_unlock(&dev->session_lock);
 		rc = -EBADE;
 		goto err_session_init;
 	}
-	mutex_lock(&dev->session_lock);
-	list_add_tail(&new_session->list, &dev->sess_head);
-	mutex_unlock(&dev->session_lock);
+
 	return new_session;
 
 err_session_init:
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 916df1d..8cd3889 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1057,30 +1057,32 @@
 		dprintk(VIDC_ERR, "cannot write to shared Q's");
 		goto err_q_null;
 	}
-	mutex_lock(&device->clk_pwr_lock);
-	result = venus_hfi_clk_gating_off(device);
-	if (result) {
-		dprintk(VIDC_ERR, "%s : Clock enable failed\n",
-			__func__);
-		goto err_q_write;
-	}
-	result = venus_hfi_scale_clocks(device, device->clk_load);
-	if (result) {
-		dprintk(VIDC_ERR, "Clock scaling failed\n");
-		goto err_q_write;
-	}
 	if (!venus_hfi_write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
+		mutex_lock(&device->clk_pwr_lock);
+		result = venus_hfi_clk_gating_off(device);
+		if (result) {
+			dprintk(VIDC_ERR, "%s : Clock enable failed\n",
+					__func__);
+			mutex_unlock(&device->clk_pwr_lock);
+			goto err_q_write;
+		}
+		result = venus_hfi_scale_clocks(device, device->clk_load);
+		if (result) {
+			dprintk(VIDC_ERR, "Clock scaling failed\n");
+			mutex_unlock(&device->clk_pwr_lock);
+			goto err_q_write;
+		}
 		if (rx_req_is_set)
 			venus_hfi_write_register(
 				device,
 				VIDC_CPU_IC_SOFTINT,
 				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
 		result = 0;
+		mutex_unlock(&device->clk_pwr_lock);
 	} else {
 		dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full");
 	}
 err_q_write:
-	mutex_unlock(&device->clk_pwr_lock);
 err_q_null:
 	mutex_unlock(&device->write_lock);
 	return result;
@@ -1104,26 +1106,27 @@
 		goto read_error_null;
 	}
 	q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
-	mutex_lock(&device->clk_pwr_lock);
-	rc = venus_hfi_clk_gating_off(device);
-	if (rc) {
-		dprintk(VIDC_ERR,
-			"%s : Clock enable failed\n", __func__);
-		goto read_error;
-	}
 	if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
+		mutex_lock(&device->clk_pwr_lock);
+		rc = venus_hfi_clk_gating_off(device);
+		if (rc) {
+			dprintk(VIDC_ERR,
+					"%s : Clock enable failed\n", __func__);
+			mutex_unlock(&device->clk_pwr_lock);
+			goto read_error;
+		}
 		if (tx_req_is_set)
 			venus_hfi_write_register(
 				device,
 				VIDC_CPU_IC_SOFTINT,
 				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
 		rc = 0;
+		mutex_unlock(&device->clk_pwr_lock);
 	} else {
 		dprintk(VIDC_INFO, "venus_hfi_iface_msgq_read:queue_empty");
 		rc = -ENODATA;
 	}
 read_error:
-	mutex_unlock(&device->clk_pwr_lock);
 read_error_null:
 	mutex_unlock(&device->read_lock);
 	return rc;
@@ -1146,27 +1149,28 @@
 		rc = -ENODATA;
 		goto dbg_error_null;
 	}
-	mutex_lock(&device->clk_pwr_lock);
-	rc = venus_hfi_clk_gating_off(device);
-	if (rc) {
-		dprintk(VIDC_ERR,
-			"%s : Clock enable failed\n", __func__);
-		goto dbg_error;
-	}
 	q_info = &device->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
 	if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
+		mutex_lock(&device->clk_pwr_lock);
+		rc = venus_hfi_clk_gating_off(device);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"%s : Clock enable failed\n", __func__);
+			mutex_unlock(&device->clk_pwr_lock);
+			goto dbg_error;
+		}
 		if (tx_req_is_set)
 			venus_hfi_write_register(
 				device,
 				VIDC_CPU_IC_SOFTINT,
 				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
 		rc = 0;
+		mutex_unlock(&device->clk_pwr_lock);
 	} else {
 		dprintk(VIDC_INFO, "venus_hfi_iface_dbgq_read:queue_empty");
 		rc = -ENODATA;
 	}
 dbg_error:
-	mutex_unlock(&device->clk_pwr_lock);
 dbg_error_null:
 	mutex_unlock(&device->read_lock);
 	return rc;
@@ -1251,7 +1255,7 @@
 
 	for (i = 0; i < num_entries; i++) {
 		rc = msm_iommu_map_contig_buffer(venus_qdss_entries[i][0],
-			domain, 1 , venus_qdss_entries[i][1],
+			domain, partition, venus_qdss_entries[i][1],
 			SZ_4K, 0, &iova);
 		if (rc) {
 			dprintk(VIDC_ERR,
@@ -1567,20 +1571,59 @@
 	return 0;
 }
 
+static int venus_hfi_is_cmd_pending(struct venus_hfi_device *dev)
+{
+	struct hfi_queue_header *queue;
+	struct vidc_iface_q_info *q_info;
+	u32 write_ptr, read_ptr;
+	u32 rc = 0;
+	q_info = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
+	if (!q_info)
+		dprintk(VIDC_ERR, "cannot read shared Q's");
+	queue = (struct hfi_queue_header *) q_info->q_hdr;
+	if (!queue) {
+		dprintk(VIDC_ERR, "queue not present");
+		return -ENOENT;
+	}
+	write_ptr = (u32)queue->qhdr_write_idx;
+	read_ptr = (u32)queue->qhdr_read_idx;
+	rc = read_ptr - write_ptr;
+	return rc;
+}
+
+static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
+{
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return;
+	}
+	if (!device->clocks_enabled) {
+		dprintk(VIDC_DBG, "Clocks are already disabled");
+		goto already_disabled;
+	}
+	venus_hfi_clk_disable(device);
+	if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work,
+			msecs_to_jiffies(msm_vidc_pwr_collapse_delay)))
+		dprintk(VIDC_DBG, "PM work already scheduled\n");
+already_disabled:
+	device->clocks_enabled = 0;
+}
+
 static void venus_hfi_core_clear_interrupt(struct venus_hfi_device *device)
 {
 	u32 intr_status = 0;
-	int rc = 0;
+	int rc = 0, ctrl_status;
 
 	if (!device->callback)
 		return;
+
+	mutex_lock(&device->write_lock);
 	mutex_lock(&device->clk_pwr_lock);
 	rc = venus_hfi_clk_gating_off(device);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"%s : Clock enable failed\n", __func__);
-		mutex_unlock(&device->clk_pwr_lock);
-		return;
+		goto err_clk_gating_off;
 	}
 	intr_status = venus_hfi_read_register(
 			device,
@@ -1603,8 +1646,23 @@
 			VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
 	venus_hfi_write_register(device,
 			VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
-	mutex_unlock(&device->clk_pwr_lock);
+	rc = venus_hfi_is_cmd_pending(device);
+	ctrl_status = venus_hfi_read_register(
+			device,
+			VIDC_CPU_CS_SCIACMDARG0);
+	dprintk(VIDC_INFO,
+			"CLEAR INTERRUPT - cmd_pending %d, ctrl_status 0x%x\n",
+			rc, ctrl_status);
+	if ((ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)
+			&& !rc) {
+		dprintk(VIDC_DBG, "SYS_IDLE interrupt, disable clocks\n");
+		venus_hfi_clk_gating_on(device);
+	}
+
 	dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
+err_clk_gating_off:
+	mutex_unlock(&device->clk_pwr_lock);
+	mutex_unlock(&device->write_lock);
 }
 
 static int venus_hfi_core_set_resource(void *device,
@@ -2321,26 +2379,6 @@
 	device->callback(SYS_WATCHDOG_TIMEOUT, &cmd_done);
 }
 
-static int venus_hfi_is_cmd_pending(struct venus_hfi_device *dev)
-{
-	struct hfi_queue_header *queue;
-	struct vidc_iface_q_info *q_info;
-	u32 write_ptr, read_ptr;
-	u32 rc = 0;
-	q_info = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
-	if (!q_info)
-		dprintk(VIDC_ERR, "cannot read shared Q's");
-	queue = (struct hfi_queue_header *) q_info->q_hdr;
-	if (!queue) {
-		dprintk(VIDC_ERR, "queue not present");
-		return -ENOENT;
-	}
-	write_ptr = (u32)queue->qhdr_write_idx;
-	read_ptr = (u32)queue->qhdr_read_idx;
-	rc = read_ptr - write_ptr;
-	return rc;
-}
-
 static int venus_hfi_core_pc_prep(void *device)
 {
 	struct hfi_cmd_sys_pc_prep_packet pkt;
@@ -2408,24 +2446,6 @@
 	mutex_unlock(&device->clk_pwr_lock);
 }
 
-static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
-{
-	if (!device) {
-		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
-		return;
-	}
-	if (!device->clocks_enabled) {
-		dprintk(VIDC_DBG, "Clocks are already disabled");
-		goto already_disabled;
-	}
-	venus_hfi_clk_disable(device);
-	if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work,
-			msecs_to_jiffies(msm_vidc_pwr_collapse_delay)))
-		dprintk(VIDC_DBG, "PM work already scheduled\n");
-already_disabled:
-	device->clocks_enabled = 0;
-}
-
 static int venus_hfi_try_clk_gating(struct venus_hfi_device *device)
 {
 	int rc = 0;
@@ -2506,10 +2526,12 @@
 				(struct hfi_msg_sys_debug_packet *) packet;
 			dprintk(VIDC_FW, "FW-SAYS: %s", pkt->rg_msg_data);
 		}
-		if (rc == HFI_MSG_SYS_IDLE)
+		if (rc == HFI_MSG_SYS_IDLE) {
+			dprintk(VIDC_DBG, "Received HFI_MSG_SYS_IDLE\n");
 			rc = venus_hfi_try_clk_gating(device);
-		else if (rc == HFI_MSG_SYS_PC_PREP_DONE) {
-			dprintk(VIDC_DBG, "Received HFI_MSG_SYS_PC_PREP_DONE");
+		} else if (rc == HFI_MSG_SYS_PC_PREP_DONE) {
+			dprintk(VIDC_DBG,
+					"Received HFI_MSG_SYS_PC_PREP_DONE\n");
 			rc = venus_hfi_try_clk_gating(device);
 			if (rc)
 				dprintk(VIDC_ERR,
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 31d03b6..9e25e42 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -3476,13 +3476,26 @@
 		radio->riva_data_req.cmd_params.start_addr = ctrl->value;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN:
-		radio->riva_data_req.cmd_params.length = ctrl->value;
+		if ((ctrl->value > 0) &&
+			(ctrl->value <= MAX_RIVA_PEEK_RSP_SIZE)) {
+			radio->riva_data_req.cmd_params.length = ctrl->value;
+		} else {
+			FMDERR("Length %d is more than the buffer size %d\n",
+			ctrl->value, MAX_RIVA_PEEK_RSP_SIZE);
+			retval = -EINVAL;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RIVA_POKE:
-		memcpy(radio->riva_data_req.data, (void *)ctrl->value,
-					radio->riva_data_req.cmd_params.length);
-		radio->riva_data_req.cmd_params.subopcode = RIVA_POKE_OPCODE;
-		retval = hci_poke_data(&radio->riva_data_req , radio->fm_hdev);
+		if (radio->riva_data_req.cmd_params.length <= MAX_RIVA_PEEK_RSP_SIZE) {
+			memcpy(radio->riva_data_req.data, (void *)ctrl->value,
+						radio->riva_data_req.cmd_params.length);
+			radio->riva_data_req.cmd_params.subopcode = RIVA_POKE_OPCODE;
+			retval = hci_poke_data(&radio->riva_data_req , radio->fm_hdev);
+		} else {
+			FMDERR("Can not copy into driver's buffer. Length %d is more than"
+			 "the buffer size %d\n", ctrl->value, MAX_RIVA_PEEK_RSP_SIZE);
+			retval = -EINVAL;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR:
 		radio->ssbi_data_accs.start_addr = ctrl->value;
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index e0a99e2..6b9f2b3 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -3051,7 +3051,7 @@
 	int retval = 0;
 	int bytes_to_copy;
 	int bytes_copied = 0;
-	int bytes_left = 0;
+	__u32 bytes_left = 0;
 	int chunk_index = 0;
 	char tx_data[XFR_REG_NUM];
 	struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
@@ -3066,15 +3066,15 @@
 
 		chunk_index = 0;
 		bytes_copied = 0;
-		bytes_left = min((int)(ctrl->controls[0]).size,
-			MAX_PS_LENGTH);
+		bytes_left = min((ctrl->controls[0]).size,
+			(__u32)MAX_PS_LENGTH);
 		data = (ctrl->controls[0]).string;
 
 		/* send payload to FM hardware */
 		while (bytes_left) {
 			chunk_index++;
 			FMDBG("chunk is %d", chunk_index);
-			bytes_to_copy = min(bytes_left, XFR_REG_NUM);
+			bytes_to_copy = min(bytes_left, (__u32)XFR_REG_NUM);
 			/*Clear the tx_data */
 			memset(tx_data, 0, XFR_REG_NUM);
 			if (copy_from_user(tx_data,
@@ -3116,12 +3116,12 @@
 		FMDBG("Passed RT String : %s\n",
 			(ctrl->controls[0]).string);
 		bytes_left =
-		    min((int)(ctrl->controls[0]).size, MAX_RT_LENGTH);
+		    min((ctrl->controls[0]).size, (__u32)MAX_RT_LENGTH);
 		data = (ctrl->controls[0]).string;
 		/* send payload to FM hardware */
 		while (bytes_left) {
 			chunk_index++;
-			bytes_to_copy = min(bytes_left, XFR_REG_NUM);
+			bytes_to_copy = min(bytes_left, (__u32)XFR_REG_NUM);
 			memset(tx_data, 0, XFR_REG_NUM);
 			if (copy_from_user(tx_data,
 				    data + bytes_copied, bytes_to_copy))
@@ -4466,8 +4466,8 @@
 
 	struct marimba_fm_platform_data *tavarua_pdata;
 	struct tavarua_device *radio;
-	int retval;
-	int i;
+	int retval = 0;
+	int i = 0, j = 0;
 	FMDBG("%s: probe called\n", __func__);
 	/* private data allocation */
 	radio = kzalloc(sizeof(struct tavarua_device), GFP_KERNEL);
@@ -4480,6 +4480,7 @@
 	tavarua_pdata = pdev->dev.platform_data;
 	radio->pdata = tavarua_pdata;
 	radio->dev = &pdev->dev;
+	radio->wqueue = NULL;
 	platform_set_drvdata(pdev, radio);
 
 	/* video device allocation */
@@ -4509,15 +4510,16 @@
 		if (kfifo_alloc_rc!=0) {
 			printk(KERN_ERR "%s: failed allocating buffers %d\n",
 				__func__, kfifo_alloc_rc);
-			goto err_bufs;
+		        retval = -ENOMEM;
+		        goto err_all;
 		}
 	}
 	/* initializing the device count  */
 	atomic_set(&radio->users, 1);
 	radio->xfr_in_progress = 0;
 	radio->xfr_bytes_left = 0;
-	for (i = 0; i < TAVARUA_XFR_MAX; i++)
-		radio->pending_xfrs[i] = 0;
+	for (j = 0; j < TAVARUA_XFR_MAX; j++)
+		radio->pending_xfrs[j] = 0;
 
 	/* init transmit data */
 	radio->tx_mode = TAVARUA_TX_RT;
@@ -4548,11 +4550,14 @@
     /*Start the worker thread for event handling and register read_int_stat
 	as worker function*/
 	radio->wqueue  = create_singlethread_workqueue("kfmradio");
-	if (!radio->wqueue)
-		return -ENOMEM;
+	if (!radio->wqueue) {
+	        retval = -ENOMEM;
+		goto err_all;
+        }
 
 	/* register video device */
-	if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
+	retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+	if (retval != 0) {
 		printk(KERN_WARNING DRIVER_NAME
 				": Could not register video device\n");
 		goto err_all;
@@ -4562,9 +4567,11 @@
 
 err_all:
 	video_device_release(radio->videodev);
-err_bufs:
-	for (; i > -1; i--)
+	if (radio->wqueue)
+		destroy_workqueue(radio->wqueue);
+	for (i--; i >= 0; i--) {
 		kfifo_free(&radio->data_buf[i]);
+        }
 err_radio:
 	kfree(radio);
 err_initial:
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index a30607c..93726f2 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -251,6 +251,12 @@
 			break;
 	}
 	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+
+	if ((entry != NULL) && (entry->svc.listener_id != listener_id)) {
+		pr_err("Service id: %u is not found\n", listener_id);
+		return NULL;
+	}
+
 	return entry;
 }
 
@@ -494,6 +500,11 @@
 		}
 		spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
 				flags);
+
+		if (ptr_svc == NULL) {
+			pr_err("Listener Svc %d does not exist\n", lstnr);
+			return -EINVAL;
+		}
 		if (ptr_svc->svc.listener_id != lstnr) {
 			pr_warning("Service requested for does on exist\n");
 			return -ERESTARTSYS;
@@ -860,6 +871,10 @@
 			req_ptr, send_svc_ireq_ptr);
 		return -EINVAL;
 	}
+	if ((!req_ptr->cmd_req_buf) || (!req_ptr->resp_buf)) {
+		pr_err("Invalid req/resp buffer, exiting\n");
+		return -EINVAL;
+	}
 	send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id;
 	send_svc_ireq_ptr->key_type =
 	((struct qseecom_rpmb_provision_key *)req_ptr->cmd_req_buf)->key_type;
@@ -1273,6 +1288,11 @@
 	struct qseecom_registered_listener_list *this_lstnr;
 
 	this_lstnr = __qseecom_find_svc(data->listener.id);
+	if (!this_lstnr) {
+		pr_err("Invalid listener ID\n");
+		return -ENODATA;
+	}
+
 	while (1) {
 		if (wait_event_freezable(this_lstnr->rcv_req_wq,
 				__qseecom_listener_has_rcvd_req(data,
diff --git a/drivers/misc/smsc_hub.c b/drivers/misc/smsc_hub.c
index 0147e66..6f98dc7 100644
--- a/drivers/misc/smsc_hub.c
+++ b/drivers/misc/smsc_hub.c
@@ -385,26 +385,27 @@
 static int __devinit smsc_hub_probe(struct platform_device *pdev)
 {
 	int ret = 0;
-	const struct smsc_hub_platform_data *pdata;
+	struct smsc_hub_platform_data *pdata;
 	struct device_node *node = pdev->dev.of_node;
 	struct i2c_adapter *i2c_adap;
 	struct i2c_board_info i2c_info;
+	struct of_dev_auxdata *hsic_host_auxdata;
 
 	if (pdev->dev.of_node) {
 		dev_dbg(&pdev->dev, "device tree enabled\n");
-		pdev->dev.platform_data = msm_hub_dt_to_pdata(pdev);
-		if (IS_ERR(pdev->dev.platform_data))
-			return PTR_ERR(pdev->dev.platform_data);
-
-		dev_set_name(&pdev->dev, smsc_hub_driver.driver.name);
+		hsic_host_auxdata = dev_get_platdata(&pdev->dev);
+		pdata = msm_hub_dt_to_pdata(pdev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	} else {
+		pdata = pdev->dev.platform_data;
 	}
 
-	if (!pdev->dev.platform_data) {
+	if (!pdata) {
 		dev_err(&pdev->dev, "No platform data\n");
 		return -ENODEV;
 	}
 
-	pdata = pdev->dev.platform_data;
 	if (!pdata->hub_reset)
 		return -EINVAL;
 
@@ -413,7 +414,7 @@
 		return -ENOMEM;
 
 	smsc_hub->dev = &pdev->dev;
-	smsc_hub->pdata = pdev->dev.platform_data;
+	smsc_hub->pdata = pdata;
 
 	smsc_hub->hub_vbus_reg = devm_regulator_get(&pdev->dev, "hub_vbus");
 	ret = PTR_ERR(smsc_hub->hub_vbus_reg);
@@ -494,7 +495,7 @@
 	i2c_put_adapter(i2c_adap);
 
 i2c_add_fail:
-	ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+	ret = of_platform_populate(node, NULL, hsic_host_auxdata, &pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add child node, ret=%d\n", ret);
 		goto uninit_gpio;
@@ -523,7 +524,7 @@
 {
 	const struct smsc_hub_platform_data *pdata;
 
-	pdata = pdev->dev.platform_data;
+	pdata = smsc_hub->pdata;
 	if (smsc_hub->client) {
 		i2c_unregister_device(smsc_hub->client);
 		smsc_hub->client = NULL;
diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
index 14dd313..45ec5c2 100644
--- a/drivers/mmc/core/cd-gpio.c
+++ b/drivers/mmc/core/cd-gpio.c
@@ -111,8 +111,12 @@
 {
 	struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
 
+	if (!cd || !gpio_is_valid(cd->gpio))
+		return;
+
 	free_irq(host->hotplug.irq, host);
 	gpio_free(cd->gpio);
+	cd->gpio = -EINVAL;
 	kfree(cd);
 }
 EXPORT_SYMBOL(mmc_cd_gpio_free);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 995d9e4..a296e48 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -61,6 +61,7 @@
 
 /* Flushing a large amount of cached data may take a long time. */
 #define MMC_FLUSH_REQ_TIMEOUT_MS 90000 /* msec */
+#define MMC_CACHE_DISBALE_TIMEOUT_MS 180000 /* msec */
 
 static struct workqueue_struct *workqueue;
 
@@ -3393,14 +3394,14 @@
 
 		if (card->ext_csd.cache_ctrl ^ enable) {
 			if (!enable)
-				timeout = MMC_FLUSH_REQ_TIMEOUT_MS;
+				timeout = MMC_CACHE_DISBALE_TIMEOUT_MS;
 
 			err = mmc_switch_ignore_timeout(card,
 					EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_CACHE_CTRL, enable, timeout);
 
 			if (err == -ETIMEDOUT && !enable) {
-				pr_debug("%s:cache disable operation timeout\n",
+				pr_err("%s:cache disable operation timeout\n",
 						mmc_hostname(card->host));
 				rc = mmc_interrupt_hpi(card);
 				if (rc)
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index 10dea37..bd4ecf3 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -520,6 +520,7 @@
 		 */
 		regd = ath_world_regdomain(reg);
 		wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+		wiphy->country_ie_pref = NL80211_COUNTRY_IE_FOLLOW_POWER;
 	} else {
 		/*
 		 * This gets applied in the case of the absence of CRDA,
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 33d11b1..9d23e84 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -142,6 +142,7 @@
 #define MSM_PRONTO_PLL_BASE				0xfb21b1c0
 #define PRONTO_PLL_STATUS_OFFSET		0x1c
 
+#define MSM_PRONTO_TXP_STATUS           0xfb08040c
 #define MSM_PRONTO_TXP_PHY_ABORT        0xfb080488
 #define MSM_PRONTO_BRDG_ERR_SRC         0xfb080fb0
 
@@ -154,6 +155,7 @@
 #define WCNSS_CTRL_CHANNEL			"WCNSS_CTRL"
 #define WCNSS_MAX_FRAME_SIZE		(4*1024)
 #define WCNSS_VERSION_LEN			30
+#define WCNSS_MAX_BUILD_VER_LEN		256
 
 /* message types */
 #define WCNSS_CTRL_MSG_START	0x01000000
@@ -166,6 +168,8 @@
 #define	WCNSS_CALDATA_DNLD_REQ        (WCNSS_CTRL_MSG_START + 6)
 #define	WCNSS_CALDATA_DNLD_RSP        (WCNSS_CTRL_MSG_START + 7)
 #define	WCNSS_VBATT_LEVEL_IND         (WCNSS_CTRL_MSG_START + 8)
+#define	WCNSS_BUILD_VER_REQ           (WCNSS_CTRL_MSG_START + 9)
+#define	WCNSS_BUILD_VER_RSP           (WCNSS_CTRL_MSG_START + 10)
 
 
 #define VALID_VERSION(version) \
@@ -339,6 +343,7 @@
 	void __iomem *pronto_ccpu_base;
 	void __iomem *pronto_saw2_base;
 	void __iomem *pronto_pll_base;
+	void __iomem *wlan_tx_status;
 	void __iomem *wlan_tx_phy_aborts;
 	void __iomem *wlan_brdg_err_source;
 	void __iomem *fiq_reg;
@@ -515,6 +520,10 @@
 	pr_info_ratelimited("%s:  PRONTO_PMU_SOFT_RESET %08x\n",
 						__func__, reg);
 
+	reg_addr = penv->pronto_saw2_base + PRONTO_SAW2_SPM_STS_OFFSET;
+	reg = readl_relaxed(reg_addr);
+	pr_info_ratelimited("%s: PRONTO_SAW2_SPM_STS %08x\n", __func__, reg);
+
 	reg_addr = penv->msm_wcnss_base + PRONTO_PMU_COM_GDSCR_OFFSET;
 	reg = readl_relaxed(reg_addr);
 	pr_info_ratelimited("%s:  PRONTO_PMU_COM_GDSCR %08x\n",
@@ -563,10 +572,6 @@
 	reg = readl_relaxed(reg_addr);
 	pr_info_ratelimited("%s: CCU_CCPU_LAST_ADDR2 %08x\n", __func__, reg);
 
-	reg_addr = penv->pronto_saw2_base + PRONTO_SAW2_SPM_STS_OFFSET;
-	reg = readl_relaxed(reg_addr);
-	pr_info_ratelimited("%s: PRONTO_SAW2_SPM_STS %08x\n", __func__, reg);
-
 	reg_addr = penv->pronto_pll_base + PRONTO_PLL_STATUS_OFFSET;
 	reg = readl_relaxed(reg_addr);
 	pr_info_ratelimited("%s: PRONTO_PLL_STATUS %08x\n", __func__, reg);
@@ -664,6 +669,8 @@
 	reg = readl_relaxed(penv->wlan_brdg_err_source);
 	pr_info_ratelimited("%s: WLAN_BRDG_ERR_SOURCE %08x\n", __func__, reg);
 
+	reg = readl_relaxed(penv->wlan_tx_status);
+	pr_info_ratelimited("%s: WLAN_TX_STATUS %08x\n", __func__, reg);
 }
 EXPORT_SYMBOL(wcnss_pronto_log_debug_regs);
 
@@ -1411,7 +1418,9 @@
 	int len = 0;
 	int rc = 0;
 	unsigned char buf[sizeof(struct wcnss_version)];
+	unsigned char build[WCNSS_MAX_BUILD_VER_LEN+1];
 	struct smd_msg_hdr *phdr;
+	struct smd_msg_hdr smd_msg;
 	struct wcnss_version *pversion;
 	int hw_type;
 	unsigned char fw_status = 0;
@@ -1468,6 +1477,12 @@
 			break;
 
 		case WCNSS_PRONTO_HW:
+			smd_msg.msg_type = WCNSS_BUILD_VER_REQ;
+			smd_msg.msg_len = sizeof(smd_msg);
+			rc = wcnss_smd_tx(&smd_msg, smd_msg.msg_len);
+			if (rc < 0)
+				pr_err("wcnss: smd tx failed: %s\n", __func__);
+
 			/* supported only if pronto major >= 1 and minor >= 4 */
 			if ((pversion->major >= 1) && (pversion->minor >= 4)) {
 				pr_info("wcnss: schedule dnld work for pronto\n");
@@ -1482,6 +1497,21 @@
 		}
 		break;
 
+	case WCNSS_BUILD_VER_RSP:
+		if (len > WCNSS_MAX_BUILD_VER_LEN) {
+			pr_err("wcnss: invalid build version data from wcnss %d\n",
+					len);
+			return;
+		}
+		rc = smd_read(penv->smd_ch, build, len);
+		if (rc < len) {
+			pr_err("wcnss: incomplete data read from smd\n");
+			return;
+		}
+		build[len] = 0;
+		pr_info("wcnss: build version %s\n", build);
+		break;
+
 	case WCNSS_NVBIN_DNLD_RSP:
 		penv->nv_downloaded = true;
 		fw_status = wcnss_fw_status();
@@ -1965,7 +1995,12 @@
 			pr_err("%s: ioremap wlan BRDG ERR failed\n", __func__);
 			goto fail_ioremap8;
 		}
-
+		penv->wlan_tx_status = ioremap(MSM_PRONTO_TXP_STATUS, SZ_8);
+		if (!penv->wlan_tx_status) {
+			ret = -ENOMEM;
+			pr_err("%s: ioremap wlan TX STATUS failed\n", __func__);
+			goto fail_ioremap9;
+		}
 	}
 	penv->adc_tm_dev = qpnp_get_adc_tm(&penv->pdev->dev, "wcnss");
 	if (IS_ERR(penv->adc_tm_dev)) {
@@ -1991,6 +2026,9 @@
 fail_pil:
 	if (penv->riva_ccu_base)
 		iounmap(penv->riva_ccu_base);
+	if (penv->wlan_tx_status)
+		iounmap(penv->wlan_tx_status);
+fail_ioremap9:
 	if (penv->wlan_brdg_err_source)
 		iounmap(penv->wlan_brdg_err_source);
 fail_ioremap8:
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 5f0ba94..9ccb993 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -327,10 +327,9 @@
 	for(; lookup->compatible != NULL; lookup++) {
 		if (!of_device_is_compatible(np, lookup->compatible))
 			continue;
-		if (of_address_to_resource(np, 0, &res))
-			continue;
-		if (res.start != lookup->phys_addr)
-			continue;
+		if (!of_address_to_resource(np, 0, &res))
+			if (res.start != lookup->phys_addr)
+				continue;
 		pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
 		return lookup;
 	}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index b918110..4688514 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -152,6 +152,7 @@
 	POWER_SUPPLY_ATTR(current_max),
 	POWER_SUPPLY_ATTR(input_current_max),
 	POWER_SUPPLY_ATTR(input_current_trim),
+	POWER_SUPPLY_ATTR(input_current_settled),
 	POWER_SUPPLY_ATTR(current_now),
 	POWER_SUPPLY_ATTR(current_avg),
 	POWER_SUPPLY_ATTR(power_now),
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 9727787..8c03bbd 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -765,10 +765,22 @@
 	return get_battery_status(chip) == POWER_SUPPLY_STATUS_FULL;
 }
 
+#define BAT_PRES_BIT		BIT(7)
 static bool is_battery_present(struct qpnp_bms_chip *chip)
 {
 	union power_supply_propval ret = {0,};
+	int rc;
+	u8 batt_pres;
 
+	/* first try to use the batt_pres register if given */
+	if (chip->batt_pres_addr) {
+		rc = qpnp_read_wrapper(chip, &batt_pres,
+				chip->batt_pres_addr, 1);
+		if (!rc && (batt_pres & BAT_PRES_BIT))
+			return true;
+		else
+			return false;
+	}
 	if (chip->batt_psy == NULL)
 		chip->batt_psy = power_supply_get_by_name("battery");
 	if (chip->batt_psy) {
@@ -2254,6 +2266,7 @@
 			(uint16_t)ocv_raw);
 }
 
+#define BAD_SOC_THRESH	-10
 static int calculate_raw_soc(struct qpnp_bms_chip *chip,
 					struct raw_soc_params *raw,
 					struct soc_params *params,
@@ -2270,7 +2283,7 @@
 	soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
 				(params->fcc_uah - params->uuc_uah));
 
-	if (chip->first_time_calc_soc && soc < 0) {
+	if (chip->first_time_calc_soc && soc > BAD_SOC_THRESH && soc < 0) {
 		/*
 		 * first time calcualtion and the pon ocv  is too low resulting
 		 * in a bad soc. Adjust ocv to get 0 soc
@@ -2295,7 +2308,7 @@
 	if (soc > 100)
 		soc = 100;
 
-	if (soc < 0) {
+	if (soc > BAD_SOC_THRESH && soc < 0) {
 		pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
 				remaining_usable_charge_uah,
 				params->ocv_charge_uah,
@@ -3488,7 +3501,7 @@
 			|| shutdown_soc_out_of_limit) {
 		chip->battery_removed = true;
 		chip->shutdown_soc_invalid = true;
-		chip->shutdown_iavg_ma = 0;
+		chip->shutdown_iavg_ma = MIN_IAVG_MA;
 		pr_debug("Ignoring shutdown SoC: invalid = %d, offmode = %d, out_of_limit = %d\n",
 				invalid_stored_soc, offmode_battery_replaced,
 				shutdown_soc_out_of_limit);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index a65ac5b..095fddf 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -101,6 +101,7 @@
 #define BUCK_VCHG_OV				0x77
 #define BUCK_TEST_SMBC_MODES			0xE6
 #define BUCK_CTRL_TRIM1				0xF1
+#define BUCK_CTRL_TRIM3				0xF3
 #define SEC_ACCESS				0xD0
 #define BAT_IF_VREF_BAT_THM_CTRL		0x4A
 #define BAT_IF_BPD_CTRL				0x48
@@ -310,6 +311,9 @@
 	bool				btc_disabled;
 	bool				use_default_batt_values;
 	bool				duty_cycle_100p;
+	bool				ibat_calibration_enabled;
+	bool				aicl_settled;
+	bool				use_external_rsense;
 	unsigned int			bpd_detection;
 	unsigned int			max_bat_chg_current;
 	unsigned int			warm_bat_chg_ma;
@@ -362,6 +366,7 @@
 	bool				batfet_ext_en;
 	struct work_struct		batfet_lcl_work;
 	struct qpnp_vadc_chip		*vadc_dev;
+	struct qpnp_iadc_chip		*iadc_dev;
 	struct qpnp_adc_tm_chip		*adc_tm_dev;
 	struct mutex			jeita_configure_lock;
 	spinlock_t			usbin_health_monitor_lock;
@@ -369,6 +374,7 @@
 	struct alarm			reduce_power_stage_alarm;
 	struct work_struct		reduce_power_stage_work;
 	bool				power_stage_workaround_running;
+	bool				power_stage_workaround_enable;
 };
 
 
@@ -420,6 +426,16 @@
 	return -EINVAL;
 }
 
+static bool
+is_within_range(int value, int left, int right)
+{
+	if (left >= right && left >= value && value >= right)
+		return 1;
+	if (left <= right && left <= value && value <= right)
+		return 1;
+	return 0;
+}
+
 static int
 qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
 			u16 base, int count)
@@ -622,6 +638,22 @@
 	return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
 }
 
+static bool
+qpnp_chg_is_ibat_loop_active(struct qpnp_chg_chip *chip)
+{
+	int rc;
+	u8 buck_sts;
+
+	rc = qpnp_chg_read(chip, &buck_sts,
+			INT_RT_STS(chip->buck_base), 1);
+	if (rc) {
+		pr_err("failed to read buck RT status rc=%d\n", rc);
+		return 0;
+	}
+
+	return !!(buck_sts & IBAT_LOOP_IRQ);
+}
+
 #define USB_VALID_MASK 0xC0
 #define USB_COARSE_DET 0x10
 #define USB_VALID_UVP_VALUE    0x00
@@ -1403,10 +1435,10 @@
 				       (chip->usb_valid_check_ovp)) {
 				usbin_health =
 					qpnp_chg_check_usbin_health(chip);
-				if (chip->usbin_health != usbin_health) {
+				if ((chip->usbin_health != usbin_health)
+					&& (usbin_health == USBIN_OVP)) {
 					chip->usbin_health = usbin_health;
-					if (usbin_health == USBIN_OVP)
-						psy_health_sts =
+					psy_health_sts =
 					POWER_SUPPLY_HEALTH_OVERVOLTAGE;
 					power_supply_set_health_state(
 						chip->usb_psy,
@@ -1419,8 +1451,9 @@
 				qpnp_chg_set_appropriate_vddmax(chip);
 				chip->chg_done = false;
 			}
-			qpnp_chg_usb_suspend_enable(chip, 1);
+			qpnp_chg_usb_suspend_enable(chip, 0);
 			chip->prev_usb_max_ma = -EINVAL;
+			chip->aicl_settled = false;
 		} else {
 			/* when OVP clamped usbin, and then decrease
 			 * the charger voltage to lower than the OVP
@@ -1431,10 +1464,10 @@
 				       (chip->usb_valid_check_ovp)) {
 				usbin_health =
 					qpnp_chg_check_usbin_health(chip);
-				if (chip->usbin_health != usbin_health) {
+				if ((chip->usbin_health != usbin_health)
+					&& (usbin_health == USBIN_OK)) {
 					chip->usbin_health = usbin_health;
-					 if (usbin_health == USBIN_OK)
-						psy_health_sts =
+					psy_health_sts =
 						POWER_SUPPLY_HEALTH_GOOD;
 					power_supply_set_health_state(
 						chip->usb_psy,
@@ -1655,6 +1688,7 @@
 	case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 	case POWER_SUPPLY_PROP_COOL_TEMP:
 	case POWER_SUPPLY_PROP_WARM_TEMP:
@@ -1768,6 +1802,7 @@
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
 	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 	POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
@@ -2132,7 +2167,8 @@
 
 		if (ret.intval <= 2 && !chip->use_default_batt_values &&
 						get_prop_batt_present(chip)) {
-			qpnp_chg_usb_suspend_enable(chip, 1);
+			if (ret.intval ==  2)
+				qpnp_chg_usb_suspend_enable(chip, 1);
 			qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
 		} else {
 			qpnp_chg_usb_suspend_enable(chip, 0);
@@ -2151,7 +2187,8 @@
 
 			if ((chip->flags & POWER_STAGE_WA)
 			&& ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
-			&& !chip->power_stage_workaround_running) {
+			&& !chip->power_stage_workaround_running
+			&& chip->power_stage_workaround_enable) {
 				chip->power_stage_workaround_running = true;
 				pr_debug("usb wall chg inserted starting power stage workaround charger_monitor = %d\n",
 						charger_monitor);
@@ -2241,6 +2278,9 @@
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
 		val->intval = qpnp_chg_iusb_trim_get(chip);
 		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
+		val->intval = chip->aicl_settled;
+		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		val->intval = qpnp_chg_vinmin_get(chip) * 1000;
 		break;
@@ -2347,6 +2387,24 @@
 			QPNP_CHG_I_MASK, temp, 1);
 }
 
+static int
+qpnp_chg_ibatmax_get(struct qpnp_chg_chip *chip, int *chg_current)
+{
+	int rc;
+	u8 temp;
+
+	*chg_current = 0;
+	rc = qpnp_chg_read(chip, &temp, chip->chgr_base + CHGR_IBAT_MAX, 1);
+	if (rc) {
+		pr_err("failed read ibat_max rc=%d\n", rc);
+		return rc;
+	}
+
+	*chg_current = ((temp & QPNP_CHG_I_MASK) * QPNP_CHG_I_STEP_MA);
+
+	return 0;
+}
+
 #define QPNP_CHG_TCHG_MASK	0x7F
 #define QPNP_CHG_TCHG_MIN	4
 #define QPNP_CHG_TCHG_MAX	512
@@ -2381,6 +2439,155 @@
 		chip->chgr_base + CHGR_VDD_SAFE, 1);
 }
 
+#define IBAT_TRIM_TGT_MA		500
+#define IBAT_TRIM_OFFSET_MASK		0x7F
+#define IBAT_TRIM_GOOD_BIT		BIT(7)
+#define IBAT_TRIM_LOW_LIM		20
+#define IBAT_TRIM_HIGH_LIM		114
+#define IBAT_TRIM_MEAN			64
+
+static void
+qpnp_chg_trim_ibat(struct qpnp_chg_chip *chip, u8 ibat_trim)
+{
+	int ibat_now_ma, ibat_diff_ma, rc;
+	struct qpnp_iadc_result i_result;
+	enum qpnp_iadc_channels iadc_channel;
+
+	iadc_channel = chip->use_external_rsense ?
+				EXTERNAL_RSENSE : INTERNAL_RSENSE;
+	rc = qpnp_iadc_read(chip->iadc_dev, iadc_channel, &i_result);
+	if (rc) {
+		pr_err("Unable to read bat rc=%d\n", rc);
+		return;
+	}
+
+	ibat_now_ma = i_result.result_ua / 1000;
+
+	if (qpnp_chg_is_ibat_loop_active(chip)) {
+		ibat_diff_ma = ibat_now_ma - IBAT_TRIM_TGT_MA;
+
+		if (abs(ibat_diff_ma) > 50) {
+			ibat_trim += (ibat_diff_ma / 20);
+			ibat_trim &= IBAT_TRIM_OFFSET_MASK;
+			/* reject new ibat_trim if it is outside limits */
+			if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
+						IBAT_TRIM_HIGH_LIM))
+				return;
+		}
+		ibat_trim |= IBAT_TRIM_GOOD_BIT;
+		rc = qpnp_chg_write(chip, &ibat_trim,
+				chip->buck_base + BUCK_CTRL_TRIM3, 1);
+		if (rc)
+			pr_err("failed to set IBAT_TRIM rc=%d\n", rc);
+
+		pr_debug("ibat_now=%dmA, itgt=%dmA, ibat_diff=%dmA, ibat_trim=%x\n",
+					ibat_now_ma, IBAT_TRIM_TGT_MA,
+					ibat_diff_ma, ibat_trim);
+	} else {
+		pr_debug("ibat loop not active - cannot calibrate ibat\n");
+	}
+}
+
+static int
+qpnp_chg_input_current_settled(struct qpnp_chg_chip *chip)
+{
+	int rc, ibat_max_ma;
+	u8 reg, chgr_sts, ibat_trim, i;
+
+	chip->aicl_settled = true;
+
+	/*
+	 * Perform the ibat calibration.
+	 * This is for devices which have a IBAT_TRIM error
+	 * which can show IBAT_MAX out of spec.
+	 */
+	if (!chip->ibat_calibration_enabled)
+		return 0;
+
+	if (chip->type != SMBB)
+		return 0;
+
+	rc = qpnp_chg_read(chip, &reg,
+			chip->buck_base + BUCK_CTRL_TRIM3, 1);
+	if (rc) {
+		pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
+		return rc;
+	}
+	if (reg & IBAT_TRIM_GOOD_BIT) {
+		pr_debug("IBAT_TRIM_GOOD bit already set. Quitting!\n");
+		return 0;
+	}
+	ibat_trim = reg & IBAT_TRIM_OFFSET_MASK;
+
+	if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
+					IBAT_TRIM_HIGH_LIM)) {
+		pr_debug("Improper ibat_trim value=%x setting to value=%x\n",
+						ibat_trim, IBAT_TRIM_MEAN);
+		ibat_trim = IBAT_TRIM_MEAN;
+		rc = qpnp_chg_masked_write(chip,
+				chip->buck_base + BUCK_CTRL_TRIM3,
+				IBAT_TRIM_OFFSET_MASK, ibat_trim, 1);
+		if (rc) {
+			pr_err("failed to set ibat_trim to %x rc=%d\n",
+						IBAT_TRIM_MEAN, rc);
+			return rc;
+		}
+	}
+
+	rc = qpnp_chg_read(chip, &chgr_sts,
+				INT_RT_STS(chip->chgr_base), 1);
+	if (rc) {
+		pr_err("failed to read interrupt sts rc=%d\n", rc);
+		return rc;
+	}
+	if (!(chgr_sts & FAST_CHG_ON_IRQ)) {
+		pr_debug("Not in fastchg\n");
+		return rc;
+	}
+
+	/* save the ibat_max to restore it later */
+	rc = qpnp_chg_ibatmax_get(chip, &ibat_max_ma);
+	if (rc) {
+		pr_debug("failed to save ibatmax rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_chg_ibatmax_set(chip, IBAT_TRIM_TGT_MA);
+	if (rc) {
+		pr_err("failed to set ibatmax rc=%d\n", rc);
+		return rc;
+	}
+
+	for (i = 0; i < 3; i++) {
+		/*
+		 * ibat settling delay - to make sure the BMS controller
+		 * has sufficient time to sample ibat for the configured
+		 * ibat_max
+		 */
+		msleep(20);
+		if (qpnp_chg_is_ibat_loop_active(chip))
+			qpnp_chg_trim_ibat(chip, ibat_trim);
+		else
+			pr_debug("ibat loop not active\n");
+
+		/* read the adjusted ibat_trim for further adjustments */
+		rc = qpnp_chg_read(chip, &ibat_trim,
+			chip->buck_base + BUCK_CTRL_TRIM3, 1);
+		if (rc) {
+			pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
+			break;
+		}
+	}
+
+	/* restore IBATMAX */
+	rc = qpnp_chg_ibatmax_set(chip, ibat_max_ma);
+	if (rc)
+		pr_err("failed to restore ibatmax rc=%d\n", rc);
+
+	return rc;
+}
+
+
 #define BOOST_MIN_UV	4200000
 #define BOOST_MAX_UV	5500000
 #define BOOST_STEP_UV	50000
@@ -3375,6 +3582,9 @@
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
 		qpnp_chg_iusb_trim_set(chip, val->intval);
 		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
+		qpnp_chg_input_current_settled(chip);
+		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		qpnp_chg_vinmin_set(chip, val->intval / 1000);
 		break;
@@ -4096,6 +4306,11 @@
 			return rc;
 	}
 
+	/* Get the use-external-rsense property */
+	chip->use_external_rsense = of_property_read_bool(
+			chip->spmi->dev.of_node,
+			"qcom,use-external-rsense");
+
 	/* Get the btc-disabled property */
 	chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
 					"qcom,btc-disabled");
@@ -4124,17 +4339,25 @@
 	if (chip->use_default_batt_values)
 		chip->charging_disabled = true;
 
+	chip->power_stage_workaround_enable =
+			of_property_read_bool(chip->spmi->dev.of_node,
+					"qcom,power-stage-reduced");
+
+	chip->ibat_calibration_enabled =
+			of_property_read_bool(chip->spmi->dev.of_node,
+					"qcom,ibat-calibration-enabled");
+
 	of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
 		&(chip->thermal_levels));
 
 	if (chip->thermal_levels > sizeof(int)) {
-		chip->thermal_mitigation = kzalloc(
+		chip->thermal_mitigation = devm_kzalloc(chip->dev,
 			chip->thermal_levels,
 			GFP_KERNEL);
 
 		if (chip->thermal_mitigation == NULL) {
 			pr_err("thermal mitigation kzalloc() failed.\n");
-			return rc;
+			return -ENOMEM;
 		}
 
 		chip->thermal_levels /= sizeof(int);
@@ -4159,7 +4382,8 @@
 	struct spmi_resource *spmi_resource;
 	int rc = 0;
 
-	chip = kzalloc(sizeof *chip, GFP_KERNEL);
+	chip = devm_kzalloc(&spmi->dev,
+			sizeof(struct qpnp_chg_chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pr_err("kzalloc() failed.\n");
 		return -ENOMEM;
@@ -4191,7 +4415,7 @@
 	/* Get all device tree properties */
 	rc = qpnp_charger_read_dt_props(chip);
 	if (rc)
-		goto fail_chg_enable;
+		return rc;
 
 	/*
 	 * Check if bat_if is set in DT and make sure VADC is present
@@ -4231,6 +4455,17 @@
 				goto fail_chg_enable;
 			}
 
+			if (subtype == SMBB_BAT_IF_SUBTYPE) {
+				chip->iadc_dev = qpnp_get_iadc(chip->dev,
+						"chg");
+				if (IS_ERR(chip->iadc_dev)) {
+					rc = PTR_ERR(chip->iadc_dev);
+					if (rc != -EPROBE_DEFER)
+						pr_err("iadc property missing\n");
+					goto fail_chg_enable;
+				}
+			}
+
 			rc = qpnp_chg_load_battery_data(chip);
 			if (rc)
 				goto fail_chg_enable;
@@ -4503,9 +4738,6 @@
 fail_chg_enable:
 	regulator_unregister(chip->otg_vreg.rdev);
 	regulator_unregister(chip->boost_vreg.rdev);
-	kfree(chip->thermal_mitigation);
-	kfree(chip);
-	dev_set_drvdata(&spmi->dev, NULL);
 	return rc;
 }
 
@@ -4518,15 +4750,27 @@
 		qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
 							&chip->adc_param);
 	}
-	cancel_work_sync(&chip->adc_measure_work);
+
+	cancel_delayed_work_sync(&chip->aicl_check_work);
+	power_supply_unregister(&chip->dc_psy);
+	cancel_work_sync(&chip->soc_check_work);
+	cancel_delayed_work_sync(&chip->usbin_health_check);
+	cancel_delayed_work_sync(&chip->arb_stop_work);
 	cancel_delayed_work_sync(&chip->eoc_work);
+	cancel_work_sync(&chip->adc_disable_work);
+	cancel_work_sync(&chip->adc_measure_work);
+	power_supply_unregister(&chip->batt_psy);
+	cancel_work_sync(&chip->batfet_lcl_work);
+	cancel_work_sync(&chip->insertion_ocv_work);
+	cancel_work_sync(&chip->reduce_power_stage_work);
+	alarm_cancel(&chip->reduce_power_stage_alarm);
+
+	mutex_destroy(&chip->batfet_vreg_lock);
+	mutex_destroy(&chip->jeita_configure_lock);
 
 	regulator_unregister(chip->otg_vreg.rdev);
 	regulator_unregister(chip->boost_vreg.rdev);
 
-	dev_set_drvdata(&spmi->dev, NULL);
-	kfree(chip);
-
 	return 0;
 }
 
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 44949d2..83fa657 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -32,6 +32,7 @@
 #include <linux/lzo.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
+#include <linux/ratelimit.h>
 
 #include "zram_drv.h"
 
@@ -39,6 +40,12 @@
 static int zram_major;
 static struct zram *zram_devices;
 
+/*
+ * We don't need to see memory allocation errors more than once every 1
+ * second to know that a problem is occurring.
+ */
+#define ALLOC_ERROR_LOG_RATE_MS 1000
+
 /* Module params (documentation at end) */
 static unsigned int num_devices = 1;
 
@@ -221,7 +228,8 @@
 		goto free_buffer;
 	}
 
-	meta->mem_pool = zs_create_pool(GFP_NOIO | __GFP_HIGHMEM);
+	meta->mem_pool = zs_create_pool(GFP_NOIO | __GFP_HIGHMEM |
+					__GFP_NOWARN);
 	if (!meta->mem_pool) {
 		pr_err("Error creating memory pool\n");
 		goto free_table;
@@ -399,6 +407,7 @@
 	struct page *page;
 	unsigned char *user_mem, *cmem, *src, *uncmem = NULL;
 	struct zram_meta *meta = zram->meta;
+	static unsigned long zram_rs_time;
 
 	page = bvec->bv_page;
 	src = meta->compress_buffer;
@@ -440,6 +449,14 @@
 		goto out;
 	}
 
+	/*
+	 * zram_slot_free_notify could miss free so that let's
+	 * double check.
+	 */
+	if (unlikely(meta->table[index].handle ||
+			zram_test_flag(meta, index, ZRAM_ZERO)))
+		zram_free_page(zram, index);
+
 	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
 			       meta->compress_workmem);
 
@@ -464,8 +481,10 @@
 
 	handle = zs_malloc(meta->mem_pool, clen);
 	if (!handle) {
-		pr_info("Error allocating memory for compressed page: %u, size=%zu\n",
-			index, clen);
+		if (printk_timed_ratelimit(&zram_rs_time,
+					   ALLOC_ERROR_LOG_RATE_MS))
+			pr_info("Error allocating memory for compressed page: %u, size=%zu\n",
+				index, clen);
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -505,6 +524,20 @@
 	return ret;
 }
 
+static void handle_pending_slot_free(struct zram *zram)
+{
+	struct zram_slot_free *free_rq;
+
+	spin_lock(&zram->slot_free_lock);
+	while (zram->slot_free_rq) {
+		free_rq = zram->slot_free_rq;
+		zram->slot_free_rq = free_rq->next;
+		zram_free_page(zram, free_rq->index);
+		kfree(free_rq);
+	}
+	spin_unlock(&zram->slot_free_lock);
+}
+
 static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
 			int offset, struct bio *bio, int rw)
 {
@@ -512,10 +545,12 @@
 
 	if (rw == READ) {
 		down_read(&zram->lock);
+		handle_pending_slot_free(zram);
 		ret = zram_bvec_read(zram, bvec, index, offset, bio);
 		up_read(&zram->lock);
 	} else {
 		down_write(&zram->lock);
+		handle_pending_slot_free(zram);
 		ret = zram_bvec_write(zram, bvec, index, offset);
 		up_write(&zram->lock);
 	}
@@ -523,11 +558,13 @@
 	return ret;
 }
 
-static void zram_reset_device(struct zram *zram)
+static void zram_reset_device(struct zram *zram, bool reset_capacity)
 {
 	size_t index;
 	struct zram_meta *meta;
 
+	flush_work(&zram->free_work);
+
 	down_write(&zram->init_lock);
 	if (!zram->init_done) {
 		up_write(&zram->init_lock);
@@ -552,7 +589,8 @@
 	memset(&zram->stats, 0, sizeof(zram->stats));
 
 	zram->disksize = 0;
-	set_capacity(zram->disk, 0);
+	if (reset_capacity)
+		set_capacity(zram->disk, 0);
 	up_write(&zram->init_lock);
 }
 
@@ -636,7 +674,7 @@
 	if (bdev)
 		fsync_bdev(bdev);
 
-	zram_reset_device(zram);
+	zram_reset_device(zram, true);
 	return len;
 }
 
@@ -721,16 +759,40 @@
 	bio_io_error(bio);
 }
 
+static void zram_slot_free(struct work_struct *work)
+{
+	struct zram *zram;
+
+	zram = container_of(work, struct zram, free_work);
+	down_write(&zram->lock);
+	handle_pending_slot_free(zram);
+	up_write(&zram->lock);
+}
+
+static void add_slot_free(struct zram *zram, struct zram_slot_free *free_rq)
+{
+	spin_lock(&zram->slot_free_lock);
+	free_rq->next = zram->slot_free_rq;
+	zram->slot_free_rq = free_rq;
+	spin_unlock(&zram->slot_free_lock);
+}
+
 static void zram_slot_free_notify(struct block_device *bdev,
 				unsigned long index)
 {
 	struct zram *zram;
+	struct zram_slot_free *free_rq;
 
 	zram = bdev->bd_disk->private_data;
-	down_write(&zram->lock);
-	zram_free_page(zram, index);
-	up_write(&zram->lock);
 	atomic64_inc(&zram->stats.notify_free);
+
+	free_rq = kmalloc(sizeof(struct zram_slot_free), GFP_ATOMIC);
+	if (!free_rq)
+		return;
+
+	free_rq->index = index;
+	add_slot_free(zram, free_rq);
+	schedule_work(&zram->free_work);
 }
 
 static const struct block_device_operations zram_devops = {
@@ -777,6 +839,10 @@
 	init_rwsem(&zram->lock);
 	init_rwsem(&zram->init_lock);
 
+	INIT_WORK(&zram->free_work, zram_slot_free);
+	spin_lock_init(&zram->slot_free_lock);
+	zram->slot_free_rq = NULL;
+
 	zram->queue = blk_alloc_queue(GFP_KERNEL);
 	if (!zram->queue) {
 		pr_err("Error allocating disk queue for device %d\n",
@@ -903,10 +969,12 @@
 	for (i = 0; i < num_devices; i++) {
 		zram = &zram_devices[i];
 
-		get_disk(zram->disk);
 		destroy_device(zram);
-		zram_reset_device(zram);
-		put_disk(zram->disk);
+		/*
+		 * Shouldn't access zram->disk after destroy_device
+		 * because destroy_device already released zram->disk.
+		 */
+		zram_reset_device(zram, false);
 	}
 
 	unregister_blkdev(zram_major, "zram");
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
index 9e57bfb..508a19f 100644
--- a/drivers/staging/zram/zram_drv.h
+++ b/drivers/staging/zram/zram_drv.h
@@ -32,7 +32,7 @@
  * Pages that compress to size greater than this are stored
  * uncompressed in memory.
  */
-static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
+static const size_t max_zpage_size = PAGE_SIZE / 10 * 9;
 
 /*
  * NOTE: max_zpage_size must be less than or equal to:
@@ -94,11 +94,20 @@
 	struct zs_pool *mem_pool;
 };
 
+struct zram_slot_free {
+	unsigned long index;
+	struct zram_slot_free *next;
+};
+
 struct zram {
 	struct zram_meta *meta;
 	struct rw_semaphore lock; /* protect compression buffers, table,
 				   * 32bit stat counters against concurrent
 				   * notifications, reads and writes */
+
+	struct work_struct free_work;  /* handle pending free request */
+	struct zram_slot_free *slot_free_rq; /* list head of free request */
+
 	struct request_queue *queue;
 	struct gendisk *disk;
 	int init_done;
@@ -109,6 +118,7 @@
 	 * we can store in a disk.
 	 */
 	u64 disksize;	/* bytes */
+	spinlock_t slot_free_lock;
 
 	struct zram_stats stats;
 };
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c
index 1a67537..523b937 100644
--- a/drivers/staging/zsmalloc/zsmalloc-main.c
+++ b/drivers/staging/zsmalloc/zsmalloc-main.c
@@ -472,7 +472,7 @@
 	set_page_private(page, 0);
 	page->mapping = NULL;
 	page->freelist = NULL;
-	page_mapcount_reset(page);
+	reset_page_mapcount(page);
 }
 
 static void free_zspage(struct page *first_page)
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 00df613..3bf1ae0 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -38,9 +38,11 @@
 #include <linux/regulator/consumer.h>
 
 #define MAX_RAILS 5
+#define MAX_THRESHOLD 2
 
 static struct msm_thermal_data msm_thermal_info;
-static uint32_t limited_max_freq = MSM_CPUFREQ_NO_LIMIT;
+static uint32_t limited_max_freq = UINT_MAX;
+static uint32_t limited_min_freq;
 static struct delayed_work check_temp_work;
 static bool core_control_enabled;
 static uint32_t cpus_offlined;
@@ -77,8 +79,10 @@
 	uint32_t cpu;
 	bool offline;
 	bool user_offline;
+	bool thresh_cleared;
 	const char *sensor_type;
-	struct sensor_threshold thresh[2];
+	uint32_t sensor_id;
+	struct sensor_threshold thresh[MAX_THRESHOLD];
 };
 
 struct rail {
@@ -154,6 +158,25 @@
 
 #define PSM_REG_MODE_FROM_ATTRIBS(attr) \
 	(container_of(attr, struct psm_rail, mode_attr));
+
+static int  msm_thermal_cpufreq_callback(struct notifier_block *nfb,
+		unsigned long event, void *data)
+{
+	struct cpufreq_policy *policy = data;
+
+	switch (event) {
+	case CPUFREQ_INCOMPATIBLE:
+		cpufreq_verify_within_limits(policy, limited_min_freq,
+				limited_max_freq);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block msm_thermal_cpufreq_notifier = {
+	.notifier_call = msm_thermal_cpufreq_callback,
+};
+
 /* If freq table exists, then we can send freq request */
 static int check_freq_table(void)
 {
@@ -174,37 +197,26 @@
 {
 	int cpu = 0;
 	int ret = 0;
-	struct cpufreq_policy *policy = NULL;
 
 	if (!freq_table_get) {
 		ret = check_freq_table();
 		if (ret) {
-			pr_err("%s:Fail to get freq table\n", __func__);
+			pr_err("%s:Fail to get freq table\n", KBUILD_MODNAME);
 			return ret;
 		}
 	}
 	/* If min is larger than allowed max */
-	if (min != MSM_CPUFREQ_NO_LIMIT &&
-			min > table[limit_idx_high].frequency)
-		min = table[limit_idx_high].frequency;
+	min = min(min, table[limit_idx_high].frequency);
 
-	for_each_possible_cpu(cpu) {
-		ret = msm_cpufreq_set_freq_limits(cpu, min, limited_max_freq);
-		if (ret) {
-			pr_err("%s:Fail to set limits for cpu%d\n",
-					__func__, cpu);
-			return ret;
-		}
+	limited_min_freq = min;
 
-		if (cpu_online(cpu)) {
-			policy = cpufreq_cpu_get(cpu);
-			if (!policy)
-				continue;
-			cpufreq_driver_target(policy, policy->cur,
-					CPUFREQ_RELATION_L);
-			cpufreq_cpu_put(policy);
-		}
+	get_online_cpus();
+	for_each_online_cpu(cpu) {
+		if (cpufreq_update_policy(cpu))
+			pr_info("%s: Unable to update policy for cpu:%d\n",
+				KBUILD_MODNAME, cpu);
 	}
+	put_online_cpus();
 
 	return ret;
 }
@@ -599,27 +611,90 @@
 {
 	int ret = 0;
 
-	ret = msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, max_freq);
-	if (ret)
-		return ret;
-
-	limited_max_freq = max_freq;
-	if (max_freq != MSM_CPUFREQ_NO_LIMIT)
+	if (max_freq != UINT_MAX)
 		pr_info("%s: Limiting cpu%d max frequency to %d\n",
 				KBUILD_MODNAME, cpu, max_freq);
 	else
 		pr_info("%s: Max frequency reset for cpu%d\n",
 				KBUILD_MODNAME, cpu);
+	get_online_cpus();
+	for_each_online_cpu(cpu) {
+		if (cpufreq_update_policy(cpu))
+			pr_info("%s: Unable to update policy for cpu:%d\n",
+				KBUILD_MODNAME, cpu);
+	}
+	put_online_cpus();
 
-	if (cpu_online(cpu)) {
-		struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-		if (!policy)
-			return ret;
-		ret = cpufreq_driver_target(policy, policy->cur,
-				CPUFREQ_RELATION_H);
-		cpufreq_cpu_put(policy);
+	return ret;
+}
+
+static int set_and_activate_threshold(uint32_t sensor_id,
+	struct sensor_threshold *threshold)
+{
+	int ret = 0;
+
+	ret = sensor_set_trip(sensor_id, threshold);
+	if (ret != 0) {
+		pr_err("%s: Error in setting trip %d\n",
+			KBUILD_MODNAME, threshold->trip);
+		goto set_done;
 	}
 
+	ret = sensor_activate_trip(sensor_id, threshold, true);
+	if (ret != 0) {
+		pr_err("%s: Error in enabling trip %d\n",
+			KBUILD_MODNAME, threshold->trip);
+		goto set_done;
+	}
+
+set_done:
+	return ret;
+}
+
+static int set_threshold(uint32_t sensor_id,
+	struct sensor_threshold *threshold)
+{
+	struct tsens_device tsens_dev;
+	int i = 0, ret = 0;
+	long temp;
+
+	if ((!threshold) || check_sensor_id(sensor_id)) {
+		pr_err("%s: Invalid input\n", KBUILD_MODNAME);
+		ret = -EINVAL;
+		goto set_threshold_exit;
+	}
+
+	tsens_dev.sensor_num = sensor_id;
+	ret = tsens_get_temp(&tsens_dev, &temp);
+	if (ret) {
+		pr_err("%s: Unable to read TSENS sensor %d\n",
+			KBUILD_MODNAME, tsens_dev.sensor_num);
+		goto set_threshold_exit;
+	}
+	while (i < MAX_THRESHOLD) {
+		switch (threshold[i].trip) {
+		case THERMAL_TRIP_CONFIGURABLE_HI:
+			if (threshold[i].temp >= temp) {
+				ret = set_and_activate_threshold(sensor_id,
+					&threshold[i]);
+				if (ret)
+					goto set_threshold_exit;
+			}
+			break;
+		case THERMAL_TRIP_CONFIGURABLE_LOW:
+			if (threshold[i].temp <= temp) {
+				ret = set_and_activate_threshold(sensor_id,
+					&threshold[i]);
+				if (ret)
+					goto set_threshold_exit;
+			}
+			break;
+		default:
+			break;
+		}
+		i++;
+	}
+set_threshold_exit:
 	return ret;
 }
 
@@ -676,7 +751,7 @@
 /* Call with core_control_mutex locked */
 static int __ref update_offline_cores(int val)
 {
-	int cpu = 0;
+	uint32_t cpu = 0;
 	int ret = 0;
 
 	if (!core_control_enabled)
@@ -700,8 +775,7 @@
 static __ref int do_hotplug(void *data)
 {
 	int ret = 0;
-	int cpu = 0;
-	uint32_t mask = 0;
+	uint32_t cpu = 0, mask = 0;
 
 	if (!core_control_enabled)
 		return -EINVAL;
@@ -713,6 +787,11 @@
 
 		mutex_lock(&core_control_mutex);
 		for_each_possible_cpu(cpu) {
+			if (cpus[cpu].thresh_cleared) {
+                                set_threshold(cpus[cpu].sensor_id,
+					cpus[cpu].thresh);
+				cpus[cpu].thresh_cleared = false;
+                        }
 			if (cpus[cpu].offline || cpus[cpu].user_offline)
 				mask |= BIT(cpu);
 		}
@@ -835,7 +914,6 @@
 
 static void __ref do_freq_control(long temp)
 {
-	int ret = 0;
 	int cpu = 0;
 	uint32_t max_freq = limited_max_freq;
 
@@ -855,7 +933,7 @@
 		limit_idx += msm_thermal_info.freq_step;
 		if (limit_idx >= limit_idx_high) {
 			limit_idx = limit_idx_high;
-			max_freq = MSM_CPUFREQ_NO_LIMIT;
+			max_freq = UINT_MAX;
 		} else
 			max_freq = table[limit_idx].frequency;
 	}
@@ -863,17 +941,13 @@
 	if (max_freq == limited_max_freq)
 		return;
 
+	limited_max_freq = max_freq;
 	/* Update new limits */
 	for_each_possible_cpu(cpu) {
 		if (!(msm_thermal_info.freq_control_mask & BIT(cpu)))
 			continue;
-		ret = update_cpu_max_freq(cpu, max_freq);
-		if (ret)
-			pr_debug(
-			"%s: Unable to limit cpu%d max freq to %d\n",
-					KBUILD_MODNAME, cpu, max_freq);
+		update_cpu_max_freq(cpu, max_freq);
 	}
-
 }
 
 static void __ref check_temp(struct work_struct *work)
@@ -988,10 +1062,12 @@
 	default:
 		break;
 	}
-	if (hotplug_task)
+	if (hotplug_task) {
+		cpu_node->thresh_cleared = true;
 		complete(&hotplug_notify_complete);
-	else
+	} else {
 		pr_err("%s: Hotplug task is not initialized\n", KBUILD_MODNAME);
+	}
 	return 0;
 }
 /* Adjust cpus offlined bit based on temperature reading. */
@@ -1005,8 +1081,7 @@
 	for_each_possible_cpu(cpu) {
 		if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
 			continue;
-		tsens_dev.sensor_num = sensor_get_id(\
-				(char *)cpus[cpu].sensor_type);
+		tsens_dev.sensor_num = cpus[cpu].sensor_id;
 		if (tsens_get_temp(&tsens_dev, &temp)) {
 			pr_err("%s: Unable to read TSENS sensor %d\n",
 				KBUILD_MODNAME, tsens_dev.sensor_num);
@@ -1039,24 +1114,23 @@
 		return;
 
 	for_each_possible_cpu(cpu) {
+		cpus[cpu].cpu = (uint32_t)cpu;
+		cpus[cpu].thresh_cleared = false;
+		cpus[cpu].sensor_id =
+			sensor_get_id((char *)cpus[cpu].sensor_type);
 		if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
 			continue;
-		cpus[cpu].cpu = (uint32_t)cpu;
 		cpus[cpu].thresh[0].temp = msm_thermal_info.hotplug_temp_degC;
 		cpus[cpu].thresh[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
 		cpus[cpu].thresh[0].notify = hotplug_notify;
 		cpus[cpu].thresh[0].data = (void *)&cpus[cpu];
-		sensor_set_trip(sensor_get_id((char *)cpus[cpu].sensor_type),
-				&cpus[cpu].thresh[0]);
 
 		cpus[cpu].thresh[1].temp = msm_thermal_info.hotplug_temp_degC -
 				msm_thermal_info.hotplug_temp_hysteresis_degC;
 		cpus[cpu].thresh[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
 		cpus[cpu].thresh[1].notify = hotplug_notify;
 		cpus[cpu].thresh[1].data = (void *)&cpus[cpu];
-		sensor_set_trip(sensor_get_id((char *)cpus[cpu].sensor_type),
-				&cpus[cpu].thresh[1]);
-
+		set_threshold(cpus[cpu].sensor_id, cpus[cpu].thresh);
 	}
 	init_completion(&hotplug_notify_complete);
 	hotplug_task = kthread_run(do_hotplug, NULL, "msm_thermal:hotplug");
@@ -1086,12 +1160,17 @@
 	cancel_delayed_work(&check_temp_work);
 	flush_scheduled_work();
 
-	if (limited_max_freq == MSM_CPUFREQ_NO_LIMIT)
+	if (limited_max_freq == UINT_MAX)
 		return;
 
-	for_each_possible_cpu(cpu) {
-		update_cpu_max_freq(cpu, MSM_CPUFREQ_NO_LIMIT);
+	limited_max_freq = UINT_MAX;
+	get_online_cpus();
+	for_each_online_cpu(cpu) {
+		if (cpufreq_update_policy(cpu))
+			pr_info("%s: Unable to update policy for cpu:%d\n",
+				KBUILD_MODNAME, cpu);
 	}
+	put_online_cpus();
 }
 
 static int __ref set_enabled(const char *val, const struct kernel_param *kp)
@@ -1104,7 +1183,7 @@
 		hotplug_init();
 	} else
 		pr_info("%s: no action for enabled = %d\n",
-				KBUILD_MODNAME, enabled);
+			KBUILD_MODNAME, enabled);
 
 	pr_info("%s: enabled = %d\n", KBUILD_MODNAME, enabled);
 
@@ -1345,7 +1424,11 @@
 		return -EINVAL;
 
 	enabled = 1;
-
+	ret = cpufreq_register_notifier(&msm_thermal_cpufreq_notifier,
+			CPUFREQ_POLICY_NOTIFIER);
+	if (ret)
+		pr_err("%s: cannot register cpufreq notifier\n",
+			KBUILD_MODNAME);
 	INIT_DELAYED_WORK(&check_temp_work, check_temp);
 	schedule_delayed_work(&check_temp_work, 0);
 
@@ -1659,7 +1742,7 @@
 		key = "qcom,freq-req";
 		rails[i].freq_req = of_property_read_bool(child_node, key);
 		if (rails[i].freq_req)
-			rails[i].min_level = MSM_CPUFREQ_NO_LIMIT;
+			rails[i].min_level = 0;
 		else {
 			key = "qcom,min-level";
 			ret = of_property_read_u32(child_node, key,
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 8d9da6b..739696d 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -89,30 +89,21 @@
 }
 EXPORT_SYMBOL(sensor_get_id);
 
-static long get_min(struct sensor_info *sensor, long temp)
+static int __update_sensor_thresholds(struct sensor_info *sensor)
 {
-	long min = LONG_MIN;
-	struct sensor_threshold *pos, *var;
-
-	list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
-		if (pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW)
-			if (pos->temp < temp && pos->temp > min)
-				min = pos->temp;
-	}
-
-	return min;
-}
-
-static void __update_sensor_thresholds(struct sensor_info *sensor)
-{
-	long min = LONG_MIN;
-	long max = LONG_MAX;
-	long max_of_min = LONG_MIN;
-	long min_of_max = LONG_MAX;
+	long max_of_low_thresh = LONG_MIN;
+	long min_of_high_thresh = LONG_MAX;
 	struct sensor_threshold *pos, *var;
 	enum thermal_trip_type type;
-	int i;
-	long curr_temp;
+	int i, ret = 0;
+
+	if (!sensor->tz->ops->set_trip_temp ||
+		!sensor->tz->ops->activate_trip_type ||
+		!sensor->tz->ops->get_trip_type ||
+		!sensor->tz->ops->get_trip_temp) {
+		ret = -ENODEV;
+		goto update_done;
+	}
 
 	for (i = 0; ((sensor->max_idx == -1) || (sensor->min_idx == -1)) &&
 		(sensor->tz->ops->get_trip_type) && (i < sensor->tz->trips);
@@ -128,60 +119,85 @@
 			THERMAL_TRIP_CONFIGURABLE_HI, &sensor->threshold_max);
 	}
 
-	sensor->tz->ops->get_temp(sensor->tz, &curr_temp);
 	list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+		if (!pos->active)
+			continue;
 		if (pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW) {
-			if (pos->temp > max_of_min)
-				max_of_min = pos->temp;
-			if (pos->temp < curr_temp && pos->temp > min)
-				min = pos->temp;
+			if (pos->temp > max_of_low_thresh)
+				max_of_low_thresh = pos->temp;
 		}
 		if (pos->trip == THERMAL_TRIP_CONFIGURABLE_HI) {
-			if (pos->temp < min_of_max)
-				min_of_max = pos->temp;
-			if (pos->temp > curr_temp && pos->temp < max)
-				max = pos->temp;
+			if (pos->temp < min_of_high_thresh)
+				min_of_high_thresh = pos->temp;
 		}
 	}
 
-	pr_debug("sensor %d: min of max: %ld max of min: %ld\n",
-			sensor->sensor_id, max_of_min, min_of_max);
+	pr_debug("sensor %d: Thresholds: max of low: %ld min of high: %ld\n",
+		sensor->sensor_id, max_of_low_thresh,
+		min_of_high_thresh);
 
-	/* If we haven't found a max and min bounding the curr_temp,
-	 * use the min of max and max of min instead.
-	 */
-	if (max == LONG_MAX)
-		max = min_of_max;
-	if (min == LONG_MIN) {
-		min = get_min(sensor, max);
-		if (min == LONG_MIN)
-			min = max_of_min;
+	if ((min_of_high_thresh != sensor->threshold_max) &&
+		(min_of_high_thresh != LONG_MAX)) {
+		ret = sensor->tz->ops->set_trip_temp(sensor->tz,
+			sensor->max_idx, min_of_high_thresh);
+		if (ret) {
+			pr_err("sensor %d: Unable to set high threshold %d",
+				sensor->sensor_id, ret);
+			goto update_done;
+		}
+		sensor->threshold_max = min_of_high_thresh;
+	}
+	ret = sensor->tz->ops->activate_trip_type(sensor->tz,
+		sensor->max_idx,
+		(min_of_high_thresh == LONG_MAX) ?
+		THERMAL_TRIP_ACTIVATION_DISABLED :
+		THERMAL_TRIP_ACTIVATION_ENABLED);
+	if (ret) {
+		pr_err("sensor %d: Unable to activate high threshold %d",
+			sensor->sensor_id, ret);
+		goto update_done;
 	}
 
-	if (sensor->tz->ops->set_trip_temp) {
-		if (max != sensor->threshold_max) {
-			sensor->tz->ops->set_trip_temp(sensor->tz,
-				sensor->max_idx, max);
-			sensor->threshold_max = max;
+	if ((max_of_low_thresh != sensor->threshold_min) &&
+		(max_of_low_thresh != LONG_MIN)) {
+		ret = sensor->tz->ops->set_trip_temp(sensor->tz,
+			sensor->min_idx, max_of_low_thresh);
+		if (ret) {
+			pr_err("sensor %d: Unable to set low threshold %d",
+				sensor->sensor_id, ret);
+			goto update_done;
 		}
-		if (min != sensor->threshold_min) {
-			sensor->tz->ops->set_trip_temp(sensor->tz,
-				sensor->min_idx, min);
-			sensor->threshold_min = min;
-		}
+		sensor->threshold_min = max_of_low_thresh;
+	}
+	ret = sensor->tz->ops->activate_trip_type(sensor->tz,
+		sensor->min_idx,
+		(max_of_low_thresh == LONG_MIN) ?
+		THERMAL_TRIP_ACTIVATION_DISABLED :
+		THERMAL_TRIP_ACTIVATION_ENABLED);
+	if (ret) {
+		pr_err("sensor %d: Unable to activate low threshold %d",
+			sensor->sensor_id, ret);
+		goto update_done;
 	}
 
-	pr_debug("sensor %d: curr_temp: %ld min: %ld max: %ld\n",
-		sensor->sensor_id, curr_temp,
+	pr_debug("sensor %d: low: %ld high: %ld\n",
+		sensor->sensor_id,
 		sensor->threshold_min, sensor->threshold_max);
+
+update_done:
+	return ret;
 }
 
 static void sensor_update_work(struct work_struct *work)
 {
 	struct sensor_info *sensor = container_of(work, struct sensor_info,
 						work);
+	int ret = 0;
 	mutex_lock(&sensor->lock);
-	__update_sensor_thresholds(sensor);
+	ret = __update_sensor_thresholds(sensor);
+	if (ret)
+		pr_err("sensor %d: Error %d setting threshold\n",
+			sensor->sensor_id, ret);
 	mutex_unlock(&sensor->lock);
 }
 
@@ -202,7 +218,7 @@
 		return 0;
 
 	list_for_each_entry_safe(pos, var, &tz->sensor.threshold_list, list) {
-		if (pos->trip != trip)
+		if ((pos->trip != trip) || (!pos->active))
 			continue;
 		if (((trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
 			(pos->temp <= tz->sensor.threshold_min) &&
@@ -210,6 +226,7 @@
 			((trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
 				(pos->temp >= tz->sensor.threshold_max) &&
 				(pos->temp <= temp))) {
+			pos->active = 0;
 			pos->notify(trip, temp, pos->data);
 		}
 	}
@@ -220,6 +237,29 @@
 }
 EXPORT_SYMBOL(thermal_sensor_trip);
 
+int sensor_activate_trip(uint32_t sensor_id,
+	struct sensor_threshold *threshold, bool enable)
+{
+	struct sensor_info *sensor = get_sensor(sensor_id);
+	int ret = 0;
+
+	if (!sensor || !threshold) {
+		pr_err("Sensor %d: uninitialized data\n",
+			sensor_id);
+		ret = -ENODEV;
+		goto activate_trip_exit;
+	}
+
+	mutex_lock(&sensor->lock);
+	threshold->active = (enable) ? 1 : 0;
+	ret = __update_sensor_thresholds(sensor);
+	mutex_unlock(&sensor->lock);
+
+activate_trip_exit:
+	return ret;
+}
+EXPORT_SYMBOL(sensor_activate_trip);
+
 int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
 {
 	struct sensor_threshold *pos, *var;
@@ -241,8 +281,7 @@
 		INIT_LIST_HEAD(&threshold->list);
 		list_add(&threshold->list, &sensor->threshold_list);
 	}
-
-	__update_sensor_thresholds(sensor);
+	threshold->active = 0; /* Do not allow active threshold right away */
 	mutex_unlock(&sensor->lock);
 
 	return 0;
@@ -254,6 +293,7 @@
 {
 	struct sensor_threshold *pos, *var;
 	struct sensor_info *sensor = get_sensor(sensor_id);
+	int ret = 0;
 
 	if (!sensor)
 		return -ENODEV;
@@ -261,15 +301,16 @@
 	mutex_lock(&sensor->lock);
 	list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
 		if (pos == threshold) {
+			pos->active = 0;
 			list_del(&pos->list);
 			break;
 		}
 	}
 
-	__update_sensor_thresholds(sensor);
+	ret = __update_sensor_thresholds(sensor);
 	mutex_unlock(&sensor->lock);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL(sensor_cancel_trip);
 
@@ -283,36 +324,36 @@
 	return 0;
 }
 
+static void get_trip_threshold(struct thermal_zone_device *tz, int trip,
+	struct sensor_threshold **threshold)
+{
+	enum thermal_trip_type type;
+
+	tz->ops->get_trip_type(tz, trip, &type);
+
+	if (type == THERMAL_TRIP_CONFIGURABLE_HI)
+		*threshold = &tz->tz_threshold[0];
+	else if (type == THERMAL_TRIP_CONFIGURABLE_LOW)
+		*threshold = &tz->tz_threshold[1];
+	else
+		*threshold = NULL;
+}
+
 int sensor_set_trip_temp(struct thermal_zone_device *tz,
 		int trip, long temp)
 {
 	int ret = 0;
-	enum thermal_trip_type type;
+	struct sensor_threshold *threshold = NULL;
 
 	if (!tz->ops->get_trip_type)
 		return -EPERM;
 
-	tz->ops->get_trip_type(tz, trip, &type);
-	switch (type) {
-	case THERMAL_TRIP_CONFIGURABLE_HI:
-		tz->tz_threshold[0].temp = temp;
-		tz->tz_threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
-		tz->tz_threshold[0].notify = tz_notify_trip;
-		tz->tz_threshold[0].data = tz;
-		ret = sensor_set_trip(tz->sensor.sensor_id,
-					&tz->tz_threshold[0]);
-		break;
-	case THERMAL_TRIP_CONFIGURABLE_LOW:
-		tz->tz_threshold[1].temp = temp;
-		tz->tz_threshold[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
-		tz->tz_threshold[1].notify = tz_notify_trip;
-		tz->tz_threshold[1].data = tz;
-		ret = sensor_set_trip(tz->sensor.sensor_id,
-					&tz->tz_threshold[1]);
-		break;
-	default:
+	get_trip_threshold(tz, trip, &threshold);
+	if (threshold) {
+		threshold->temp = temp;
+		ret = sensor_set_trip(tz->sensor.sensor_id, threshold);
+	} else {
 		ret = tz->ops->set_trip_temp(tz, trip, temp);
-		break;
 	}
 
 	return ret;
@@ -333,10 +374,12 @@
 	INIT_LIST_HEAD(&sensor->threshold_list);
 	INIT_LIST_HEAD(&tz->tz_threshold[0].list);
 	INIT_LIST_HEAD(&tz->tz_threshold[1].list);
-	tz->tz_threshold[0].notify = NULL;
-	tz->tz_threshold[0].data = NULL;
-	tz->tz_threshold[1].notify = NULL;
-	tz->tz_threshold[1].data = NULL;
+	tz->tz_threshold[0].notify = tz_notify_trip;
+	tz->tz_threshold[0].data = tz;
+	tz->tz_threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
+	tz->tz_threshold[1].notify = tz_notify_trip;
+	tz->tz_threshold[1].data = tz;
+	tz->tz_threshold[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
 	list_add(&sensor->sensor_list, &sensor_info_list);
 	INIT_WORK(&sensor->work, sensor_update_work);
 
@@ -489,23 +532,40 @@
 		const char *buf, size_t count)
 {
 	struct thermal_zone_device *tz = to_thermal_zone(dev);
-	int trip, result;
+	int trip, result = 0;
+	bool activate;
+	struct sensor_threshold *threshold = NULL;
 
-	if (!tz->ops->activate_trip_type)
-		return -EPERM;
+	if (!tz->ops->get_trip_type ||
+		!tz->ops->activate_trip_type) {
+		result = -EPERM;
+		goto trip_activate_exit;
+	}
 
-	if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
-		return -EINVAL;
-
-	if (!strncmp(buf, "enabled", sizeof("enabled")))
-		result = tz->ops->activate_trip_type(tz, trip,
-					THERMAL_TRIP_ACTIVATION_ENABLED);
-	else if (!strncmp(buf, "disabled", sizeof("disabled")))
-		result = tz->ops->activate_trip_type(tz, trip,
-					THERMAL_TRIP_ACTIVATION_DISABLED);
-	else
+	if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) {
 		result = -EINVAL;
+		goto trip_activate_exit;
+	}
 
+	if (!strcmp(buf, "enabled")) {
+		activate = true;
+	} else if (!strcmp(buf, "disabled")) {
+		activate = false;
+	} else {
+		result = -EINVAL;
+		goto trip_activate_exit;
+	}
+
+	get_trip_threshold(tz, trip, &threshold);
+	if (threshold)
+		result = sensor_activate_trip(tz->sensor.sensor_id,
+			threshold, activate);
+	else
+		result = tz->ops->activate_trip_type(tz, trip,
+			activate ? THERMAL_TRIP_ACTIVATION_ENABLED :
+			THERMAL_TRIP_ACTIVATION_DISABLED);
+
+trip_activate_exit:
 	if (result)
 		return result;
 
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index a243a05..078929b 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -155,7 +155,6 @@
 	struct tasklet_struct tlet;
 	struct msm_hs_sps_ep_conn_data prod;
 };
-
 enum buffer_states {
 	NONE_PENDING = 0x0,
 	FIFO_OVERRUN = 0x1,
@@ -219,6 +218,7 @@
 	struct msm_bus_scale_pdata *bus_scale_table;
 	bool rx_discard_flush_issued;
 	int rx_count_callback;
+	bool rx_bam_inprogress;
 	unsigned int *reg_ptr;
 };
 
@@ -998,6 +998,14 @@
 	mutex_lock(&msm_uport->clk_mutex);
 	msm_hs_write(uport, UART_DM_IMR, 0);
 
+	/* Clear the Rx Ready Ctl bit - This ensures that
+	* flow control lines stop the other side from sending
+	* data while we change the parameters
+	*/
+	data = msm_hs_read(uport, UART_DM_MR1);
+	data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
+	msm_hs_write(uport, UART_DM_MR1, data);
+
 	/*
 	 * Disable Rx channel of UARTDM
 	 * DMA Rx Stall happens if enqueue and flush of Rx command happens
@@ -1071,18 +1079,6 @@
 	/* write parity/bits per char/stop bit configuration */
 	msm_hs_write(uport, UART_DM_MR2, data);
 
-	/* Configure HW flow control */
-	data = msm_hs_read(uport, UART_DM_MR1);
-
-	data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
-
-	if (c_cflag & CRTSCTS) {
-		data |= UARTDM_MR1_CTS_CTL_BMSK;
-		data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
-	}
-
-	msm_hs_write(uport, UART_DM_MR1, data);
-
 	uport->ignore_status_mask = termios->c_iflag & INPCK;
 	uport->ignore_status_mask |= termios->c_iflag & IGNPAR;
 	uport->ignore_status_mask |= termios->c_iflag & IGNBRK;
@@ -1106,6 +1102,10 @@
 		 */
 		mb();
 		if (is_blsp_uart(msm_uport)) {
+			if (msm_uport->rx_bam_inprogress)
+				ret = wait_event_timeout(msm_uport->rx.wait,
+					msm_uport->rx_bam_inprogress == false,
+					RX_FLUSH_COMPLETE_TIMEOUT);
 			ret = sps_disconnect(sps_pipe_handle);
 			if (ret)
 				pr_err("%s(): sps_disconnect failed\n",
@@ -1127,6 +1127,20 @@
 		}
 	}
 
+	/* Configure HW flow control
+	 * UART Core would see status of CTS line when it is sending data
+	 * to remote uart to confirm that it can receive or not.
+	 * UART Core would trigger RFR if it is not having any space with
+	 * RX FIFO.
+	 */
+	data = msm_hs_read(uport, UART_DM_MR1);
+	data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
+	if (c_cflag & CRTSCTS) {
+		data |= UARTDM_MR1_CTS_CTL_BMSK;
+		data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
+	}
+	msm_hs_write(uport, UART_DM_MR1, data);
+
 	msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 	mb();
 	mutex_unlock(&msm_uport->clk_mutex);
@@ -1358,10 +1372,13 @@
 	msm_uport->rx.flush = FLUSH_NONE;
 
 	if (is_blsp_uart(msm_uport)) {
+		msm_uport->rx_bam_inprogress = true;
 		sps_pipe_handle = rx->prod.pipe_handle;
 		/* Queue transfer request to SPS */
 		sps_transfer_one(sps_pipe_handle, rx->rbuffer,
 			UARTDM_RX_BUF_SIZE, msm_uport, flags);
+		msm_uport->rx_bam_inprogress = false;
+		wake_up(&msm_uport->rx.wait);
 	} else {
 		msm_dmov_enqueue_cmd(msm_uport->dma_rx_channel,
 				&msm_uport->rx.xfer);
@@ -1531,10 +1548,13 @@
 	if (!msm_uport->rx.buffer_pending) {
 		if (is_blsp_uart(msm_uport)) {
 			msm_uport->rx.flush = FLUSH_NONE;
+			msm_uport->rx_bam_inprogress = true;
 			sps_pipe_handle = rx->prod.pipe_handle;
 			/* Queue transfer request to SPS */
 			sps_transfer_one(sps_pipe_handle, rx->rbuffer,
 				UARTDM_RX_BUF_SIZE, msm_uport, sps_flags);
+			msm_uport->rx_bam_inprogress = false;
+			wake_up(&msm_uport->rx.wait);
 		} else {
 			msm_hs_start_rx_locked(uport);
 		}
@@ -2832,9 +2852,9 @@
 	/* Now save the sps pipe handle */
 	ep->pipe_handle = sps_pipe_handle;
 	pr_debug("msm_serial_hs: success !! %s: pipe_handle=0x%x\n"
-		"desc_fifo.phys_base=0x%x\n",
+		"desc_fifo.phys_base=0x%llx\n",
 		is_producer ? "READ" : "WRITE",
-		(u32)sps_pipe_handle, sps_config->desc.phys_base);
+		(u32) sps_pipe_handle, (u64) sps_config->desc.phys_base);
 	return 0;
 
 get_config_err:
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index a4a4f28..0ff8ad7 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -523,6 +523,10 @@
 {
 	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
 
+	if (port->suspended) {
+		pr_err("%s: System is in Suspend state\n", __func__);
+		return;
+	}
 	msm_hsl_port->imr |= UARTDM_ISR_TXLEV_BMSK;
 	msm_hsl_write(port, msm_hsl_port->imr,
 		regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 6f3ea9b..ad66113 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -111,4 +111,11 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called uio_pruss.
 
+config UIO_MSM_SHAREDMEM
+	bool "MSM shared memory driver"
+	default n
+	help
+	  Provides the clients with their respective alloted shared memory
+	  addresses which are used as transport buffer.
+
 endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index d4dd9a5..c4d177a 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_UIO_PCI_GENERIC)	+= uio_pci_generic.o
 obj-$(CONFIG_UIO_NETX)	+= uio_netx.o
 obj-$(CONFIG_UIO_PRUSS)         += uio_pruss.o
+obj-$(CONFIG_UIO_MSM_SHAREDMEM) += msm_sharedmem.o
diff --git a/drivers/uio/msm_sharedmem.c b/drivers/uio/msm_sharedmem.c
new file mode 100644
index 0000000..438f002
--- /dev/null
+++ b/drivers/uio/msm_sharedmem.c
@@ -0,0 +1,87 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/uio_driver.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+
+#define DRIVER_NAME "msm_sharedmem"
+
+static int msm_sharedmem_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct uio_info *info = NULL;
+	struct resource *clnt_res = NULL;
+
+	/* Get the addresses from platform-data */
+	if (!pdev->dev.of_node) {
+		pr_err("Node not found\n");
+		ret = -ENODEV;
+		goto out;
+	}
+	clnt_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!clnt_res) {
+		pr_err("resource not found\n");
+		return -ENODEV;
+	}
+
+	info = devm_kzalloc(&pdev->dev, sizeof(struct uio_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->name = clnt_res->name;
+	info->version = "1.0";
+	info->mem[0].addr = clnt_res->start;
+	info->mem[0].size = resource_size(clnt_res);
+	info->mem[0].memtype = UIO_MEM_PHYS;
+
+	/* Setup device */
+	ret = uio_register_device(&pdev->dev, info);
+	if (ret)
+		goto out;
+
+	dev_set_drvdata(&pdev->dev, info);
+	pr_debug("Device created for client '%s'\n", clnt_res->name);
+out:
+	return ret;
+}
+
+static int msm_sharedmem_remove(struct platform_device *pdev)
+{
+	struct uio_info *info = dev_get_drvdata(&pdev->dev);
+
+	uio_unregister_device(info);
+
+	return 0;
+}
+
+static struct of_device_id msm_sharedmem_of_match[] = {
+	{.compatible = "qcom,sharedmem-uio",},
+	{},
+};
+MODULE_DEVICE_TABLE(of, msm_sharedmem_of_match);
+
+static struct platform_driver msm_sharedmem_driver = {
+	.probe          = msm_sharedmem_probe,
+	.remove         = msm_sharedmem_remove,
+	.driver         = {
+		.name   = DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = msm_sharedmem_of_match,
+	},
+};
+
+module_platform_driver(msm_sharedmem_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 554cce8..97592c4 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -2288,8 +2288,12 @@
 		if (mdwc->otg_xceiv && !mdwc->ext_inuse &&
 		    (mdwc->ext_xceiv.otg_capability || !init)) {
 			mdwc->ext_xceiv.bsv = val->intval;
+			/*
+			 * set debouncing delay to 120msec. Otherwise battery
+			 * charging CDP complaince test fails if delay > 120ms.
+			 */
 			queue_delayed_work(system_nrt_wq,
-							&mdwc->resume_work, 20);
+							&mdwc->resume_work, 12);
 
 			if (!init)
 				init = true;
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 9599936..cacd635 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -93,6 +93,19 @@
 	return 0;
 }
 
+static void dwc3_otg_set_hsphy_auto_suspend(struct dwc3_otg *dotg, bool susp)
+{
+	struct dwc3 *dwc = dotg->dwc;
+	u32 reg;
+
+	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+	if (susp)
+		reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+	else
+		reg &= ~(DWC3_GUSB2PHYCFG_SUSPHY);
+	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+}
+
 /**
  * dwc3_otg_set_host_power - Enable port power control for host operation
  *
@@ -194,6 +207,7 @@
 		 * remove_hcd, But we may not use standard set_host method
 		 * anymore.
 		 */
+		dwc3_otg_set_hsphy_auto_suspend(dotg, true);
 		dwc3_otg_set_host_regs(dotg);
 		/*
 		 * FIXME If micro A cable is disconnected during system suspend,
@@ -242,6 +256,7 @@
 						ext_xceiv->ext_block_reset)
 			ext_xceiv->ext_block_reset(ext_xceiv, true);
 
+		dwc3_otg_set_hsphy_auto_suspend(dotg, false);
 		dwc3_otg_set_peripheral_regs(dotg);
 
 		/* re-init core and OTG registers as block reset clears these */
@@ -309,12 +324,14 @@
 						ext_xceiv->ext_block_reset)
 			ext_xceiv->ext_block_reset(ext_xceiv, false);
 
+		dwc3_otg_set_hsphy_auto_suspend(dotg, true);
 		dwc3_otg_set_peripheral_regs(dotg);
 		usb_gadget_vbus_connect(otg->gadget);
 	} else {
 		dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n",
 					__func__, otg->gadget->name);
 		usb_gadget_vbus_disconnect(otg->gadget);
+		dwc3_otg_set_hsphy_auto_suspend(dotg, false);
 	}
 
 	return 0;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 38c4b86..ad3a3a9 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2623,13 +2623,10 @@
 		}
 	}
 
-	/*
-	 * Notify suspend only to gadget driver, but not resume. Resume is
-	 * notified as part of wakeup event in dwc3_gadget_wakeup_interrupt().
-	 */
 	if (next == DWC3_LINK_STATE_U0) {
 		if (dwc->link_state == DWC3_LINK_STATE_U3) {
 			dbg_event(0xFF, "RESUME", 0);
+			dwc->gadget_driver->resume(&dwc->gadget);
 		}
 	} else if (next == DWC3_LINK_STATE_U3) {
 		dbg_event(0xFF, "SUSPEND", 0);
@@ -2920,7 +2917,11 @@
 
 		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
-		dwc3_gadget_usb2_phy_suspend(dwc, true);
+		/*
+		 * Clear autosuspend bit in dwc3 register for USB2. It will be
+		 * enabled before setting run/stop bit.
+		 */
+		dwc3_gadget_usb2_phy_suspend(dwc, false);
 		dwc3_gadget_usb3_phy_suspend(dwc, true);
 	}
 
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 6765078..c65ed25 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2181,6 +2181,22 @@
 	}
 }
 
+static inline void check_streaming_func(struct usb_gadget *gadget,
+		struct android_usb_platform_data *pdata,
+		char *name)
+{
+	int i;
+
+	for (i = 0; i < pdata->streaming_func_count; i++) {
+		if (!strcmp(name,
+			pdata->streaming_func[i])) {
+			pr_debug("set streaming_enabled to true\n");
+			gadget->streaming_enabled = true;
+			break;
+		}
+	}
+}
+
 static int android_enable_function(struct android_dev *dev,
 				   struct android_configuration *conf,
 				   char *name)
@@ -2188,6 +2204,9 @@
 	struct android_usb_function **functions = dev->functions;
 	struct android_usb_function *f;
 	struct android_usb_function_holder *f_holder;
+	struct android_usb_platform_data *pdata = dev->pdata;
+	struct usb_gadget *gadget = dev->cdev->gadget;
+
 	while ((f = *functions++)) {
 		if (!strcmp(name, f->name)) {
 			if (f->android_dev && f->android_dev != dev)
@@ -2205,6 +2224,13 @@
 				f_holder->f = f;
 				list_add_tail(&f_holder->enabled_list,
 					      &conf->enabled_functions);
+				pr_debug("func:%s is enabled.\n", f->name);
+				/*
+				 * compare enable function with streaming func
+				 * list and based on the same request streaming.
+				 */
+				check_streaming_func(gadget, pdata, f->name);
+
 				return 0;
 			}
 		}
@@ -2577,6 +2603,10 @@
 {
 	struct android_dev *dev = cdev_to_android_dev(c->cdev);
 
+	if (c->cdev->gadget->streaming_enabled) {
+		c->cdev->gadget->streaming_enabled = false;
+		pr_debug("setting streaming_enabled to false.\n");
+	}
 	android_unbind_enabled_functions(dev, c);
 }
 
@@ -2745,8 +2775,10 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&cdev->lock, flags);
-	dev->suspended = 1;
-	schedule_work(&dev->work);
+	if (!dev->suspended) {
+		dev->suspended = 1;
+		schedule_work(&dev->work);
+	}
 	spin_unlock_irqrestore(&cdev->lock, flags);
 
 	composite_suspend(gadget);
@@ -2759,8 +2791,10 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&cdev->lock, flags);
-	dev->suspended = 0;
-	schedule_work(&dev->work);
+	if (dev->suspended) {
+		dev->suspended = 0;
+		schedule_work(&dev->work);
+	}
 	spin_unlock_irqrestore(&cdev->lock, flags);
 
 	composite_resume(gadget);
@@ -2895,7 +2929,7 @@
 	struct android_usb_platform_data *pdata;
 	struct android_dev *android_dev;
 	struct resource *res;
-	int ret = 0;
+	int ret = 0, i, len = 0;
 
 	if (pdev->dev.of_node) {
 		dev_dbg(&pdev->dev, "device tree enabled\n");
@@ -2912,6 +2946,33 @@
 				"qcom,android-usb-cdrom");
 		pdata->internal_ums = of_property_read_bool(pdev->dev.of_node,
 				"qcom,android-usb-internal-ums");
+		len = of_property_count_strings(pdev->dev.of_node,
+				"qcom,streaming-func");
+		if (len > MAX_STREAMING_FUNCS) {
+			pr_err("Invalid number of functions used.\n");
+			return -EINVAL;
+		}
+
+		for (i = 0; i < len; i++) {
+			const char *name = NULL;
+
+			of_property_read_string_index(pdev->dev.of_node,
+				"qcom,streaming-func", i, &name);
+			if (!name)
+				continue;
+
+			if (sizeof(name) > FUNC_NAME_LEN) {
+				pr_err("Function name is bigger than allowed.\n");
+				continue;
+			}
+
+			strlcpy(pdata->streaming_func[i], name,
+				sizeof(pdata->streaming_func[i]));
+			pr_debug("name of streaming function:%s\n",
+				pdata->streaming_func[i]);
+		}
+
+		pdata->streaming_func_count = len;
 	} else {
 		pdata = pdev->dev.platform_data;
 	}
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index a9c073b..f1e4220 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -271,6 +271,10 @@
 				1 << (pdata->log2_itc-1);
 
 		is_l1_supported = pdata->l1_supported;
+		/* Set ahb2ahb bypass flag if it is requested. */
+		if (pdata->enable_ahb2ahb_bypass)
+			ci13xxx_msm_udc_driver.flags |=
+				CI13XXX_ENABLE_AHB2AHB_BYPASS;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 3f8d924..6a92684 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -70,10 +70,6 @@
 #include <mach/usb_trace.h>
 #include "ci13xxx_udc.h"
 
-/* Turns on streaming. overrides CI13XXX_DISABLE_STREAMING */
-static unsigned int streaming;
-module_param(streaming, uint, S_IRUGO | S_IWUSR);
-
 /******************************************************************************
  * DEFINE
  *****************************************************************************/
@@ -392,20 +388,32 @@
 static int hw_device_state(u32 dma)
 {
 	struct ci13xxx *udc = _udc;
+	struct usb_gadget *gadget = &udc->gadget;
 
 	if (dma) {
-		if (streaming || !(udc->udc_driver->flags &
-				CI13XXX_DISABLE_STREAMING))
+		if (gadget->streaming_enabled || !(udc->udc_driver->flags &
+				CI13XXX_DISABLE_STREAMING)) {
 			hw_cwrite(CAP_USBMODE, USBMODE_SDIS, 0);
-		else
+			pr_debug("%s(): streaming mode is enabled. USBMODE:%x\n",
+				__func__, hw_cread(CAP_USBMODE, ~0));
+		} else {
 			hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
-
+			pr_debug("%s(): streaming mode is disabled. USBMODE:%x\n",
+				__func__, hw_cread(CAP_USBMODE, ~0));
+		}
 		hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
 
 		if (udc->udc_driver->notify_event)
 			udc->udc_driver->notify_event(udc,
 				CI13XXX_CONTROLLER_CONNECT_EVENT);
 
+		/* Set BIT(31) to enable AHB2AHB Bypass functionality */
+		if (udc->udc_driver->flags & CI13XXX_ENABLE_AHB2AHB_BYPASS) {
+			hw_awrite(ABS_AHBMODE, AHB2AHB_BYPASS, AHB2AHB_BYPASS);
+			pr_debug("%s(): ByPass Mode is enabled. AHBMODE:%x\n",
+					__func__, hw_aread(ABS_AHBMODE, ~0));
+		}
+
 		/* interrupt, error, port change, reset, sleep/suspend */
 		hw_cwrite(CAP_USBINTR, ~0,
 			     USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
@@ -413,6 +421,12 @@
 	} else {
 		hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
 		hw_cwrite(CAP_USBINTR, ~0, 0);
+		/* Clear BIT(31) to disable AHB2AHB Bypass functionality */
+		if (udc->udc_driver->flags & CI13XXX_ENABLE_AHB2AHB_BYPASS) {
+			hw_awrite(ABS_AHBMODE, AHB2AHB_BYPASS, 0);
+			pr_debug("%s(): ByPass Mode is disabled. AHBMODE:%x\n",
+					__func__, hw_aread(ABS_AHBMODE, ~0));
+		}
 	}
 	return 0;
 }
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index f90ea86..47fe138 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -136,6 +136,7 @@
 #define CI13XXX_DISABLE_STREAMING	BIT(3)
 #define CI13XXX_ZERO_ITC		BIT(4)
 #define CI13XXX_IS_OTG			BIT(5)
+#define CI13XXX_ENABLE_AHB2AHB_BYPASS	BIT(6)
 
 #define CI13XXX_CONTROLLER_RESET_EVENT			0
 #define CI13XXX_CONTROLLER_CONNECT_EVENT		1
@@ -197,6 +198,9 @@
 /* TESTMODE */
 #define TESTMODE_FORCE        BIT(0)
 
+/* AHB_MODE */
+#define AHB2AHB_BYPASS	      BIT(31)
+
 /* USBCMD */
 #define USBCMD_RS             BIT(0)
 #define USBCMD_RST            BIT(1)
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index dcfa2bc..7e474f3 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -18,6 +18,7 @@
 #include <linux/usb/usb_qdss.h>
 #include <linux/usb/msm_hsusb.h>
 
+#include "gadget_chips.h"
 #include "f_qdss.h"
 #include "u_qdss.c"
 
@@ -395,7 +396,9 @@
 			goto fail;
 		}
 	}
-	dwc3_tx_fifo_resize_request(qdss->data, true);
+
+	if (gadget_is_dwc3(gadget))
+		dwc3_tx_fifo_resize_request(qdss->data, true);
 
 	return 0;
 fail:
@@ -408,12 +411,15 @@
 static void qdss_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct f_qdss  *qdss = func_to_qdss(f);
+	struct usb_gadget *gadget = c->cdev->gadget;
 
 	pr_debug("qdss_unbind\n");
 
-	dwc3_tx_fifo_resize_request(qdss->data, false);
+	if (gadget_is_dwc3(gadget))
+		dwc3_tx_fifo_resize_request(qdss->data, false);
+
 	clear_eps(f);
-	clear_desc(c->cdev->gadget, f);
+	clear_desc(gadget, f);
 }
 
 static void qdss_eps_disable(struct usb_function *f)
@@ -824,7 +830,8 @@
 	ch->app_conn = 0;
 	spin_unlock_irqrestore(&d_lock, flags);
 
-	msm_dwc3_restart_usb_session(gadget);
+	if (gadget_is_dwc3(gadget))
+		msm_dwc3_restart_usb_session(gadget);
 }
 EXPORT_SYMBOL(usb_qdss_close);
 
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 7903764..aee7b58 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -379,13 +379,35 @@
 					struct sk_buff *skb)
 {
 	struct sk_buff *skb2;
+	struct rndis_packet_msg_type *header = NULL;
+	struct f_rndis *rndis = func_to_rndis(&port->func);
 
-	skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
-	if (skb2)
-		rndis_add_hdr(skb2);
+	if (rndis->port.multi_pkt_xfer) {
+		if (port->header) {
+			header = port->header;
+			memset(header, 0, sizeof(*header));
+			header->MessageType = cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
+			header->MessageLength = cpu_to_le32(skb->len +
+							sizeof(*header));
+			header->DataOffset = cpu_to_le32(36);
+			header->DataLength = cpu_to_le32(skb->len);
+			pr_debug("MessageLength:%d DataLength:%d\n",
+						header->MessageLength,
+						header->DataLength);
+			return skb;
+		} else {
+			pr_err("RNDIS header is NULL.\n");
+			return NULL;
+		}
+	} else {
+		skb2 = skb_realloc_headroom(skb,
+				sizeof(struct rndis_packet_msg_type));
+		if (skb2)
+			rndis_add_hdr(skb2);
 
-	dev_kfree_skb_any(skb);
-	return skb2;
+		dev_kfree_skb_any(skb);
+		return skb2;
+	}
 }
 
 static void rndis_response_available(void *_rndis)
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 9e789c5..734619f 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -197,6 +197,7 @@
 }
 
 static void rx_complete(struct usb_ep *ep, struct usb_request *req);
+static void tx_complete(struct usb_ep *ep, struct usb_request *req);
 
 static int
 rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
@@ -256,7 +257,6 @@
 
 	req->buf = skb->data;
 	req->length = size;
-	req->complete = rx_complete;
 	req->context = skb;
 
 	retval = usb_ep_queue(out, req, gfp_flags);
@@ -349,6 +349,7 @@
 {
 	unsigned		i;
 	struct usb_request	*req;
+	bool			usb_in;
 
 	if (!n)
 		return -ENOMEM;
@@ -359,10 +360,22 @@
 		if (i-- == 0)
 			goto extra;
 	}
+
+	if (ep->desc->bEndpointAddress & USB_DIR_IN)
+		usb_in = true;
+	else
+		usb_in = false;
+
 	while (i--) {
 		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
 		if (!req)
 			return list_empty(list) ? -ENOMEM : 0;
+		/* update completion handler */
+		if (usb_in)
+			req->complete = tx_complete;
+		else
+			req->complete = rx_complete;
+
 		list_add(&req->list, list);
 	}
 	return 0;
@@ -479,7 +492,7 @@
 
 static void tx_complete(struct usb_ep *ep, struct usb_request *req)
 {
-	struct sk_buff	*skb = req->context;
+	struct sk_buff	*skb;
 	struct eth_dev	*dev;
 	struct net_device *net;
 	struct usb_request *new_req;
@@ -553,7 +566,6 @@
 				}
 
 				new_req->length = length;
-				new_req->complete = tx_complete;
 				retval = usb_ep_queue(in, new_req, GFP_ATOMIC);
 				switch (retval) {
 				default:
@@ -585,6 +597,7 @@
 			spin_unlock(&dev->req_lock);
 		}
 	} else {
+		skb = req->context;
 		spin_unlock(&dev->req_lock);
 		dev_kfree_skb_any(skb);
 	}
@@ -613,7 +626,7 @@
 	list_for_each(act, &dev->tx_reqs) {
 		req = container_of(act, struct usb_request, list);
 		if (!req->buf)
-			req->buf = kmalloc(dev->tx_req_bufsize,
+			req->buf = kzalloc(dev->tx_req_bufsize,
 						GFP_ATOMIC);
 			if (!req->buf)
 				goto free_buf;
@@ -626,6 +639,7 @@
 	list_for_each(act, &dev->tx_reqs) {
 		req = container_of(act, struct usb_request, list);
 		kfree(req->buf);
+		req->buf = NULL;
 	}
 	return -ENOMEM;
 }
@@ -710,28 +724,37 @@
 	 * or the hardware can't use skb buffers.
 	 * or there's not enough space for extra headers we need
 	 */
+	spin_lock_irqsave(&dev->lock, flags);
 	if (dev->wrap) {
-		unsigned long	flags;
-
-		spin_lock_irqsave(&dev->lock, flags);
 		if (dev->port_usb)
 			skb = dev->wrap(dev->port_usb, skb);
-		spin_unlock_irqrestore(&dev->lock, flags);
-		if (!skb)
+		if (!skb) {
+			spin_unlock_irqrestore(&dev->lock, flags);
 			goto drop;
+		}
 	}
 
-	spin_lock_irqsave(&dev->req_lock, flags);
-	dev->tx_skb_hold_count++;
-	spin_unlock_irqrestore(&dev->req_lock, flags);
-
 	if (multi_pkt_xfer) {
+
+		pr_debug("req->length:%d header_len:%u\n"
+				"skb->len:%d skb->data_len:%d\n",
+				req->length, dev->header_len,
+				skb->len, skb->data_len);
+		/* Add RNDIS Header */
+		memcpy(req->buf + req->length, dev->port_usb->header,
+						dev->header_len);
+		/* Increment req length by header size */
+		req->length += dev->header_len;
+		spin_unlock_irqrestore(&dev->lock, flags);
+		/* Copy received IP data from SKB */
 		memcpy(req->buf + req->length, skb->data, skb->len);
-		req->length = req->length + skb->len;
+		/* Increment req length by skb data length */
+		req->length += skb->len;
 		length = req->length;
 		dev_kfree_skb_any(skb);
 
 		spin_lock_irqsave(&dev->req_lock, flags);
+		dev->tx_skb_hold_count++;
 		if (dev->tx_skb_hold_count < dev->dl_max_pkts_per_xfer) {
 			if (dev->no_tx_req_used > TX_REQ_THRESHOLD) {
 				list_add(&req->list, &dev->tx_reqs);
@@ -741,19 +764,15 @@
 		}
 
 		dev->no_tx_req_used++;
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-
-		spin_lock_irqsave(&dev->lock, flags);
 		dev->tx_skb_hold_count = 0;
-		spin_unlock_irqrestore(&dev->lock, flags);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
 	} else {
+		spin_unlock_irqrestore(&dev->lock, flags);
 		length = skb->len;
 		req->buf = skb->data;
 		req->context = skb;
 	}
 
-	req->complete = tx_complete;
-
 	/* NCM requires no zlp if transfer is dwNtbInMaxSize */
 	if (dev->port_usb->is_fixed &&
 	    length == dev->port_usb->fixed_in_len &&
@@ -806,7 +825,7 @@
 		spin_lock_irqsave(&dev->req_lock, flags);
 		if (list_empty(&dev->tx_reqs))
 			netif_start_queue(net);
-		list_add(&req->list, &dev->tx_reqs);
+		list_add_tail(&req->list, &dev->tx_reqs);
 		spin_unlock_irqrestore(&dev->req_lock, flags);
 	}
 success:
@@ -1085,6 +1104,14 @@
 	if (!dev)
 		return ERR_PTR(-EINVAL);
 
+	link->header = kzalloc(sizeof(struct rndis_packet_msg_type),
+							GFP_ATOMIC);
+	if (!link->header) {
+		pr_err("RNDIS header memory allocation failed.\n");
+		result = -ENOMEM;
+		goto fail;
+	}
+
 	link->in_ep->driver_data = dev;
 	result = usb_ep_enable(link->in_ep);
 	if (result != 0) {
@@ -1105,6 +1132,7 @@
 		result = alloc_requests(dev, link, qlen(dev->gadget));
 
 	if (result == 0) {
+
 		dev->zlp = link->is_zlp_ok;
 		DBG(dev, "qlen %d\n", qlen(dev->gadget));
 
@@ -1139,10 +1167,15 @@
 fail1:
 		(void) usb_ep_disable(link->in_ep);
 	}
-fail0:
+
 	/* caller is responsible for cleanup on error */
-	if (result < 0)
+	if (result < 0) {
+fail0:
+		kfree(link->header);
+fail:
 		return ERR_PTR(result);
+	}
+
 	return dev->net;
 }
 
@@ -1184,11 +1217,16 @@
 		list_del(&req->list);
 
 		spin_unlock(&dev->req_lock);
-		if (link->multi_pkt_xfer)
+		if (link->multi_pkt_xfer) {
 			kfree(req->buf);
+			req->buf = NULL;
+		}
 		usb_ep_free_request(link->in_ep, req);
 		spin_lock(&dev->req_lock);
 	}
+	/* Free rndis header buffer memory */
+	kfree(link->header);
+	link->header = NULL;
 	spin_unlock(&dev->req_lock);
 	link->in_ep->driver_data = NULL;
 	link->in_ep->desc = NULL;
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 05984d8..2c5da77 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -66,6 +66,8 @@
 	/* called on network open/close */
 	void				(*open)(struct gether *);
 	void				(*close)(struct gether *);
+	struct rndis_packet_msg_type	*header;
+
 };
 
 #define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
diff --git a/drivers/usb/gadget/u_qdss.c b/drivers/usb/gadget/u_qdss.c
index e241e29..23d4d06 100644
--- a/drivers/usb/gadget/u_qdss.c
+++ b/drivers/usb/gadget/u_qdss.c
@@ -14,6 +14,7 @@
 #include <linux/device.h>
 #include <linux/usb/msm_hsusb.h>
 #include <mach/usb_bam.h>
+#include "gadget_chips.h"
 
 struct  usb_qdss_bam_connect_info {
 	u32 usb_bam_pipe_idx;
@@ -88,8 +89,11 @@
 			&bam_info.usb_bam_pipe_idx, &bam_info.peer_pipe_idx,
 			NULL, bam_info.data_fifo);
 
-		msm_data_fifo_config(data_ep, bam_info.data_fifo->phys_base,
-			bam_info.data_fifo->size, bam_info.usb_bam_pipe_idx);
+		if (gadget_is_dwc3(gadget))
+			msm_data_fifo_config(data_ep,
+					     bam_info.data_fifo->phys_base,
+					     bam_info.data_fifo->size,
+					     bam_info.usb_bam_pipe_idx);
 	} else {
 		kfree(bam_info.data_fifo);
 		res = usb_bam_disconnect_pipe(idx);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 276bbb0..45fbfa8 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -470,6 +470,20 @@
 	int ret;
 	struct msm_otg_platform_data *pdata = motg->pdata;
 
+	/*
+	 * AHB2AHB Bypass mode shouldn't be enable before doing
+	 * async clock reset. If it is enable, disable the same.
+	 */
+	val = readl_relaxed(USB_AHBMODE);
+	if (val & AHB2AHB_BYPASS) {
+		pr_err("%s(): AHB2AHB_BYPASS SET: AHBMODE:%x\n",
+				__func__, val);
+		val &= ~AHB2AHB_BYPASS_BIT_MASK;
+		writel_relaxed(val | AHB2AHB_BYPASS_CLEAR, USB_AHBMODE);
+		pr_err("%s(): AHBMODE: %x\n", __func__,
+				readl_relaxed(USB_AHBMODE));
+	}
+
 	ret = msm_otg_link_clk_reset(motg, 1);
 	if (ret)
 		return ret;
@@ -1275,7 +1289,8 @@
 	else if (motg->chg_type == USB_CDP_CHARGER)
 		charger_type = POWER_SUPPLY_TYPE_USB_CDP;
 	else if (motg->chg_type == USB_DCP_CHARGER ||
-			motg->chg_type == USB_PROPRIETARY_CHARGER)
+			motg->chg_type == USB_PROPRIETARY_CHARGER ||
+			motg->chg_type == USB_FLOATED_CHARGER)
 		charger_type = POWER_SUPPLY_TYPE_USB_DCP;
 	else if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
 		motg->chg_type == USB_ACA_A_CHARGER ||
@@ -3834,6 +3849,8 @@
 		ci_pdata.log2_itc = otg_pdata->log2_itc;
 		ci_pdata.usb_core_id = 0;
 		ci_pdata.l1_supported = otg_pdata->l1_supported;
+		ci_pdata.enable_ahb2ahb_bypass =
+				otg_pdata->enable_ahb2ahb_bypass;
 		retval = platform_device_add_data(pdev, &ci_pdata,
 			sizeof(ci_pdata));
 		if (retval)
@@ -4164,6 +4181,8 @@
 
 	pdata->l1_supported = of_property_read_bool(node,
 				"qcom,hsusb-l1-supported");
+	pdata->enable_ahb2ahb_bypass = of_property_read_bool(node,
+				"qcom,ahb-async-bridge-bypass");
 
 	return pdata;
 }
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index 5c3960d..31e93a5 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -166,6 +166,9 @@
 	int tooff = 0, fromoff = 0;
 	int size;
 
+	if (!to || !from)
+		return -EINVAL;
+
 	if (to->start > from->start)
 		fromoff = to->start - from->start;
 	else
@@ -177,9 +180,12 @@
 		return -EINVAL;
 	size *= sizeof(u16);
 
-	memcpy(to->red+tooff, from->red+fromoff, size);
-	memcpy(to->green+tooff, from->green+fromoff, size);
-	memcpy(to->blue+tooff, from->blue+fromoff, size);
+	if (from->red && to->red)
+		memcpy(to->red+tooff, from->red+fromoff, size);
+	if (from->green && to->green)
+		memcpy(to->green+tooff, from->green+fromoff, size);
+	if (from->blue && to->blue)
+		memcpy(to->blue+tooff, from->blue+fromoff, size);
 	if (from->transp && to->transp)
 		memcpy(to->transp+tooff, from->transp+fromoff, size);
 	return 0;
@@ -190,6 +196,9 @@
 	int tooff = 0, fromoff = 0;
 	int size;
 
+	if (!to || !from)
+		return -EINVAL;
+
 	if (to->start > from->start)
 		fromoff = to->start - from->start;
 	else
@@ -201,12 +210,15 @@
 		return -EINVAL;
 	size *= sizeof(u16);
 
-	if (copy_to_user(to->red+tooff, from->red+fromoff, size))
-		return -EFAULT;
-	if (copy_to_user(to->green+tooff, from->green+fromoff, size))
-		return -EFAULT;
-	if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
-		return -EFAULT;
+	if (from->red && to->red)
+		if (copy_to_user(to->red+tooff, from->red+fromoff, size))
+			return -EFAULT;
+	if (from->green && to->green)
+		if (copy_to_user(to->green+tooff, from->green+fromoff, size))
+			return -EFAULT;
+	if (from->blue && to->blue)
+		if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
+			return -EFAULT;
 	if (from->transp && to->transp)
 		if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
 			return -EFAULT;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index d6a664a..6b84107 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1113,6 +1113,10 @@
 		if (copy_from_user(&cmap, argp, sizeof(cmap)))
 			return -EFAULT;
 		ret = fb_set_user_cmap(&cmap, info);
+		if (ret) {
+			if (info)
+				fb_dealloc_cmap(&info->cmap);
+		}
 		break;
 	case FBIOGETCMAP:
 		if (copy_from_user(&cmap, argp, sizeof(cmap)))
diff --git a/drivers/video/msm/mdss/Kconfig b/drivers/video/msm/mdss/Kconfig
index 7682a49..b49e08e 100644
--- a/drivers/video/msm/mdss/Kconfig
+++ b/drivers/video/msm/mdss/Kconfig
@@ -20,3 +20,11 @@
 	  Support the HDMI to MHL conversion.
 	  MHL (Mobile High-Definition Link) technology
 	  uses USB connector to output HDMI content
+
+config FB_MSM_MDSS_DSI_CTRL_STATUS
+	tristate "DSI controller status check feature"
+	---help---
+	  Check DSI controller status periodically (default period is 5
+	  seconds) by sending Bus-Turn-Around (BTA) command. If DSI controller
+	  fails to acknowledge the BTA command, it sends PANEL_ALIVE=0 status
+	  to HAL layer to reset the controller.
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index ba14d67..8f5fa26 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -41,3 +41,5 @@
 obj-$(CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL) += qpic_panel_ili_qvga.o
 
 obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
+
+obj-$(CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS) += mdss_dsi_status.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index e416a55..452e63a 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -77,7 +77,7 @@
 
 	if (status) {
 		MIPI_OUTP(ctrl_base + DSI_ACK_ERR_STATUS, status);
-		pr_debug("%s: status=%x\n", __func__, status);
+		pr_err("%s: status=%x\n", __func__, status);
 	}
 }
 
@@ -88,7 +88,7 @@
 	status = MIPI_INP(ctrl_base + DSI_TIMEOUT_STATUS);
 	if (status & 0x0111) {
 		MIPI_OUTP(ctrl_base + DSI_TIMEOUT_STATUS, status);
-		pr_debug("%s: status=%x\n", __func__, status);
+		pr_err("%s: status=%x\n", __func__, status);
 	}
 }
 
@@ -100,7 +100,7 @@
 
 	if (status & 0x011111) {
 		MIPI_OUTP(ctrl_base + DSI_DLN0_PHY_ERR, status);
-		pr_debug("%s: status=%x\n", __func__, status);
+		pr_err("%s: status=%x\n", __func__, status);
 	}
 }
 
@@ -112,7 +112,7 @@
 
 	if (status & 0x44444489) {
 		MIPI_OUTP(ctrl_base + DSI_FIFO_STATUS, status);
-		pr_debug("%s: status=%x\n", __func__, status);
+		pr_err("%s: status=%x\n", __func__, status);
 	}
 }
 
@@ -124,7 +124,7 @@
 
 	if (status & 0x80000000) {
 		MIPI_OUTP(ctrl_base + DSI_STATUS, status);
-		pr_debug("%s: status=%x\n", __func__, status);
+		pr_err("%s: status=%x\n", __func__, status);
 	}
 }
 
@@ -1070,6 +1070,27 @@
 	return dsi_pan_node;
 }
 
+static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable)
+{
+	u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
+
+	pr_debug("%s:\n", __func__);
+
+	if (enable) {
+		msm_dsi_ahb_ctrl(1);
+		msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
+					&byteclk_rate, &pclk_rate);
+		msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
+					byteclk_rate, pclk_rate);
+		msm_dsi_clk_enable();
+	} else {
+		msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
+		msm_dsi_clk_disable();
+		msm_dsi_ahb_ctrl(0);
+	}
+	return 0;
+}
+
 static int __devinit msm_dsi_probe(struct platform_device *pdev)
 {
 	struct dsi_interface intf;
@@ -1188,6 +1209,7 @@
 	intf.on = msm_dsi_on;
 	intf.off = msm_dsi_off;
 	intf.cont_on = msm_dsi_cont_on;
+	intf.clk_ctrl = msm_dsi_clk_ctrl;
 	intf.op_mode_config = msm_dsi_op_mode_config;
 	intf.tx = msm_dsi_cmds_tx;
 	intf.rx = msm_dsi_cmds_rx;
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 65cca0e..f3d0ad4 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -104,6 +104,18 @@
 	return rc;
 }
 
+static int dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable)
+{
+	int rc = 0;
+
+	pr_debug("%s:\n", __func__);
+
+	if (dsi_intf.clk_ctrl)
+		rc = dsi_intf.clk_ctrl(pdata, enable);
+
+	return rc;
+}
+
 static int dsi_event_handler(struct mdss_panel_data *pdata,
 				int event, void *arg)
 {
@@ -130,6 +142,9 @@
 	case MDSS_EVENT_CONT_SPLASH_BEGIN:
 		rc = dsi_splash_on(pdata);
 		break;
+	case MDSS_EVENT_PANEL_CLK_CTRL:
+		rc = dsi_clk_ctrl(pdata, (int)arg);
+		break;
 	default:
 		pr_debug("%s: unhandled event=%d\n", __func__, event);
 		break;
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index e15f640..cb007e3 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -27,6 +27,7 @@
 	int (*on)(struct mdss_panel_data *pdata);
 	int (*off)(struct mdss_panel_data *pdata);
 	int (*cont_on)(struct mdss_panel_data *pdata);
+	int (*clk_ctrl)(struct mdss_panel_data *pdata, int enable);
 	void (*op_mode_config)(int mode, struct mdss_panel_data *pdata);
 	int (*tx)(struct mdss_panel_data *pdata,
 		struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt);
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 638fcb3..e4ae7ea 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -184,11 +184,11 @@
 	u32 mdp_interrupt = 0;
 
 	spin_lock(&mdata->irq_lock);
-	if (!mdata->irq_mask) {
+	if (!mdata->irq_mask)
 		pr_err("spurious interrupt\n");
-		spin_unlock(&mdata->irq_lock);
-		return IRQ_HANDLED;
-	}
+
+	clk_enable(mdp3_res->clocks[MDP3_CLK_AHB]);
+	clk_enable(mdp3_res->clocks[MDP3_CLK_CORE]);
 
 	mdp_interrupt = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
 	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_interrupt);
@@ -202,6 +202,10 @@
 		mdp_interrupt = mdp_interrupt >> 1;
 		i++;
 	}
+
+	clk_disable(mdp3_res->clocks[MDP3_CLK_AHB]);
+	clk_disable(mdp3_res->clocks[MDP3_CLK_CORE]);
+
 	spin_unlock(&mdata->irq_lock);
 
 	return IRQ_HANDLED;
@@ -281,8 +285,6 @@
 	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
 	memset(mdp3_res->irq_ref_count, 0, sizeof(u32) * MDP3_MAX_INTR);
 	mdp3_res->irq_mask = 0;
-	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0);
-	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, 0xfffffff);
 	disable_irq_nosync(mdp3_res->irq);
 	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
 }
@@ -415,10 +417,10 @@
 	count = mdp3_res->clock_ref_count[clk_idx];
 	if (count == 1 && enable) {
 		pr_debug("clk=%d en=%d\n", clk_idx, enable);
-		ret = clk_prepare_enable(clk);
+		ret = clk_enable(clk);
 	} else if (count == 0) {
 		pr_debug("clk=%d disable\n", clk_idx);
-		clk_disable_unprepare(clk);
+		clk_disable(clk);
 		ret = 0;
 	} else if (count < 0) {
 		pr_err("clk=%d count=%d\n", clk_idx, count);
@@ -554,7 +556,7 @@
 		clk_put(mdp3_res->clocks[MDP3_CLK_DSI]);
 }
 
-int mdp3_clk_enable(int enable)
+int mdp3_clk_enable(int enable, int dsi_clk)
 {
 	int rc;
 
@@ -564,11 +566,62 @@
 	rc = mdp3_clk_update(MDP3_CLK_AHB, enable);
 	rc |= mdp3_clk_update(MDP3_CLK_CORE, enable);
 	rc |= mdp3_clk_update(MDP3_CLK_VSYNC, enable);
-	rc |= mdp3_clk_update(MDP3_CLK_DSI, enable);
+	if (dsi_clk)
+		rc |= mdp3_clk_update(MDP3_CLK_DSI, enable);
 	mutex_unlock(&mdp3_res->res_mutex);
 	return rc;
 }
 
+int mdp3_clk_prepare(void)
+{
+	int rc = 0;
+
+	mutex_lock(&mdp3_res->res_mutex);
+	mdp3_res->clk_prepare_count++;
+	if (mdp3_res->clk_prepare_count == 1) {
+		rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_AHB]);
+		if (rc < 0)
+			goto error0;
+		rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_CORE]);
+		if (rc < 0)
+			goto error1;
+		rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_VSYNC]);
+		if (rc < 0)
+			goto error2;
+		rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_DSI]);
+		if (rc < 0)
+			goto error3;
+	}
+	mutex_unlock(&mdp3_res->res_mutex);
+	return rc;
+
+error3:
+	clk_unprepare(mdp3_res->clocks[MDP3_CLK_VSYNC]);
+error2:
+	clk_unprepare(mdp3_res->clocks[MDP3_CLK_CORE]);
+error1:
+	clk_unprepare(mdp3_res->clocks[MDP3_CLK_AHB]);
+error0:
+	mdp3_res->clk_prepare_count--;
+	mutex_unlock(&mdp3_res->res_mutex);
+	return rc;
+}
+
+void mdp3_clk_unprepare(void)
+{
+	mutex_lock(&mdp3_res->res_mutex);
+	mdp3_res->clk_prepare_count--;
+	if (mdp3_res->clk_prepare_count == 0) {
+		clk_unprepare(mdp3_res->clocks[MDP3_CLK_AHB]);
+		clk_unprepare(mdp3_res->clocks[MDP3_CLK_CORE]);
+		clk_unprepare(mdp3_res->clocks[MDP3_CLK_VSYNC]);
+		clk_unprepare(mdp3_res->clocks[MDP3_CLK_DSI]);
+	} else if (mdp3_res->clk_prepare_count < 0) {
+		pr_err("mdp3 clk unprepare mismatch\n");
+	}
+	mutex_unlock(&mdp3_res->res_mutex);
+}
+
 static int mdp3_irq_setup(void)
 {
 	int ret;
@@ -1512,8 +1565,17 @@
 static int mdp3_init(struct msm_fb_data_type *mfd)
 {
 	int rc;
+
 	rc = mdp3_ctrl_init(mfd);
-	rc |= mdp3_ppp_res_init(mfd);
+	if (rc) {
+		pr_err("mdp3 ctl init fail\n");
+		return rc;
+	}
+
+	rc = mdp3_ppp_res_init(mfd);
+	if (rc)
+		pr_err("mdp3 ppp res init fail\n");
+
 	return rc;
 }
 
@@ -1671,6 +1733,11 @@
 	return mdp3_res->domains[MDP3_DMA_IOMMU_DOMAIN].domain_idx;
 }
 
+int mdp3_get_cont_spash_en(void)
+{
+	return mdp3_res->cont_splash_en;
+}
+
 int mdp3_continuous_splash_copy(struct mdss_panel_data *pdata)
 {
 	unsigned long splash_phys, phys;
@@ -1726,7 +1793,7 @@
 		rc = (status == 0x080000);
 	}
 
-	mdp3_res->splash_mem_addr = MDP3_REG_READ(MDP3_REG_DMA_S_IBUF_ADDR);
+	mdp3_res->splash_mem_addr = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_ADDR);
 
 	mdp3_clk_update(MDP3_CLK_AHB, 0);
 	mdp3_clk_update(MDP3_CLK_CORE, 0);
@@ -1740,9 +1807,19 @@
 
 	pr_debug("mdp3__continuous_splash_on\n");
 
-	rc = mdp3_clk_enable(1);
+	mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE,
+			MDP3_CLIENT_DMA_P);
+
+	rc = mdp3_clk_prepare();
+	if (rc) {
+		pr_err("fail to prepare clk\n");
+		return rc;
+	}
+
+	rc = mdp3_clk_enable(1, 1);
 	if (rc) {
 		pr_err("fail to enable clk\n");
+		mdp3_clk_unprepare();
 		return rc;
 	}
 
@@ -1776,11 +1853,15 @@
 		mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_VIDEO].active = 1;
 	else
 		mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_CMD].active = 1;
+
+	mdp3_res->cont_splash_en = 1;
 	return 0;
 
 splash_on_err:
-	if (mdp3_clk_enable(0))
+	if (mdp3_clk_enable(0, 1))
 		pr_err("%s: Unable to disable mdp3 clocks\n", __func__);
+
+	mdp3_clk_unprepare();
 	return rc;
 }
 
@@ -1813,10 +1894,13 @@
 
 static void mdp3_debug_enable_clock(int on)
 {
-	if (on)
-		mdp3_clk_enable(1);
-	else
-		mdp3_clk_enable(0);
+	if (on) {
+		mdp3_clk_prepare();
+		mdp3_clk_enable(1, 0);
+	} else {
+		mdp3_clk_enable(0, 0);
+		mdp3_clk_unprepare();
+	}
 }
 
 static int mdp3_debug_init(struct platform_device *pdev)
@@ -1859,6 +1943,52 @@
 			mdp3_res->underrun_cnt);
 }
 
+static ssize_t mdp3_show_capabilities(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	size_t len = PAGE_SIZE;
+	int cnt = 0;
+
+#define SPRINT(fmt, ...) \
+		(cnt += scnprintf(buf + cnt, len - cnt, fmt, ##__VA_ARGS__))
+
+	SPRINT("mdp_version=3\n");
+	SPRINT("hw_rev=%d\n", 304);
+	SPRINT("dma_pipes=%d\n", 1);
+	SPRINT("\n");
+
+	return cnt;
+}
+
+static DEVICE_ATTR(caps, S_IRUGO, mdp3_show_capabilities, NULL);
+
+static struct attribute *mdp3_fs_attrs[] = {
+	&dev_attr_caps.attr,
+	NULL
+};
+
+static struct attribute_group mdp3_fs_attr_group = {
+	.attrs = mdp3_fs_attrs
+};
+
+static int mdp3_register_sysfs(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int rc;
+
+	rc = sysfs_create_group(&dev->kobj, &mdp3_fs_attr_group);
+
+	return rc;
+}
+
+int mdp3_create_sysfs_link(struct device *dev)
+{
+	int rc;
+	rc = sysfs_create_link_nowarn(&dev->kobj,
+			&mdp3_res->pdev->dev.kobj, "mdp");
+
+	return rc;
+}
 
 static int mdp3_probe(struct platform_device *pdev)
 {
@@ -1918,6 +2048,10 @@
 		goto probe_done;
 	}
 
+	rc = mdp3_register_sysfs(pdev);
+	if (rc)
+		pr_err("unable to register mdp sysfs nodes\n");
+
 	rc = mdss_fb_register_mdp_instance(&mdp3_interface);
 	if (rc)
 		pr_err("unable to register mdp instance\n");
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 4480c20..c0d630e 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -25,6 +25,8 @@
 #include "mdp3_dma.h"
 #include "mdss_fb.h"
 
+#define MDP_VSYNC_CLK_RATE	19200000
+
 enum  {
 	MDP3_CLK_AHB,
 	MDP3_CLK_CORE,
@@ -152,6 +154,9 @@
 	struct mdss_panel_cfg pan_cfg;
 	u32 splash_mem_addr;
 	u32 splash_mem_size;
+
+	int clk_prepare_count;
+	int cont_splash_en;
 };
 
 struct mdp3_img_data {
@@ -175,7 +180,9 @@
 void mdp3_irq_register(void);
 void mdp3_irq_deregister(void);
 int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client);
-int mdp3_clk_enable(int enable);
+int mdp3_clk_enable(int enable, int dsi_clk);
+int mdp3_clk_prepare(void);
+void mdp3_clk_unprepare(void);
 int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
 int mdp3_put_img(struct mdp3_img_data *data, int client);
 int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data,
@@ -186,6 +193,8 @@
 void mdp3_free(void);
 int mdp3_parse_dt_splash(struct msm_fb_data_type *mfd);
 void mdp3_release_splash_memory(void);
+int mdp3_create_sysfs_link(struct device *dev);
+int mdp3_get_cont_spash_en(void);
 
 #define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
 #define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index e92e178..14107c5 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -26,12 +26,15 @@
 #include "mdp3_ppp.h"
 
 #define MDP_CORE_CLK_RATE	100000000
-#define MDP_VSYNC_CLK_RATE	19200000
+#define VSYNC_EXPIRE_TICK	4
 
 static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd);
 static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx);
 static int mdp3_histogram_stop(struct mdp3_session_data *session,
 					u32 block);
+static int mdp3_ctrl_clk_enable(struct msm_fb_data_type *mfd, int enable);
+static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable);
+static int mdp3_ctrl_get_intf_type(struct msm_fb_data_type *mfd);
 
 static void mdp3_bufq_init(struct mdp3_buffer_queue *bufq)
 {
@@ -88,6 +91,29 @@
 	return bufq->count;
 }
 
+static void mdp3_dispatch_clk_off(struct work_struct *work)
+{
+	struct mdp3_session_data *session;
+
+	pr_debug("%s\n", __func__);
+	session = container_of(work, struct mdp3_session_data,
+				clk_off_work);
+	if (!session)
+		return;
+
+	mutex_lock(&session->lock);
+	if (session->vsync_enabled ||
+			atomic_read(&session->vsync_countdown) != 0) {
+		mutex_unlock(&session->lock);
+		pr_debug("Ignoring clk shut down\n");
+		return;
+	}
+
+	mdp3_ctrl_vsync_enable(session->mfd, 0);
+	mdp3_ctrl_clk_enable(session->mfd, 0);
+	mutex_unlock(&session->lock);
+}
+
 void vsync_notify_handler(void *arg)
 {
 	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
@@ -95,6 +121,22 @@
 	sysfs_notify_dirent(session->vsync_event_sd);
 }
 
+void vsync_count_down(void *arg)
+{
+	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
+	/* We are counting down to turn off clocks */
+	atomic_dec(&session->vsync_countdown);
+	if (atomic_read(&session->vsync_countdown) == 0)
+		schedule_work(&session->clk_off_work);
+}
+
+void mdp3_ctrl_reset_countdown(struct mdp3_session_data *session,
+		struct msm_fb_data_type *mfd)
+{
+	if (mdp3_ctrl_get_intf_type(mfd) == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+		atomic_set(&session->vsync_countdown, VSYNC_EXPIRE_TICK);
+}
+
 static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
 {
 	struct mdp3_session_data *mdp3_session;
@@ -115,17 +157,37 @@
 		vsync_client.handler = vsync_notify_handler;
 		vsync_client.arg = mdp3_session;
 		arg = &vsync_client;
+	} else if (atomic_read(&mdp3_session->vsync_countdown)) {
+		/*
+		 * Now that vsync is no longer needed we will
+		 * shutdown dsi clocks as soon as cnt down == 0
+		 * for cmd mode panels
+		 */
+		vsync_client.handler = vsync_count_down;
+		vsync_client.arg = mdp3_session;
+		arg = &vsync_client;
+		enable = 1;
 	}
 
-	mutex_lock(&mdp3_session->lock);
+	mdp3_clk_enable(1, 0);
 	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
-	if (enable && mdp3_session->status == 1 && !mdp3_session->intf->active)
+	mdp3_clk_enable(0, 0);
+
+	/*
+	 * Need to fake vsync whenever dsi interface is not
+	 * active or when dsi clocks are currently off
+	 */
+	if (enable && mdp3_session->status == 1
+			&& !mdp3_session->intf->active) {
 		mod_timer(&mdp3_session->vsync_timer,
 			jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
-	 else if (!enable)
+	} else if (enable && !mdp3_session->clk_on) {
+		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
+		mdp3_ctrl_clk_enable(mfd, 1);
+	} else if (!enable) {
 		del_timer(&mdp3_session->vsync_timer);
+	}
 
-	mutex_unlock(&mdp3_session->lock);
 	return 0;
 }
 
@@ -209,6 +271,33 @@
 	.attrs = vsync_fs_attrs,
 };
 
+static int mdp3_ctrl_clk_enable(struct msm_fb_data_type *mfd, int enable)
+{
+	struct mdp3_session_data *session;
+	struct mdss_panel_data *panel;
+	int rc = 0;
+
+	pr_debug("mdp3_ctrl_clk_enable %d\n", enable);
+
+	session = mfd->mdp.private1;
+	panel = session->panel;
+
+	if (!panel->event_handler)
+		return 0;
+
+	if ((enable && session->clk_on == 0) ||
+				(!enable && session->clk_on == 1)) {
+		rc = panel->event_handler(panel,
+			MDSS_EVENT_PANEL_CLK_CTRL, (void *)enable);
+		rc |= mdp3_clk_enable(enable, 1);
+	} else {
+		pr_debug("enable = %d, clk_on=%d\n", enable, session->clk_on);
+	}
+
+	session->clk_on = enable;
+	return rc;
+}
+
 static int mdp3_ctrl_res_req_bus(struct msm_fb_data_type *mfd, int status)
 {
 	int rc = 0;
@@ -236,12 +325,24 @@
 		mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE,
 				MDP3_CLIENT_DMA_P);
 
-		rc = mdp3_clk_enable(true);
-		if (rc)
+		rc = mdp3_clk_prepare();
+		if (rc) {
+			pr_err("mdp3 clk prepare fail\n");
 			return rc;
+		}
 
+		rc = mdp3_clk_enable(1, 1);
+		if (rc) {
+			pr_err("mdp3 clk enable fail\n");
+			mdp3_clk_unprepare();
+			return rc;
+		}
 	} else {
-		rc = mdp3_clk_enable(false);
+		rc = mdp3_clk_enable(0, 1);
+		if (rc)
+			pr_err("mdp3 clk disable fail\n");
+		else
+			mdp3_clk_unprepare();
 	}
 	return rc;
 }
@@ -473,6 +574,7 @@
 		goto on_error;
 	}
 
+	mdp3_session->clk_on = 1;
 	pr_debug("mdp3_ctrl_on dma start\n");
 	if (mfd->fbi->screen_base) {
 		rc = mdp3_session->dma->start(mdp3_session->dma,
@@ -509,36 +611,44 @@
 	panel = mdp3_session->panel;
 	mutex_lock(&mdp3_session->lock);
 
+	if (panel && panel->set_backlight)
+		panel->set_backlight(panel, 0);
+
 	if (!mdp3_session->status) {
 		pr_debug("fb%d is off already", mfd->index);
 		goto off_error;
 	}
 
+	mdp3_ctrl_clk_enable(mfd, 1);
+
 	mdp3_histogram_stop(mdp3_session, MDP_BLOCK_DMA_P);
 
 	rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
 	if (rc)
 		pr_debug("fail to stop the MDP3 dma\n");
 
+
 	if (panel->event_handler)
 		rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
 	if (rc)
 		pr_err("fail to turn off the panel\n");
 
-
-
 	mdp3_irq_deregister();
 
 	pr_debug("mdp3_ctrl_off stop clock\n");
-	rc = mdp3_ctrl_res_req_clk(mfd, 0);
-	if (rc)
-		pr_err("mdp clock resource release failed\n");
+	if (mdp3_session->clk_on) {
+		rc = mdp3_clk_enable(0, 1);
+		if (rc)
+			pr_err("mdp clock resource release failed\n");
 
-	pr_debug("mdp3_ctrl_off stop dsi controller\n");
-	if (panel->event_handler)
-		rc = panel->event_handler(panel, MDSS_EVENT_BLANK, NULL);
-	if (rc)
-		pr_err("fail to turn off the panel\n");
+		pr_debug("mdp3_ctrl_off stop dsi controller\n");
+		if (panel->event_handler)
+			rc = panel->event_handler(panel,
+				MDSS_EVENT_BLANK, NULL);
+		if (rc)
+			pr_err("fail to turn off the panel\n");
+	}
+	mdp3_clk_unprepare();
 
 	pr_debug("mdp3_ctrl_off release bus\n");
 	rc = mdp3_ctrl_res_req_bus(mfd, 0);
@@ -549,6 +659,9 @@
 	if (rc)
 		pr_err("fail to dettach MDP DMA SMMU\n");
 
+	mdp3_session->vsync_enabled = 0;
+	atomic_set(&mdp3_session->vsync_countdown, 0);
+	mdp3_session->clk_on = 0;
 off_error:
 	mdp3_session->status = 0;
 	mdp3_bufq_deinit(&mdp3_session->bufq_out);
@@ -842,6 +955,8 @@
 
 	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
 	if (data) {
+		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
+		mdp3_ctrl_clk_enable(mfd, 1);
 		mdp3_session->dma->update(mdp3_session->dma,
 			(void *)data->addr,
 			mdp3_session->intf);
@@ -910,12 +1025,16 @@
 	}
 
 	if (mfd->fbi->screen_base) {
+		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
+		mdp3_ctrl_clk_enable(mfd, 1);
 		mdp3_session->dma->update(mdp3_session->dma,
 				(void *)mfd->iova + offset,
 				mdp3_session->intf);
 	} else {
 		pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
+		mdp3_clk_enable(1, 0);
 		mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
+		mdp3_clk_enable(0, 0);
 	}
 
 	if (mdp3_session->first_commit) {
@@ -1031,10 +1150,11 @@
 
 	if (session->histo_status) {
 		pr_err("mdp3_histogram_start already started\n");
-		ret = -EBUSY;
-		goto histogram_start_err;
+		mutex_unlock(&session->histo_lock);
+		return -EBUSY;
 	}
 
+	mdp3_clk_enable(1, 0);
 	ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_RESET);
 	if (ret) {
 		pr_err("mdp3_histogram_start reset error\n");
@@ -1060,6 +1180,7 @@
 	session->histo_status = 1;
 
 histogram_start_err:
+	mdp3_clk_enable(0, 0);
 	mutex_unlock(&session->histo_lock);
 	return ret;
 }
@@ -1082,7 +1203,9 @@
 		goto histogram_stop_err;
 	}
 
+	mdp3_clk_enable(1, 0);
 	ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_CANCEL);
+	mdp3_clk_enable(0, 0);
 	if (ret)
 		pr_err("mdp3_histogram_stop error\n");
 
@@ -1099,11 +1222,17 @@
 	int ret;
 	struct mdp3_dma_histogram_data *mdp3_histo;
 
+	pr_debug("%s\n", __func__);
 	if (!session->dma->get_histo) {
 		pr_err("mdp3_histogram_collect not supported\n");
 		return -EINVAL;
 	}
 
+	if (!session->clk_on) {
+		pr_debug("mdp/dsi clock off currently\n");
+		return -EPERM;
+	}
+
 	mutex_lock(&session->histo_lock);
 
 	if (!session->histo_status) {
@@ -1114,7 +1243,9 @@
 
 	mutex_unlock(&session->histo_lock);
 
+	mdp3_clk_enable(1, 0);
 	ret = session->dma->get_histo(session->dma);
+	mdp3_clk_enable(0, 0);
 	if (ret) {
 		pr_debug("mdp3_histogram_collect error = %d\n", ret);
 		return ret;
@@ -1196,7 +1327,9 @@
 	ccs.post_lv = data->csc_data.csc_post_lv;
 
 	mutex_lock(&session->lock);
+	mdp3_clk_enable(1, 0);
 	ret = session->dma->config_ccs(session->dma, &config, &ccs);
+	mdp3_clk_enable(0, 0);
 	mutex_unlock(&session->lock);
 	return ret;
 }
@@ -1338,8 +1471,10 @@
 		return -EPERM;
 	}
 
+	mdp3_clk_enable(1, 0);
 	rc = mdp3_session->dma->config_lut(mdp3_session->dma, &lut_config,
 					&lut);
+	mdp3_clk_enable(0, 0);
 	if (rc)
 		pr_err("mdp3_ctrl_lut_update failed\n");
 
@@ -1355,7 +1490,7 @@
 	int rc = -EINVAL;
 	struct mdp3_session_data *mdp3_session;
 	struct msmfb_metadata metadata;
-	struct mdp_overlay req;
+	struct mdp_overlay *req = NULL;
 	struct msmfb_overlay_data ov_data;
 	int val;
 
@@ -1363,6 +1498,8 @@
 	if (!mdp3_session)
 		return -ENODEV;
 
+	req = &mdp3_session->req_overlay;
+
 	if (!mdp3_session->status && cmd != MSMFB_METADATA_GET) {
 		pr_err("mdp3_ctrl_ioctl_handler, display off!\n");
 		return -EPERM;
@@ -1381,7 +1518,10 @@
 	case MSMFB_VSYNC_CTRL:
 	case MSMFB_OVERLAY_VSYNC_CTRL:
 		if (!copy_from_user(&val, argp, sizeof(val))) {
+			mutex_lock(&mdp3_session->lock);
+			mdp3_session->vsync_enabled = val;
 			rc = mdp3_ctrl_vsync_enable(mfd, val);
+			mutex_unlock(&mdp3_session->lock);
 		} else {
 			pr_err("MSMFB_OVERLAY_VSYNC_CTRL failed\n");
 			rc = -EFAULT;
@@ -1402,23 +1542,23 @@
 			rc = copy_to_user(argp, &metadata, sizeof(metadata));
 		break;
 	case MSMFB_OVERLAY_GET:
-		rc = copy_from_user(&req, argp, sizeof(req));
+		rc = copy_from_user(req, argp, sizeof(*req));
 		if (!rc) {
-			rc = mdp3_overlay_get(mfd, &req);
+			rc = mdp3_overlay_get(mfd, req);
 
 		if (!IS_ERR_VALUE(rc))
-			rc = copy_to_user(argp, &req, sizeof(req));
+			rc = copy_to_user(argp, req, sizeof(*req));
 		}
 		if (rc)
 			pr_err("OVERLAY_GET failed (%d)\n", rc);
 		break;
 	case MSMFB_OVERLAY_SET:
-		rc = copy_from_user(&req, argp, sizeof(req));
+		rc = copy_from_user(req, argp, sizeof(*req));
 		if (!rc) {
-			rc = mdp3_overlay_set(mfd, &req);
+			rc = mdp3_overlay_set(mfd, req);
 
 		if (!IS_ERR_VALUE(rc))
-			rc = copy_to_user(argp, &req, sizeof(req));
+			rc = copy_to_user(argp, req, sizeof(*req));
 		}
 		if (rc)
 			pr_err("OVERLAY_SET failed (%d)\n", rc);
@@ -1470,6 +1610,8 @@
 	}
 	memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
 	mutex_init(&mdp3_session->lock);
+	INIT_WORK(&mdp3_session->clk_off_work, mdp3_dispatch_clk_off);
+	atomic_set(&mdp3_session->vsync_countdown, 0);
 	mutex_init(&mdp3_session->histo_lock);
 	mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
 	if (!mdp3_session->dma) {
@@ -1525,6 +1667,10 @@
 		goto init_done;
 	}
 
+	rc = mdp3_create_sysfs_link(dev);
+	if (rc)
+		pr_warn("problem creating link to mdp sysfs\n");
+
 	kobject_uevent(&dev->kobj, KOBJ_ADD);
 	pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
 
@@ -1533,6 +1679,9 @@
 		mdp3_ctrl_off(mfd);
 	}
 
+	if (mdp3_get_cont_spash_en())
+		mdp3_session->clk_on = 1;
+
 init_done:
 	if (IS_ERR_VALUE(rc))
 		kfree(mdp3_session);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 7c4f6ac..8d7627e 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -45,13 +45,19 @@
 	int vsync_period;
 	struct sysfs_dirent *vsync_event_sd;
 	struct mdp_overlay overlay;
+	struct mdp_overlay req_overlay;
 	struct mdp3_buffer_queue bufq_in;
 	struct mdp3_buffer_queue bufq_out;
+	struct work_struct clk_off_work;
 	int histo_status;
 	struct mutex histo_lock;
 	int lut_sel;
 	int cc_vect_sel;
 	bool first_commit;
+	int clk_on;
+
+	int vsync_enabled;
+	atomic_t vsync_countdown; /* Used to count down  */
 };
 
 int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 89f3e27..3a2c94b 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -828,6 +828,9 @@
 					MDP3_DMA_CALLBACK_TYPE_DMA_DONE);
 	mdp3_irq_disable(MDP3_INTR_LCDC_UNDERFLOW);
 
+	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0);
+	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, 0xfffffff);
+
 	init_completion(&dma->dma_comp);
 	dma->vsync_client.handler = NULL;
 	return ret;
diff --git a/drivers/video/msm/mdss/mdp3_hwio.h b/drivers/video/msm/mdss/mdp3_hwio.h
index 90ee357..8846ec5 100644
--- a/drivers/video/msm/mdss/mdp3_hwio.h
+++ b/drivers/video/msm/mdss/mdp3_hwio.h
@@ -221,6 +221,9 @@
 #define MDP3_PPP_BG_UNPACK_PATTERN1	0x101D8
 #define MDP3_PPP_BG_UNPACK_PATTERN2	0x101DC
 
+#define MDP3_TFETCH_SOLID_FILL		0x20004
+#define MDP3_TFETCH_FILL_COLOR		0x20040
+
 #define MDP3_PPP_BLEND_PARAM		0x1014C
 
 #define MDP3_PPP_BLEND_BG_ALPHA_SEL	0x70010
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index d16cb3f..6187db4 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -36,6 +36,8 @@
 #define MDP_PPP_MAX_BPP 4
 #define MDP_PPP_DYNAMIC_FACTOR 3
 #define MDP_PPP_MAX_READ_WRITE 3
+#define ENABLE_SOLID_FILL	0x2
+#define DISABLE_SOLID_FILL	0x0
 
 static const bool valid_fmt[MDP_IMGTYPE_LIMIT] = {
 	[MDP_RGB_565] = true,
@@ -370,14 +372,14 @@
 		ib = (ab * 3) / 2;
 	}
 	mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
-	rc = mdp3_clk_enable(on_off);
+	rc = mdp3_clk_enable(on_off, 0);
 	if (rc < 0) {
 		pr_err("%s: mdp3_clk_enable failed\n", __func__);
 		return rc;
 	}
 	rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
 	if (rc < 0) {
-		mdp3_clk_enable(!on_off);
+		mdp3_clk_enable(!on_off, 0);
 		pr_err("%s: scale_set_quota failed\n", __func__);
 		return rc;
 	}
@@ -390,6 +392,23 @@
 	/* Wait for the pipe to clear */
 	do { } while (mdp3_ppp_pipe_wait() <= 0);
 	config_ppp_op_mode(blit_op);
+	if (blit_op->solid_fill) {
+		MDP3_REG_WRITE(0x10138, 0x10000000);
+		MDP3_REG_WRITE(0x1014c, 0xffffffff);
+		MDP3_REG_WRITE(0x101b8, 0);
+		MDP3_REG_WRITE(0x101bc, 0);
+		MDP3_REG_WRITE(0x1013c, 0);
+		MDP3_REG_WRITE(0x10140, 0);
+		MDP3_REG_WRITE(0x10144, 0);
+		MDP3_REG_WRITE(0x10148, 0);
+		MDP3_REG_WRITE(MDP3_TFETCH_FILL_COLOR,
+					blit_op->solid_fill_color);
+		MDP3_REG_WRITE(MDP3_TFETCH_SOLID_FILL,
+					ENABLE_SOLID_FILL);
+	} else {
+		MDP3_REG_WRITE(MDP3_TFETCH_SOLID_FILL,
+					DISABLE_SOLID_FILL);
+	}
 	mdp3_ppp_kickoff();
 }
 
@@ -489,6 +508,26 @@
 
 	if (req->flags & MDP_BLUR)
 		blit_op->mdp_op |= MDPOP_ASCALE | MDPOP_BLUR;
+
+	if (req->flags & MDP_SOLID_FILL) {
+		blit_op->solid_fill = true;
+
+		/* Avoid odd width, as it could hang ppp during solid fill */
+		blit_op->dst.roi.width = (blit_op->dst.roi.width / 2) * 2;
+		blit_op->src.roi.width = (blit_op->src.roi.width / 2) * 2;
+
+		/* Avoid RGBA format, as it could hang ppp during solid fill */
+		if (blit_op->src.color_fmt == MDP_RGBA_8888)
+			blit_op->src.color_fmt = MDP_RGBX_8888;
+		if (blit_op->dst.color_fmt == MDP_RGBA_8888)
+			blit_op->dst.color_fmt = MDP_RGBX_8888;
+		blit_op->solid_fill_color = (req->const_color.g & 0xFF)|
+				(req->const_color.b & 0xFF) << 8 |
+				(req->const_color.r & 0xFF)  << 16 |
+				(req->const_color.alpha & 0xFF) << 24;
+	} else {
+		blit_op->solid_fill = false;
+	}
 }
 
 static void mdp3_ppp_tile_workaround(struct ppp_blit_op *blit_op,
@@ -791,9 +830,10 @@
 	}
 	is_bpp_4 = (ret == 4) ? 1 : 0;
 
-	if ((is_bpp_4 && (remainder == 6 || remainder == 14)))
+	if ((is_bpp_4 && (remainder == 6 || remainder == 14)) &&
+						!(req->flags & MDP_SOLID_FILL))
 		ret = mdp3_ppp_blit_workaround(mfd, req, remainder,
-				src_data, dst_data);
+							src_data, dst_data);
 	else
 		ret = mdp3_ppp_blit(mfd, req, src_data, dst_data);
 	return ret;
diff --git a/drivers/video/msm/mdss/mdp3_ppp.h b/drivers/video/msm/mdss/mdp3_ppp.h
index b4252ca..9753e94 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.h
+++ b/drivers/video/msm/mdss/mdp3_ppp.h
@@ -332,6 +332,8 @@
 	struct ppp_img_desc bg;
 	struct ppp_blend blend;
 	uint32_t mdp_op; /* Operations */
+	uint32_t solid_fill_color;
+	bool solid_fill;
 };
 
 struct ppp_edge_rep {
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 927cfa9..bb1f8ae 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -1305,6 +1305,7 @@
 	}
 
 	ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
+	ctrl_pdata->check_status = mdss_dsi_bta_status_check;
 
 	if (ctrl_pdata->bklt_ctrl == BL_PWM)
 		mdss_dsi_panel_pwm_cfg(ctrl_pdata);
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 13dad06..7202c62 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -118,6 +118,8 @@
 
 #define DSI_INTR_ERROR_MASK		BIT(25)
 #define DSI_INTR_ERROR			BIT(24)
+#define DSI_INTR_BTA_DONE_MASK          BIT(21)
+#define DSI_INTR_BTA_DONE               BIT(20)
 #define DSI_INTR_VIDEO_DONE_MASK	BIT(17)
 #define DSI_INTR_VIDEO_DONE		BIT(16)
 #define DSI_INTR_CMD_MDP_DONE_MASK	BIT(9)
@@ -133,6 +135,7 @@
 
 #define DSI_VIDEO_TERM  BIT(16)
 #define DSI_MDP_TERM    BIT(8)
+#define DSI_BTA_TERM    BIT(1)
 #define DSI_CMD_TERM    BIT(0)
 
 extern struct device dsi_dev;
@@ -315,6 +318,7 @@
 	int (*on) (struct mdss_panel_data *pdata);
 	int (*off) (struct mdss_panel_data *pdata);
 	int (*partial_update_fnc) (struct mdss_panel_data *pdata);
+	int (*check_status) (struct mdss_dsi_ctrl_pdata *pdata);
 	struct mdss_panel_data panel_data;
 	unsigned char *ctrl_base;
 	int reg_size;
@@ -360,6 +364,7 @@
 	struct completion dma_comp;
 	struct completion mdp_comp;
 	struct completion video_comp;
+	struct completion bta_comp;
 	spinlock_t irq_lock;
 	spinlock_t mdp_lock;
 	int mdp_busy;
@@ -428,6 +433,7 @@
 				struct dcs_cmd_req *cmdreq);
 struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_cmdlist_kickoff(int intf);
+int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl);
 
 int mdss_dsi_panel_init(struct device_node *node,
 		struct mdss_dsi_ctrl_pdata *ctrl_pdata,
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index bb2818b..750fbf3 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -49,6 +49,8 @@
 
 #define DSI_EVENT_Q_MAX	4
 
+#define DSI_BTA_EVENT_TIMEOUT (HZ / 10)
+
 /* event */
 struct dsi_event_q {
 	struct mdss_dsi_ctrl_pdata *ctrl;
@@ -98,6 +100,7 @@
 	init_completion(&ctrl->dma_comp);
 	init_completion(&ctrl->mdp_comp);
 	init_completion(&ctrl->video_comp);
+	init_completion(&ctrl->bta_comp);
 	spin_lock_init(&ctrl->irq_lock);
 	spin_lock_init(&ctrl->mdp_lock);
 	mutex_init(&ctrl->mutex);
@@ -1107,14 +1110,14 @@
 
 	if (mode == DSI_VIDEO_MODE) {
 		dsi_ctrl |= 0x03;
-		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
+		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_BTA_DONE_MASK;
 	} else {		/* command mode */
 		dsi_ctrl |= 0x05;
 		if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
 			dsi_ctrl |= 0x02;
 
 		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
-				DSI_INTR_CMD_MDP_DONE_MASK;
+			DSI_INTR_CMD_MDP_DONE_MASK | DSI_INTR_BTA_DONE_MASK;
 	}
 
 	if (ctrl_pdata->shared_pdata.broadcast_enable)
@@ -1160,6 +1163,45 @@
 	pr_debug("%s: BTA done, status = %d\n", __func__, status);
 }
 
+int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+	int ret = 0;
+	unsigned long flag;
+
+	if (ctrl_pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+
+		/*
+		 * This should not return error otherwise
+		 * BTA status thread will treat it as dead panel scenario
+		 * and request for blank/unblank
+		 */
+		return 0;
+	}
+
+	pr_debug("%s: Checking BTA status\n", __func__);
+
+	mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+	spin_lock_irqsave(&ctrl_pdata->mdp_lock, flag);
+	INIT_COMPLETION(ctrl_pdata->bta_comp);
+	mdss_dsi_enable_irq(ctrl_pdata, DSI_BTA_TERM);
+	spin_unlock_irqrestore(&ctrl_pdata->mdp_lock, flag);
+	MIPI_OUTP(ctrl_pdata->ctrl_base + 0x098, 0x01); /* trigger  */
+	wmb();
+
+	ret = wait_for_completion_killable_timeout(&ctrl_pdata->bta_comp,
+						DSI_BTA_EVENT_TIMEOUT);
+	if (ret <= 0) {
+		mdss_dsi_disable_irq(ctrl_pdata, DSI_BTA_TERM);
+		pr_err("%s: DSI BTA error: %i\n", __func__, ret);
+	}
+
+	mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+	pr_debug("%s: BTA done with ret: %d\n", __func__, ret);
+
+	return ret;
+}
+
 static char set_tear_on[2] = {0x35, 0x00};
 static struct dsi_cmd_desc dsi_tear_on_cmd = {
 	{DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on)}, set_tear_on};
@@ -2078,5 +2120,12 @@
 		spin_unlock(&ctrl->mdp_lock);
 	}
 
+	if (isr & DSI_INTR_BTA_DONE) {
+		spin_lock(&ctrl->mdp_lock);
+		mdss_dsi_disable_irq_nosync(ctrl, DSI_BTA_TERM);
+		complete(&ctrl->bta_comp);
+		spin_unlock(&ctrl->mdp_lock);
+	}
+
 	return IRQ_HANDLED;
 }
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 9932186..03dbd4d 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -293,6 +293,15 @@
 	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
 				panel_data);
 
+	/*
+	 * Some backlight controllers specify a minimum duty cycle
+	 * for the backlight brightness. If the brightness is less
+	 * than it, the controller can malfunction.
+	 */
+
+	if ((bl_level < pdata->panel_info.bl_min) && (bl_level != 0))
+		bl_level = pdata->panel_info.bl_min;
+
 	switch (ctrl_pdata->bklt_ctrl) {
 	case BL_WLED:
 		led_trigger_event(bl_led_trigger, bl_level);
@@ -389,7 +398,7 @@
 		if (dchdr->dlen > len) {
 			pr_err("%s: dtsi cmd=%x error, len=%d",
 				__func__, dchdr->dtype, dchdr->dlen);
-			return -ENOMEM;
+			goto exit_free;
 		}
 		bp += sizeof(*dchdr);
 		len -= sizeof(*dchdr);
@@ -401,14 +410,13 @@
 	if (len != 0) {
 		pr_err("%s: dcs_cmd=%x len=%d error!",
 				__func__, buf[0], blen);
-		kfree(buf);
-		return -ENOMEM;
+		goto exit_free;
 	}
 
 	pcmds->cmds = kzalloc(cnt * sizeof(struct dsi_cmd_desc),
 						GFP_KERNEL);
 	if (!pcmds->cmds)
-		return -ENOMEM;
+		goto exit_free;
 
 	pcmds->cmd_cnt = cnt;
 	pcmds->buf = buf;
@@ -436,6 +444,10 @@
 		pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt, pcmds->link_state);
 
 	return 0;
+
+exit_free:
+	kfree(buf);
+	return -ENOMEM;
 }
 
 
diff --git a/drivers/video/msm/mdss/mdss_dsi_status.c b/drivers/video/msm/mdss/mdss_dsi_status.c
new file mode 100644
index 0000000..f0c4f4c
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_status.c
@@ -0,0 +1,208 @@
+/* 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/notifier.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/iopoll.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+
+#include "mdss_fb.h"
+#include "mdss_dsi.h"
+#include "mdss_panel.h"
+#include "mdss_mdp.h"
+
+#define STATUS_CHECK_INTERVAL 5000
+
+struct dsi_status_data {
+	struct notifier_block fb_notifier;
+	struct delayed_work check_status;
+	struct msm_fb_data_type *mfd;
+	uint32_t check_interval;
+};
+struct dsi_status_data *pstatus_data;
+static uint32_t interval = STATUS_CHECK_INTERVAL;
+
+/*
+ * check_dsi_ctrl_status() - Check DSI controller status periodically.
+ * @work  : dsi controller status data
+ *
+ * This function calls check_status API on DSI controller to send the BTA
+ * command. If DSI controller fails to acknowledge the BTA command, it sends
+ * the PANEL_ALIVE=0 status to HAL layer.
+ */
+static void check_dsi_ctrl_status(struct work_struct *work)
+{
+	struct dsi_status_data *pdsi_status = NULL;
+	struct mdss_panel_data *pdata = NULL;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	struct mdss_overlay_private *mdp5_data = NULL;
+	struct mdss_mdp_ctl *ctl = NULL;
+	int ret = 0;
+
+	pdsi_status = container_of(to_delayed_work(work),
+		struct dsi_status_data, check_status);
+	if (!pdsi_status) {
+		pr_err("%s: DSI status data not available\n", __func__);
+		return;
+	}
+
+	pdata = dev_get_platdata(&pdsi_status->mfd->pdev->dev);
+	if (!pdata) {
+		pr_err("%s: Panel data not available\n", __func__);
+		return;
+	}
+
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+							panel_data);
+	if (!ctrl_pdata || !ctrl_pdata->check_status) {
+		pr_err("%s: DSI ctrl or status_check callback not available\n",
+								__func__);
+		return;
+	}
+
+	mdp5_data = mfd_to_mdp5_data(pdsi_status->mfd);
+	ctl = mfd_to_ctl(pdsi_status->mfd);
+
+	if (ctl->shared_lock)
+		mutex_lock(ctl->shared_lock);
+	mutex_lock(&mdp5_data->ov_lock);
+
+	/*
+	 * For the command mode panels, we return pan display
+	 * IOCTL on vsync interrupt. So, after vsync interrupt comes
+	 * and when DMA_P is in progress, if the panel stops responding
+	 * and if we trigger BTA before DMA_P finishes, then the DSI
+	 * FIFO will not be cleared since the DSI data bus control
+	 * doesn't come back to the host after BTA. This may cause the
+	 * display reset not to be proper. Hence, wait for DMA_P done
+	 * for command mode panels before triggering BTA.
+	 */
+	if (ctl->wait_pingpong)
+		ctl->wait_pingpong(ctl, NULL);
+
+	pr_debug("%s: DSI ctrl wait for ping pong done\n", __func__);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	ret = ctrl_pdata->check_status(ctrl_pdata);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	mutex_unlock(&mdp5_data->ov_lock);
+	if (ctl->shared_lock)
+		mutex_unlock(ctl->shared_lock);
+
+	if ((pdsi_status->mfd->panel_power_on)) {
+		if (ret > 0) {
+			schedule_delayed_work(&pdsi_status->check_status,
+				msecs_to_jiffies(pdsi_status->check_interval));
+		} else {
+			char *envp[2] = {"PANEL_ALIVE=0", NULL};
+			pdata->panel_info.panel_dead = true;
+			ret = kobject_uevent_env(
+				&pdsi_status->mfd->fbi->dev->kobj,
+							KOBJ_CHANGE, envp);
+			pr_err("%s: Panel has gone bad, sending uevent - %s\n",
+							__func__, envp[0]);
+		}
+	}
+}
+
+/*
+ * fb_event_callback() - Call back function for the fb_register_client()
+ *			 notifying events
+ * @self  : notifier block
+ * @event : The event that was triggered
+ * @data  : Of type struct fb_event
+ *
+ * This function listens for FB_BLANK_UNBLANK and FB_BLANK_POWERDOWN events
+ * from frame buffer. DSI status check work is either scheduled again after
+ * PANEL_STATUS_CHECK_INTERVAL or cancelled based on the event.
+ */
+static int fb_event_callback(struct notifier_block *self,
+				unsigned long event, void *data)
+{
+	struct fb_event *evdata = data;
+	struct dsi_status_data *pdata = container_of(self,
+				struct dsi_status_data, fb_notifier);
+	pdata->mfd = evdata->info->par;
+
+	if (event == FB_EVENT_BLANK && evdata) {
+		int *blank = evdata->data;
+		switch (*blank) {
+		case FB_BLANK_UNBLANK:
+			schedule_delayed_work(&pdata->check_status,
+				msecs_to_jiffies(pdata->check_interval));
+			break;
+		case FB_BLANK_POWERDOWN:
+			cancel_delayed_work(&pdata->check_status);
+			break;
+		}
+	}
+	return 0;
+}
+
+int __init mdss_dsi_status_init(void)
+{
+	int rc = 0;
+
+	pstatus_data = kzalloc(sizeof(struct dsi_status_data), GFP_KERNEL);
+	if (!pstatus_data) {
+		pr_err("%s: can't allocate memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	pstatus_data->fb_notifier.notifier_call = fb_event_callback;
+
+	rc = fb_register_client(&pstatus_data->fb_notifier);
+	if (rc < 0) {
+		pr_err("%s: fb_register_client failed, returned with rc=%d\n",
+								__func__, rc);
+		kfree(pstatus_data);
+		return -EPERM;
+	}
+
+	pstatus_data->check_interval = interval;
+	pr_info("%s: DSI status check interval:%d\n", __func__,	interval);
+
+	INIT_DELAYED_WORK(&pstatus_data->check_status, check_dsi_ctrl_status);
+
+	pr_debug("%s: DSI ctrl status work queue initialized\n", __func__);
+
+	return rc;
+}
+
+void __exit mdss_dsi_status_exit(void)
+{
+	fb_unregister_client(&pstatus_data->fb_notifier);
+	cancel_delayed_work_sync(&pstatus_data->check_status);
+	kfree(pstatus_data);
+	pr_debug("%s: DSI ctrl status work queue removed\n", __func__);
+}
+
+module_param(interval, uint, 0);
+MODULE_PARM_DESC(interval,
+		"Duration in milliseconds to send BTA command for checking"
+		"DSI status periodically");
+
+module_init(mdss_dsi_status_init);
+module_exit(mdss_dsi_status_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 971351b..81473db 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -98,8 +98,10 @@
 void mdss_fb_no_update_notify_timer_cb(unsigned long data)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
-	if (!mfd)
+	if (!mfd) {
 		pr_err("%s mfd NULL\n", __func__);
+		return;
+	}
 	mfd->no_update.value = NOTIFY_TYPE_NO_UPDATE;
 	complete(&mfd->no_update.comp);
 }
@@ -107,9 +109,10 @@
 static int mdss_fb_notify_update(struct msm_fb_data_type *mfd,
 							unsigned long *argp)
 {
-	int ret, notify, to_user;
+	int ret;
+	unsigned long notify = 0x0, to_user = 0x0;
 
-	ret = copy_from_user(&notify, argp, sizeof(int));
+	ret = copy_from_user(&notify, argp, sizeof(unsigned long));
 	if (ret) {
 		pr_err("%s:ioctl failed\n", __func__);
 		return ret;
@@ -122,12 +125,12 @@
 		INIT_COMPLETION(mfd->update.comp);
 		ret = wait_for_completion_interruptible_timeout(
 						&mfd->update.comp, 4 * HZ);
-		to_user = mfd->update.value;
+		to_user = (unsigned int)mfd->update.value;
 	} else if (notify == NOTIFY_UPDATE_STOP) {
 		INIT_COMPLETION(mfd->no_update.comp);
 		ret = wait_for_completion_interruptible_timeout(
 						&mfd->no_update.comp, 4 * HZ);
-		to_user = mfd->no_update.value;
+		to_user = (unsigned int)mfd->no_update.value;
 	} else {
 		if (mfd->panel_power_on) {
 			INIT_COMPLETION(mfd->power_off_comp);
@@ -139,7 +142,7 @@
 	if (ret == 0)
 		ret = -ETIMEDOUT;
 	else if (ret > 0)
-		ret = copy_to_user(argp, &to_user, sizeof(int));
+		ret = copy_to_user(argp, &to_user, sizeof(unsigned long));
 	return ret;
 }
 
@@ -705,8 +708,10 @@
 	case FB_BLANK_UNBLANK:
 		if (!mfd->panel_power_on && mfd->mdp.on_fnc) {
 			ret = mfd->mdp.on_fnc(mfd);
-			if (ret == 0)
+			if (ret == 0) {
 				mfd->panel_power_on = true;
+				mfd->panel_info->panel_dead = false;
+			}
 			mutex_lock(&mfd->update.lock);
 			mfd->update.type = NOTIFY_TYPE_UPDATE;
 			mutex_unlock(&mfd->update.lock);
@@ -1410,7 +1415,7 @@
 	u32 wait_for_finish = disp_commit->wait_for_finish;
 	int ret = 0;
 
-	if ((!mfd->op_enable) || (!mfd->panel_power_on))
+	if (!mfd || (!mfd->op_enable) || (!mfd->panel_power_on))
 		return -EPERM;
 
 	if (var->xoffset > (info->var.xres_virtual - info->var.xres))
@@ -1969,7 +1974,8 @@
 		return -EINVAL;
 	mfd = (struct msm_fb_data_type *)info->par;
 	mdss_fb_power_setting_idle(mfd);
-	if ((cmd != MSMFB_VSYNC_CTRL) && (cmd != MSMFB_OVERLAY_VSYNC_CTRL))
+	if ((cmd != MSMFB_VSYNC_CTRL) && (cmd != MSMFB_OVERLAY_VSYNC_CTRL) &&
+			(cmd != MSMFB_ASYNC_BLIT) && (cmd != MSMFB_BLIT))
 		mdss_fb_pan_idle(mfd);
 
 	switch (cmd) {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index cf0c287..5174cab 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -16,6 +16,13 @@
 #include "mdss_hdmi_edid.h"
 
 #define DBC_START_OFFSET 4
+
+/*
+ * As per CEA-861-E specification 7.5.2, there can be
+ * upto 31 bytes following any tag (data block type).
+ */
+#define MAX_DATA_BLOCK_SIZE 31
+
 #define HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd) \
 	(!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
 
@@ -32,6 +39,19 @@
 /* Support for first 5 EDID blocks */
 #define MAX_EDID_BLOCK_SIZE (0x80 * 5)
 
+#define BUFF_SIZE_3D 128
+
+enum data_block_types {
+	RESERVED,
+	AUDIO_DATA_BLOCK,
+	VIDEO_DATA_BLOCK,
+	VENDOR_SPECIFIC_DATA_BLOCK,
+	SPEAKER_ALLOCATION_DATA_BLOCK,
+	VESA_DTC_DATA_BLOCK,
+	RESERVED2,
+	USE_EXTENDED_TAG
+};
+
 struct hdmi_edid_sink_data {
 	u32 disp_mode_list[HDMI_VFRMT_MAX];
 	u32 disp_3d_mode_list[HDMI_VFRMT_MAX];
@@ -524,7 +544,8 @@
 	}
 
 	/* A Tage code of 7 identifies extended data blocks */
-	etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+	etag = hdmi_edid_find_block(in_buf, start_offset, USE_EXTENDED_TAG,
+		&len);
 
 	while (etag != NULL) {
 		/* The extended data block should at least be 2 bytes long */
@@ -570,7 +591,8 @@
 
 		/* There could be more that one extended data block */
 		start_offset = etag - in_buf + len + 1;
-		etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+		etag = hdmi_edid_find_block(in_buf, start_offset,
+			USE_EXTENDED_TAG, &len);
 	}
 } /* hdmi_edid_extract_extended_data_blocks */
 
@@ -585,11 +607,12 @@
 		return;
 	}
 
-	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
+	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+		VENDOR_SPECIFIC_DATA_BLOCK, &len);
 
 	edid_ctrl->present_3d = 0;
-	if (vsd == NULL || len < 9) {
-		DEV_DBG("%s: blk-id 3 not found or not long enough\n",
+	if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
+		DEV_DBG("%s: No/Invalid vendor Specific Data Block\n",
 			__func__);
 		return;
 	}
@@ -616,9 +639,13 @@
 		return;
 	}
 
-	adb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 1, &len);
-	if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE))
+	adb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, AUDIO_DATA_BLOCK,
+		&len);
+	if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE)) {
+		DEV_DBG("%s: No/Invalid Audio Data Block\n",
+			__func__);
 		return;
+	}
 
 	memcpy(edid_ctrl->audio_data_block, adb + 1, len);
 	edid_ctrl->adb_size = len;
@@ -644,9 +671,13 @@
 		return;
 	}
 
-	sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 4, &len);
-	if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE))
+	sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+		SPEAKER_ALLOCATION_DATA_BLOCK, &len);
+	if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) {
+		DEV_DBG("%s: No/Invalid Speaker Allocation Data Block\n",
+			__func__);
 		return;
+	}
 
 	memcpy(edid_ctrl->spkr_alloc_data_block, sadb + 1, len);
 	edid_ctrl->sadb_size = len;
@@ -673,9 +704,11 @@
 		return;
 	}
 
-	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
+	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+		VENDOR_SPECIFIC_DATA_BLOCK, &len);
 
-	if (vsd == NULL || len < 12 || !(vsd[8] & BIT(7))) {
+	if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE ||
+		!(vsd[8] & BIT(7))) {
 		edid_ctrl->video_latency = (u16)-1;
 		edid_ctrl->audio_latency = (u16)-1;
 		DEV_DBG("%s: EDID: No audio/video latency present\n", __func__);
@@ -699,9 +732,14 @@
 		return 0;
 	}
 
-	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
-	if (vsd == NULL || len < 8)
+	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+		VENDOR_SPECIFIC_DATA_BLOCK, &len);
+
+	if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
+		DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
+			__func__);
 		return 0;
+	}
 
 	DEV_DBG("%s: EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n", __func__,
 		((u32)vsd[4] << 8) + (u32)vsd[5], (u32)vsd[7] * 5);
@@ -898,11 +936,14 @@
 	u16 structure_all, structure_mask;
 	const u8 *vsd = num_of_cea_blocks ?
 		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
-				3, &len) : NULL;
+			VENDOR_SPECIFIC_DATA_BLOCK, &len) : NULL;
 	int i;
 
-	if (!vsd)
+	if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
+		DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
+			__func__);
 		return -ENXIO;
+	}
 
 	offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
 	if (offset >= len - 1)
@@ -1044,10 +1085,11 @@
 		return;
 	}
 
-	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &db_len);
+	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+		VENDOR_SPECIFIC_DATA_BLOCK, &db_len);
 
-	if (vsd == NULL || db_len < 9) {
-		DEV_DBG("%s: blk-id 3 not found or not long enough\n",
+	if (vsd == NULL || db_len == 0 || db_len > MAX_DATA_BLOCK_SIZE) {
+		DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
 			__func__);
 		return;
 	}
@@ -1097,8 +1139,14 @@
 	edid_blk0 = &data_buf[0x0];
 	edid_blk1 = &data_buf[0x80];
 	svd = num_of_cea_blocks ?
-		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, 2,
-			&len) : NULL;
+		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
+			VIDEO_DATA_BLOCK, &len) : NULL;
+
+	if (svd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
+		DEV_DBG("%s: No/Invalid Video Data Block\n",
+			__func__);
+		return;
+	}
 
 	sink_data = &edid_ctrl->sink_data;
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index 80b27ed..8ff9059 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -31,6 +31,8 @@
 #define HDCP_KEYS_STATE_PROD_AKSV	6
 #define HDCP_KEYS_STATE_RESERVED	7
 
+#define HDCP_INT_CLR (BIT(1) | BIT(5) | BIT(7) | BIT(9) | BIT(13))
+
 struct hdmi_hdcp_ctrl {
 	u32 auth_retries;
 	u32 tp_msgid;
@@ -289,6 +291,10 @@
 	}
 	DEV_DBG("%s: %s: BCAPS=%02x\n", __func__, HDCP_STATE_NAME, bcaps);
 
+	/* receiver (0), repeater (1) */
+	hdcp_ctrl->current_tp.ds_type =
+		(bcaps & BIT(6)) >> 6 ? DS_REPEATER : DS_RECEIVER;
+
 	/*
 	 * HDCP setup prior to enabling HDCP_CTRL.
 	 * Setup seed values for random number An.
@@ -644,40 +650,12 @@
 	memset(ksv_fifo, 0,
 		sizeof(hdcp_ctrl->current_tp.ksv_list));
 
-	/* Read BCAPS at offset 0x40 */
-	memset(&ddc_data, 0, sizeof(ddc_data));
-	ddc_data.dev_addr = 0x74;
-	ddc_data.offset = 0x40;
-	ddc_data.data_buf = &bcaps;
-	ddc_data.data_len = 1;
-	ddc_data.request_len = 1;
-	ddc_data.retry = 5;
-	ddc_data.what = "Bcaps";
-	ddc_data.no_align = false;
-	rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
-	if (rc) {
-		DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
-			HDCP_STATE_NAME);
-		goto error;
-	}
-	DEV_DBG("%s: %s: BCAPS=%02x (%s)\n", __func__, HDCP_STATE_NAME, bcaps,
-		(bcaps & BIT(6)) ? "repeater" : "no repeater");
-
-	/* receiver (0), repeater (1) */
-	hdcp_ctrl->current_tp.ds_type =
-		(bcaps & BIT(6)) >> 6 ? DS_REPEATER : DS_RECEIVER;
-
-	/* if REPEATER (Bit 6), perform Part2 Authentication */
-	if (!(bcaps & BIT(6))) {
-		DEV_INFO("%s: %s: auth part II skipped, no repeater\n",
-			__func__, HDCP_STATE_NAME);
-		return 0;
-	}
-
-	/* Wait until READY bit is set in BCAPS */
+	/*
+	 * Wait until READY bit is set in BCAPS, as per HDCP specifications
+	 * maximum permitted time to check for READY bit is five seconds.
+	 */
 	timeout_count = 50;
-	while (!(bcaps & BIT(5)) && timeout_count) {
-		msleep(100);
+	do {
 		timeout_count--;
 		/* Read BCAPS at offset 0x40 */
 		memset(&ddc_data, 0, sizeof(ddc_data));
@@ -695,7 +673,8 @@
 				HDCP_STATE_NAME);
 			goto error;
 		}
-	}
+		msleep(100);
+	} while (!(bcaps & BIT(5)) && timeout_count);
 
 	/* Read BSTATUS at offset 0x41 */
 	memset(&ddc_data, 0, sizeof(ddc_data));
@@ -976,11 +955,15 @@
 		goto error;
 	}
 
-	rc = hdmi_hdcp_authentication_part2(hdcp_ctrl);
-	if (rc) {
-		DEV_DBG("%s: %s: HDCP Auth Part II failed\n", __func__,
-			HDCP_STATE_NAME);
-		goto error;
+	if (hdcp_ctrl->current_tp.ds_type == DS_REPEATER) {
+		rc = hdmi_hdcp_authentication_part2(hdcp_ctrl);
+		if (rc) {
+			DEV_DBG("%s: %s: HDCP Auth Part II failed\n", __func__,
+				HDCP_STATE_NAME);
+			goto error;
+		}
+	} else {
+		DEV_INFO("%s: Downstream device is not a repeater\n", __func__);
 	}
 	/* Disabling software DDC before going into part3 to make sure
 	 * there is no Arbitration between software and hardware for DDC */
@@ -1158,16 +1141,15 @@
 	}
 
 	/*
-	 * Need to set the state to inactive here so that any ongoing
-	 * reauth works will know that the HDCP session has been turned off
+	 * Disable HDCP interrupts.
+	 * Also, need to set the state to inactive here so that any ongoing
+	 * reauth works will know that the HDCP session has been turned off.
 	 */
 	mutex_lock(hdcp_ctrl->init_data.mutex);
+	DSS_REG_W(io, HDMI_HDCP_INT_CTRL, 0);
 	hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE;
 	mutex_unlock(hdcp_ctrl->init_data.mutex);
 
-	/* Disable HDCP interrupts */
-	DSS_REG_W(io, HDMI_HDCP_INT_CTRL, 0);
-
 	/*
 	 * Cancel any pending auth/reauth attempts.
 	 * If one is ongoing, this will wait for it to finish.
@@ -1212,7 +1194,7 @@
 	if (HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) {
 		DEV_ERR("%s: HDCP inactive. Just clear int and return.\n",
 			__func__);
-		DSS_REG_W(io, HDMI_HDCP_INT_CTRL, hdcp_int_val);
+		DSS_REG_W(io, HDMI_HDCP_INT_CTRL, HDCP_INT_CLR);
 		return 0;
 	}
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index e46e361..87b7526 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -372,6 +372,7 @@
 static void hdmi_tx_wait_for_audio_engine(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	u32 status = 0;
+	u32 wait_for_vote = 50;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -385,6 +386,18 @@
 		return;
 	}
 
+	/*
+	 * wait for 5 sec max for audio engine to acknowledge if hdmi tx core
+	 * can be safely turned off. Sleep for a reasonable time to make sure
+	 * vote_hdmi_core_on variable is updated properly by audio.
+	 */
+	while (hdmi_ctrl->vote_hdmi_core_on && --wait_for_vote)
+		msleep(100);
+
+
+	if (!wait_for_vote)
+		DEV_ERR("%s: HDMI core still voted for power on\n", __func__);
+
 	if (readl_poll_timeout(io->base + HDMI_AUDIO_PKT_CTRL, status,
 				(status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US,
 				AUDIO_POLL_TIMEOUT_US))
@@ -2238,6 +2251,29 @@
 	return 0;
 }
 
+static int hdmi_tx_get_cable_status(struct platform_device *pdev, u32 vote)
+{
+	struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
+	unsigned long flags;
+	u32 hpd;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -ENODEV;
+	}
+
+	spin_lock_irqsave(&hdmi_ctrl->hpd_state_lock, flags);
+	hpd = hdmi_ctrl->hpd_state;
+	spin_unlock_irqrestore(&hdmi_ctrl->hpd_state_lock, flags);
+
+	hdmi_ctrl->vote_hdmi_core_on = false;
+
+	if (vote && hpd)
+		hdmi_ctrl->vote_hdmi_core_on = true;
+
+	return hpd;
+}
+
 int msm_hdmi_register_audio_codec(struct platform_device *pdev,
 	struct msm_hdmi_audio_codec_ops *ops)
 {
@@ -2250,6 +2286,7 @@
 
 	ops->audio_info_setup = hdmi_tx_audio_info_setup;
 	ops->get_audio_edid_blk = hdmi_tx_get_audio_edid_blk;
+	ops->hdmi_cable_status = hdmi_tx_get_cable_status;
 
 	return 0;
 } /* hdmi_tx_audio_register */
@@ -2456,6 +2493,10 @@
 	mutex_unlock(&hdmi_ctrl->mutex);
 
 	DEV_INFO("%s: HDMI Core: OFF\n", __func__);
+
+	if (hdmi_ctrl->hdmi_tx_hpd_done)
+		hdmi_ctrl->hdmi_tx_hpd_done(
+			hdmi_ctrl->downstream_data);
 } /* hdmi_tx_power_off_work */
 
 static int hdmi_tx_power_off(struct mdss_panel_data *panel_data)
@@ -2558,6 +2599,9 @@
 
 	hdmi_tx_hpd_polarity_setup(hdmi_ctrl, HPD_DISCONNECT_POLARITY);
 
+	if (hdmi_ctrl->hdmi_tx_hpd_done)
+		hdmi_ctrl->hdmi_tx_hpd_done(hdmi_ctrl->downstream_data);
+
 	return 0;
 } /* hdmi_tx_power_on */
 
@@ -2565,6 +2609,7 @@
 {
 	int rc = 0;
 	struct dss_io_data *io = NULL;
+	unsigned long flags;
 
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -2604,7 +2649,10 @@
 		DEV_INFO("%s: Failed to disable hpd power. Error=%d\n",
 			__func__, rc);
 
+	spin_lock_irqsave(&hdmi_ctrl->hpd_state_lock, flags);
 	hdmi_ctrl->hpd_state = false;
+	spin_unlock_irqrestore(&hdmi_ctrl->hpd_state_lock, flags);
+
 	hdmi_ctrl->hpd_initialized = false;
 } /* hdmi_tx_hpd_off */
 
@@ -2730,6 +2778,7 @@
 {
 	struct dss_io_data *io = NULL;
 	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;
+	unsigned long flags;
 
 	if (!hdmi_ctrl) {
 		DEV_WARN("%s: invalid input data, ISR ignored\n", __func__);
@@ -2744,8 +2793,10 @@
 	}
 
 	if (DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(0)) {
+		spin_lock_irqsave(&hdmi_ctrl->hpd_state_lock, flags);
 		hdmi_ctrl->hpd_state =
 			(DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
+		spin_unlock_irqrestore(&hdmi_ctrl->hpd_state_lock, flags);
 
 		/*
 		 * Ack the current hpd interrupt and stop listening to
@@ -2844,6 +2895,8 @@
 
 	INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
 
+	spin_lock_init(&hdmi_ctrl->hpd_state_lock);
+
 	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
 	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index fd95582..66071e9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -58,6 +58,7 @@
 	struct switch_dev sdev;
 	struct switch_dev audio_sdev;
 	struct workqueue_struct *workq;
+	spinlock_t hpd_state_lock;
 
 	uint32_t video_resolution;
 
@@ -68,6 +69,7 @@
 	u32 hpd_off_pending;
 	u32 hpd_feature_on;
 	u32 hpd_initialized;
+	u32 vote_hdmi_core_on;
 	u8  timing_gen_on;
 	u32 mhl_max_pclk;
 	u8  mhl_hpd_on;
@@ -84,6 +86,9 @@
 
 	struct hdmi_tx_ddc_ctrl ddc_ctrl;
 
+	void (*hdmi_tx_hpd_done) (void *data);
+	void *downstream_data;
+
 	void *feature_data[HDMI_TX_FEAT_MAX];
 };
 
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index a9667a4..f36e3c5 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -37,7 +37,6 @@
 #define MAX_IMG_HEIGHT		0x3FFF
 #define MAX_DST_W		MAX_MIXER_WIDTH
 #define MAX_DST_H		MAX_MIXER_HEIGHT
-#define MAX_PLANES		4
 #define MAX_DOWNSCALE_RATIO	4
 #define MAX_UPSCALE_RATIO	20
 #define MAX_DECIMATION		4
@@ -52,6 +51,11 @@
 /* wait for at most 2 vsync for lowest refresh rate (24hz) */
 #define KOFF_TIMEOUT msecs_to_jiffies(84)
 
+#define OVERFETCH_DISABLE_TOP		BIT(0)
+#define OVERFETCH_DISABLE_BOTTOM	BIT(1)
+#define OVERFETCH_DISABLE_LEFT		BIT(2)
+#define OVERFETCH_DISABLE_RIGHT		BIT(3)
+
 #ifdef MDSS_MDP_DEBUG_REG
 static inline void mdss_mdp_reg_write(u32 addr, u32 val)
 {
@@ -341,9 +345,6 @@
 	u8 vert_deci;
 	struct mdss_mdp_img_rect src;
 	struct mdss_mdp_img_rect dst;
-	u32 phase_step_x;
-	u32 phase_step_y;
-
 	struct mdss_mdp_format_params *src_fmt;
 	struct mdss_mdp_plane_sizes src_planes;
 
@@ -370,6 +371,9 @@
 
 	struct mdp_overlay_pp_params pp_cfg;
 	struct mdss_pipe_pp_res pp_res;
+	struct mdp_scale_data scale;
+	u8 chroma_sample_h;
+	u8 chroma_sample_v;
 };
 
 struct mdss_mdp_writeback_arg {
@@ -629,6 +633,7 @@
 int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd,
 					struct mdp_mixer_cfg *mixer_cfg);
 
+int mdss_mdp_pipe_program_pixel_extn(struct mdss_mdp_pipe *pipe);
 #define mfd_to_mdp5_data(mfd) (mfd->mdp.private1)
 #define mfd_to_mdata(mfd) (((struct mdss_overlay_private *)\
 				(mfd->mdp.private1))->mdata)
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 4f9045e..aa7c4dd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1560,9 +1560,17 @@
 struct mdss_mdp_mixer *mdss_mdp_mixer_get(struct mdss_mdp_ctl *ctl, int mux)
 {
 	struct mdss_mdp_mixer *mixer = NULL;
-	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(ctl->mfd);
-	if (!ctl)
+	struct mdss_overlay_private *mdp5_data = NULL;
+	if (!ctl || !ctl->mfd) {
+		pr_err("ctl not initialized\n");
 		return NULL;
+	}
+
+	mdp5_data = mfd_to_mdp5_data(ctl->mfd);
+	if (!mdp5_data) {
+		pr_err("ctl not initialized\n");
+		return NULL;
+	}
 
 	switch (mux) {
 	case MDSS_MDP_MIXER_MUX_DEFAULT:
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index c8af903..8d59107 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -201,6 +201,9 @@
 #define MDSS_MDP_REG_SSPP_CURRENT_SRC2_ADDR		0x0AC
 #define MDSS_MDP_REG_SSPP_CURRENT_SRC3_ADDR		0x0B0
 #define MDSS_MDP_REG_SSPP_DECIMATION_CONFIG		0x0B4
+#define MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_LR		0x100
+#define MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_TB		0x104
+#define MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_REQ_PIXELS	0x108
 
 #define MDSS_MDP_REG_VIG_OP_MODE			0x200
 #define MDSS_MDP_REG_VIG_QSEED2_CONFIG			0x204
@@ -356,6 +359,8 @@
 #define MDSS_MDP_REG_WB_CSC_BASE			0x260
 #define MDSS_MDP_REG_WB_DST_ADDR_SW_STATUS		0x2B0
 
+#define MDSS_MDP_MAX_AD_AL	65535
+#define MDSS_MDP_MAX_AD_STR	255
 
 #define MDSS_MDP_REG_AD_BYPASS				0x000
 #define MDSS_MDP_REG_AD_CTRL_0				0x004
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index 6056f21..d3e18ac 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -532,6 +532,7 @@
 int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
 {
 	struct mdss_mdp_cmd_ctx *ctx;
+	struct mdss_panel_info *pinfo;
 	unsigned long flags;
 	struct mdss_mdp_vsync_handler *tmp, *handle;
 	int need_wait = 0;
@@ -555,9 +556,23 @@
 
 	if (need_wait)
 		if (wait_for_completion_timeout(&ctx->stop_comp, STOP_TIMEOUT)
-		    <= 0)
+		    <= 0) {
 			WARN(1, "stop cmd time out\n");
 
+			if (IS_ERR_OR_NULL(ctl->panel_data)) {
+				pr_err("no panel data\n");
+			} else {
+				pinfo = &ctl->panel_data->panel_info;
+
+				if (pinfo->panel_dead) {
+					mdss_mdp_irq_disable
+						(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
+								ctx->pp_num);
+					ctx->rdptr_enabled = 0;
+				}
+			}
+		}
+
 	if (cancel_work_sync(&ctx->clk_work))
 		pr_debug("no pending clk work\n");
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 7c79ceb..bd1c3eb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -294,6 +294,7 @@
 	struct mdss_mdp_video_ctx *ctx;
 	struct mdss_mdp_vsync_handler *tmp, *handle;
 	int rc;
+	u32 frame_rate = 0;
 
 	pr_debug("stop ctl=%d\n", ctl->num);
 
@@ -313,6 +314,14 @@
 		WARN(rc, "intf %d blank error (%d)\n", ctl->intf_num, rc);
 
 		mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
+		/* wait for at least one VSYNC on HDMI intf for proper TG OFF */
+		if (MDSS_INTF_HDMI == ctx->intf_type) {
+			frame_rate = mdss_panel_get_framerate
+					(&(ctl->panel_data->panel_info));
+			if (!(frame_rate >= 24 && frame_rate <= 240))
+				frame_rate = 24;
+			msleep((1000/frame_rate) + 1);
+		}
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 		ctx->timegen_en = false;
 
@@ -429,10 +438,9 @@
 		} else {
 			rc = 0;
 		}
-
-		mdss_mdp_ctl_notify(ctl,
-			rc ? MDP_NOTIFY_FRAME_TIMEOUT : MDP_NOTIFY_FRAME_DONE);
 	}
+	mdss_mdp_ctl_notify(ctl,
+			rc ? MDP_NOTIFY_FRAME_TIMEOUT : MDP_NOTIFY_FRAME_DONE);
 
 	if (ctx->wait_pending) {
 		ctx->wait_pending = 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index c565d98..121b9e5 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -282,7 +282,12 @@
 	int rc;
 
 	src = pipe->src.w >> pipe->horz_deci;
-	rc = mdss_mdp_calc_phase_step(src, pipe->dst.w, &pipe->phase_step_x);
+
+	if (pipe->scale.enable_pxl_ext)
+		return 0;
+	memset(&pipe->scale, 0, sizeof(struct mdp_scale_data));
+	rc = mdss_mdp_calc_phase_step(src, pipe->dst.w,
+			&pipe->scale.phase_step_x[0]);
 	if (rc) {
 		pr_err("Horizontal scaling calculation failed=%d! %d->%d\n",
 				rc, src, pipe->dst.w);
@@ -290,16 +295,43 @@
 	}
 
 	src = pipe->src.h >> pipe->vert_deci;
-	rc = mdss_mdp_calc_phase_step(src, pipe->dst.h, &pipe->phase_step_y);
+	rc = mdss_mdp_calc_phase_step(src, pipe->dst.h,
+			&pipe->scale.phase_step_y[0]);
 	if (rc) {
 		pr_err("Vertical scaling calculation failed=%d! %d->%d\n",
 				rc, src, pipe->dst.h);
 		return rc;
 	}
-
+	pipe->scale.init_phase_x[0] = (pipe->scale.phase_step_x[0] -
+					(1 << PHASE_STEP_SHIFT)) / 2;
+	pipe->scale.init_phase_y[0] = (pipe->scale.phase_step_y[0] -
+					(1 << PHASE_STEP_SHIFT)) / 2;
 	return 0;
 }
 
+static inline void __mdss_mdp_overlay_set_chroma_sample(
+	struct mdss_mdp_pipe *pipe)
+{
+	pipe->chroma_sample_v = pipe->chroma_sample_h = 0;
+
+	switch (pipe->src_fmt->chroma_sample) {
+	case MDSS_MDP_CHROMA_H1V2:
+		pipe->chroma_sample_v = 1;
+		break;
+	case MDSS_MDP_CHROMA_H2V1:
+		pipe->chroma_sample_h = 1;
+		break;
+	case MDSS_MDP_CHROMA_420:
+		pipe->chroma_sample_v = 1;
+		pipe->chroma_sample_h = 1;
+		break;
+	}
+	if (pipe->horz_deci)
+		pipe->chroma_sample_h = 0;
+	if (pipe->vert_deci)
+		pipe->chroma_sample_v = 0;
+}
+
 static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
 				       struct mdp_overlay *req,
 				       struct mdss_mdp_pipe **ppipe)
@@ -442,7 +474,10 @@
 	pipe->dst.h = req->dst_rect.h;
 	pipe->horz_deci = req->horz_deci;
 	pipe->vert_deci = req->vert_deci;
+
+	memcpy(&pipe->scale, &req->scale, sizeof(struct mdp_scale_data));
 	pipe->src_fmt = fmt;
+	__mdss_mdp_overlay_set_chroma_sample(pipe);
 
 	pipe->mixer_stage = req->z_order;
 	pipe->is_fg = req->is_fg;
@@ -458,8 +493,17 @@
 		pr_debug("Unintended blend_op %d on layer with no alpha plane\n",
 			pipe->blend_op);
 
-	pipe->overfetch_disable = fmt->is_yuv &&
-			!(pipe->flags & MDP_SOURCE_ROTATED_90);
+	if (fmt->is_yuv && !(pipe->flags & MDP_SOURCE_ROTATED_90) &&
+			!pipe->scale.enable_pxl_ext) {
+		pipe->overfetch_disable = OVERFETCH_DISABLE_BOTTOM;
+
+		if (!(pipe->flags & MDSS_MDP_DUAL_PIPE) ||
+				(pipe->flags & MDSS_MDP_RIGHT_MIXER))
+			pipe->overfetch_disable |= OVERFETCH_DISABLE_RIGHT;
+		pr_debug("overfetch flags=%x\n", pipe->overfetch_disable);
+	} else {
+		pipe->overfetch_disable = 0;
+	}
 
 	req->id = pipe->ndx;
 	pipe->req_data = *req;
@@ -516,7 +560,7 @@
 		}
 	}
 
-	if (pipe->flags & MDP_DEINTERLACE) {
+	if ((pipe->flags & MDP_DEINTERLACE) && !pipe->scale.enable_pxl_ext) {
 		if (pipe->flags & MDP_SOURCE_ROTATED_90) {
 			pipe->src.w /= 2;
 			pipe->img_width /= 2;
@@ -539,6 +583,12 @@
 		!mdp5_data->mdata->has_wfd_blk)
 		mdss_mdp_smp_release(pipe);
 
+	/*
+	 * Clear previous SMP reservations and reserve according to the
+	 * latest configuration
+	 */
+	mdss_mdp_smp_unreserve(pipe);
+
 	ret = mdss_mdp_smp_reserve(pipe);
 	if (ret) {
 		pr_debug("mdss_mdp_smp_reserve failed. ret=%d\n", ret);
@@ -1475,15 +1525,26 @@
 static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl,
 						ktime_t t)
 {
-	struct msm_fb_data_type *mfd = ctl->mfd;
-	struct mdss_overlay_private *mdp5_data;
+	struct msm_fb_data_type *mfd = NULL;
+	struct mdss_overlay_private *mdp5_data = NULL;
 
+	if (!ctl) {
+		pr_err("ctl is NULL\n");
+		return;
+	}
+
+	mfd = ctl->mfd;
 	if (!mfd || !mfd->mdp.private1) {
 		pr_warn("Invalid handle for vsync\n");
 		return;
 	}
 
 	mdp5_data = mfd_to_mdp5_data(mfd);
+	if (!mdp5_data) {
+		pr_err("mdp5_data is NULL\n");
+		return;
+	}
+
 	pr_debug("vsync on fb%d play_cnt=%d\n", mfd->index, ctl->play_cnt);
 
 	mdp5_data->vsync_time = t;
@@ -2105,7 +2166,7 @@
 					  u32 cmd, void __user *argp)
 {
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
-	struct mdp_overlay req;
+	struct mdp_overlay *req = NULL;
 	int val, ret = -ENOSYS;
 	struct msmfb_metadata metadata;
 
@@ -2121,12 +2182,15 @@
 		break;
 
 	case MSMFB_OVERLAY_GET:
-		ret = copy_from_user(&req, argp, sizeof(req));
+		req = kmalloc(sizeof(struct mdp_overlay), GFP_KERNEL);
+		if (!req)
+			return -ENOMEM;
+		ret = copy_from_user(req, argp, sizeof(*req));
 		if (!ret) {
-			ret = mdss_mdp_overlay_get(mfd, &req);
+			ret = mdss_mdp_overlay_get(mfd, req);
 
 			if (!IS_ERR_VALUE(ret))
-				ret = copy_to_user(argp, &req, sizeof(req));
+				ret = copy_to_user(argp, req, sizeof(*req));
 		}
 
 		if (ret)
@@ -2134,12 +2198,15 @@
 		break;
 
 	case MSMFB_OVERLAY_SET:
-		ret = copy_from_user(&req, argp, sizeof(req));
+		req = kmalloc(sizeof(struct mdp_overlay), GFP_KERNEL);
+		if (!req)
+			return -ENOMEM;
+		ret = copy_from_user(req, argp, sizeof(*req));
 		if (!ret) {
-			ret = mdss_mdp_overlay_set(mfd, &req);
+			ret = mdss_mdp_overlay_set(mfd, req);
 
 			if (!IS_ERR_VALUE(ret))
-				ret = copy_to_user(argp, &req, sizeof(req));
+				ret = copy_to_user(argp, req, sizeof(*req));
 		}
 		if (ret)
 			pr_debug("OVERLAY_SET failed (%d)\n", ret);
@@ -2224,6 +2291,7 @@
 		break;
 	}
 
+	kfree(req);
 	return ret;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 779f74c..25cb9dd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -581,6 +581,8 @@
 	mdss_mdp_smp_free(pipe);
 	pipe->flags = 0;
 	pipe->bwc_mode = 0;
+	memset(&pipe->scale, 0, sizeof(struct mdp_scale_data));
+
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
 	return 0;
@@ -728,24 +730,43 @@
 	dst = pipe->dst;
 	src = pipe->src;
 
-	mdss_mdp_crop_rect(&src, &dst, &sci);
+	if (pipe->mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
+		mdss_mdp_crop_rect(&src, &dst, &sci);
 
 	src_size = (src.h << 16) | src.w;
 	src_xy = (src.y << 16) | src.x;
 	dst_size = (dst.h << 16) | dst.w;
 	dst_xy = (dst.y << 16) | dst.x;
 
-	img_size = (height << 16) | width;
-
 	ystride0 =  (pipe->src_planes.ystride[0]) |
 			(pipe->src_planes.ystride[1] << 16);
 	ystride1 =  (pipe->src_planes.ystride[2]) |
 			(pipe->src_planes.ystride[3] << 16);
 
-	if (pipe->overfetch_disable) {
-		img_size = src_size;
-		src_xy = 0;
+	/*
+	 * Software overfetch is used when scalar pixel extension is
+	 * not enabled
+	 */
+	if (pipe->overfetch_disable && !pipe->scale.enable_pxl_ext) {
+		if (pipe->overfetch_disable & OVERFETCH_DISABLE_BOTTOM) {
+			height = pipe->src.h;
+			if (!(pipe->overfetch_disable & OVERFETCH_DISABLE_TOP))
+				height += pipe->src.y;
+		}
+		if (pipe->overfetch_disable & OVERFETCH_DISABLE_RIGHT) {
+			width = pipe->src.w;
+			if (!(pipe->overfetch_disable & OVERFETCH_DISABLE_LEFT))
+				width += pipe->src.x;
+		}
+		if (pipe->overfetch_disable & OVERFETCH_DISABLE_LEFT)
+			src_xy &= ~0xFFFF;
+		if (pipe->overfetch_disable & OVERFETCH_DISABLE_TOP)
+			src_xy &= ~(0xFFFF << 16);
+
+		pr_debug("overfetch w=%d/%d h=%d/%d src_xy=0x%08x\n", width,
+			pipe->img_width, height, pipe->img_height, src_xy);
 	}
+	img_size = (height << 16) | width;
 
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_IMG_SIZE, img_size);
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_SIZE, src_size);
@@ -812,6 +833,9 @@
 
 	mdss_mdp_pipe_sspp_setup(pipe, &opmode);
 
+	if (pipe->scale.enable_pxl_ext)
+		opmode |= (1 << 31);
+
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, src_format);
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN, unpack);
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_OP_MODE, opmode);
@@ -843,33 +867,42 @@
 }
 
 static int mdss_mdp_src_addr_setup(struct mdss_mdp_pipe *pipe,
-				   struct mdss_mdp_data *data)
+				   struct mdss_mdp_data *src_data)
 {
 	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+	struct mdss_mdp_data data = *src_data;
 	int ret = 0;
 
 	pr_debug("pnum=%d\n", pipe->num);
 
-	data->bwc_enabled = pipe->bwc_mode;
+	data.bwc_enabled = pipe->bwc_mode;
 
-	ret = mdss_mdp_data_check(data, &pipe->src_planes);
+	ret = mdss_mdp_data_check(&data, &pipe->src_planes);
 	if (ret)
 		return ret;
 
-	if (pipe->overfetch_disable)
-		mdss_mdp_data_calc_offset(data, pipe->src.x, pipe->src.y,
+	if (pipe->overfetch_disable && !pipe->scale.enable_pxl_ext) {
+		u32 x = 0, y = 0;
+
+		if (pipe->overfetch_disable & OVERFETCH_DISABLE_LEFT)
+			x = pipe->src.x;
+		if (pipe->overfetch_disable & OVERFETCH_DISABLE_TOP)
+			y = pipe->src.y;
+
+		mdss_mdp_data_calc_offset(&data, x, y,
 			&pipe->src_planes, pipe->src_fmt);
+	}
 
 	/* planar format expects YCbCr, swap chroma planes if YCrCb */
 	if (mdata->mdp_rev < MDSS_MDP_HW_REV_102 &&
 			(pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_PLANAR)
 				&& (pipe->src_fmt->element[0] == C1_B_Cb))
-		swap(data->p[1].addr, data->p[2].addr);
+		swap(data.p[1].addr, data.p[2].addr);
 
-	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC0_ADDR, data->p[0].addr);
-	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC1_ADDR, data->p[1].addr);
-	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC2_ADDR, data->p[2].addr);
-	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC3_ADDR, data->p[3].addr);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC0_ADDR, data.p[0].addr);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC1_ADDR, data.p[1].addr);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC2_ADDR, data.p[2].addr);
+	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC3_ADDR, data.p[3].addr);
 
 	return 0;
 }
@@ -900,8 +933,9 @@
 			     struct mdss_mdp_data *src_data)
 {
 	int ret = 0;
-	u32 params_changed, opmode;
 	struct mdss_mdp_ctl *ctl;
+	u32 params_changed;
+	u32 opmode = 0;
 
 	if (!pipe) {
 		pr_err("pipe not setup properly for queue\n");
@@ -982,3 +1016,53 @@
 {
 	return (pipe == pipe->mixer->stage_pipe[pipe->mixer_stage]);
 }
+
+static inline void __mdss_mdp_pipe_program_pixel_extn_helper(
+	struct mdss_mdp_pipe *pipe, u32 plane, u32 off)
+{
+	u32 src_h = pipe->src.h >> pipe->vert_deci;
+	u32 mask = 0xFF;
+
+	/*
+	 * CB CR plane required pxls need to be accounted
+	 * for chroma decimation.
+	 */
+	if (plane == 1)
+		src_h >>= pipe->chroma_sample_v;
+	writel_relaxed(((pipe->scale.right_ftch[plane] & mask) << 24)|
+		((pipe->scale.right_rpt[plane] & mask) << 16)|
+		((pipe->scale.left_ftch[plane] & mask) << 8)|
+		(pipe->scale.left_rpt[plane] & mask), pipe->base +
+			MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_LR + off);
+	writel_relaxed(((pipe->scale.btm_ftch[plane] & mask) << 24)|
+		((pipe->scale.btm_rpt[plane] & mask) << 16)|
+		((pipe->scale.top_ftch[plane] & mask) << 8)|
+		(pipe->scale.top_rpt[plane] & mask), pipe->base +
+			MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_TB + off);
+	mask = 0xFFFF;
+	writel_relaxed((((src_h + pipe->scale.num_ext_pxls_top[plane] +
+		pipe->scale.num_ext_pxls_btm[plane]) & mask) << 16) |
+		((pipe->scale.roi_w[plane] +
+		pipe->scale.num_ext_pxls_left[plane] +
+		pipe->scale.num_ext_pxls_right[plane]) & mask), pipe->base +
+			MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_REQ_PIXELS + off);
+}
+
+/**
+ * mdss_mdp_pipe_program_pixel_extn - Program the source pipe's
+ *				      sw pixel extension
+ * @pipe:	Source pipe struct containing pixel extn values
+ *
+ * Function programs the pixel extn values calculated during
+ * scale setup.
+ */
+int mdss_mdp_pipe_program_pixel_extn(struct mdss_mdp_pipe *pipe)
+{
+	/* Y plane pixel extn */
+	__mdss_mdp_pipe_program_pixel_extn_helper(pipe, 0, 0);
+	/* CB CR plane pixel extn */
+	__mdss_mdp_pipe_program_pixel_extn_helper(pipe, 1, 16);
+	/* Alpha plane pixel extn */
+	__mdss_mdp_pipe_program_pixel_extn_helper(pipe, 3, 32);
+	return 0;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index b31f6c1..dfeec22 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -629,7 +629,7 @@
 		}
 	}
 
-	*op = opmode;
+	*op |= opmode;
 
 	return 0;
 }
@@ -637,12 +637,15 @@
 static int mdss_mdp_scale_setup(struct mdss_mdp_pipe *pipe)
 {
 	u32 scale_config = 0;
-	u32 phasex_step = 0, phasey_step = 0;
+	int init_phasex = 0, init_phasey = 0;
+	int phasex_step = 0, phasey_step = 0;
 	u32 chroma_sample;
 	u32 filter_mode;
 	struct mdss_data_type *mdata;
 	u32 src_w, src_h;
 
+	pr_debug("pipe=%d, change pxl ext=%d\n", pipe->num,
+			pipe->scale.enable_pxl_ext);
 	mdata = mdss_mdp_get_mdata();
 	if (mdata->mdp_rev >= MDSS_MDP_HW_REV_102 && pipe->src_fmt->is_yuv)
 		filter_mode = MDSS_MDP_SCALE_FILTER_CA;
@@ -689,7 +692,8 @@
 	if ((src_h != pipe->dst.h) ||
 	    (pipe->pp_res.pp_sts.sharp_sts & PP_STS_ENABLE) ||
 	    (chroma_sample == MDSS_MDP_CHROMA_420) ||
-	    (chroma_sample == MDSS_MDP_CHROMA_H1V2)) {
+	    (chroma_sample == MDSS_MDP_CHROMA_H1V2) ||
+	    pipe->scale.enable_pxl_ext) {
 		pr_debug("scale y - src_h=%d dst_h=%d\n", src_h, pipe->dst.h);
 
 		if ((src_h / MAX_DOWNSCALE_RATIO) > pipe->dst.h) {
@@ -699,7 +703,8 @@
 		}
 
 		scale_config |= MDSS_MDP_SCALEY_EN;
-		phasey_step = pipe->phase_step_y;
+		phasey_step = pipe->scale.phase_step_y[0];
+		init_phasey = pipe->scale.init_phase_y[0];
 
 		if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
 			u32 chroma_shift = 0;
@@ -708,11 +713,11 @@
 			    (chroma_sample == MDSS_MDP_CHROMA_H1V2)))
 				chroma_shift = 1; /* 2x upsample chroma */
 
-			if (src_h <= pipe->dst.h) {
+			if (src_h <= pipe->dst.h)
 				scale_config |= /* G/Y, A */
 					(filter_mode << 10) |
 					(MDSS_MDP_SCALE_FILTER_BIL << 18);
-			} else
+			else
 				scale_config |= /* G/Y, A */
 					(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
 					(MDSS_MDP_SCALE_FILTER_PCMN << 18);
@@ -724,6 +729,8 @@
 				scale_config |= /* CrCb */
 					(MDSS_MDP_SCALE_FILTER_PCMN << 14);
 
+			writel_relaxed(init_phasey, pipe->base +
+				MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEY);
 			writel_relaxed(phasey_step >> chroma_shift, pipe->base +
 				MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPY);
 		} else {
@@ -741,7 +748,8 @@
 	if ((src_w != pipe->dst.w) ||
 	    (pipe->pp_res.pp_sts.sharp_sts & PP_STS_ENABLE) ||
 	    (chroma_sample == MDSS_MDP_CHROMA_420) ||
-	    (chroma_sample == MDSS_MDP_CHROMA_H2V1)) {
+	    (chroma_sample == MDSS_MDP_CHROMA_H2V1) ||
+	    pipe->scale.enable_pxl_ext) {
 		pr_debug("scale x - src_w=%d dst_w=%d\n", src_w, pipe->dst.w);
 
 		if ((src_w / MAX_DOWNSCALE_RATIO) > pipe->dst.w) {
@@ -751,7 +759,8 @@
 		}
 
 		scale_config |= MDSS_MDP_SCALEX_EN;
-		phasex_step = pipe->phase_step_x;
+		init_phasex = pipe->scale.init_phase_x[0];
+		phasex_step = pipe->scale.phase_step_x[0];
 
 		if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
 			u32 chroma_shift = 0;
@@ -761,11 +770,11 @@
 			    (chroma_sample == MDSS_MDP_CHROMA_H2V1)))
 				chroma_shift = 1; /* 2x upsample chroma */
 
-			if (src_w <= pipe->dst.w) {
+			if (src_w <= pipe->dst.w)
 				scale_config |= /* G/Y, A */
 					(filter_mode << 8) |
 					(MDSS_MDP_SCALE_FILTER_BIL << 16);
-			} else
+			else
 				scale_config |= /* G/Y, A */
 					(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
 					(MDSS_MDP_SCALE_FILTER_PCMN << 16);
@@ -777,6 +786,8 @@
 				scale_config |= /* CrCb */
 					(MDSS_MDP_SCALE_FILTER_PCMN << 12);
 
+			writel_relaxed(init_phasex, pipe->base +
+				MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEX);
 			writel_relaxed(phasex_step >> chroma_shift, pipe->base +
 				MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPX);
 		} else {
@@ -791,12 +802,44 @@
 		}
 	}
 
+	if (pipe->scale.enable_pxl_ext &&
+		pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
+
+		/*program x,y initial phase and phase step*/
+		writel_relaxed(pipe->scale.init_phase_x[0],
+			pipe->base + MDSS_MDP_REG_VIG_QSEED2_C03_INIT_PHASEX);
+		writel_relaxed(pipe->scale.phase_step_x[0],
+			pipe->base + MDSS_MDP_REG_VIG_QSEED2_C03_PHASESTEPX);
+		writel_relaxed(pipe->scale.init_phase_x[1],
+			pipe->base + MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEX);
+		writel_relaxed(pipe->scale.phase_step_x[1],
+			pipe->base + MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPX);
+
+		writel_relaxed(pipe->scale.init_phase_y[0],
+			pipe->base + MDSS_MDP_REG_VIG_QSEED2_C03_INIT_PHASEY);
+		writel_relaxed(pipe->scale.phase_step_y[0],
+			pipe->base + MDSS_MDP_REG_VIG_QSEED2_C03_PHASESTEPY);
+		writel_relaxed(pipe->scale.init_phase_y[1],
+			pipe->base + MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEY);
+		writel_relaxed(pipe->scale.phase_step_y[1],
+			pipe->base + MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPY);
+
+		/*program pixel extn values for the SSPP*/
+		mdss_mdp_pipe_program_pixel_extn(pipe);
+	} else {
+		writel_relaxed(phasex_step, pipe->base +
+		   MDSS_MDP_REG_SCALE_PHASE_STEP_X);
+		writel_relaxed(phasey_step, pipe->base +
+		   MDSS_MDP_REG_SCALE_PHASE_STEP_Y);
+		writel_relaxed(init_phasex, pipe->base +
+			MDSS_MDP_REG_SCALE_INIT_PHASE_X);
+		writel_relaxed(init_phasey, pipe->base +
+			MDSS_MDP_REG_SCALE_INIT_PHASE_Y);
+	}
+
 	writel_relaxed(scale_config, pipe->base +
 	   MDSS_MDP_REG_SCALE_CONFIG);
-	writel_relaxed(phasex_step, pipe->base +
-	   MDSS_MDP_REG_SCALE_PHASE_STEP_X);
-	writel_relaxed(phasey_step, pipe->base +
-	   MDSS_MDP_REG_SCALE_PHASE_STEP_Y);
+
 	return 0;
 }
 
@@ -2248,6 +2291,7 @@
 	return ret;
 }
 
+#define MDSS_MAX_HIST_BIN_SIZE 16777215
 int mdss_mdp_histogram_start(struct mdp_histogram_start_req *req)
 {
 	u32 done_shift_bit;
@@ -2256,9 +2300,13 @@
 	int i, ret = 0;
 	u32 disp_num, dspp_num = 0;
 	u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
+	u32 frame_size;
 	struct mdss_mdp_pipe *pipe;
 	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 
+	if (!mdss_is_ready())
+		return -EPROBE_DEFER;
+
 	if ((PP_BLOCK(req->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
 		(PP_BLOCK(req->block) >= MDP_BLOCK_MAX))
 		return -EINVAL;
@@ -2278,6 +2326,16 @@
 		ret = -EPERM;
 		goto hist_exit;
 	}
+
+	frame_size = (mdata->ctl_off[mixer_id[0]].width *
+					mdata->ctl_off[mixer_id[0]].height);
+	if (!frame_size ||
+		((MDSS_MAX_HIST_BIN_SIZE / frame_size) < req->frame_cnt)) {
+		pr_err("%s, too many frames for given display size, %d",
+						__func__, req->frame_cnt);
+		ret = -EINVAL;
+		goto hist_exit;
+	}
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 
 	if (PP_LOCAT(req->block) == MDSS_PP_SSPP_CFG) {
@@ -2944,6 +3002,11 @@
 			ret = -EINVAL;
 			goto error;
 		}
+		if (input->in.amb_light > MDSS_MDP_MAX_AD_AL) {
+			pr_warn("invalid input ambient light");
+			ret = -EINVAL;
+			goto error;
+		}
 		ad->ad_data_mode = MDSS_AD_INPUT_AMBIENT;
 		pr_debug("ambient = %d", input->in.amb_light);
 		ad->ad_data = input->in.amb_light;
@@ -2958,6 +3021,11 @@
 			ret = -EINVAL;
 			goto error;
 		}
+		if (input->in.strength > MDSS_MDP_MAX_AD_STR) {
+			pr_warn("invalid input strength");
+			ret = -EINVAL;
+			goto error;
+		}
 		ad->ad_data_mode = MDSS_AD_INPUT_STRENGTH;
 		pr_debug("strength = %d", input->in.strength);
 		ad->ad_data = input->in.strength;
@@ -3520,8 +3588,8 @@
 		return ret;
 	}
 
-	if (cfg->size == 0) {
-		pr_err("Invalid buffer size");
+	if (cfg->size == 0 || cfg->size > PAGE_SIZE) {
+		pr_err("Invalid buffer size %d", cfg->size);
 		return ret;
 	}
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 1170d1e..b680823 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -592,7 +592,7 @@
 		return -EINVAL;
 
 	unit = 1 << PHASE_STEP_SHIFT;
-	*out_phase = mult_frac(src, unit, dst);
+	*out_phase = mult_frac(unit, src, dst);
 
 	/* check if overflow is possible */
 	if (src > dst) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index c4e1956..d29323d3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -132,6 +132,16 @@
 
 	pr_debug("setting secure=%d\n", enable);
 
+	if (!ctl || !ctl->mdata) {
+		pr_err("%s : ctl is NULL", __func__);
+		return -EINVAL;
+	}
+
+	if (!wb) {
+		pr_err("unable to start, writeback is not initialized\n");
+		return -ENODEV;
+	}
+
 	ctl->is_secure = enable;
 	wb->is_secure = enable;
 
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 75fc095..b859598 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -299,6 +299,8 @@
 	struct ion_handle *splash_ihdl;
 	u32 panel_power_on;
 
+	uint32_t panel_dead;
+
 	struct lcd_panel_info lcdc;
 	struct fbc_panel_info fbc;
 	struct mipi_panel_info mipi;
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 4bbd07a..8da837b 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -90,8 +90,8 @@
 	 * unusual file system layouts.
 	 */
 	if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) {
-		block_cluster = EXT4_B2C(sbi, (start -
-					       ext4_block_bitmap(sb, gdp)));
+		block_cluster = EXT4_B2C(sbi,
+					 ext4_block_bitmap(sb, gdp) - start);
 		if (block_cluster < num_clusters)
 			block_cluster = -1;
 		else if (block_cluster == num_clusters) {
@@ -102,7 +102,7 @@
 
 	if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) {
 		inode_cluster = EXT4_B2C(sbi,
-					 start - ext4_inode_bitmap(sb, gdp));
+					 ext4_inode_bitmap(sb, gdp) - start);
 		if (inode_cluster < num_clusters)
 			inode_cluster = -1;
 		else if (inode_cluster == num_clusters) {
@@ -114,7 +114,7 @@
 	itbl_blk = ext4_inode_table(sb, gdp);
 	for (i = 0; i < sbi->s_itb_per_group; i++) {
 		if (ext4_block_in_group(sb, itbl_blk + i, block_group)) {
-			c = EXT4_B2C(sbi, start - itbl_blk + i);
+			c = EXT4_B2C(sbi, itbl_blk + i - start);
 			if ((c < num_clusters) || (c == inode_cluster) ||
 			    (c == block_cluster) || (c == itbl_cluster))
 				continue;
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 0739ece..d525e84 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -726,25 +726,27 @@
 };
 
 /* LOG CODES */
+static const uint32_t log_code_last_tbl[] = {
+	0x0,	/* EQUIP ID 0 */
+	0x182F,	/* EQUIP ID 1 */
+	0x0,	/* EQUIP ID 2 */
+	0x0,	/* EQUIP ID 3 */
+	0x4910,	/* EQUIP ID 4 */
+	0x5420,	/* EQUIP ID 5 */
+	0x0,	/* EQUIP ID 6 */
+	0x74FF,	/* EQUIP ID 7 */
+	0x0,	/* EQUIP ID 8 */
+	0x0,	/* EQUIP ID 9 */
+	0xA38A,	/* EQUIP ID 10 */
+	0xB201,	/* EQUIP ID 11 */
+	0x0,	/* EQUIP ID 12 */
+	0x0,	/* EQUIP ID 13 */
+	0x0,	/* EQUIP ID 14 */
+	0x0,	/* EQUIP ID 15 */
+};
 
-#define LOG_0	0x0
-#define LOG_1	0x1808
-#define LOG_2	0x0
-#define LOG_3	0x0
-#define LOG_4	0x4910
-#define LOG_5	0x5420
-#define LOG_6	0x0
-#define LOG_7	0x74FF
-#define LOG_8	0x0
-#define LOG_9	0x0
-#define LOG_10	0xA38A
-#define LOG_11	0xB201
-#define LOG_12	0x0
-#define LOG_13	0x0
-#define LOG_14	0x0
-#define LOG_15	0x0
-
-#define LOG_GET_ITEM_NUM(xx_code) (xx_code & 0x0FFF)
-#define LOG_GET_EQUIP_ID(xx_code) ((xx_code & 0xF000) >> 12)
+#define LOG_GET_ITEM_NUM(xx_code)	(xx_code & 0x0FFF)
+#define LOG_GET_EQUIP_ID(xx_code)	((xx_code & 0xF000) >> 12)
+#define LOG_ITEMS_TO_SIZE(num_items)	((num_items+7)/8)
 
 #endif
diff --git a/include/linux/kref.h b/include/linux/kref.h
index 9c07dce..6f515f2 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -18,6 +18,7 @@
 #include <linux/bug.h>
 #include <linux/atomic.h>
 #include <linux/kernel.h>
+#include <linux/mutex.h>
 
 struct kref {
 	atomic_t refcount;
@@ -93,4 +94,43 @@
 {
 	return kref_sub(kref, 1, release);
 }
+
+static inline int kref_put_mutex(struct kref *kref,
+				 void (*release)(struct kref *kref),
+				 struct mutex *lock)
+{
+	WARN_ON(release == NULL);
+        if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) {
+		mutex_lock(lock);
+		if (unlikely(!atomic_dec_and_test(&kref->refcount))) {
+			mutex_unlock(lock);
+			return 0;
+		}
+		release(kref);
+		return 1;
+	}
+	return 0;
+}
+
+
+/**
+ * kref_get_unless_zero - Increment refcount for object unless it is zero.
+ * @kref: object.
+ *
+ * Return non-zero if the increment succeeded. Otherwise return 0.
+ *
+ * This function is intended to simplify locking around refcounting for
+ * objects that can be looked up from a lookup structure, and which are
+ * removed from that lookup structure in the object destructor.
+ * Operations on such objects require at least a read lock around
+ * lookup + kref_get, and a write lock around kref_put + remove from lookup
+ * structure. Furthermore, RCU implementations become extremely tricky.
+ * With a lookup followed by a kref_get_unless_zero *with return value check*
+ * locking in the kref_put path can be deferred to the actual removal from
+ * the lookup structure and RCU lookups become trivial.
+ */
+static inline int __must_check kref_get_unless_zero(struct kref *kref)
+{
+	return atomic_add_unless(&kref->refcount, 1, 0);
+}
 #endif /* _KREF_H_ */
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index 227fd3e..9a584c0 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -2,6 +2,7 @@
 #define LINUX_MM_INLINE_H
 
 #include <linux/huge_mm.h>
+#include <linux/swap.h>
 
 /**
  * page_is_file_cache - should the page be on a file LRU or anon LRU?
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 7539e03..381fff5 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -375,7 +375,6 @@
 	 * free areas of different sizes
 	 */
 	spinlock_t		lock;
-	int                     all_unreclaimable; /* All pages pinned */
 #if defined CONFIG_COMPACTION || defined CONFIG_CMA
 	/* Set to true when the PG_migrate_skip bits should be cleared */
 	bool			compact_blockskip_flush;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 0c08421..803ebeb 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -156,6 +156,7 @@
 
 #define MDSS_MDP_ROT_ONLY		0x80
 #define MDSS_MDP_RIGHT_MIXER		0x100
+#define MDSS_MDP_DUAL_PIPE		0x200
 
 /* mdp_blit_req flag values */
 #define MDP_ROT_NOP 0
@@ -168,6 +169,7 @@
 #define MDP_BLUR 0x10
 #define MDP_BLEND_FG_PREMULT 0x20000
 #define MDP_IS_FG 0x40000
+#define MDP_SOLID_FILL 0x0000100
 #define MDP_DEINTERLACE 0x80000000
 #define MDP_SHARPENING  0x40000000
 #define MDP_NO_DMA_BARRIER_START	0x20000000
@@ -253,11 +255,19 @@
 
 #define MDP_BLIT_REQ_VERSION 2
 
+struct color {
+	uint32_t r;
+	uint32_t g;
+	uint32_t b;
+	uint32_t alpha;
+};
+
 struct mdp_blit_req {
 	struct mdp_img src;
 	struct mdp_img dst;
 	struct mdp_rect src_rect;
 	struct mdp_rect dst_rect;
+	struct color const_color;
 	uint32_t alpha;
 	uint32_t transp_mask;
 	uint32_t flags;
@@ -442,6 +452,33 @@
 	BLEND_OP_MAX,
 };
 
+#define MAX_PLANES	4
+struct mdp_scale_data {
+	uint8_t enable_pxl_ext;
+
+	int init_phase_x[MAX_PLANES];
+	int phase_step_x[MAX_PLANES];
+	int init_phase_y[MAX_PLANES];
+	int phase_step_y[MAX_PLANES];
+
+	int num_ext_pxls_left[MAX_PLANES];
+	int num_ext_pxls_right[MAX_PLANES];
+	int num_ext_pxls_top[MAX_PLANES];
+	int num_ext_pxls_btm[MAX_PLANES];
+
+	int left_ftch[MAX_PLANES];
+	int left_rpt[MAX_PLANES];
+	int right_ftch[MAX_PLANES];
+	int right_rpt[MAX_PLANES];
+
+	int top_rpt[MAX_PLANES];
+	int btm_rpt[MAX_PLANES];
+	int top_ftch[MAX_PLANES];
+	int btm_ftch[MAX_PLANES];
+
+	uint32_t roi_w[MAX_PLANES];
+};
+
 struct mdp_overlay {
 	struct msmfb_img src;
 	struct mdp_rect src_rect;
@@ -457,6 +494,7 @@
 	uint8_t horz_deci;
 	uint8_t vert_deci;
 	struct mdp_overlay_pp_params overlay_pp_cfg;
+	struct mdp_scale_data scale;
 };
 
 struct msmfb_overlay_3d {
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 22b004e..0065203 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -105,6 +105,7 @@
 	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CURRENT_AVG,
 	POWER_SUPPLY_PROP_POWER_NOW,
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 036b107..c1fcf34 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -197,6 +197,18 @@
 	struct block_device *bdev;	/* swap device or bdev of swap file */
 	struct file *swap_file;		/* seldom referenced */
 	unsigned int old_block_size;	/* seldom referenced */
+	spinlock_t lock;		/*
+					 * protect map scan related fields like
+					 * swap_map, lowest_bit, highest_bit,
+					 * inuse_pages, cluster_next,
+					 * cluster_nr, lowest_alloc and
+					 * highest_alloc. other fields are only
+					 * changed at swapon/swapoff, so are
+					 * protected by swap_lock. changing
+					 * flags need hold this lock and
+					 * swap_lock. If both locks need hold,
+					 * hold swap_lock first.
+					 */
 };
 
 struct swap_list_t {
@@ -204,9 +216,6 @@
 	int next;	/* swapfile to be used next */
 };
 
-/* Swap 50% full? Release swapcache more aggressively.. */
-#define vm_swap_full() (nr_swap_pages*2 < total_swap_pages)
-
 /* linux/mm/page_alloc.c */
 extern unsigned long totalram_pages;
 extern unsigned long totalreserve_pages;
@@ -335,8 +344,20 @@
 			struct vm_area_struct *vma, unsigned long addr);
 
 /* linux/mm/swapfile.c */
-extern long nr_swap_pages;
+extern atomic_long_t nr_swap_pages;
 extern long total_swap_pages;
+
+/* Swap 50% full? Release swapcache more aggressively.. */
+static inline bool vm_swap_full(void)
+{
+	return atomic_long_read(&nr_swap_pages) * 2 < total_swap_pages;
+}
+
+static inline long get_nr_swap_pages(void)
+{
+	return atomic_long_read(&nr_swap_pages);
+}
+
 extern void si_swapinfo(struct sysinfo *);
 extern swp_entry_t get_swap_page(void);
 extern swp_entry_t get_swap_page_of_type(int);
@@ -370,9 +391,10 @@
 
 #else /* CONFIG_SWAP */
 
-#define nr_swap_pages				0L
+#define get_nr_swap_pages()			0L
 #define total_swap_pages			0L
 #define total_swapcache_pages			0UL
+#define vm_swap_full()				0
 
 #define si_swapinfo(val) \
 	do { (val)->freeswap = (val)->totalswap = 0; } while (0)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index ed6d41b..faf98fe 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -102,6 +102,7 @@
 	enum thermal_trip_type trip;
 	int (*notify)(enum thermal_trip_type type, int temp, void *data);
 	void *data;
+	uint8_t active;
 	struct list_head list;
 };
 
@@ -189,6 +190,8 @@
 int sensor_get_id(char *name);
 int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
 int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
+int sensor_activate_trip(uint32_t sensor_id, struct sensor_threshold *threshold,
+			bool enable);
 int thermal_sensor_trip(struct thermal_zone_device *tz,
 		enum thermal_trip_type trip, long temp);
 
diff --git a/include/linux/usb/android.h b/include/linux/usb/android.h
index e17e978..8d5e51b 100644
--- a/include/linux/usb/android.h
+++ b/include/linux/usb/android.h
@@ -19,12 +19,16 @@
 
 #include <linux/usb/composite.h>
 
+#define MAX_STREAMING_FUNCS 3
+#define FUNC_NAME_LEN 10
 struct android_usb_platform_data {
 	int (*update_pid_and_serial_num)(uint32_t, const char *);
 	u32 swfi_latency;
 	u8 usb_core_id;
 	bool cdrom;
 	bool internal_ums;
+	char streaming_func[MAX_STREAMING_FUNCS][FUNC_NAME_LEN];
+	int  streaming_func_count;
 };
 
 #ifndef CONFIG_TARGET_CORE
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index fea832e..3844f41 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -508,6 +508,7 @@
  * @dev: Driver model state for this abstract device.
  * @usb_core_id: Identifies the usb core controlled by this usb_gadget.
  *		 Used in case of more then one core operates concurrently.
+ * @streaming_enabled: Enable streaming mode with usb core.
  *
  * Gadgets have a mostly-portable "gadget driver" implementing device
  * functions, handling all usb configurations and interfaces.  Gadget
@@ -546,6 +547,7 @@
 	struct device			dev;
 	u8				usb_core_id;
 	bool				l1_supported;
+	bool				streaming_enabled;
 };
 
 static inline void set_gadget_data(struct usb_gadget *gadget, void *data)
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 07f9b90..9eb9cd8 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -229,7 +229,9 @@
  *              between 1 to 7.
  * @l1_supported: enable link power management support.
  * @dpdm_pulldown_added: Indicates whether pull down resistors are
-		connected on data lines or not.
+ *		connected on data lines or not.
+ * @enable_ahb2ahb_bypass: Indicates whether enable AHB2AHB BYPASS
+ *		mode with controller in device mode.
  */
 struct msm_otg_platform_data {
 	int *phy_init_seq;
@@ -258,6 +260,7 @@
 	int log2_itc;
 	bool l1_supported;
 	bool dpdm_pulldown_added;
+	bool enable_ahb2ahb_bypass;
 };
 
 /* phy related flags */
@@ -462,6 +465,7 @@
 	int log2_itc;
 	void *prv_data;
 	bool l1_supported;
+	bool enable_ahb2ahb_bypass;
 };
 
 /**
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 58ab4eb..2a5ebd4 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -49,6 +49,10 @@
 #define L1_CONFIG_PHY_LPM	BIT(10)
 #define L1_CONFIG_PLL		BIT(11)
 
+#define AHB2AHB_BYPASS		BIT(31)
+#define AHB2AHB_BYPASS_BIT_MASK	BIT(31)
+#define AHB2AHB_BYPASS_CLEAR	(0 << 31)
+
 #define PORTSC_PHCD            (1 << 23) /* phy suspend mode */
 #define PORTSC_PTS_MASK         (3 << 30)
 #define PORTSC_PTS_ULPI         (3 << 30)
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 1d10474..2d59889 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -140,7 +140,6 @@
 }
 
 extern unsigned long global_reclaimable_pages(void);
-extern unsigned long zone_reclaimable_pages(struct zone *zone);
 
 #ifdef CONFIG_NUMA
 /*
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index cccf851..c48586e 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -571,6 +571,7 @@
 
 struct msm_camera_led_cfg_t {
 	enum msm_camera_led_config_t cfgtype;
+	uint32_t led_current;
 };
 
 #define VIDIOC_MSM_SENSOR_CFG \
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index de42c38..ed4ffa2 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -90,6 +90,7 @@
 	uint32_t offset;
 	uint8_t native_buff;
 	uint8_t processed_divert;
+	uint32_t identity;
 };
 
 struct msm_cpp_stream_buff_info_t {
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4ecadd8..7932ba1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1801,22 +1801,28 @@
  * enum wiphy_flags - wiphy capability flags
  *
  * @WIPHY_FLAG_CUSTOM_REGULATORY:  tells us the driver for this device
- * 	has its own custom regulatory domain and cannot identify the
- * 	ISO / IEC 3166 alpha2 it belongs to. When this is enabled
- * 	we will disregard the first regulatory hint (when the
- * 	initiator is %REGDOM_SET_BY_CORE).
- * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will
- *	ignore regulatory domain settings until it gets its own regulatory
- *	domain via its regulatory_hint() unless the regulatory hint is
- *	from a country IE. After its gets its own regulatory domain it will
- *	only allow further regulatory domain settings to further enhance
- *	compliance. For example if channel 13 and 14 are disabled by this
- *	regulatory domain no user regulatory domain can enable these channels
- *	at a later time. This can be used for devices which do not have
- *	calibration information guaranteed for frequencies or settings
- *	outside of its regulatory domain. If used in combination with
- *	WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings
- *	will be followed.
+ *	has its own custom regulatory domain and cannot identify the
+ *	ISO / IEC 3166 alpha2 it belongs to. When this is enabled
+ *	we will disregard the first regulatory hint (when the
+ *	initiator is %REGDOM_SET_BY_CORE). wiphys can set the custom
+ *	regulatory domain using wiphy_apply_custom_regulatory()
+ *	prior to wiphy registration.
+ * @WIPHY_FLAG_STRICT_REGULATORY: tells us that the wiphy for this device
+ *	has regulatory domain that it wishes to be considered as the
+ *	superset for regulatory rules. After this device gets its regulatory
+ *	domain programmed further regulatory hints shall only be considered
+ *	for this device to enhance regulatory compliance, forcing the
+ *	device to only possibly use subsets of the original regulatory
+ *	rules. For example if channel 13 and 14 are disabled by this
+ *	device's regulatory domain no user specified regulatory hint which
+ *	has these channels enabled would enable them for this wiphy,
+ *	the device's original regulatory domain will be trusted as the
+ *	base. You can program the superset of regulatory rules for this
+ *	wiphy with regulatory_hint() for cards programmed with an
+ *	ISO3166-alpha2 country code. wiphys that use regulatory_hint()
+ *	will have their wiphy->regd programmed once the regulatory
+ *	domain is set, and all other regulatory hints will be ignored
+ *	until their own regulatory domain gets programmed.
  * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure
  *	that passive scan flags and beaconing flags may not be lifted by
  *	cfg80211 due to regulatory beacon hints. For more information on beacon
@@ -1884,6 +1890,34 @@
 };
 
 /**
+ * enum nl80211_country_ie_pref - country IE processing preferences
+ *
+ * enumerates the different preferences a 802.11 card can advertize
+ * for parsing the country IEs. As per the current implementation
+ * country IEs are only used derive the apha2, the information
+ * for power settings that comes with the country IE is ignored
+ * and we use the power settings from regdb.
+ *
+ * @NL80211_COUNTRY_IE_FOLLOW_CORE - This is the default behaviour.
+ *	It allows the core to update channel flags according to the
+ *	ISO3166-alpha2 in the country IE. The applied power is -
+ *	MIN(power specified by custom domain, power obtained from regdb)
+ * @NL80211_COUNTRY_IE_FOLLOW_POWER - for devices that have a
+ *	preference that even though they may have programmed their own
+ *	custom power setting prior to wiphy registration, they want
+ *	to ensure their channel power settings are updated for this
+ *	connection with the power settings derived from alpha2 of the
+ *	country IE.
+ * @NL80211_COUNTRY_IE_IGNORE_CORE - for devices that have a preference to
+ *	to ignore all country IE information processed by the core.
+ */
+enum nl80211_country_ie_pref {
+	NL80211_COUNTRY_IE_FOLLOW_CORE,
+	NL80211_COUNTRY_IE_FOLLOW_POWER,
+	NL80211_COUNTRY_IE_IGNORE_CORE,
+};
+
+/**
  * struct ieee80211_iface_limit - limit on certain interface types
  * @max: maximum number of interfaces of these types
  * @types: interface types (bits)
@@ -2100,6 +2134,8 @@
  *
  * @max_acl_mac_addrs: Maximum number of MAC addresses that the device
  *	supports for ACL.
+ * @country_ie_pref: country IE processing preferences specified
+ *	by enum nl80211_country_ie_pref
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -2164,6 +2200,8 @@
 	 */
 	u32 probe_resp_offload;
 
+	u8 country_ie_pref;
+
 	/* If multiple wiphys are registered and you're handed e.g.
 	 * a regular netdev with assigned ieee80211_ptr, you won't
 	 * know whether it points to a wiphy your driver has registered
@@ -2691,6 +2729,30 @@
 extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
 
 /**
+ * regulatory_hint_user - hint to the wireless core a regulatory domain
+ * which the driver has received from an application
+ * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain
+ * 	should be in. If @rd is set this should be NULL. Note that if you
+ * 	set this to NULL you should still set rd->alpha2 to some accepted
+ * 	alpha2.
+ *
+ * Wireless drivers can use this function to hint to the wireless core
+ * the current regulatory domain as specified by trusted applications,
+ * it is the driver's responsibilty to estbalish which applications it
+ * trusts.
+ *
+ * The wiphy should be registered to cfg80211 prior to this call.
+ * For cfg80211 drivers this means you must first use wiphy_register(),
+ * for mac80211 drivers you must first use ieee80211_register_hw().
+ *
+ * Drivers should check the return value, its possible you can get
+ * an -ENOMEM or an -EINVAL.
+ *
+ * Return: 0 on success. -ENOMEM, -EINVAL.
+ */
+extern int regulatory_hint_user(const char *alpha2);
+
+/**
  * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
  * @wiphy: the wireless device we want to process the regulatory domain on
  * @regd: the custom regulatory domain to use for this wiphy
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index bbda72e..104f86e 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -3676,6 +3676,7 @@
 } __packed;
 
 #define ASM_SESSION_CMD_PAUSE 0x00010BD3
+#define ASM_SESSION_CMD_SUSPEND 0x00010DEC
 #define ASM_SESSION_CMD_GET_SESSIONTIME_V3 0x00010D9D
 #define ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS 0x00010BD5
 
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 0dd1f1c..65ca46f 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -54,6 +54,7 @@
 #define CMD_EOS            0x0003
 #define CMD_CLOSE          0x0004
 #define CMD_OUT_FLUSH      0x0005
+#define CMD_SUSPEND        0x0006
 
 /* bit 0:1 represents priority of stream */
 #define STREAM_PRIORITY_NORMAL	0x0000
diff --git a/include/sound/soc.h b/include/sound/soc.h
index b1e536d..50d0471 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -561,6 +561,7 @@
 #endif
 
 struct snd_soc_jack {
+	struct mutex mutex;
 	struct snd_jack *jack;
 	struct snd_soc_codec *codec;
 	struct list_head pins;
diff --git a/mm/internal.h b/mm/internal.h
index 3439ef4..f5369cc 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -90,6 +90,8 @@
  */
 extern int isolate_lru_page(struct page *page);
 extern void putback_lru_page(struct page *page);
+extern unsigned long zone_reclaimable_pages(struct zone *zone);
+extern bool zone_reclaimable(struct zone *zone);
 
 /*
  * in mm/page_alloc.c
diff --git a/mm/mmap.c b/mm/mmap.c
index 848ef52..9932edb 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -133,7 +133,7 @@
 		 */
 		free -= global_page_state(NR_SHMEM);
 
-		free += nr_swap_pages;
+		free += get_nr_swap_pages();
 
 		/*
 		 * Any slabs which are created with the
diff --git a/mm/nommu.c b/mm/nommu.c
index bb8f4f0..6bb7042 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1928,7 +1928,7 @@
 		 */
 		free -= global_page_state(NR_SHMEM);
 
-		free += nr_swap_pages;
+		free += get_nr_swap_pages();
 
 		/*
 		 * Any slabs which are created with the
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 26adea8..a5e8dc2 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -34,8 +34,11 @@
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h> /* __set_page_dirty_buffers */
 #include <linux/pagevec.h>
+#include <linux/mm_inline.h>
 #include <trace/events/writeback.h>
 
+#include "internal.h"
+
 /*
  * Sleep at most 200ms at a time in balance_dirty_pages().
  */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 46ccd2f..a1e4f77 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -57,6 +57,7 @@
 #include <linux/ftrace_event.h>
 #include <linux/memcontrol.h>
 #include <linux/prefetch.h>
+#include <linux/mm_inline.h>
 #include <linux/migrate.h>
 #include <linux/page-debug-flags.h>
 
@@ -647,7 +648,6 @@
 	int mt = 0;
 
 	spin_lock(&zone->lock);
-	zone->all_unreclaimable = 0;
 	zone->pages_scanned = 0;
 
 	while (to_free) {
@@ -693,7 +693,6 @@
 				int migratetype)
 {
 	spin_lock(&zone->lock);
-	zone->all_unreclaimable = 0;
 	zone->pages_scanned = 0;
 
 	__free_one_page(page, zone, order, migratetype);
@@ -2997,7 +2996,7 @@
 			K(zone_page_state(zone, NR_FREE_CMA_PAGES)),
 			K(zone_page_state(zone, NR_WRITEBACK_TEMP)),
 			zone->pages_scanned,
-			(zone->all_unreclaimable ? "yes" : "no")
+			(!zone_reclaimable(zone) ? "yes" : "no")
 			);
 		printk("lowmem_reserve[]:");
 		for (i = 0; i < MAX_NR_ZONES; i++)
diff --git a/mm/page_io.c b/mm/page_io.c
index dc76b4d..1499e1c 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -1,3 +1,4 @@
+
 /*
  *  linux/mm/page_io.c
  *
@@ -18,8 +19,16 @@
 #include <linux/bio.h>
 #include <linux/swapops.h>
 #include <linux/writeback.h>
+#include <linux/blkdev.h>
+#include <linux/ratelimit.h>
 #include <asm/pgtable.h>
 
+/*
+ * We don't need to see swap errors more than once every 1 second to know
+ * that a problem is occurring.
+ */
+#define SWAP_ERROR_LOG_RATE_MS 1000
+
 static struct bio *get_swap_bio(gfp_t gfp_flags,
 				struct page *page, bio_end_io_t end_io)
 {
@@ -44,6 +53,7 @@
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct page *page = bio->bi_io_vec[0].bv_page;
+	static unsigned long swap_error_rs_time;
 
 	if (!uptodate) {
 		SetPageError(page);
@@ -56,7 +66,9 @@
 		 * Also clear PG_reclaim to avoid rotate_reclaimable_page()
 		 */
 		set_page_dirty(page);
-		printk(KERN_ALERT "Write-error on swap-device (%u:%u:%Lu)\n",
+		if (printk_timed_ratelimit(&swap_error_rs_time,
+					   SWAP_ERROR_LOG_RATE_MS))
+			printk(KERN_ALERT "Write-error on swap-device (%u:%u:%Lu)\n",
 				imajor(bio->bi_bdev->bd_inode),
 				iminor(bio->bi_bdev->bd_inode),
 				(unsigned long long)bio->bi_sector);
@@ -78,9 +90,54 @@
 				imajor(bio->bi_bdev->bd_inode),
 				iminor(bio->bi_bdev->bd_inode),
 				(unsigned long long)bio->bi_sector);
-	} else {
-		SetPageUptodate(page);
+		goto out;
 	}
+
+	SetPageUptodate(page);
+
+	/*
+	 * There is no guarantee that the page is in swap cache - the software
+	 * suspend code (at least) uses end_swap_bio_read() against a non-
+	 * swapcache page.  So we must check PG_swapcache before proceeding with
+	 * this optimization.
+	 */
+	if (likely(PageSwapCache(page))) {
+		struct swap_info_struct *sis;
+
+		sis = page_swap_info(page);
+		if (sis->flags & SWP_BLKDEV) {
+			/*
+			 * The swap subsystem performs lazy swap slot freeing,
+			 * expecting that the page will be swapped out again.
+			 * So we can avoid an unnecessary write if the page
+			 * isn't redirtied.
+			 * This is good for real swap storage because we can
+			 * reduce unnecessary I/O and enhance wear-leveling
+			 * if an SSD is used as the as swap device.
+			 * But if in-memory swap device (eg zram) is used,
+			 * this causes a duplicated copy between uncompressed
+			 * data in VM-owned memory and compressed data in
+			 * zram-owned memory.  So let's free zram-owned memory
+			 * and make the VM-owned decompressed page *dirty*,
+			 * so the page should be swapped out somewhere again if
+			 * we again wish to reclaim it.
+			 */
+			struct gendisk *disk = sis->bdev->bd_disk;
+			if (disk->fops->swap_slot_free_notify) {
+				swp_entry_t entry;
+				unsigned long offset;
+
+				entry.val = page_private(page);
+				offset = swp_offset(entry);
+
+				SetPageDirty(page);
+				disk->fops->swap_slot_free_notify(sis->bdev,
+						offset);
+			}
+		}
+	}
+
+out:
 	unlock_page(page);
 	bio_put(bio);
 }
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 4c5ff7f..eb6a79c 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -58,7 +58,8 @@
 	printk("Swap cache stats: add %lu, delete %lu, find %lu/%lu\n",
 		swap_cache_info.add_total, swap_cache_info.del_total,
 		swap_cache_info.find_success, swap_cache_info.find_total);
-	printk("Free swap  = %ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10));
+	printk("Free swap  = %ldkB\n",
+		get_nr_swap_pages() << (PAGE_SHIFT - 10));
 	printk("Total swap = %lukB\n", total_swap_pages << (PAGE_SHIFT - 10));
 }
 
diff --git a/mm/swapfile.c b/mm/swapfile.c
index a6c07fd..9ae4c8d 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -45,9 +45,11 @@
 
 static DEFINE_SPINLOCK(swap_lock);
 static unsigned int nr_swapfiles;
-long nr_swap_pages;
+atomic_long_t nr_swap_pages;
+/* protected with swap_lock. reading in vm_swap_full() doesn't need lock */
 long total_swap_pages;
 static int least_priority;
+static atomic_t highest_priority_index = ATOMIC_INIT(-1);
 
 static const char Bad_file[] = "Bad swap file entry ";
 static const char Unused_file[] = "Unused swap file entry ";
@@ -221,7 +223,7 @@
 			si->lowest_alloc = si->max;
 			si->highest_alloc = 0;
 		}
-		spin_unlock(&swap_lock);
+		spin_unlock(&si->lock);
 
 		/*
 		 * If seek is expensive, start searching for new cluster from
@@ -240,7 +242,7 @@
 			if (si->swap_map[offset])
 				last_in_cluster = offset + SWAPFILE_CLUSTER;
 			else if (offset == last_in_cluster) {
-				spin_lock(&swap_lock);
+				spin_lock(&si->lock);
 				offset -= SWAPFILE_CLUSTER - 1;
 				si->cluster_next = offset;
 				si->cluster_nr = SWAPFILE_CLUSTER - 1;
@@ -261,7 +263,7 @@
 			if (si->swap_map[offset])
 				last_in_cluster = offset + SWAPFILE_CLUSTER;
 			else if (offset == last_in_cluster) {
-				spin_lock(&swap_lock);
+				spin_lock(&si->lock);
 				offset -= SWAPFILE_CLUSTER - 1;
 				si->cluster_next = offset;
 				si->cluster_nr = SWAPFILE_CLUSTER - 1;
@@ -275,7 +277,7 @@
 		}
 
 		offset = scan_base;
-		spin_lock(&swap_lock);
+		spin_lock(&si->lock);
 		si->cluster_nr = SWAPFILE_CLUSTER - 1;
 		si->lowest_alloc = 0;
 	}
@@ -291,9 +293,9 @@
 	/* reuse swap entry of cache-only swap if not busy. */
 	if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
 		int swap_was_freed;
-		spin_unlock(&swap_lock);
+		spin_unlock(&si->lock);
 		swap_was_freed = __try_to_reclaim_swap(si, offset);
-		spin_lock(&swap_lock);
+		spin_lock(&si->lock);
 		/* entry was freed successfully, try to use this again */
 		if (swap_was_freed)
 			goto checks;
@@ -333,13 +335,13 @@
 			    si->lowest_alloc <= last_in_cluster)
 				last_in_cluster = si->lowest_alloc - 1;
 			si->flags |= SWP_DISCARDING;
-			spin_unlock(&swap_lock);
+			spin_unlock(&si->lock);
 
 			if (offset < last_in_cluster)
 				discard_swap_cluster(si, offset,
 					last_in_cluster - offset + 1);
 
-			spin_lock(&swap_lock);
+			spin_lock(&si->lock);
 			si->lowest_alloc = 0;
 			si->flags &= ~SWP_DISCARDING;
 
@@ -353,10 +355,10 @@
 			 * could defer that delay until swap_writepage,
 			 * but it's easier to keep this self-contained.
 			 */
-			spin_unlock(&swap_lock);
+			spin_unlock(&si->lock);
 			wait_on_bit(&si->flags, ilog2(SWP_DISCARDING),
 				wait_for_discard, TASK_UNINTERRUPTIBLE);
-			spin_lock(&swap_lock);
+			spin_lock(&si->lock);
 		} else {
 			/*
 			 * Note pages allocated by racing tasks while
@@ -372,14 +374,14 @@
 	return offset;
 
 scan:
-	spin_unlock(&swap_lock);
+	spin_unlock(&si->lock);
 	while (++offset <= si->highest_bit) {
 		if (!si->swap_map[offset]) {
-			spin_lock(&swap_lock);
+			spin_lock(&si->lock);
 			goto checks;
 		}
 		if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
-			spin_lock(&swap_lock);
+			spin_lock(&si->lock);
 			goto checks;
 		}
 		if (unlikely(--latency_ration < 0)) {
@@ -390,11 +392,11 @@
 	offset = si->lowest_bit;
 	while (++offset < scan_base) {
 		if (!si->swap_map[offset]) {
-			spin_lock(&swap_lock);
+			spin_lock(&si->lock);
 			goto checks;
 		}
 		if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
-			spin_lock(&swap_lock);
+			spin_lock(&si->lock);
 			goto checks;
 		}
 		if (unlikely(--latency_ration < 0)) {
@@ -402,7 +404,7 @@
 			latency_ration = LATENCY_LIMIT;
 		}
 	}
-	spin_lock(&swap_lock);
+	spin_lock(&si->lock);
 
 no_page:
 	si->flags -= SWP_SCANNING;
@@ -415,13 +417,34 @@
 	pgoff_t offset;
 	int type, next;
 	int wrapped = 0;
+	int hp_index;
 
 	spin_lock(&swap_lock);
-	if (nr_swap_pages <= 0)
+	if (atomic_long_read(&nr_swap_pages) <= 0)
 		goto noswap;
-	nr_swap_pages--;
+	atomic_long_dec(&nr_swap_pages);
 
 	for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) {
+		hp_index = atomic_xchg(&highest_priority_index, -1);
+		/*
+		 * highest_priority_index records current highest priority swap
+		 * type which just frees swap entries. If its priority is
+		 * higher than that of swap_list.next swap type, we use it.  It
+		 * isn't protected by swap_lock, so it can be an invalid value
+		 * if the corresponding swap type is swapoff. We double check
+		 * the flags here. It's even possible the swap type is swapoff
+		 * and swapon again and its priority is changed. In such rare
+		 * case, low prority swap type might be used, but eventually
+		 * high priority swap will be used after several rounds of
+		 * swap.
+		 */
+		if (hp_index != -1 && hp_index != type &&
+		    swap_info[type]->prio < swap_info[hp_index]->prio &&
+		    (swap_info[hp_index]->flags & SWP_WRITEOK)) {
+			type = hp_index;
+			swap_list.next = type;
+		}
+
 		si = swap_info[type];
 		next = si->next;
 		if (next < 0 ||
@@ -430,22 +453,29 @@
 			wrapped++;
 		}
 
-		if (!si->highest_bit)
+		spin_lock(&si->lock);
+		if (!si->highest_bit) {
+			spin_unlock(&si->lock);
 			continue;
-		if (!(si->flags & SWP_WRITEOK))
+		}
+		if (!(si->flags & SWP_WRITEOK)) {
+			spin_unlock(&si->lock);
 			continue;
+		}
 
 		swap_list.next = next;
+
+		spin_unlock(&swap_lock);
 		/* This is called for allocating swap entry for cache */
 		offset = scan_swap_map(si, SWAP_HAS_CACHE);
-		if (offset) {
-			spin_unlock(&swap_lock);
+		spin_unlock(&si->lock);
+		if (offset)
 			return swp_entry(type, offset);
-		}
+		spin_lock(&swap_lock);
 		next = swap_list.next;
 	}
 
-	nr_swap_pages++;
+	atomic_long_inc(&nr_swap_pages);
 noswap:
 	spin_unlock(&swap_lock);
 	return (swp_entry_t) {0};
@@ -457,19 +487,19 @@
 	struct swap_info_struct *si;
 	pgoff_t offset;
 
-	spin_lock(&swap_lock);
 	si = swap_info[type];
+	spin_lock(&si->lock);
 	if (si && (si->flags & SWP_WRITEOK)) {
-		nr_swap_pages--;
+		atomic_long_dec(&nr_swap_pages);
 		/* This is called for allocating swap entry, not cache */
 		offset = scan_swap_map(si, 1);
 		if (offset) {
-			spin_unlock(&swap_lock);
+			spin_unlock(&si->lock);
 			return swp_entry(type, offset);
 		}
-		nr_swap_pages++;
+		atomic_long_inc(&nr_swap_pages);
 	}
-	spin_unlock(&swap_lock);
+	spin_unlock(&si->lock);
 	return (swp_entry_t) {0};
 }
 
@@ -491,7 +521,7 @@
 		goto bad_offset;
 	if (!p->swap_map[offset])
 		goto bad_free;
-	spin_lock(&swap_lock);
+	spin_lock(&p->lock);
 	return p;
 
 bad_free:
@@ -509,6 +539,27 @@
 	return NULL;
 }
 
+/*
+ * This swap type frees swap entry, check if it is the highest priority swap
+ * type which just frees swap entry. get_swap_page() uses
+ * highest_priority_index to search highest priority swap type. The
+ * swap_info_struct.lock can't protect us if there are multiple swap types
+ * active, so we use atomic_cmpxchg.
+ */
+static void set_highest_priority_index(int type)
+{
+	int old_hp_index, new_hp_index;
+
+	do {
+		old_hp_index = atomic_read(&highest_priority_index);
+		if (old_hp_index != -1 &&
+			swap_info[old_hp_index]->prio >= swap_info[type]->prio)
+			break;
+		new_hp_index = type;
+	} while (atomic_cmpxchg(&highest_priority_index,
+		old_hp_index, new_hp_index) != old_hp_index);
+}
+
 static unsigned char swap_entry_free(struct swap_info_struct *p,
 				     swp_entry_t entry, unsigned char usage)
 {
@@ -552,10 +603,8 @@
 			p->lowest_bit = offset;
 		if (offset > p->highest_bit)
 			p->highest_bit = offset;
-		if (swap_list.next >= 0 &&
-		    p->prio > swap_info[swap_list.next]->prio)
-			swap_list.next = p->type;
-		nr_swap_pages++;
+		set_highest_priority_index(p->type);
+		atomic_long_inc(&nr_swap_pages);
 		p->inuse_pages--;
 		if ((p->flags & SWP_BLKDEV) &&
 				disk->fops->swap_slot_free_notify)
@@ -576,7 +625,7 @@
 	p = swap_info_get(entry);
 	if (p) {
 		swap_entry_free(p, entry, 1);
-		spin_unlock(&swap_lock);
+		spin_unlock(&p->lock);
 	}
 }
 
@@ -593,7 +642,7 @@
 		count = swap_entry_free(p, entry, SWAP_HAS_CACHE);
 		if (page)
 			mem_cgroup_uncharge_swapcache(page, entry, count != 0);
-		spin_unlock(&swap_lock);
+		spin_unlock(&p->lock);
 	}
 }
 
@@ -612,7 +661,7 @@
 	p = swap_info_get(entry);
 	if (p) {
 		count = swap_count(p->swap_map[swp_offset(entry)]);
-		spin_unlock(&swap_lock);
+		spin_unlock(&p->lock);
 	}
 	return count;
 }
@@ -700,7 +749,7 @@
 				page = NULL;
 			}
 		}
-		spin_unlock(&swap_lock);
+		spin_unlock(&p->lock);
 	}
 	if (page) {
 		/*
@@ -829,11 +878,13 @@
 	if ((unsigned int)type < nr_swapfiles) {
 		struct swap_info_struct *sis = swap_info[type];
 
+		spin_lock(&sis->lock);
 		if (sis->flags & SWP_WRITEOK) {
 			n = sis->pages;
 			if (free)
 				n -= sis->inuse_pages;
 		}
+		spin_unlock(&sis->lock);
 	}
 	spin_unlock(&swap_lock);
 	return n;
@@ -1529,7 +1580,7 @@
 		p->prio = --least_priority;
 	p->swap_map = swap_map;
 	p->flags |= SWP_WRITEOK;
-	nr_swap_pages += p->pages;
+	atomic_long_add(p->pages, &nr_swap_pages);
 	total_swap_pages += p->pages;
 
 	/* insert swap space into swap_list: */
@@ -1606,14 +1657,16 @@
 		/* just pick something that's safe... */
 		swap_list.next = swap_list.head;
 	}
+	spin_lock(&p->lock);
 	if (p->prio < 0) {
 		for (i = p->next; i >= 0; i = swap_info[i]->next)
 			swap_info[i]->prio = p->prio--;
 		least_priority++;
 	}
-	nr_swap_pages -= p->pages;
+	atomic_long_sub(p->pages, &nr_swap_pages);
 	total_swap_pages -= p->pages;
 	p->flags &= ~SWP_WRITEOK;
+	spin_unlock(&p->lock);
 	spin_unlock(&swap_lock);
 
 	oom_score_adj = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX);
@@ -1638,14 +1691,17 @@
 
 	mutex_lock(&swapon_mutex);
 	spin_lock(&swap_lock);
+	spin_lock(&p->lock);
 	drain_mmlist();
 
 	/* wait for anyone still in scan_swap_map */
 	p->highest_bit = 0;		/* cuts scans short */
 	while (p->flags >= SWP_SCANNING) {
+		spin_unlock(&p->lock);
 		spin_unlock(&swap_lock);
 		schedule_timeout_uninterruptible(1);
 		spin_lock(&swap_lock);
+		spin_lock(&p->lock);
 	}
 
 	swap_file = p->swap_file;
@@ -1654,6 +1710,7 @@
 	swap_map = p->swap_map;
 	p->swap_map = NULL;
 	p->flags = 0;
+	spin_unlock(&p->lock);
 	spin_unlock(&swap_lock);
 	mutex_unlock(&swapon_mutex);
 	vfree(swap_map);
@@ -1857,6 +1914,7 @@
 	p->flags = SWP_USED;
 	p->next = -1;
 	spin_unlock(&swap_lock);
+	spin_lock_init(&p->lock);
 
 	return p;
 }
@@ -2178,7 +2236,7 @@
 		if ((si->flags & SWP_USED) && !(si->flags & SWP_WRITEOK))
 			nr_to_be_unused += si->inuse_pages;
 	}
-	val->freeswap = nr_swap_pages + nr_to_be_unused;
+	val->freeswap = atomic_long_read(&nr_swap_pages) + nr_to_be_unused;
 	val->totalswap = total_swap_pages + nr_to_be_unused;
 	spin_unlock(&swap_lock);
 }
@@ -2211,7 +2269,7 @@
 	p = swap_info[type];
 	offset = swp_offset(entry);
 
-	spin_lock(&swap_lock);
+	spin_lock(&p->lock);
 	if (unlikely(offset >= p->max))
 		goto unlock_out;
 
@@ -2246,7 +2304,7 @@
 	p->swap_map[offset] = count | has_cache;
 
 unlock_out:
-	spin_unlock(&swap_lock);
+	spin_unlock(&p->lock);
 out:
 	return err;
 
@@ -2371,7 +2429,7 @@
 	}
 
 	if (!page) {
-		spin_unlock(&swap_lock);
+		spin_unlock(&si->lock);
 		return -ENOMEM;
 	}
 
@@ -2419,7 +2477,7 @@
 	list_add_tail(&page->lru, &head->lru);
 	page = NULL;			/* now it's attached, don't free it */
 out:
-	spin_unlock(&swap_lock);
+	spin_unlock(&si->lock);
 outer:
 	if (page)
 		__free_page(page);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 1438de9..d0e40e5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -158,8 +158,28 @@
 	return &mz->zone->reclaim_stat;
 }
 
+unsigned long zone_reclaimable_pages(struct zone *zone)
+{
+	int nr;
+
+	nr = zone_page_state(zone, NR_ACTIVE_FILE) +
+	     zone_page_state(zone, NR_INACTIVE_FILE);
+
+	if (get_nr_swap_pages() > 0)
+		nr += zone_page_state(zone, NR_ACTIVE_ANON) +
+		      zone_page_state(zone, NR_INACTIVE_ANON);
+
+	return nr;
+}
+
+bool zone_reclaimable(struct zone *zone)
+{
+	return zone->pages_scanned < zone_reclaimable_pages(zone) * 6;
+}
+
 static unsigned long zone_nr_lru_pages(struct mem_cgroup_zone *mz,
 				       enum lru_list lru)
+
 {
 	if (!mem_cgroup_disabled())
 		return mem_cgroup_zone_nr_lru_pages(mz->mem_cgroup,
@@ -454,6 +474,8 @@
 		if (!PageWriteback(page)) {
 			/* synchronous write or broken a_ops? */
 			ClearPageReclaim(page);
+			if (PageError(page))
+				return PAGE_ACTIVATE;
 		}
 		trace_mm_vmscan_writepage(page, trace_reclaim_flags(page));
 		inc_zone_page_state(page, NR_VMSCAN_WRITE);
@@ -1648,13 +1670,13 @@
 	 * latencies, so it's better to scan a minimum amount there as
 	 * well.
 	 */
-	if (current_is_kswapd() && mz->zone->all_unreclaimable)
+	if (current_is_kswapd() && !zone_reclaimable(mz->zone))
 		force_scan = true;
 	if (!global_reclaim(sc))
 		force_scan = true;
 
 	/* If we have no swap space, do not bother scanning anon pages. */
-	if (!sc->may_swap || (nr_swap_pages <= 0)) {
+	if (!sc->may_swap || (get_nr_swap_pages() <= 0)) {
 		noswap = 1;
 		fraction[0] = 0;
 		fraction[1] = 1;
@@ -1798,7 +1820,7 @@
 	 */
 	pages_for_compaction = (2UL << sc->order);
 	inactive_lru_pages = zone_nr_lru_pages(mz, LRU_INACTIVE_FILE);
-	if (nr_swap_pages > 0)
+	if (get_nr_swap_pages() > 0)
 		inactive_lru_pages += zone_nr_lru_pages(mz, LRU_INACTIVE_ANON);
 	if (sc->nr_reclaimed < pages_for_compaction &&
 			inactive_lru_pages > pages_for_compaction)
@@ -1995,8 +2017,8 @@
 		if (global_reclaim(sc)) {
 			if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 				continue;
-			if (zone->all_unreclaimable &&
-					sc->priority != DEF_PRIORITY)
+			if (sc->priority != DEF_PRIORITY &&
+			    !zone_reclaimable(zone))
 				continue;	/* Let kswapd poll it */
 			if (COMPACTION_BUILD) {
 				/*
@@ -2034,11 +2056,6 @@
 	return aborted_reclaim;
 }
 
-static bool zone_reclaimable(struct zone *zone)
-{
-	return zone->pages_scanned < zone_reclaimable_pages(zone) * 6;
-}
-
 /* All zones in zonelist are unreclaimable? */
 static bool all_unreclaimable(struct zonelist *zonelist,
 		struct scan_control *sc)
@@ -2052,7 +2069,7 @@
 			continue;
 		if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 			continue;
-		if (!zone->all_unreclaimable)
+		if (zone_reclaimable(zone))
 			return false;
 	}
 
@@ -2377,7 +2394,7 @@
 		 * they must be considered balanced here as well if kswapd
 		 * is to sleep
 		 */
-		if (zone->all_unreclaimable) {
+		if (!zone_reclaimable(zone)) {
 			balanced += zone->present_pages;
 			continue;
 		}
@@ -2470,8 +2487,8 @@
 			if (!populated_zone(zone))
 				continue;
 
-			if (zone->all_unreclaimable &&
-			    sc.priority != DEF_PRIORITY)
+			if (sc.priority != DEF_PRIORITY &&
+			    !zone_reclaimable(zone))
 				continue;
 
 			/*
@@ -2525,8 +2542,8 @@
 			if (!populated_zone(zone))
 				continue;
 
-			if (zone->all_unreclaimable &&
-			    sc.priority != DEF_PRIORITY)
+			if (sc.priority != DEF_PRIORITY &&
+			    !zone_reclaimable(zone))
 				continue;
 
 			sc.nr_scanned = 0;
@@ -2576,8 +2593,6 @@
 				sc.nr_reclaimed += reclaim_state->reclaimed_slab;
 				total_scanned += sc.nr_scanned;
 
-				if (nr_slab == 0 && !zone_reclaimable(zone))
-					zone->all_unreclaimable = 1;
 			}
 
 			/*
@@ -2589,7 +2604,7 @@
 			    total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2)
 				sc.may_writepage = 1;
 
-			if (zone->all_unreclaimable) {
+			if (!zone_reclaimable(zone)) {
 				if (end_zone && end_zone == i)
 					end_zone--;
 				continue;
@@ -2912,27 +2927,13 @@
 	nr = global_page_state(NR_ACTIVE_FILE) +
 	     global_page_state(NR_INACTIVE_FILE);
 
-	if (nr_swap_pages > 0)
+	if (get_nr_swap_pages() > 0)
 		nr += global_page_state(NR_ACTIVE_ANON) +
 		      global_page_state(NR_INACTIVE_ANON);
 
 	return nr;
 }
 
-unsigned long zone_reclaimable_pages(struct zone *zone)
-{
-	int nr;
-
-	nr = zone_page_state(zone, NR_ACTIVE_FILE) +
-	     zone_page_state(zone, NR_INACTIVE_FILE);
-
-	if (nr_swap_pages > 0)
-		nr += zone_page_state(zone, NR_ACTIVE_ANON) +
-		      zone_page_state(zone, NR_INACTIVE_ANON);
-
-	return nr;
-}
-
 #ifdef CONFIG_HIBERNATION
 /*
  * Try to free `nr_to_reclaim' of memory, system-wide, and return the number of
@@ -3227,7 +3228,7 @@
 	    zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages)
 		return ZONE_RECLAIM_FULL;
 
-	if (zone->all_unreclaimable)
+	if (!zone_reclaimable(zone))
 		return ZONE_RECLAIM_FULL;
 
 	/*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 959a558..9559032 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -19,6 +19,9 @@
 #include <linux/math64.h>
 #include <linux/writeback.h>
 #include <linux/compaction.h>
+#include <linux/mm_inline.h>
+
+#include "internal.h"
 
 #ifdef CONFIG_VM_EVENT_COUNTERS
 DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
@@ -1027,7 +1030,7 @@
 		   "\n  all_unreclaimable: %u"
 		   "\n  start_pfn:         %lu"
 		   "\n  inactive_ratio:    %u",
-		   zone->all_unreclaimable,
+		   !zone_reclaimable(zone),
 		   zone->zone_start_pfn,
 		   zone->inactive_ratio);
 	seq_putc(m, '\n');
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index b96094c..036f8ae 100755
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -883,7 +883,19 @@
 	chan->max_antenna_gain = min(chan->orig_mag,
 		(int) MBI_TO_DBI(power_rule->max_antenna_gain));
 	chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
-	chan->max_power = min(chan->max_power, chan->max_reg_power);
+	if (chan->orig_mpwr) {
+		/*
+		 * Devices that use NL80211_COUNTRY_IE_FOLLOW_POWER will always
+		 * follow the passed country IE power settings.
+		 */
+		if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
+		    wiphy->country_ie_pref & NL80211_COUNTRY_IE_FOLLOW_POWER)
+			chan->max_power = chan->max_reg_power;
+		else
+			chan->max_power = min(chan->orig_mpwr,
+					      chan->max_reg_power);
+	} else
+		chan->max_power = chan->max_reg_power;
 }
 
 static void handle_band(struct wiphy *wiphy,
@@ -1295,6 +1307,8 @@
 	case NL80211_REGDOM_SET_BY_CORE:
 		return 0;
 	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+		if (wiphy->country_ie_pref & NL80211_COUNTRY_IE_IGNORE_CORE)
+			return -EALREADY;
 
 		last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
 
@@ -1648,6 +1662,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(regulatory_hint_user);
 
 /* Driver hints */
 int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index e2aaaf5..017880c 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -22,8 +22,6 @@
 bool reg_is_valid_request(const char *alpha2);
 bool reg_supported_dfs_region(u8 dfs_region);
 
-int regulatory_hint_user(const char *alpha2);
-
 int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
 void reg_device_remove(struct wiphy *wiphy);
 
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 6785fe1..55fec32 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -2582,6 +2582,8 @@
 	 */
 	{MSM8X10_WCD_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
 	{MSM8X10_WCD_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+	{MSM8X10_WCD_A_RX_HPH_L_TEST, 0x01, 0x01},
+	{MSM8X10_WCD_A_RX_HPH_R_TEST, 0x01, 0x01},
 
 	/* Initialize gain registers to use register gain */
 	{MSM8X10_WCD_A_RX_HPH_L_GAIN, 0x20, 0x20},
@@ -3007,10 +3009,21 @@
 
 	return NULL;
 }
+static int msm8x10_wcd_device_down(struct snd_soc_codec *codec)
+{
+	dev_dbg(codec->dev, "%s: device down!\n", __func__);
+
+	snd_soc_card_change_online_state(codec->card, 0);
+	return 0;
+}
 
 static int msm8x10_wcd_device_up(struct snd_soc_codec *codec)
 {
-	pr_debug("%s: device up!\n", __func__);
+	dev_dbg(codec->dev, "%s: device up!\n", __func__);
+
+	snd_soc_card_change_online_state(codec->card, 1);
+	/* delay is required to make sure sound card state updated */
+	usleep_range(5000, 5100);
 
 	mutex_lock(&codec->mutex);
 
@@ -3029,7 +3042,9 @@
 	bool timedout;
 	unsigned long timeout;
 
-	if (value == SUBSYS_AFTER_POWERUP) {
+	if (value == SUBSYS_BEFORE_SHUTDOWN)
+		msm8x10_wcd_device_down(registered_codec);
+	else if (value == SUBSYS_AFTER_POWERUP) {
 		pr_debug("%s: ADSP is about to power up. bring up codec\n",
 			 __func__);
 
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index e5d5c32..b406feb 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -21,6 +21,8 @@
 
 #define MSM_HDMI_PCM_RATES	SNDRV_PCM_RATE_48000
 
+static int msm_hdmi_audio_codec_return_value;
+
 struct msm_hdmi_audio_codec_rx_data {
 	struct platform_device *hdmi_core_pdev;
 	struct msm_hdmi_audio_codec_ops hdmi_ops;
@@ -54,8 +56,8 @@
 	int rc;
 
 	codec_data = snd_soc_codec_get_drvdata(codec);
-	rc = codec_data->hdmi_ops.get_audio_edid_blk(codec_data->hdmi_core_pdev,
-						     &edid_blk);
+	rc = codec_data->hdmi_ops.get_audio_edid_blk(
+			codec_data->hdmi_core_pdev, &edid_blk);
 
 	if (!IS_ERR_VALUE(rc)) {
 		memcpy(ucontrol->value.bytes.data, edid_blk.audio_data_blk,
@@ -80,6 +82,24 @@
 	},
 };
 
+static int msm_hdmi_audio_codec_rx_dai_startup(
+		struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct msm_hdmi_audio_codec_rx_data *codec_data =
+			dev_get_drvdata(dai->codec->dev);
+
+	msm_hdmi_audio_codec_return_value =
+		codec_data->hdmi_ops.hdmi_cable_status(
+		codec_data->hdmi_core_pdev, 1);
+	if (IS_ERR_VALUE(msm_hdmi_audio_codec_return_value)) {
+		dev_err(dai->dev,
+			"%s() HDMI core is not ready\n", __func__);
+	}
+
+	return msm_hdmi_audio_codec_return_value;
+}
+
 static int msm_hdmi_audio_codec_rx_dai_hw_params(
 		struct snd_pcm_substream *substream,
 		struct snd_pcm_hw_params *params,
@@ -89,10 +109,17 @@
 	u32 level_shift  = 0; /* 0dB */
 	bool down_mix = 0;
 	u32 num_channels = params_channels(params);
+	int rc = 0;
 
 	struct msm_hdmi_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->codec->dev);
 
+	if (IS_ERR_VALUE(msm_hdmi_audio_codec_return_value)) {
+		dev_err(dai->dev,
+			"%s() HDMI core is not ready\n", __func__);
+		return msm_hdmi_audio_codec_return_value;
+	}
+
 	switch (num_channels) {
 	case 2:
 		channel_allocation  = 0;
@@ -108,19 +135,47 @@
 		return -EINVAL;
 	}
 
-	dev_dbg(dai->dev, "%s() num_ch %u  samplerate %u channel_allocation = %u\n",
+	dev_dbg(dai->dev,
+		"%s() num_ch %u  samplerate %u channel_allocation = %u\n",
 		__func__, num_channels, params_rate(params),
 		channel_allocation);
 
-	codec_data->hdmi_ops.audio_info_setup(codec_data->hdmi_core_pdev,
-			params_rate(params), num_channels, channel_allocation,
-			level_shift, down_mix);
+	rc = codec_data->hdmi_ops.audio_info_setup(
+			codec_data->hdmi_core_pdev,
+			params_rate(params), num_channels,
+			channel_allocation, level_shift, down_mix);
+	if (IS_ERR_VALUE(rc)) {
+		dev_err(dai->dev,
+			"%s() HDMI core is not ready\n", __func__);
+	}
 
-	return 0;
+	return rc;
+}
+
+static void msm_hdmi_audio_codec_rx_dai_shutdown(
+		struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	int rc;
+
+	struct msm_hdmi_audio_codec_rx_data *codec_data =
+			dev_get_drvdata(dai->codec->dev);
+
+	rc = codec_data->hdmi_ops.hdmi_cable_status(
+			codec_data->hdmi_core_pdev, 0);
+	if (IS_ERR_VALUE(rc)) {
+		dev_err(dai->dev,
+			"%s() HDMI core had problems releasing HDMI audio flag\n",
+			__func__);
+	}
+
+	return;
 }
 
 static struct snd_soc_dai_ops msm_hdmi_audio_codec_rx_dai_ops = {
+	.startup	= msm_hdmi_audio_codec_rx_dai_startup,
 	.hw_params	= msm_hdmi_audio_codec_rx_dai_hw_params,
+	.shutdown	= msm_hdmi_audio_codec_rx_dai_shutdown
 };
 
 static int msm_hdmi_audio_codec_rx_probe(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index bc02513..c62f875 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -260,6 +260,8 @@
 
 #define TAIKO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
 
+#define TAIKO_SLIM_PGD_PORT_INT_TX_EN0 (TAIKO_SLIM_PGD_PORT_INT_EN0 + 2)
+
 enum {
 	AIF1_PB = 0,
 	AIF1_CAP,
@@ -4884,6 +4886,46 @@
 	return ret;
 }
 
+static void taiko_codec_enable_int_port(struct wcd9xxx_codec_dai_data *dai,
+					  struct snd_soc_codec *codec)
+{
+	struct wcd9xxx_ch *ch;
+	int port_num = 0;
+	unsigned short reg = 0;
+	u8 val = 0;
+	if (!dai || !codec) {
+		pr_err("%s: Invalid params\n", __func__);
+		return;
+	}
+	list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
+		if (ch->port >= TAIKO_RX_PORT_START_NUMBER) {
+			port_num = ch->port - TAIKO_RX_PORT_START_NUMBER;
+			reg = TAIKO_SLIM_PGD_PORT_INT_EN0 + (port_num / 8);
+			val = wcd9xxx_interface_reg_read(codec->control_data,
+				reg);
+			if (!(val & (1 << (port_num % 8)))) {
+				val |= (1 << (port_num % 8));
+				wcd9xxx_interface_reg_write(
+					codec->control_data, reg, val);
+				val = wcd9xxx_interface_reg_read(
+					codec->control_data, reg);
+			}
+		} else {
+			port_num = ch->port;
+			reg = TAIKO_SLIM_PGD_PORT_INT_TX_EN0 + (port_num / 8);
+			val = wcd9xxx_interface_reg_read(codec->control_data,
+				reg);
+			if (!(val & (1 << (port_num % 8)))) {
+				val |= (1 << (port_num % 8));
+				wcd9xxx_interface_reg_write(codec->control_data,
+					reg, val);
+				val = wcd9xxx_interface_reg_read(
+					codec->control_data, reg);
+			}
+		}
+	}
+}
+
 static int taiko_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
 				     struct snd_kcontrol *kcontrol,
 				     int event)
@@ -4910,6 +4952,7 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
+		taiko_codec_enable_int_port(dai, codec);
 		(void) taiko_codec_enable_slim_chmask(dai, true);
 		ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
 					      dai->rate, dai->bit_width,
@@ -4974,6 +5017,7 @@
 		/*Enable spkr VI clocks*/
 		snd_soc_update_bits(codec,
 		TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
+		taiko_codec_enable_int_port(dai, codec);
 		(void) taiko_codec_enable_slim_chmask(dai, true);
 		ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
 					dai->rate, dai->bit_width,
@@ -5021,6 +5065,7 @@
 	dai = &taiko_p->dai[w->shift];
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
+		taiko_codec_enable_int_port(dai, codec);
 		(void) taiko_codec_enable_slim_chmask(dai, true);
 		ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
 					      dai->rate, dai->bit_width,
@@ -5629,8 +5674,9 @@
 	unsigned long status = 0;
 	int i, j, port_id, k;
 	u32 bit;
-	u8 val;
+	u8 val, int_val = 0;
 	bool tx, cleared;
+	unsigned short reg = 0;
 
 	for (i = TAIKO_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
 	     i <= TAIKO_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
@@ -5645,12 +5691,28 @@
 					TAIKO_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
 		if (val & TAIKO_SLIM_IRQ_OVERFLOW)
 			pr_err_ratelimited(
-			    "%s: overflow error on %s port %d, value %x\n",
-			    __func__, (tx ? "TX" : "RX"), port_id, val);
+			   "%s: overflow error on %s port %d, value %x\n",
+			   __func__, (tx ? "TX" : "RX"), port_id, val);
 		if (val & TAIKO_SLIM_IRQ_UNDERFLOW)
 			pr_err_ratelimited(
-			    "%s: underflow error on %s port %d, value %x\n",
-			    __func__, (tx ? "TX" : "RX"), port_id, val);
+			   "%s: underflow error on %s port %d, value %x\n",
+			   __func__, (tx ? "TX" : "RX"), port_id, val);
+		if ((val & TAIKO_SLIM_IRQ_OVERFLOW) ||
+			(val & TAIKO_SLIM_IRQ_UNDERFLOW)) {
+			if (!tx)
+				reg = TAIKO_SLIM_PGD_PORT_INT_EN0 +
+					(port_id / 8);
+			else
+				reg = TAIKO_SLIM_PGD_PORT_INT_TX_EN0 +
+					(port_id / 8);
+			int_val = wcd9xxx_interface_reg_read(
+				codec->control_data, reg);
+			if (int_val & (1 << (port_id % 8))) {
+				int_val = int_val ^ (1 << (port_id % 8));
+				wcd9xxx_interface_reg_write(codec->control_data,
+					reg, int_val);
+			}
+		}
 		if (val & TAIKO_SLIM_IRQ_PORT_CLOSED) {
 			/*
 			 * INT SOURCE register starts from RX to TX
@@ -5975,6 +6037,10 @@
 
 	/* Set HPH Path to low power mode */
 	TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x55),
+
+	/* BUCK default */
+	TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x51),
+	TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
 };
 
 static const struct wcd9xxx_reg_mask_val taiko_1_0_reg_defaults[] = {
@@ -5983,13 +6049,9 @@
 	 * Taiko 2.0 will have appropriate defaults for these registers.
 	 */
 
-	/* BUCK default */
-	TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x50),
-
 	/* Required defaults for class H operation */
 	TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xF4),
 	TAIKO_REG_VAL(TAIKO_A_BIAS_CURR_CTL_2, 0x08),
-	TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
 	TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
 
 	/* Choose max non-overlap time for NCP */
@@ -6040,7 +6102,7 @@
 	TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_6_ADC_IB, 0x44),
 	TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
 	TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x8),
-	TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x51),
+	TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_4, 0x51),
 	TAIKO_REG_VAL(TAIKO_A_NCP_DTEST, 0x10),
 	TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xA4),
 	TAIKO_REG_VAL(TAIKO_A_RX_HPH_OCP_CTL, 0x69),
@@ -6081,6 +6143,7 @@
 	TAIKO_REG_VAL(TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL, 0x0),
 	TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B4_CTL, 0x37),
 	TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B5_CTL, 0x7f),
+	TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B5_CTL, 0x7f),
 };
 
 static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index 05f2191..b104a6b 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -22,12 +22,11 @@
 #define CLSH_COMPUTE_HPH_L 0x02
 #define CLSH_COMPUTE_HPH_R 0x03
 
+#define BUCK_VREF_0P494V 0x3F
 #define BUCK_VREF_2V 0xFF
+#define BUCK_VREF_0P494V 0x3F
 #define BUCK_VREF_1P8V 0xE6
 
-#define NCP_FCLK_LEVEL_8 0x08
-#define NCP_FCLK_LEVEL_5 0x05
-
 #define BUCK_SETTLE_TIME_US 50
 #define NCP_SETTLE_TIME_US 50
 
@@ -414,12 +413,16 @@
 	{32164, 22},
 };
 
-static inline void wcd9xxx_enable_clsh_block(
-	struct snd_soc_codec *codec,
-	bool on)
+static inline void
+wcd9xxx_enable_clsh_block(struct snd_soc_codec *codec,
+			  struct wcd9xxx_clsh_cdc_data *clsh_d, bool enable)
 {
-	snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
-		0x01, on ? 0x01 : 0x00);
+	if ((enable && ++clsh_d->clsh_users == 1) ||
+	    (!enable && --clsh_d->clsh_users == 0))
+		snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
+				    0x01, enable ? 0x01 : 0x00);
+	dev_dbg(codec->dev, "%s: clsh_users %d, enable %d", __func__,
+		clsh_d->clsh_users, enable);
 }
 
 static inline void wcd9xxx_enable_anc_delay(
@@ -430,64 +433,56 @@
 		0x02, on ? 0x02 : 0x00);
 }
 
-static inline void wcd9xxx_enable_ncp(
-	struct snd_soc_codec *codec,
-	bool on)
+static inline void
+wcd9xxx_enable_buck(struct snd_soc_codec *codec,
+		    struct wcd9xxx_clsh_cdc_data *clsh_d, bool enable)
 {
-	snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
-		0x01, on ? 0x01 : 0x00);
+	if ((enable && ++clsh_d->buck_users == 1) ||
+	    (!enable && --clsh_d->buck_users == 0))
+		snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
+				    0x80, enable ? 0x80 : 0x00);
+	dev_dbg(codec->dev, "%s: buck_users %d, enable %d", __func__,
+		clsh_d->buck_users, enable);
 }
 
-static inline void wcd9xxx_enable_buck(
-	struct snd_soc_codec *codec,
-	bool on)
-{
-	snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
-		0x80, on ? 0x80 : 0x00);
-}
+static void (*clsh_state_fp[NUM_CLSH_STATES])(struct snd_soc_codec *,
+					      struct wcd9xxx_clsh_cdc_data *,
+					      u8 req_state, bool req_type);
 
-static int cdc_lo_count;
-
-static void (*clsh_state_fp[NUM_CLSH_STATES])
-			(struct snd_soc_codec *,
-			 struct wcd9xxx_clsh_cdc_data *,
-			 u8 req_state, bool req_type);
-
-static const char *state_to_str(u8 state)
-{
-	if (state == WCD9XXX_CLSH_STATE_IDLE)
-		return "STATE_IDLE";
-	else if (state == WCD9XXX_CLSH_STATE_EAR)
-		return "STATE_EAR";
-	else if (state == WCD9XXX_CLSH_STATE_HPHL)
-		return "STATE_HPH_L";
-	else if (state == WCD9XXX_CLSH_STATE_HPHR)
-		return "STATE_HPH_R";
-	else if (state == (WCD9XXX_CLSH_STATE_HPHL
-				| WCD9XXX_CLSH_STATE_HPHR))
-		return "STATE_HPH_L_R";
-	else if (state == WCD9XXX_CLSH_STATE_LO)
-		return "STATE_LO";
-
-	return "UNKNOWN_STATE";
-}
-
-static void wcd9xxx_cfg_clsh_buck(
-		struct snd_soc_codec *codec)
+static const char *state_to_str(u8 state, char *buf, size_t buflen)
 {
 	int i;
-	const struct wcd9xxx_reg_mask_val reg_set[] = {
-		{WCD9XXX_A_BUCK_CTRL_CCL_4, 0x0B, 0x00},
-		{WCD9XXX_A_BUCK_CTRL_CCL_1, 0xF0, 0x50},
-		{WCD9XXX_A_BUCK_CTRL_CCL_3, 0x03, 0x00},
-		{WCD9XXX_A_BUCK_CTRL_CCL_3, 0x0B, 0x00},
+	int cnt = 0;
+	/*
+	 * This array of strings should match with enum wcd9xxx_clsh_state_bit.
+	 */
+	const char *states[] = {
+		"STATE_EAR",
+		"STATE_HPH_L",
+		"STATE_HPH_R",
+		"STATE_LO",
 	};
 
-	for (i = 0; i < ARRAY_SIZE(reg_set); i++)
-		snd_soc_update_bits(codec, reg_set[i].reg, reg_set[i].mask,
-						    reg_set[i].val);
+	if (state == WCD9XXX_CLSH_STATE_IDLE) {
+		snprintf(buf, buflen, "[STATE_IDLE]");
+		goto done;
+	}
 
-	dev_dbg(codec->dev, "%s: Programmed buck parameters", __func__);
+	buf[0] = '\0';
+	for (i = 0; i < ARRAY_SIZE(states); i++) {
+		if (!(state & (1 << i)))
+			continue;
+		cnt = snprintf(buf, buflen - cnt - 1, "%s%s%s", buf,
+			       buf[0] == '\0' ? "[" : "|",
+			       states[i]);
+	}
+	if (cnt > 0)
+		strlcat(buf + cnt, "]", buflen);
+
+done:
+	if (buf[0] == '\0')
+		snprintf(buf, buflen, "[STATE_UNKNOWN]");
+	return buf;
 }
 
 static void wcd9xxx_cfg_clsh_param_common(
@@ -515,26 +510,25 @@
 			 __func__);
 }
 
-static void wcd9xxx_chargepump_request(
-	struct snd_soc_codec *codec, bool on)
+static void wcd9xxx_chargepump_request(struct snd_soc_codec *codec, bool on)
 {
 	static int cp_count;
 
 	if (on && (++cp_count == 1)) {
 		snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
-							0x01, 0x01);
+				    0x01, 0x01);
 		dev_dbg(codec->dev, "%s: Charge Pump enabled, count = %d\n",
-				__func__, cp_count);
-	}
-
-	else if (!on) {
+			__func__, cp_count);
+	} else if (!on) {
 		if (--cp_count < 0) {
-			dev_dbg(codec->dev, "%s: Unbalanced disable for charge pump\n",
+			dev_dbg(codec->dev,
+				"%s: Unbalanced disable for charge pump\n",
+				__func__);
+			if (snd_soc_read(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL) &
+			    0x01) {
+				dev_dbg(codec->dev,
+					"%s: Actual chargepump is ON\n",
 					__func__);
-			if (snd_soc_read(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL)
-					& 0x01) {
-				dev_dbg(codec->dev, "%s: Actual chargepump is ON\n",
-						__func__);
 			}
 			cp_count = 0;
 			WARN_ON(1);
@@ -542,9 +536,10 @@
 
 		if (cp_count == 0) {
 			snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
-							0x01, 0x00);
-			dev_dbg(codec->dev, "%s: Charge pump disabled, count = %d\n",
-					__func__, cp_count);
+					    0x01, 0x00);
+			dev_dbg(codec->dev,
+				"%s: Charge pump disabled, count = %d\n",
+				__func__, cp_count);
 		}
 	}
 }
@@ -617,7 +612,6 @@
 	}
 }
 
-
 int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
 					struct list_head *list,
 					uint16_t reg, uint8_t mask,
@@ -657,18 +651,15 @@
 }
 EXPORT_SYMBOL(wcd9xxx_restore_registers);
 
-static void wcd9xxx_enable_buck_mode(struct snd_soc_codec *codec,
-		u8 buck_vref)
+static void wcd9xxx_set_buck_mode(struct snd_soc_codec *codec, u8 buck_vref)
 {
 	int i;
 	const struct wcd9xxx_reg_mask_val reg_set[] = {
-		{WCD9XXX_A_BUCK_MODE_5, 0x02, 0x03},
+		{WCD9XXX_A_BUCK_MODE_5, 0x02, 0x02},
 		{WCD9XXX_A_BUCK_MODE_4, 0xFF, buck_vref},
 		{WCD9XXX_A_BUCK_MODE_1, 0x04, 0x04},
-		{WCD9XXX_A_BUCK_MODE_1, 0x08, 0x00},
 		{WCD9XXX_A_BUCK_MODE_3, 0x04, 0x00},
 		{WCD9XXX_A_BUCK_MODE_3, 0x08, 0x00},
-		{WCD9XXX_A_BUCK_MODE_1, 0x80, 0x80},
 	};
 
 	for (i = 0; i < ARRAY_SIZE(reg_set); i++)
@@ -704,25 +695,51 @@
 
 }
 
-static void wcd9xxx_set_fclk_enable_ncp(struct snd_soc_codec *codec,
-		u8 fclk_level)
+static void wcd9xxx_set_fclk_get_ncp(struct snd_soc_codec *codec,
+				     struct wcd9xxx_clsh_cdc_data *clsh_d,
+				     enum ncp_fclk_level fclk_level)
 {
-	int i;
-	const struct wcd9xxx_reg_mask_val reg_set[] = {
-		{WCD9XXX_A_NCP_STATIC, 0x20, 0x20},
-		{WCD9XXX_A_NCP_EN, 0x01, 0x01},
-	};
-	snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
-						0x010, 0x00);
-	snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
-						0x0F, fclk_level);
-	for (i = 0; i < ARRAY_SIZE(reg_set); i++)
-		snd_soc_update_bits(codec, reg_set[i].reg,
-					reg_set[i].mask, reg_set[i].val);
+	clsh_d->ncp_users[fclk_level]++;
 
-	usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US);
+	pr_debug("%s: enter ncp type %d users fclk8 %d, fclk5 %d\n", __func__,
+		 fclk_level, clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
+		 clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
 
-	dev_dbg(codec->dev, "%s: set ncp done\n", __func__);
+	snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x10, 0x00);
+	/* fclk level 8 dominates level 5 */
+	if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] > 0)
+		snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x08);
+	else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_5] > 0)
+		snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x05);
+	else
+		WARN_ONCE(1, "Unexpected users %d,%d\n",
+			  clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
+			  clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
+	snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x20, 0x20);
+
+	/* enable NCP and wait until settles down */
+	if (snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x01))
+		usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US);
+	pr_debug("%s: leave\n", __func__);
+}
+
+static void wcd9xxx_set_fclk_put_ncp(struct snd_soc_codec *codec,
+				     struct wcd9xxx_clsh_cdc_data *clsh_d,
+				     enum ncp_fclk_level fclk_level)
+{
+	clsh_d->ncp_users[fclk_level]--;
+
+	pr_debug("%s: enter ncp type %d users fclk8 %d, fclk5 %d\n", __func__,
+		 fclk_level, clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
+		 clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
+
+	if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0 &&
+	    clsh_d->ncp_users[NCP_FCLK_LEVEL_5] == 0)
+		snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x00);
+	else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0)
+		/* if dominating level 8 has gone, switch to 5 */
+		snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x05);
+	pr_debug("%s: leave\n", __func__);
 }
 
 static void wcd9xxx_cfg_clsh_param_ear(struct snd_soc_codec *codec)
@@ -790,72 +807,30 @@
 			 __func__);
 }
 
-static void wcd9xxx_clsh_turnoff_postpa
-	(struct snd_soc_codec *codec)
-{
-
-	int i;
-
-	const struct wcd9xxx_reg_mask_val reg_set[] = {
-		{WCD9XXX_A_NCP_EN, 0x01, 0x00},
-		{WCD9XXX_A_BUCK_MODE_1, 0x80, 0x00},
-		{WCD9XXX_A_CDC_CLSH_B1_CTL, 0x10, 0x00},
-	};
-
-	wcd9xxx_chargepump_request(codec, false);
-
-	for (i = 0; i < ARRAY_SIZE(reg_set); i++)
-		snd_soc_update_bits(codec, reg_set[i].reg,
-				reg_set[i].mask, reg_set[i].val);
-
-	wcd9xxx_enable_clsh_block(codec, false);
-
-	dev_dbg(codec->dev, "%s: Done\n", __func__);
-}
-
-static void wcd9xxx_clsh_state_idle(struct snd_soc_codec *codec,
-			struct wcd9xxx_clsh_cdc_data *clsh_d,
-			u8 req_state, bool is_enable)
-{
-	if (is_enable) {
-		dev_dbg(codec->dev, "%s: wrong transition, cannot enable IDLE state\n",
-			   __func__);
-	} else {
-		if (req_state == WCD9XXX_CLSH_STATE_EAR) {
-			wcd9xxx_clsh_turnoff_postpa(codec);
-		} else if (req_state == WCD9XXX_CLSH_STATE_HPHL) {
-			wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L,
-					      false);
-			wcd9xxx_clsh_turnoff_postpa(codec);
-		} else if (req_state == WCD9XXX_CLSH_STATE_HPHR) {
-			wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R,
-					      false);
-			wcd9xxx_clsh_turnoff_postpa(codec);
-		} else if (req_state == WCD9XXX_CLSH_STATE_LO) {
-			wcd9xxx_enable_ncp(codec, false);
-			wcd9xxx_enable_buck(codec, false);
-		}
-	}
-}
-
 static void wcd9xxx_clsh_state_ear(struct snd_soc_codec *codec,
 			struct wcd9xxx_clsh_cdc_data *clsh_d,
 			u8 req_state, bool is_enable)
 {
+	pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
 	if (is_enable) {
-		wcd9xxx_cfg_clsh_buck(codec);
 		wcd9xxx_cfg_clsh_param_common(codec);
 		wcd9xxx_cfg_clsh_param_ear(codec);
-		wcd9xxx_enable_clsh_block(codec, true);
+		wcd9xxx_enable_clsh_block(codec, clsh_d, true);
 		wcd9xxx_chargepump_request(codec, true);
 		wcd9xxx_enable_anc_delay(codec, true);
 		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
-		wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
-		wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+		wcd9xxx_set_buck_mode(codec, BUCK_VREF_2V);
+		wcd9xxx_enable_buck(codec, clsh_d, true);
+		wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
 
 		dev_dbg(codec->dev, "%s: Enabled ear mode class h\n", __func__);
 	} else {
 		dev_dbg(codec->dev, "%s: stub fallback to ear\n", __func__);
+		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
+		wcd9xxx_enable_buck(codec, clsh_d, false);
+		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
+		wcd9xxx_chargepump_request(codec, false);
+		wcd9xxx_enable_clsh_block(codec, clsh_d, false);
 	}
 }
 
@@ -863,26 +838,26 @@
 		struct wcd9xxx_clsh_cdc_data *clsh_d,
 		u8 req_state, bool is_enable)
 {
+	pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
+
 	if (is_enable) {
-		wcd9xxx_cfg_clsh_buck(codec);
 		wcd9xxx_cfg_clsh_param_common(codec);
 		wcd9xxx_cfg_clsh_param_hph(codec);
-		wcd9xxx_enable_clsh_block(codec, true);
+		wcd9xxx_enable_clsh_block(codec, clsh_d, true);
 		wcd9xxx_chargepump_request(codec, true);
 		wcd9xxx_enable_anc_delay(codec, true);
 		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, true);
-		wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
-		wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+		wcd9xxx_set_buck_mode(codec, BUCK_VREF_0P494V);
+		wcd9xxx_enable_buck(codec, clsh_d, true);
+		wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
 
 		dev_dbg(codec->dev, "%s: Done\n", __func__);
 	} else {
-		if (req_state == WCD9XXX_CLSH_STATE_HPHR) {
-			wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R,
-					      false);
-		} else {
-			dev_dbg(codec->dev, "%s: stub fallback to hph_l\n",
-					__func__);
-		}
+		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
+		wcd9xxx_enable_buck(codec, clsh_d, false);
+		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, false);
+		wcd9xxx_chargepump_request(codec, false);
+		wcd9xxx_enable_clsh_block(codec, clsh_d, false);
 	}
 }
 
@@ -890,27 +865,26 @@
 		struct wcd9xxx_clsh_cdc_data *clsh_d,
 		u8 req_state, bool is_enable)
 {
-	if (is_enable) {
+	pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
 
-		wcd9xxx_cfg_clsh_buck(codec);
+	if (is_enable) {
 		wcd9xxx_cfg_clsh_param_common(codec);
 		wcd9xxx_cfg_clsh_param_hph(codec);
-		wcd9xxx_enable_clsh_block(codec, true);
+		wcd9xxx_enable_clsh_block(codec, clsh_d, true);
 		wcd9xxx_chargepump_request(codec, true);
 		wcd9xxx_enable_anc_delay(codec, true);
 		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
-		wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
-		wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+		wcd9xxx_set_buck_mode(codec, BUCK_VREF_0P494V);
+		wcd9xxx_enable_buck(codec, clsh_d, true);
+		wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
 
 		dev_dbg(codec->dev, "%s: Done\n", __func__);
 	} else {
-		if (req_state == WCD9XXX_CLSH_STATE_HPHL) {
-			wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L,
-					      false);
-		} else {
-			dev_dbg(codec->dev, "%s: stub fallback to hph_r\n",
-					__func__);
-		}
+		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
+		wcd9xxx_enable_buck(codec, clsh_d, false);
+		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, false);
+		wcd9xxx_chargepump_request(codec, false);
+		wcd9xxx_enable_clsh_block(codec, clsh_d, false);
 	}
 }
 
@@ -918,9 +892,11 @@
 		struct wcd9xxx_clsh_cdc_data *clsh_d,
 		u8 req_state, bool is_enable)
 {
+	pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
+
 	if (is_enable) {
 		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, true);
-		wcd9xxx_clsh_comp_req(codec, clsh_d,  CLSH_COMPUTE_HPH_R, true);
+		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
 	} else {
 		dev_dbg(codec->dev, "%s: stub fallback to hph_st\n", __func__);
 	}
@@ -930,38 +906,36 @@
 		struct wcd9xxx_clsh_cdc_data *clsh_d,
 		u8 req_state, bool is_enable)
 {
-	if (is_enable) {
-		if (++cdc_lo_count > 1)
-			return;
+	pr_debug("%s: enter %s, buck_mv %d\n", __func__,
+		 is_enable ? "enable" : "disable", clsh_d->buck_mv);
 
-		wcd9xxx_enable_buck_mode(codec, BUCK_VREF_1P8V);
-		wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_5);
+	if (is_enable) {
+		wcd9xxx_set_buck_mode(codec, BUCK_VREF_1P8V);
+		wcd9xxx_enable_buck(codec, clsh_d, true);
+		wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_5);
 
 		if (clsh_d->buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
-			wcd9xxx_enable_buck(codec, false);
+			wcd9xxx_enable_buck(codec, clsh_d, false);
 			snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
-							0x20, 0x01);
-			wcd9xxx_enable_ncp(codec, true);
+					    1 << 4, 1 << 4);
 			/* NCP settle time recommended by codec specification */
 			usleep_range(NCP_SETTLE_TIME_US,
-				NCP_SETTLE_TIME_US + 10);
-
+				     NCP_SETTLE_TIME_US + 10);
 		} else {
-			snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
-							0x40, 0x00);
-			wcd9xxx_enable_ncp(codec, true);
 			/* NCP settle time recommended by codec specification */
 			usleep_range(NCP_SETTLE_TIME_US,
-				NCP_SETTLE_TIME_US + 10);
+				     NCP_SETTLE_TIME_US + 10);
 			snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
-							0x01, 0x01);
+					    0x01, (0x01 & 0x03));
 			snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
-							0xFB, (0x02 << 2));
+					    0xFC, (0xFC & 0xB));
 		}
-		snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
-							0x04, 0x00);
+		snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1, 0x04, 0x00);
 	} else {
 		dev_dbg(codec->dev, "%s: stub fallback to lineout\n", __func__);
+		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_5);
+		if (clsh_d->buck_mv != WCD9XXX_CDC_BUCK_MV_1P8)
+			wcd9xxx_enable_buck(codec, clsh_d, false);
 	}
 }
 
@@ -969,9 +943,12 @@
 		struct wcd9xxx_clsh_cdc_data *clsh_d,
 		u8 req_state, bool is_enable)
 {
-	dev_dbg(codec->dev, "%s Wrong request for class H state machine requested to %s %s"
-			, __func__, is_enable ? "enable" : "disable",
-			state_to_str(req_state));
+	char msg[128];
+
+	dev_dbg(codec->dev,
+		"%s Wrong request for class H state machine requested to %s %s",
+		__func__, is_enable ? "enable" : "disable",
+		state_to_str(req_state, msg, sizeof(msg)));
 	WARN_ON(1);
 }
 
@@ -980,51 +957,45 @@
 		u8 req_state, bool req_type, u8 clsh_event)
 {
 	u8 old_state, new_state;
+	char msg0[128], msg1[128];
 
 	switch (clsh_event) {
-
 	case WCD9XXX_CLSH_EVENT_PRE_DAC:
-
 		/* PRE_DAC event should be used only for Enable */
 		BUG_ON(req_type != WCD9XXX_CLSH_REQ_ENABLE);
 
 		old_state = cdc_clsh_d->state;
 		new_state = old_state | req_state;
 
-		(*clsh_state_fp[new_state]) (codec, cdc_clsh_d,
-							req_state, req_type);
+		(*clsh_state_fp[req_state]) (codec, cdc_clsh_d, req_state,
+					     req_type);
 		cdc_clsh_d->state = new_state;
 		dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
-			__func__, state_to_str(old_state),
-			state_to_str(cdc_clsh_d->state));
+			__func__, state_to_str(old_state, msg0, sizeof(msg0)),
+			state_to_str(cdc_clsh_d->state, msg1, sizeof(msg1)));
 
 		break;
-
 	case WCD9XXX_CLSH_EVENT_POST_PA:
-
 		if (req_type == WCD9XXX_CLSH_REQ_DISABLE) {
-			if (req_state == WCD9XXX_CLSH_STATE_LO
-					&& --cdc_lo_count > 0)
-				break;
-
 			old_state = cdc_clsh_d->state;
 			new_state = old_state & (~req_state);
 
 			if (new_state < NUM_CLSH_STATES) {
-				(*clsh_state_fp[new_state]) (codec, cdc_clsh_d,
-							req_state, req_type);
+				(*clsh_state_fp[req_state]) (codec, cdc_clsh_d,
+							     req_state,
+							     req_type);
 				cdc_clsh_d->state = new_state;
 				dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
-					__func__, state_to_str(old_state),
-					state_to_str(cdc_clsh_d->state));
+					__func__, state_to_str(old_state, msg0,
+							       sizeof(msg0)),
+					state_to_str(cdc_clsh_d->state, msg1,
+						     sizeof(msg1)));
 
 			} else {
 				dev_dbg(codec->dev, "%s: wrong new state = %x\n",
 						__func__, new_state);
 			}
-
-
-		} else if (req_state != WCD9XXX_CLSH_STATE_LO) {
+		} else if (!(cdc_clsh_d->state & WCD9XXX_CLSH_STATE_LO)) {
 			wcd9xxx_clsh_enable_post_pa(codec, cdc_clsh_d);
 		}
 
@@ -1044,7 +1015,6 @@
 	for (i = 0; i < NUM_CLSH_STATES; i++)
 		clsh_state_fp[i] = wcd9xxx_clsh_state_err;
 
-	clsh_state_fp[WCD9XXX_CLSH_STATE_IDLE] = wcd9xxx_clsh_state_idle;
 	clsh_state_fp[WCD9XXX_CLSH_STATE_EAR] = wcd9xxx_clsh_state_ear;
 	clsh_state_fp[WCD9XXX_CLSH_STATE_HPHL] =
 						wcd9xxx_clsh_state_hph_l;
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 0239c86..324f6e9 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -63,11 +63,20 @@
 	u8	val;
 };
 
+enum ncp_fclk_level {
+	NCP_FCLK_LEVEL_8,
+	NCP_FCLK_LEVEL_5,
+	NCP_FCLK_LEVEL_MAX,
+};
+
 /* Class H data that the codec driver will maintain */
 struct wcd9xxx_clsh_cdc_data {
 	u8 state;
 	int buck_mv;
 	bool is_dynamic_vdd_cp;
+	int clsh_users;
+	int buck_users;
+	int ncp_users[NCP_FCLK_LEVEL_MAX];
 	struct wcd9xxx_resmgr *resmgr;
 };
 
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index ec99c5f..3d07f15 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -841,7 +841,8 @@
 			mbhc->zl = mbhc->zr = 0;
 			wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
 					    0, WCD9XXX_JACK_MASK);
-			mbhc->hph_status = 0;
+			mbhc->hph_status &= ~(SND_JACK_HEADSET |
+						SND_JACK_LINEOUT);
 		}
 		/* Report insertion */
 		mbhc->hph_status |= jack_type;
diff --git a/sound/soc/msm/apq8074.c b/sound/soc/msm/apq8074.c
index 3a055e2..5b12b9c 100644
--- a/sound/soc/msm/apq8074.c
+++ b/sound/soc/msm/apq8074.c
@@ -19,18 +19,22 @@
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/qpnp/clkdiv.h>
 #include <linux/regulator/consumer.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/pcm.h>
 #include <sound/jack.h>
 #include <sound/q6afe-v2.h>
-#include <asm/mach-types.h>
-#include <mach/socinfo.h>
 #include <sound/pcm_params.h>
+#include <asm/mach-types.h>
+#include <mach/subsystem_notif.h>
+#include <mach/socinfo.h>
+
 #include "qdsp6v2/msm-pcm-routing-v2.h"
+#include "qdsp6v2/q6core.h"
+#include "../codecs/wcd9xxx-common.h"
 #include "../codecs/wcd9320.h"
-#include <linux/io.h>
 
 #define DRV_NAME "apq8074-asoc-taiko"
 
@@ -82,6 +86,10 @@
 
 #define NUM_OF_AUXPCM_GPIOS 4
 
+static void *adsp_state_notifier;
+
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+
 static inline int param_is_mask(int p)
 {
 	return ((p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
@@ -1230,6 +1238,101 @@
 	return true;
 }
 
+static int msm_afe_set_config(struct snd_soc_codec *codec)
+{
+	int rc;
+	void *config_data;
+
+	pr_debug("%s: enter\n", __func__);
+	config_data = taiko_get_afe_config(codec, AFE_CDC_REGISTERS_CONFIG);
+	rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
+	if (rc) {
+		pr_err("%s: Failed to set codec registers config %d\n",
+		       __func__, rc);
+		return rc;
+	}
+
+	config_data = taiko_get_afe_config(codec, AFE_SLIMBUS_SLAVE_CONFIG);
+	rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
+	if (rc) {
+		pr_err("%s: Failed to set slimbus slave config %d\n", __func__,
+		       rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static void msm_afe_clear_config(void)
+{
+	afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
+	afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
+}
+
+static int  msm8974_adsp_state_callback(struct notifier_block *nb,
+		unsigned long value, void *priv)
+{
+	if (value == SUBSYS_BEFORE_SHUTDOWN) {
+		pr_debug("%s: ADSP is about to shutdown. Clearing AFE config\n",
+			 __func__);
+		msm_afe_clear_config();
+	} else if (value == SUBSYS_AFTER_POWERUP) {
+		pr_debug("%s: ADSP is up\n", __func__);
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+	.notifier_call = msm8974_adsp_state_callback,
+	.priority = -INT_MAX,
+};
+
+static int msm8974_taiko_codec_up(struct snd_soc_codec *codec)
+{
+	int err;
+	unsigned long timeout;
+	int adsp_ready = 0;
+
+	timeout = jiffies +
+		msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+
+	do {
+		if (!q6core_is_adsp_ready()) {
+			pr_err("%s: ADSP Audio isn't ready\n", __func__);
+		} else {
+			pr_debug("%s: ADSP Audio is ready\n", __func__);
+			adsp_ready = 1;
+			break;
+		}
+	} while (time_after(timeout, jiffies));
+
+	if (!adsp_ready) {
+		pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	err = msm_afe_set_config(codec);
+	if (err)
+		pr_err("%s: Failed to set AFE config. err %d\n",
+				__func__, err);
+	return err;
+}
+
+static int apq8074_taiko_event_cb(struct snd_soc_codec *codec,
+		enum wcd9xxx_codec_event codec_event)
+{
+	switch (codec_event) {
+	case WCD9XXX_CODEC_EVENT_CODEC_UP:
+		return msm8974_taiko_codec_up(codec);
+		break;
+	default:
+		pr_err("%s: UnSupported codec event %d\n",
+				__func__, codec_event);
+		return -EINVAL;
+	}
+}
+
 static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err;
@@ -1291,19 +1394,9 @@
 				    tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
 
 
-	config_data = taiko_get_afe_config(codec, AFE_CDC_REGISTERS_CONFIG);
-	err = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
+	err = msm_afe_set_config(codec);
 	if (err) {
-		pr_err("%s: Failed to set codec registers config %d\n",
-		       __func__, err);
-		goto out;
-	}
-
-	config_data = taiko_get_afe_config(codec, AFE_SLIMBUS_SLAVE_CONFIG);
-	err = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
-	if (err) {
-		pr_err("%s: Failed to set slimbus slave config %d\n", __func__,
-		       err);
+		pr_err("%s: Failed to set AFE config %d\n", __func__, err);
 		goto out;
 	}
 
@@ -1340,12 +1433,23 @@
 		err = taiko_hs_detect(codec, &mbhc_cfg);
 		if (err)
 			goto out;
-		else
-			return err;
 	} else {
 		err = -ENOMEM;
 		goto out;
 	}
+	adsp_state_notifier =
+	    subsys_notif_register_notifier("adsp",
+					   &adsp_state_notifier_block);
+	if (!adsp_state_notifier) {
+		pr_err("%s: Failed to register adsp state notifier\n",
+		       __func__);
+		err = -EFAULT;
+		taiko_hs_detect_exit(codec);
+		goto out;
+	}
+
+	taiko_event_register(apq8074_taiko_event_cb, rtd->codec);
+	return 0;
 out:
 	clk_put(codec_clk);
 	return err;
diff --git a/sound/soc/msm/msm-pcm-host-voice.c b/sound/soc/msm/msm-pcm-host-voice.c
index 2eafc1d..1b68bcf 100644
--- a/sound/soc/msm/msm-pcm-host-voice.c
+++ b/sound/soc/msm/msm-pcm-host-voice.c
@@ -989,7 +989,7 @@
 			spin_unlock_irqrestore(&dai_data->dsp_lock, dsp_flags);
 			ret = copy_to_user(buf,
 					   &buf_node->frame.voc_pkt,
-					   count);
+					   buf_node->frame.len);
 			if (ret) {
 				pr_err("%s: Copy to user retuned %d\n",
 					__func__, ret);
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 01422cf..cc2fd50 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -38,64 +38,60 @@
 
 #define MAX_HW_DELAY_ENTRIES	25
 
-struct sidetone_atomic_cal {
-	atomic_t	enable;
-	atomic_t	gain;
-};
-
-
 struct acdb_data {
+	uint32_t		usage_count;
+
 	struct mutex		acdb_mutex;
 
 	/* ANC Cal */
-	struct acdb_atomic_cal_block	anc_cal;
+	struct acdb_cal_block		anc_cal;
 
 	/* AANC Cal */
-	struct acdb_atomic_cal_block    aanc_cal;
+	struct acdb_cal_block		aanc_cal;
 
 	/* LSM Cal */
-	struct acdb_atomic_cal_block	lsm_cal;
+	struct acdb_cal_block		lsm_cal;
 
 	/* AudProc Cal */
-	atomic_t			asm_topology;
-	atomic_t			adm_topology[MAX_AUDPROC_TYPES];
-	struct acdb_atomic_cal_block	audproc_cal[MAX_AUDPROC_TYPES];
-	struct acdb_atomic_cal_block	audstrm_cal[MAX_AUDPROC_TYPES];
-	struct acdb_atomic_cal_block	audvol_cal[MAX_AUDPROC_TYPES];
+	uint32_t			asm_topology;
+	uint32_t			adm_topology[MAX_AUDPROC_TYPES];
+	struct acdb_cal_block		audproc_cal[MAX_AUDPROC_TYPES];
+	struct acdb_cal_block		audstrm_cal[MAX_AUDPROC_TYPES];
+	struct acdb_cal_block		audvol_cal[MAX_AUDPROC_TYPES];
 
 	/* VocProc Cal */
-	atomic_t			voice_rx_topology;
-	atomic_t			voice_tx_topology;
-	struct acdb_atomic_cal_block	vocproc_cal;
-	struct acdb_atomic_cal_block	vocstrm_cal;
-	struct acdb_atomic_cal_block	vocvol_cal;
+	uint32_t			voice_rx_topology;
+	uint32_t			voice_tx_topology;
+	struct acdb_cal_block		vocproc_cal;
+	struct acdb_cal_block		vocstrm_cal;
+	struct acdb_cal_block		vocvol_cal;
 
 	/* Voice Column data */
-	struct acdb_atomic_cal_block	vocproc_col_cal[MAX_VOCPROC_TYPES];
+	struct acdb_cal_block		vocproc_col_cal[MAX_VOCPROC_TYPES];
 	uint32_t			*col_data[MAX_VOCPROC_TYPES];
 
 	/* VocProc dev cfg cal*/
-	struct acdb_atomic_cal_block	vocproc_dev_cal;
+	struct acdb_cal_block		vocproc_dev_cal;
 
 	/* Custom topology */
-	struct acdb_atomic_cal_block	adm_custom_topology;
-	struct acdb_atomic_cal_block	asm_custom_topology;
-	atomic_t			valid_adm_custom_top;
-	atomic_t			valid_asm_custom_top;
+	struct acdb_cal_block		adm_custom_topology;
+	struct acdb_cal_block		asm_custom_topology;
+	uint32_t			valid_adm_custom_top;
+	uint32_t			valid_asm_custom_top;
 
 	/* AFE cal */
-	struct acdb_atomic_cal_block	afe_cal[MAX_AUDPROC_TYPES];
+	struct acdb_cal_block		afe_cal[MAX_AUDPROC_TYPES];
 
 	/* Sidetone Cal */
-	struct sidetone_atomic_cal	sidetone_cal;
+	struct sidetone_cal		sidetone_cal;
 
 	/* Allocation information */
 	struct ion_client		*ion_client;
 	struct ion_handle		*ion_handle;
-	atomic_t			map_handle;
-	atomic64_t			paddr;
-	atomic64_t			kvaddr;
-	atomic64_t			mem_len;
+	uint32_t			map_handle;
+	uint64_t			paddr;
+	uint64_t			kvaddr;
+	uint64_t			mem_len;
 
 	/* Speaker protection */
 	struct msm_spk_prot_cfg spk_prot_cfg;
@@ -106,62 +102,63 @@
 };
 
 static struct acdb_data		acdb_data;
-static atomic_t usage_count;
 
 uint32_t get_voice_rx_topology(void)
 {
-	return atomic_read(&acdb_data.voice_rx_topology);
+	return acdb_data.voice_rx_topology;
 }
 
 void store_voice_rx_topology(uint32_t topology)
 {
-	atomic_set(&acdb_data.voice_rx_topology, topology);
+	acdb_data.voice_rx_topology = topology;
 }
 
 uint32_t get_voice_tx_topology(void)
 {
-	return atomic_read(&acdb_data.voice_tx_topology);
+	return acdb_data.voice_tx_topology;
 }
 
 void store_voice_tx_topology(uint32_t topology)
 {
-	atomic_set(&acdb_data.voice_tx_topology, topology);
+	acdb_data.voice_tx_topology = topology;
 }
 
 uint32_t get_adm_rx_topology(void)
 {
-	return atomic_read(&acdb_data.adm_topology[RX_CAL]);
+	return acdb_data.adm_topology[RX_CAL];
 }
 
 void store_adm_rx_topology(uint32_t topology)
 {
-	atomic_set(&acdb_data.adm_topology[RX_CAL], topology);
+	acdb_data.adm_topology[RX_CAL] = topology;
 }
 
 uint32_t get_adm_tx_topology(void)
 {
-	return atomic_read(&acdb_data.adm_topology[TX_CAL]);
+	return acdb_data.adm_topology[TX_CAL];
 }
 
 void store_adm_tx_topology(uint32_t topology)
 {
-	atomic_set(&acdb_data.adm_topology[TX_CAL], topology);
+	acdb_data.adm_topology[TX_CAL] = topology;
 }
 
 uint32_t get_asm_topology(void)
 {
-	return atomic_read(&acdb_data.asm_topology);
+	return acdb_data.asm_topology;
 }
 
 void store_asm_topology(uint32_t topology)
 {
-	atomic_set(&acdb_data.asm_topology, topology);
+	acdb_data.asm_topology = topology;
 }
 
 void reset_custom_topology_flags(void)
 {
-	atomic_set(&acdb_data.valid_adm_custom_top, 1);
-	atomic_set(&acdb_data.valid_asm_custom_top, 1);
+	mutex_lock(&acdb_data.acdb_mutex);
+	acdb_data.valid_adm_custom_top = 1;
+	acdb_data.valid_asm_custom_top = 1;
+	mutex_unlock(&acdb_data.acdb_mutex);
 }
 
 int get_adm_custom_topology(struct acdb_cal_block *cal_block)
@@ -175,19 +172,19 @@
 		goto done;
 	}
 
+	mutex_lock(&acdb_data.acdb_mutex);
 	/* Only return allow one access after memory registered */
-	if (atomic_read(&acdb_data.valid_adm_custom_top) == 0) {
+	if (acdb_data.valid_adm_custom_top == 0) {
 		cal_block->cal_size = 0;
-		goto done;
+		goto unlock;
 	}
-	atomic_set(&acdb_data.valid_adm_custom_top, 0);
+	acdb_data.valid_adm_custom_top = 0;
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.adm_custom_topology.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.adm_custom_topology.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.adm_custom_topology.cal_kvaddr);
+	cal_block->cal_size = acdb_data.adm_custom_topology.cal_size;
+	cal_block->cal_paddr = acdb_data.adm_custom_topology.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.adm_custom_topology.cal_kvaddr;
+unlock:
+	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return result;
 }
@@ -197,21 +194,18 @@
 	int result = 0;
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.adm_custom_topology.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.adm_custom_topology.cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.adm_custom_topology.cal_kvaddr,
-		cal_block->cal_offset +
-		atomic64_read(&acdb_data.kvaddr));
+	acdb_data.adm_custom_topology.cal_size = cal_block->cal_size;
+	acdb_data.adm_custom_topology.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.adm_custom_topology.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -227,19 +221,19 @@
 		goto done;
 	}
 
+	mutex_lock(&acdb_data.acdb_mutex);
 	/* Only return allow one access after memory registered */
-	if (atomic_read(&acdb_data.valid_asm_custom_top) == 0) {
+	if (acdb_data.valid_asm_custom_top == 0) {
 		cal_block->cal_size = 0;
-		goto done;
+		goto unlock;
 	}
-	atomic_set(&acdb_data.valid_asm_custom_top, 0);
+	acdb_data.valid_asm_custom_top = 0;
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.asm_custom_topology.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.asm_custom_topology.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.asm_custom_topology.cal_kvaddr);
+	cal_block->cal_size = acdb_data.asm_custom_topology.cal_size;
+	cal_block->cal_paddr = acdb_data.asm_custom_topology.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.asm_custom_topology.cal_kvaddr;
+unlock:
+	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return result;
 }
@@ -249,21 +243,18 @@
 	int result = 0;
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.asm_custom_topology.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.asm_custom_topology.cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.asm_custom_topology.cal_kvaddr,
-		cal_block->cal_offset +
-		atomic64_read(&acdb_data.kvaddr));
+	acdb_data.asm_custom_topology.cal_size = cal_block->cal_size;
+	acdb_data.asm_custom_topology.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.asm_custom_topology.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -280,10 +271,8 @@
 	}
 
 	cal_block->cal_size = ACDB_TOTAL_VOICE_ALLOCATION;
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.vocproc_cal.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.vocproc_cal.cal_kvaddr);
+	cal_block->cal_paddr = acdb_data.vocproc_cal.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.vocproc_cal.cal_kvaddr;
 done:
 	return result;
 }
@@ -299,12 +288,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.aanc_cal.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.aanc_cal.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.aanc_cal.cal_kvaddr);
+	cal_block->cal_size = acdb_data.aanc_cal.cal_size;
+	cal_block->cal_paddr = acdb_data.aanc_cal.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.aanc_cal.cal_kvaddr;
 done:
 	return result;
 }
@@ -314,20 +300,18 @@
 	int result = 0;
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-		 __func__, cal_block->cal_offset,
-		(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+		 __func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.aanc_cal.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.aanc_cal.cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.aanc_cal.cal_kvaddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	acdb_data.aanc_cal.cal_size = cal_block->cal_size;
+	acdb_data.aanc_cal.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.aanc_cal.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -343,12 +327,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.lsm_cal.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.lsm_cal.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.lsm_cal.cal_kvaddr);
+	cal_block->cal_size = acdb_data.lsm_cal.cal_size;
+	cal_block->cal_paddr = acdb_data.lsm_cal.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.lsm_cal.cal_kvaddr;
 done:
 	return result;
 }
@@ -358,20 +339,18 @@
 	int result = 0;
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.lsm_cal.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.lsm_cal.cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.lsm_cal.cal_kvaddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	acdb_data.lsm_cal.cal_size = cal_block->cal_size;
+	acdb_data.lsm_cal.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.lsm_cal.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -470,7 +449,6 @@
 	pr_debug("ACDB=> %s : Path = %d num_entries = %d\n",
 		 __func__, path, delay.num_entries);
 
-	mutex_lock(&acdb_data.acdb_mutex);
 	if (path == RX_CAL)
 		delay_dest = &acdb_data.hw_delay_rx;
 	else if (path == TX_CAL)
@@ -487,7 +465,6 @@
 		       __func__, result, path);
 		result = -EFAULT;
 	}
-	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return result;
 }
@@ -503,12 +480,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.anc_cal.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.anc_cal.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.anc_cal.cal_kvaddr);
+	cal_block->cal_size = acdb_data.anc_cal.cal_size;
+	cal_block->cal_paddr = acdb_data.anc_cal.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.anc_cal.cal_kvaddr;
 done:
 	return result;
 }
@@ -518,20 +492,18 @@
 	int result = 0;
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.anc_cal.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.anc_cal.cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.anc_cal.cal_kvaddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	acdb_data.anc_cal.cal_size = cal_block->cal_size;
+	acdb_data.anc_cal.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.anc_cal.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -541,10 +513,9 @@
 	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
@@ -555,12 +526,11 @@
 		goto done;
 	}
 
-	atomic_set(&acdb_data.afe_cal[path].cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.afe_cal[path].cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.afe_cal[path].cal_kvaddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	acdb_data.afe_cal[path].cal_size = cal_block->cal_size;
+	acdb_data.afe_cal[path].cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.afe_cal[path].cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -582,12 +552,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.afe_cal[path].cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.afe_cal[path].cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.afe_cal[path].cal_kvaddr);
+	cal_block->cal_size = acdb_data.afe_cal[path].cal_size;
+	cal_block->cal_paddr = acdb_data.afe_cal[path].cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.afe_cal[path].cal_kvaddr;
 done:
 	return result;
 }
@@ -597,10 +564,9 @@
 	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
@@ -611,12 +577,11 @@
 		goto done;
 	}
 
-	atomic_set(&acdb_data.audproc_cal[path].cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.audproc_cal[path].cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.audproc_cal[path].cal_kvaddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	acdb_data.audproc_cal[path].cal_size = cal_block->cal_size;
+	acdb_data.audproc_cal[path].cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.audproc_cal[path].cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -638,12 +603,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.audproc_cal[path].cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.audproc_cal[path].cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.audproc_cal[path].cal_kvaddr);
+	cal_block->cal_size = acdb_data.audproc_cal[path].cal_size;
+	cal_block->cal_paddr = acdb_data.audproc_cal[path].cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.audproc_cal[path].cal_kvaddr;
 done:
 	return result;
 }
@@ -653,10 +615,9 @@
 	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
@@ -667,12 +628,11 @@
 		goto done;
 	}
 
-	atomic_set(&acdb_data.audstrm_cal[path].cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.audstrm_cal[path].cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.audstrm_cal[path].cal_kvaddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	acdb_data.audstrm_cal[path].cal_size = cal_block->cal_size;
+	acdb_data.audstrm_cal[path].cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.audstrm_cal[path].cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -694,12 +654,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.audstrm_cal[path].cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.audstrm_cal[path].cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.audstrm_cal[path].cal_kvaddr);
+	cal_block->cal_size = acdb_data.audstrm_cal[path].cal_size;
+	cal_block->cal_paddr = acdb_data.audstrm_cal[path].cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.audstrm_cal[path].cal_kvaddr;
 done:
 	return result;
 }
@@ -709,10 +666,9 @@
 	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
 		result = -EINVAL;
 		goto done;
 	}
@@ -723,12 +679,11 @@
 		goto done;
 	}
 
-	atomic_set(&acdb_data.audvol_cal[path].cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.audvol_cal[path].cal_paddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.audvol_cal[path].cal_kvaddr,
-		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	acdb_data.audvol_cal[path].cal_size = cal_block->cal_size;
+	acdb_data.audvol_cal[path].cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.audvol_cal[path].cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -750,12 +705,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.audvol_cal[path].cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.audvol_cal[path].cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.audvol_cal[path].cal_kvaddr);
+	cal_block->cal_size = acdb_data.audvol_cal[path].cal_size;
+	cal_block->cal_paddr = acdb_data.audvol_cal[path].cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.audvol_cal[path].cal_kvaddr;
 done:
 	return result;
 }
@@ -766,22 +718,30 @@
 	int result = 0;
 	pr_debug("%s,\n", __func__);
 
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
+		goto done;
+	}
 	if (cal_size > MAX_COL_SIZE) {
-		pr_err("%s: col size is to big %d\n", __func__,
-				cal_size);
+		pr_err("%s: col size is to big %d\n", __func__, cal_size);
+		result = -EINVAL;
+		goto done;
+	}
+	if (acdb_data.col_data[vocproc_type] == NULL) {
+		pr_err("%s: vocproc_type %d data not allocated!\n",
+			__func__, vocproc_type);
 		result = -EINVAL;
 		goto done;
 	}
 	if (copy_from_user(acdb_data.col_data[vocproc_type],
 			(void *)((uint8_t *)cal_block + sizeof(cal_size)),
 			cal_size)) {
-		pr_err("%s: fail to copy col size %d\n",
-			__func__, cal_size);
+		pr_err("%s: fail to copy col size %d\n", __func__, cal_size);
 		result = -EINVAL;
 		goto done;
 	}
-	atomic_set(&acdb_data.vocproc_col_cal[vocproc_type].cal_size,
-		cal_size);
+	acdb_data.vocproc_col_cal[vocproc_type].cal_size = cal_size;
 done:
 	return result;
 }
@@ -797,13 +757,19 @@
 		result = -EINVAL;
 		goto done;
 	}
+	if (acdb_data.col_data[vocproc_type] == NULL) {
+		pr_err("%s: vocproc_type %d data not allocated!\n",
+			__func__, vocproc_type);
+		result = -EINVAL;
+		goto done;
+	}
 
-	cal_block->cal_size = atomic_read(&acdb_data.
-				vocproc_col_cal[vocproc_type].cal_size);
-	cal_block->cal_paddr = atomic_read(&acdb_data.
-				vocproc_col_cal[vocproc_type].cal_paddr);
-	cal_block->cal_kvaddr = atomic_read(&acdb_data.
-				vocproc_col_cal[vocproc_type].cal_kvaddr);
+	cal_block->cal_size = acdb_data.
+		vocproc_col_cal[vocproc_type].cal_size;
+	cal_block->cal_paddr = acdb_data.
+		vocproc_col_cal[vocproc_type].cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.
+		vocproc_col_cal[vocproc_type].cal_kvaddr;
 done:
 	return result;
 }
@@ -815,24 +781,19 @@
 
 
 	if (cal_block->cal_offset >
-				atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
-		atomic_set(&acdb_data.vocproc_dev_cal.cal_size, 0);
+				acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
+		acdb_data.vocproc_dev_cal.cal_size = 0;
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.vocproc_dev_cal.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.vocproc_dev_cal.cal_paddr,
-		cal_block->cal_offset +
-	atomic64_read(&acdb_data.paddr));
-			atomic_set(&acdb_data.vocproc_dev_cal.cal_kvaddr,
-			cal_block->cal_offset +
-			atomic64_read(&acdb_data.kvaddr));
-
+	acdb_data.vocproc_dev_cal.cal_size = cal_block->cal_size;
+	acdb_data.vocproc_dev_cal.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.vocproc_dev_cal.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -848,12 +809,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.vocproc_dev_cal.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.vocproc_dev_cal.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.vocproc_dev_cal.cal_kvaddr);
+	cal_block->cal_size = acdb_data.vocproc_dev_cal.cal_size;
+	cal_block->cal_paddr = acdb_data.vocproc_dev_cal.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.vocproc_dev_cal.cal_kvaddr;
 done:
 	return result;
 }
@@ -866,24 +824,19 @@
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset >
-				atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
-		atomic_set(&acdb_data.vocproc_cal.cal_size, 0);
+				acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
+		acdb_data.vocproc_cal.cal_size = 0;
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.vocproc_cal.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.vocproc_cal.cal_paddr,
-		cal_block->cal_offset +
-		atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.vocproc_cal.cal_kvaddr,
-		cal_block->cal_offset +
-		atomic64_read(&acdb_data.kvaddr));
-
+	acdb_data.vocproc_cal.cal_size = cal_block->cal_size;
+	acdb_data.vocproc_cal.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.vocproc_cal.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -899,12 +852,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.vocproc_cal.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.vocproc_cal.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.vocproc_cal.cal_kvaddr);
+	cal_block->cal_size = acdb_data.vocproc_cal.cal_size;
+	cal_block->cal_paddr = acdb_data.vocproc_cal.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.vocproc_cal.cal_kvaddr;
 done:
 	return result;
 }
@@ -915,24 +865,19 @@
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset >
-			atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
-		atomic_set(&acdb_data.vocstrm_cal.cal_size, 0);
+			acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
+		acdb_data.vocstrm_cal.cal_size = 0;
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.vocstrm_cal.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.vocstrm_cal.cal_paddr,
-		cal_block->cal_offset +
-		atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.vocstrm_cal.cal_kvaddr,
-		cal_block->cal_offset +
-		atomic64_read(&acdb_data.kvaddr));
-
+	acdb_data.vocstrm_cal.cal_size = cal_block->cal_size;
+	acdb_data.vocstrm_cal.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.vocstrm_cal.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -948,12 +893,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.vocstrm_cal.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.vocstrm_cal.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.vocstrm_cal.cal_kvaddr);
+	cal_block->cal_size = acdb_data.vocstrm_cal.cal_size;
+	cal_block->cal_paddr = acdb_data.vocstrm_cal.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.vocstrm_cal.cal_kvaddr;
 done:
 	return result;
 }
@@ -963,25 +905,19 @@
 	int result = 0;
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset >
-			atomic64_read(&acdb_data.mem_len)) {
-		pr_err("%s: offset %d is > mem_len %ld\n",
-			__func__, cal_block->cal_offset,
-			(long)atomic64_read(&acdb_data.mem_len));
-		atomic_set(&acdb_data.vocvol_cal.cal_size, 0);
+	if (cal_block->cal_offset > acdb_data.mem_len) {
+		pr_err("%s: offset %d is > mem_len %llu\n",
+			__func__, cal_block->cal_offset, acdb_data.mem_len);
+		acdb_data.vocvol_cal.cal_size = 0;
 		result = -EINVAL;
 		goto done;
 	}
 
-	atomic_set(&acdb_data.vocvol_cal.cal_size,
-		cal_block->cal_size);
-	atomic_set(&acdb_data.vocvol_cal.cal_paddr,
-		cal_block->cal_offset +
-		atomic64_read(&acdb_data.paddr));
-	atomic_set(&acdb_data.vocvol_cal.cal_kvaddr,
-		cal_block->cal_offset +
-		atomic64_read(&acdb_data.kvaddr));
-
+	acdb_data.vocvol_cal.cal_size = cal_block->cal_size;
+	acdb_data.vocvol_cal.cal_paddr =
+		cal_block->cal_offset + acdb_data.paddr;
+	acdb_data.vocvol_cal.cal_kvaddr =
+		cal_block->cal_offset + acdb_data.kvaddr;
 done:
 	return result;
 }
@@ -997,12 +933,9 @@
 		goto done;
 	}
 
-	cal_block->cal_size =
-		atomic_read(&acdb_data.vocvol_cal.cal_size);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.vocvol_cal.cal_paddr);
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.vocvol_cal.cal_kvaddr);
+	cal_block->cal_size = acdb_data.vocvol_cal.cal_size;
+	cal_block->cal_paddr = acdb_data.vocvol_cal.cal_paddr;
+	cal_block->cal_kvaddr = acdb_data.vocvol_cal.cal_kvaddr;
 done:
 	return result;
 }
@@ -1011,8 +944,8 @@
 {
 	pr_debug("%s,\n", __func__);
 
-	atomic_set(&acdb_data.sidetone_cal.enable, cal_data->enable);
-	atomic_set(&acdb_data.sidetone_cal.gain, cal_data->gain);
+	acdb_data.sidetone_cal.enable = cal_data->enable;
+	acdb_data.sidetone_cal.gain = cal_data->gain;
 }
 
 int get_sidetone_cal(struct sidetone_cal *cal_data)
@@ -1026,8 +959,10 @@
 		goto done;
 	}
 
-	cal_data->enable = atomic_read(&acdb_data.sidetone_cal.enable);
-	cal_data->gain = atomic_read(&acdb_data.sidetone_cal.gain);
+	mutex_lock(&acdb_data.acdb_mutex);
+	cal_data->enable = acdb_data.sidetone_cal.enable;
+	cal_data->gain = acdb_data.sidetone_cal.gain;
+	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return result;
 }
@@ -1111,20 +1046,32 @@
 	s32 result = 0;
 	pr_debug("%s\n", __func__);
 
-	if (atomic64_read(&acdb_data.mem_len)) {
+	mutex_lock(&acdb_data.acdb_mutex);
+	if (acdb_data.mem_len)
 		pr_debug("%s: ACDB opened but memory allocated, using existing allocation!\n",
 			__func__);
-	}
 
-	atomic_set(&acdb_data.valid_adm_custom_top, 1);
-	atomic_set(&acdb_data.valid_asm_custom_top, 1);
-	atomic_inc(&usage_count);
+	acdb_data.valid_adm_custom_top = 1;
+	acdb_data.valid_asm_custom_top = 1;
+	acdb_data.usage_count++;
+	mutex_unlock(&acdb_data.acdb_mutex);
 
 	return result;
 }
 
-static void allocate_hw_delay_entries(void)
+static void deallocate_hw_delay_entries(void)
 {
+	kfree(acdb_data.hw_delay_rx.delay_info);
+	kfree(acdb_data.hw_delay_tx.delay_info);
+
+	acdb_data.hw_delay_rx.delay_info = NULL;
+	acdb_data.hw_delay_tx.delay_info = NULL;
+}
+
+static int allocate_hw_delay_entries(void)
+{
+	int	result = 0;
+
 	/* Allocate memory for hw delay entries */
 	acdb_data.hw_delay_rx.num_entries = 0;
 	acdb_data.hw_delay_tx.num_entries = 0;
@@ -1135,6 +1082,8 @@
 	if (acdb_data.hw_delay_rx.delay_info == NULL) {
 		pr_err("%s : Failed to allocate av sync delay entries rx\n",
 			__func__);
+		result = -ENOMEM;
+		goto done;
 	}
 	acdb_data.hw_delay_tx.delay_info =
 				kmalloc(sizeof(struct hw_delay_entry)*
@@ -1143,7 +1092,44 @@
 	if (acdb_data.hw_delay_tx.delay_info == NULL) {
 		pr_err("%s : Failed to allocate av sync delay entries tx\n",
 			__func__);
+		deallocate_hw_delay_entries();
+		result = -ENOMEM;
+		goto done;
 	}
+done:
+	return result;
+}
+
+static void deallocate_col_data(void)
+{
+	int	i;
+
+	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
+		kfree(acdb_data.col_data[i]);
+		acdb_data.col_data[i] = NULL;
+	}
+}
+
+static int allocate_col_data(void)
+{
+	int	result = 0;
+	int	i;
+
+	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
+		acdb_data.col_data[i] = kmalloc(MAX_COL_SIZE, GFP_KERNEL);
+		if (acdb_data.col_data[i] == NULL) {
+			pr_err("%s: kmalloc column data failed, type = %d\n",
+				__func__, i);
+			deallocate_col_data();
+			result = -ENOMEM;
+			goto done;
+		}
+		acdb_data.vocproc_col_cal[i].cal_kvaddr =
+			(uint32_t)acdb_data.col_data[i];
+	}
+
+done:
+	return result;
 }
 
 static int unmap_cal_tables(void)
@@ -1192,81 +1178,81 @@
 static int deregister_memory(void)
 {
 	int	result = 0;
-	int	i;
 	pr_debug("%s\n", __func__);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-	kfree(acdb_data.hw_delay_tx.delay_info);
-	kfree(acdb_data.hw_delay_rx.delay_info);
+	if (acdb_data.mem_len == 0)
+		goto done;
 
-	if (atomic64_read(&acdb_data.mem_len)) {
-		/* unmap all cal data */
-		result = unmap_cal_tables();
-		if (result < 0)
-			pr_err("%s: unmap_cal_tables failed, err = %d\n",
-				__func__, result);
+	pr_debug("Remove existing memory\n");
+	acdb_data.mem_len = 0;
 
-		atomic64_set(&acdb_data.mem_len, 0);
+	/* unmap all cal data */
+	result = unmap_cal_tables();
+	if (result < 0)
+		pr_err("%s: unmap_cal_tables failed, err = %d\n",
+			__func__, result);
 
-		for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
-			kfree(acdb_data.col_data[i]);
-			acdb_data.col_data[i] = NULL;
-		}
-		msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
-		acdb_data.ion_client = NULL;
-		acdb_data.ion_handle = NULL;
-		mutex_unlock(&acdb_data.acdb_mutex);
-	}
-	mutex_unlock(&acdb_data.acdb_mutex);
-	return 0;
+	msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+	acdb_data.ion_client = NULL;
+	acdb_data.ion_handle = NULL;
+
+	deallocate_col_data();
+	deallocate_hw_delay_entries();
+done:
+	return result;
 }
 
 static int register_memory(void)
 {
 	int			result;
-	int			i;
 	ion_phys_addr_t		paddr;
 	void                    *kvptr;
 	unsigned long		kvaddr;
 	unsigned long		mem_len;
 	pr_debug("%s\n", __func__);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-	allocate_hw_delay_entries();
-	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
-		acdb_data.col_data[i] = kmalloc(MAX_COL_SIZE, GFP_KERNEL);
-		atomic_set(&acdb_data.vocproc_col_cal[i].cal_kvaddr,
-			(uint32_t)acdb_data.col_data[i]);
+	result = allocate_col_data();
+	if (result) {
+		pr_err("%s: allocate_hw_delay_entries failed, rc = %d\n",
+			__func__, result);
+		goto err_done;
+	}
+
+	result = allocate_hw_delay_entries();
+	if (result) {
+		pr_err("%s: allocate_hw_delay_entries failed, rc = %d\n",
+			__func__, result);
+		goto err_col;
 	}
 
 	result = msm_audio_ion_import("audio_acdb_client",
 				&acdb_data.ion_client,
 				&acdb_data.ion_handle,
-				atomic_read(&acdb_data.map_handle),
+				acdb_data.map_handle,
 				NULL, 0,
 				&paddr, (size_t *)&mem_len, &kvptr);
 	if (result) {
 		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, result);
-		result = PTR_ERR(acdb_data.ion_client);
-		goto err_ion_handle;
+		goto err_hw_delay;
 	}
-	kvaddr = (unsigned long)kvptr;
-	atomic64_set(&acdb_data.paddr, paddr);
-	atomic64_set(&acdb_data.kvaddr, kvaddr);
-	atomic64_set(&acdb_data.mem_len, mem_len);
-	mutex_unlock(&acdb_data.acdb_mutex);
 
-	pr_debug("%s done! paddr = 0x%lx, kvaddr = 0x%lx, len = x%lx\n",
-		 __func__,
-		(long)atomic64_read(&acdb_data.paddr),
-		(long)atomic64_read(&acdb_data.kvaddr),
-		(long)atomic64_read(&acdb_data.mem_len));
+	kvaddr = (unsigned long)kvptr;
+	acdb_data.paddr = paddr;
+	acdb_data.kvaddr = kvaddr;
+	acdb_data.mem_len = mem_len;
+
+	pr_debug("%s done! paddr = 0x%llx, kvaddr = 0x%llx, len = 0x%llx\n",
+		 __func__, acdb_data.paddr, acdb_data.kvaddr,
+		 acdb_data.mem_len);
 
 	return result;
-err_ion_handle:
-	atomic64_set(&acdb_data.mem_len, 0);
-	mutex_unlock(&acdb_data.acdb_mutex);
+err_hw_delay:
+	deallocate_hw_delay_entries();
+err_col:
+	deallocate_col_data();
+err_done:
+	acdb_data.mem_len = 0;
 	return result;
 }
 static long acdb_ioctl(struct file *f,
@@ -1281,26 +1267,26 @@
 	struct msm_spk_prot_status acdb_spk_status;
 	pr_debug("%s\n", __func__);
 
+	mutex_lock(&acdb_data.acdb_mutex);
 	switch (cmd) {
 	case AUDIO_REGISTER_PMEM:
 		pr_debug("AUDIO_REGISTER_PMEM\n");
-		if (atomic_read(&acdb_data.mem_len)) {
-			deregister_memory();
-			pr_debug("Remove the existing memory\n");
-		}
+		result = deregister_memory();
+		if (result < 0)
+			pr_err("%s: deregister_memory failed returned %d!\n",
+				__func__, result);
 
 		if (copy_from_user(&map_fd, (void *)arg, sizeof(map_fd))) {
 			pr_err("%s: fail to copy memory handle!\n", __func__);
 			result = -EFAULT;
 		} else {
-			atomic_set(&acdb_data.map_handle, map_fd);
+			acdb_data.map_handle = map_fd;
 			result = register_memory();
 		}
 		goto done;
-
 	case AUDIO_DEREGISTER_PMEM:
 		pr_debug("AUDIO_DEREGISTER_PMEM\n");
-		deregister_memory();
+		result = deregister_memory();
 		goto done;
 	case AUDIO_SET_VOICE_RX_TOPOLOGY:
 		if (copy_from_user(&topology, (void *)arg,
@@ -1343,16 +1329,13 @@
 		store_asm_topology(topology);
 		goto done;
 	case AUDIO_SET_SPEAKER_PROT:
-		mutex_lock(&acdb_data.acdb_mutex);
 		if (copy_from_user(&acdb_data.spk_prot_cfg, (void *)arg,
 				sizeof(acdb_data.spk_prot_cfg))) {
 			pr_err("%s fail to copy spk_prot_cfg\n", __func__);
 			result = -EFAULT;
 		}
-		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
 	case AUDIO_GET_SPEAKER_PROT:
-		mutex_lock(&acdb_data.acdb_mutex);
 		/*Indicates calibration was succesfull*/
 		if (acdb_data.spk_prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) {
 			prot_status.r0 = acdb_data.spk_prot_cfg.r0;
@@ -1379,7 +1362,6 @@
 			sizeof(prot_status))) {
 			pr_err("%s: Failed to update prot_status\n", __func__);
 		}
-		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
 	case AUDIO_REGISTER_VOCPROC_VOL_TABLE:
 		result = register_vocvol_table();
@@ -1502,23 +1484,25 @@
 	}
 
 done:
+	mutex_unlock(&acdb_data.acdb_mutex);
 	return result;
 }
 
 static int acdb_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	int result = 0;
-	uint32_t size = vma->vm_end - vma->vm_start;
+	size_t size = vma->vm_end - vma->vm_start;
 
 	pr_debug("%s\n", __func__);
 
-	if (atomic64_read(&acdb_data.mem_len)) {
-		if (size <= atomic64_read(&acdb_data.mem_len)) {
+	mutex_lock(&acdb_data.acdb_mutex);
+	if (acdb_data.mem_len) {
+		if (size <= acdb_data.mem_len) {
 			vma->vm_page_prot = pgprot_noncached(
 						vma->vm_page_prot);
 			result = remap_pfn_range(vma,
 				vma->vm_start,
-				atomic64_read(&acdb_data.paddr) >> PAGE_SHIFT,
+				acdb_data.paddr >> PAGE_SHIFT,
 				size,
 				vma->vm_page_prot);
 		} else {
@@ -1529,25 +1513,29 @@
 		pr_err("%s: memory is not allocated, yet!\n", __func__);
 		result = -ENODEV;
 	}
+	mutex_unlock(&acdb_data.acdb_mutex);
 
 	return result;
 }
 
 static int acdb_release(struct inode *inode, struct file *f)
 {
-	s32 result = 0;
+	int result = 0;
+	pr_debug("%s\n", __func__);
 
-	atomic_dec(&usage_count);
-	atomic_read(&usage_count);
+	mutex_lock(&acdb_data.acdb_mutex);
+	acdb_data.usage_count--;
 
-	pr_debug("%s: ref count %d!\n", __func__,
-		atomic_read(&usage_count));
+	pr_debug("%s: ref count %d!\n", __func__, acdb_data.usage_count);
 
-	if (atomic_read(&usage_count) >= 1)
+	if (acdb_data.usage_count > 0) {
 		result = -EBUSY;
-	else
-		result = deregister_memory();
+		goto done;
+	}
 
+	result = deregister_memory();
+done:
+	mutex_unlock(&acdb_data.acdb_mutex);
 	return result;
 }
 
@@ -1571,9 +1559,9 @@
 	/*Speaker protection disabled*/
 	acdb_data.spk_prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
 	mutex_init(&acdb_data.acdb_mutex);
-	atomic_set(&usage_count, 0);
-	atomic_set(&acdb_data.valid_adm_custom_top, 1);
-	atomic_set(&acdb_data.valid_asm_custom_top, 1);
+	acdb_data.usage_count = 0;
+	acdb_data.valid_adm_custom_top = 1;
+	acdb_data.valid_asm_custom_top = 1;
 
 	return misc_register(&acdb_misc);
 }
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.h b/sound/soc/msm/qdsp6v2/audio_acdb.h
index e2ca395..45a83f6 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.h
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.h
@@ -35,12 +35,6 @@
 	uint32_t		cal_paddr;
 };
 
-struct acdb_atomic_cal_block {
-	atomic_t		cal_size;
-	atomic_t		cal_kvaddr;
-	atomic_t		cal_paddr;
-};
-
 struct hw_delay_entry {
 	uint32_t sample_rate;
 	uint32_t delay_usec;
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index a632644..bb926ec 100755
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -986,7 +986,7 @@
 			struct snd_dec_ddp *ddp =
 				&compr->info.codec_param.codec.options.ddp;
 			uint32_t params_length = ddp->params_length*sizeof(int);
-			if(params_length > MAX_AC3_PARAM_SIZE) {
+			if (params_length > MAX_AC3_PARAM_SIZE) {
 				/*MAX is 36*sizeof(int) this should not happen*/
 				pr_err("params_length(%d) is greater than %d",
 				params_length, MAX_AC3_PARAM_SIZE);
@@ -1023,7 +1023,7 @@
 			struct snd_dec_ddp *ddp =
 				&compr->info.codec_param.codec.options.ddp;
 			uint32_t params_length = ddp->params_length*sizeof(int);
-			if(params_length > MAX_AC3_PARAM_SIZE) {
+			if (params_length > MAX_AC3_PARAM_SIZE) {
 				/*MAX is 36*sizeof(int) this should not happen*/
 				pr_err("params_length(%d) is greater than %d",
 				params_length, MAX_AC3_PARAM_SIZE);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index d80ca19..0612805 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -40,8 +40,8 @@
 
 #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)
+#define MIN_CAPTURE_NUM_PERIODS (32 * 4)
+#define MAX_CAPTURE_NUM_PERIODS (384 * 4)
 
 static struct snd_pcm_hardware msm_afe_hardware_playback = {
 	.info =                 (SNDRV_PCM_INFO_MMAP |
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 11326f6..6f3f8ec 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -396,6 +396,18 @@
 									ret);
 		}
 	}
+	ret = snd_pcm_hw_constraint_step(runtime, 0,
+		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
+	if (ret < 0) {
+		pr_err("constraint for period bytes step ret = %d\n",
+								ret);
+	}
+	ret = snd_pcm_hw_constraint_step(runtime, 0,
+		SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
+	if (ret < 0) {
+		pr_err("constraint for buffer bytes step ret = %d\n",
+								ret);
+	}
 
 	prtd->dsp_cnt = 0;
 	prtd->set_channel_map = false;
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 27c74ce..3ee6f6e 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1144,8 +1144,8 @@
 			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
 		} else if (channel_mode == 3)	{
 			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
-			open.dev_channel_mapping[0] = PCM_CHANNEL_FR;
-			open.dev_channel_mapping[1] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_FC;
 		} else if (channel_mode == 4) {
 			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
 			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 7c4547e..7a5efb0 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1225,6 +1225,7 @@
 					data->payload_size))
 				break;
 		case ASM_SESSION_CMD_PAUSE:
+		case ASM_SESSION_CMD_SUSPEND:
 		case ASM_DATA_CMD_EOS:
 		case ASM_STREAM_CMD_CLOSE:
 		case ASM_STREAM_CMD_FLUSH:
@@ -3870,6 +3871,11 @@
 		hdr.opcode = ASM_SESSION_CMD_PAUSE;
 		state = &ac->cmd_state;
 		break;
+	case CMD_SUSPEND:
+		pr_debug("%s:CMD_SUSPEND\n", __func__);
+		hdr.opcode = ASM_SESSION_CMD_SUSPEND;
+		state = &ac->cmd_state;
+		break;
 	case CMD_FLUSH:
 		pr_debug("%s:CMD_FLUSH\n", __func__);
 		hdr.opcode = ASM_STREAM_CMD_FLUSH;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index bc3f6a7..63bbbdd 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1922,7 +1922,7 @@
 {
 	struct snd_soc_card *card = widget->dapm->card;
 	int ret;
-	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
 	ret = soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
 	mutex_unlock(&card->dapm_mutex);
 	return ret;
@@ -1970,7 +1970,7 @@
 {
 	struct snd_soc_card *card = widget->dapm->card;
 	int ret;
-	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
 	ret = soc_dapm_mixer_update_power(widget, kcontrol, connect);
 	mutex_unlock(&card->dapm_mutex);
 	return ret;
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 9eb96e5..60a401a 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -36,6 +36,7 @@
 int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
 		     struct snd_soc_jack *jack)
 {
+	mutex_init(&jack->mutex);
 	jack->codec = codec;
 	INIT_LIST_HEAD(&jack->pins);
 	INIT_LIST_HEAD(&jack->jack_zones);
@@ -75,7 +76,7 @@
 	codec = jack->codec;
 	dapm =  &codec->dapm;
 
-	mutex_lock(&codec->mutex);
+	mutex_lock(&jack->mutex);
 
 	oldstatus = jack->status;
 
@@ -109,7 +110,7 @@
 	snd_jack_report(jack->jack, jack->status);
 
 out:
-	mutex_unlock(&codec->mutex);
+	mutex_unlock(&jack->mutex);
 }
 EXPORT_SYMBOL_GPL(snd_soc_jack_report);