Merge "msm: kgsl: Don't process events if the timestamp hasn't changed"
diff --git a/Documentation/devicetree/bindings/bif/qpnp-bsi.txt b/Documentation/devicetree/bindings/bif/qpnp-bsi.txt
index 29267dd..0ff10a4 100644
--- a/Documentation/devicetree/bindings/bif/qpnp-bsi.txt
+++ b/Documentation/devicetree/bindings/bif/qpnp-bsi.txt
@@ -49,6 +49,7 @@
 - qcom,vref-microvolts:   Reference voltage used for BCL divider circuit in
                            microvolts.  If no value is specified, then
                            1800000 uV is assumed.
+- qcom,bsi-vadc:	  Corresponding VADC device phandle.
 
 All properties specified within for the BIF framework can also be used. These
 properties can be found in bif.txt.
@@ -86,6 +87,7 @@
 				qcom,channel-num = <0x31>;
 				qcom,pullup-ohms = <100000>;
 				qcom,vref-microvolts = <1800000>;
+				qcom,bsi-vadc = <&pm8941_vadc>;
 			};
 		};
 	};
diff --git a/Documentation/devicetree/bindings/hwmon/qpnp-adc-current.txt b/Documentation/devicetree/bindings/hwmon/qpnp-adc-current.txt
index 418447d..e336429 100644
--- a/Documentation/devicetree/bindings/hwmon/qpnp-adc-current.txt
+++ b/Documentation/devicetree/bindings/hwmon/qpnp-adc-current.txt
@@ -84,6 +84,8 @@
 			6 : 64
 			7 : 128
 			8 : 256
+- qcom,iadc-vadc : Corresponding phandle of the VADC device to read the die_temperature and set
+		simultaneous voltage and current conversion requests.
 
 Example:
 	/* Main Node */
@@ -97,6 +99,7 @@
                         qcom,adc-bit-resolution = <16>;
                         qcom,adc-vdd-reference = <1800>;
 			qcom,rsense = <1500>;
+			qcom,iadc-vadc = <&pm8941_vadc>;
 
 			/* Channel Node */
                         chan@0 = {
diff --git a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
index 8de8bdd..7f34a8f 100644
--- a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
+++ b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
@@ -20,6 +20,12 @@
 Channel nodes
 NOTE: Atleast one Channel node is required.
 
+Client required property:
+- qcom,<consumer name>-vadc : The phandle to the corresponding vadc device.
+			The consumer name passed to the driver when calling
+			qpnp_get_vadc() is used to associate the client
+			with the corresponding device.
+
 Required properties:
 - label : Channel name used for sysfs entry.
 - reg : AMUX channel number.
@@ -113,6 +119,12 @@
                         };
 	};
 
+Client device example:
+/* Add to the clients node that needs the VADC channel A/D */
+client_node {
+	qcom,client-vadc = <&pm8941_vadc>;
+};
+
 /* Clients have an option of measuring an analog signal through an MPP.
    MPP block is not part of the VADC block but is an individual PMIC
    block that has an option to support clients to configure an MPP as
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 0672f14..2da5c72 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -86,6 +86,7 @@
 			for storing the FCC(mAh) in the 8-bit BMS register.
 			For example - A value of 10 indicates:
 			FCC value (in mAh) = (8-bit register value) * 10.
+- qcom,bms-vadc: Corresponding VADC device's phandle.
 
 Parent node optional properties:
 - qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
@@ -148,6 +149,7 @@
 	qcom,hold-soc-est = <3>;
 	qcom,tm-temp-margin = <5000>;
 	qcom,battery-data = <&mtp_batterydata>;
+	qcom,bms-vadc = <&pm8941_vadc>;
 
 	qcom,bms-iadc@3800 {
 		reg = <0x3800 0x100>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index e3c3555..3150bbf 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -80,6 +80,7 @@
 					for the boost regulator.
 - qcom,resume-soc			Capacity in percent at which charging should resume
 					when a fully charged battery drops below this level.
+- qcom,chg-vadc				Corresponding VADC device's phandle.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
@@ -196,6 +197,7 @@
 		qcom,batt-hot-percent = <25>;
 		qcom,batt-cold-percent = <85>;
 		qcom,btc-disabled = <0>;
+		qcom,chg-vadc = <&pm8941_vadc>;
 
 		qcom,chgr@1000 {
 			reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
index 3854598..64c44b5 100644
--- a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
+++ b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
@@ -95,6 +95,7 @@
 			8 : 256
 - qcom,btm-channel-number : There are 5 BTM channels. The BTM channel numbers are statically
 			    allocated to the corresponding channel node.
+- qcom,adc_tm-vadc : phandle to the corresponding VADC device to read the ADC channels.
 
 Example:
 	/* Main Node */
@@ -111,6 +112,7 @@
 					  "low-thr-en-set";
                         qcom,adc-bit-resolution = <15>;
                         qcom,adc-vdd-reference = <1800>;
+			qcom,adc_tm-vadc = <&pm8941_vadc>;
 
 			/* Channel Node to be registered as part of thermal sysfs */
                         chan@b5 {
diff --git a/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt b/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt
index 19fbd3a..1c42692 100644
--- a/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt
+++ b/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt
@@ -37,6 +37,7 @@
 - qcom,default-temp:   Specifies the default temperature in millicelcius to use
 			if no ADC channel is present to read the real time
 			temperature.
+- qcom,temp_alarm-vadc: Corresponding VADC device's phandle.
 
 Note, if a given optional qcom,* binding is not present, then the default
 hardware state for that feature will be maintained.
@@ -61,6 +62,7 @@
 			label = "pm8941_tz";
 			qcom,channel-num = <8>;
 			qcom,threshold-set = <0>;
+			qcom,temp_alarm-vadc = <&pm8941_vadc>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/apq8074-v2-cdp.dts b/arch/arm/boot/dts/apq8074-v2.0-1-cdp.dts
similarity index 92%
rename from arch/arm/boot/dts/apq8074-v2-cdp.dts
rename to arch/arm/boot/dts/apq8074-v2.0-1-cdp.dts
index 1dc0912..0489b55 100644
--- a/arch/arm/boot/dts/apq8074-v2-cdp.dts
+++ b/arch/arm/boot/dts/apq8074-v2.0-1-cdp.dts
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "apq8074-v2.dtsi"
+/include/ "apq8074-v2.0-1.dtsi"
 /include/ "msm8974-cdp.dtsi"
 
 / {
-	model = "Qualcomm APQ 8074v2 CDP";
+	model = "Qualcomm APQ 8074v2.0-1 CDP";
 	compatible = "qcom,apq8074-cdp", "qcom,apq8074", "qcom,cdp";
 	qcom,msm-id = <184 1 0x20000>;
 };
diff --git a/arch/arm/boot/dts/apq8074-v2-dragonboard.dts b/arch/arm/boot/dts/apq8074-v2.0-1-dragonboard.dts
similarity index 89%
rename from arch/arm/boot/dts/apq8074-v2-dragonboard.dts
rename to arch/arm/boot/dts/apq8074-v2.0-1-dragonboard.dts
index 5a6f5f3..128d8bd 100644
--- a/arch/arm/boot/dts/apq8074-v2-dragonboard.dts
+++ b/arch/arm/boot/dts/apq8074-v2.0-1-dragonboard.dts
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "apq8074-v2.dtsi"
+/include/ "apq8074-v2.0-1.dtsi"
 /include/ "apq8074-dragonboard.dtsi"
 
 / {
-	model = "Qualcomm APQ 8074v2 DRAGONBOARD";
+	model = "Qualcomm APQ 8074v2.0-1 DRAGONBOARD";
 	compatible = "qcom,apq8074-dragonboard", "qcom,apq8074", "qcom,dragonboard";
 	qcom,msm-id = <184 10 0x20000>;
 };
diff --git a/arch/arm/boot/dts/apq8074-v2-liquid.dts b/arch/arm/boot/dts/apq8074-v2.0-1-liquid.dts
similarity index 89%
rename from arch/arm/boot/dts/apq8074-v2-liquid.dts
rename to arch/arm/boot/dts/apq8074-v2.0-1-liquid.dts
index a0ecb50..63c32f3 100644
--- a/arch/arm/boot/dts/apq8074-v2-liquid.dts
+++ b/arch/arm/boot/dts/apq8074-v2.0-1-liquid.dts
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "apq8074-v2.dtsi"
+/include/ "apq8074-v2.0-1.dtsi"
 /include/ "msm8974-liquid.dtsi"
 
 / {
-	model = "Qualcomm APQ 8074v2 LIQUID";
+	model = "Qualcomm APQ 8074v2.0-1 LIQUID";
 	compatible = "qcom,apq8074-liquid", "qcom,apq8074", "qcom,liquid";
 	qcom,msm-id = <184 9 0x20000>;
 };
diff --git a/arch/arm/boot/dts/apq8074-v2.dtsi b/arch/arm/boot/dts/apq8074-v2.0-1.dtsi
similarity index 97%
rename from arch/arm/boot/dts/apq8074-v2.dtsi
rename to arch/arm/boot/dts/apq8074-v2.0-1.dtsi
index c700a5c..8314fab 100644
--- a/arch/arm/boot/dts/apq8074-v2.dtsi
+++ b/arch/arm/boot/dts/apq8074-v2.0-1.dtsi
@@ -16,7 +16,7 @@
  * msm8974.dtsi file.
  */
 
-/include/ "msm8974-v2.dtsi"
+/include/ "msm8974-v2.0-1.dtsi"
 
 &soc {
 	qcom,qseecom@a700000 {
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index b027f7d..943f2a3 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -344,6 +344,12 @@
 		qcom,pet-time = <10000>;
 		qcom,ipi-ping;
 	};
+
+	qcom,msm-rng@f9bff000{
+		compatible = "qcom,msm-rng";
+		reg = <0xf9bff000 0x200>;
+		qcom,msm-rng-iface-clk;
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/mpq8092-rumi.dtsi b/arch/arm/boot/dts/mpq8092-rumi.dtsi
index cc345d8..af49eaf 100644
--- a/arch/arm/boot/dts/mpq8092-rumi.dtsi
+++ b/arch/arm/boot/dts/mpq8092-rumi.dtsi
@@ -10,6 +10,12 @@
  * GNU General Public License for more details.
  */
 
+/ {
+	aliases {
+		spi0 = &spi_0;
+	};
+};
+
 &soc {
 	timer {
 		clock-frequency = <5000000>;
@@ -41,17 +47,28 @@
 		status = "disable";
 	};
 
-	spi@f9923000 {
+	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
 		compatible = "qcom,spi-qup-v2";
-		reg = <0xf9923000 0x1000>;
-		interrupts = <0 95 0>;
-		spi-max-frequency = <24000000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		gpios = <&msmgpio 3 0>, /* CLK  */
-			<&msmgpio 1 0>, /* MISO */
-			<&msmgpio 0 0>; /* MOSI */
-		cs-gpios = <&msmgpio 9 0>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0xf9923000 0x1000>,
+		      <0xf9904000 0xf000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 95 0>, <0 238 0>;
+		spi-max-frequency = <19200000>;
+
+		qcom,gpio-mosi = <&msmgpio 0  0>;
+		qcom,gpio-miso = <&msmgpio 1  0>;
+		qcom,gpio-clk  = <&msmgpio 3  0>;
+		qcom,gpio-cs2  = <&msmgpio 11 0>;
+
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <12>;
+		qcom,bam-producer-pipe-index = <13>;
+		qcom,master-id = <86>;
 
 		ethernet-switch@2 {
 			compatible = "simtec,ks8851";
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 4f3e461..3c17655 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -68,6 +68,7 @@
 			qcom,vbatdet-delta-mv = <350>;
 			qcom,resume-soc = <99>;
 			qcom,tchg-mins = <150>;
+			qcom,chg-vadc = <&pm8110_vadc>;
 
 			qcom,chgr@1000 {
 				status = "disabled";
@@ -258,6 +259,7 @@
 			interrupt-names = "eoc-int-en-set";
 			qcom,adc-bit-resolution = <16>;
 			qcom,adc-vdd-reference = <1800>;
+			qcom,iadc-vadc = <&pm8110_vadc>;
 
 			chan@0 {
 				label = "internal_rsense";
@@ -284,6 +286,7 @@
 						"low-thr-en-set";
 			qcom,adc-bit-resolution = <15>;
 			qcom,adc-vdd-reference = <1800>;
+			qcom,adc_tm-vadc = <&pm8110_vadc>;
 		};
 
 		qcom,temp-alarm@2400 {
@@ -293,6 +296,7 @@
 			label = "pm8110_tz";
 			qcom,channel-num = <8>;
 			qcom,threshold-set = <0>;
+			qcom,temp_alarm-vadc = <&pm8110_vadc>;
 		};
 
 		pm8110_bms: qcom,bms {
@@ -320,6 +324,7 @@
 			qcom,low-ocv-correction-limit-uv = <100>;
 			qcom,high-ocv-correction-limit-uv = <50>;
 			qcom,hold-soc-est = <3>;
+			qcom,bms-vadc = <&pm8110_vadc>;
 
 			qcom,bms-iadc@3800 {
 				reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index d7c2155..e3daf6c 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -83,6 +83,7 @@
 			qcom,thermal-mitigation = <1500 700 600 325>;
 			qcom,resume-soc = <99>;
 			qcom,tchg-mins = <150>;
+			qcom,chg-vadc = <&pm8226_vadc>;
 
 			qcom,chgr@1000 {
 				status = "disabled";
@@ -196,6 +197,7 @@
 			qcom,high-ocv-correction-limit-uv = <50>;
 			qcom,hold-soc-est = <3>;
 			qcom,low-voltage-threshold = <3420000>;
+			qcom,bms-vadc = <&pm8226_vadc>;
 
 			qcom,bms-iadc@3800 {
 				reg = <0x3800 0x100>;
@@ -396,7 +398,7 @@
 			};
 		};
 
-		iadc@3600 {
+		pm8226_iadc: iadc@3600 {
 			compatible = "qcom,qpnp-iadc";
 			reg = <0x3600 0x100>;
 			#address-cells = <1>;
@@ -405,6 +407,7 @@
 			interrupt-names = "eoc-int-en-set";
 			qcom,adc-bit-resolution = <16>;
 			qcom,adc-vdd-reference = <1800>;
+			qcom,iadc-vadc = <&pm8226_vadc>;
 
 			chan@0 {
 				label = "internal_rsense";
@@ -431,6 +434,7 @@
 						"low-thr-en-set";
 			qcom,adc-bit-resolution = <15>;
 			qcom,adc-vdd-reference = <1800>;
+			qcom,adc_tm-vadc = <&pm8226_vadc>;
 		};
 
 		qcom,temp-alarm@2400 {
@@ -440,6 +444,7 @@
 			label = "pm8226_tz";
 			qcom,channel-num = <8>;
 			qcom,threshold-set = <0>;
+			qcom,temp_alarm-vadc = <&pm8226_vadc>;
 		};
 
 		qcom,pm8226_rtc {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 2460377..fad57a6 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -39,6 +39,7 @@
 		label = "pm8941_tz";
 		qcom,channel-num = <8>;
 		qcom,threshold-set = <0>;
+		qcom,temp_alarm-vadc = <&pm8941_vadc>;
 	};
 
 	qcom,power-on@800 {
@@ -100,6 +101,7 @@
 		qcom,min-clock-period = <1000>;
 		qcom,max-clock-period = <160000>;
 		qcom,sample-rate = <4>;
+		qcom,bsi-vadc = <&pm8941_vadc>;
 	};
 
 	pm8941_coincell: qcom,coincell@2800 {
@@ -132,6 +134,7 @@
 		qcom,low-ocv-correction-limit-uv = <100>;
 		qcom,high-ocv-correction-limit-uv = <50>;
 		qcom,hold-soc-est = <3>;
+		qcom,bms-vadc = <&pm8941_vadc>;
 
 		qcom,bms-iadc@3800 {
 			reg = <0x3800 0x100>;
@@ -200,6 +203,7 @@
 		qcom,vbatdet-delta-mv = <100>;
 		qcom,resume-soc = <99>;
 		qcom,tchg-mins = <150>;
+		qcom,chg-vadc = <&pm8941_vadc>;
 
 		qcom,chgr@1000 {
 			status = "disabled";
@@ -806,6 +810,7 @@
 		interrupt-names = "eoc-int-en-set";
 		qcom,adc-bit-resolution = <16>;
 		qcom,adc-vdd-reference = <1800>;
+		qcom,iadc-vadc = <&pm8941_vadc>;
 
 		chan@0 {
 			label = "internal_rsense";
@@ -832,6 +837,7 @@
 					"low-thr-en-set";
 		qcom,adc-bit-resolution = <15>;
 		qcom,adc-vdd-reference = <1800>;
+		qcom,adc_tm-vadc = <&pm8941_vadc>;
 
 		/* Channel Node */
 		chan@b9 {
diff --git a/arch/arm/boot/dts/msm-pma8084.dtsi b/arch/arm/boot/dts/msm-pma8084.dtsi
index ecbfc53..3368b36 100644
--- a/arch/arm/boot/dts/msm-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm-pma8084.dtsi
@@ -77,6 +77,7 @@
 			interrupts = <0x0 0x24 0x0>;
 			label = "pma8084_tz";
 			qcom,threshold-set = <0>;
+			qcom,temp_alarm-vadc = <&pma8084_vadc>;
 		};
 
 		qcom,coincell@2800 {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index d94b41d..ef4b236 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -319,7 +319,7 @@
 				qcom,ctrl-delay-us = <0>;
 				qcom,boost-curr-lim = <3>;
 				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
+				qcom,switch-freq = <11>;
 				qcom,ovp-val = <0>;
 				qcom,num-strings = <1>;
 				qcom,id = <0>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 825e853..ce7f9e9 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -327,7 +327,7 @@
 				qcom,ctrl-delay-us = <0>;
 				qcom,boost-curr-lim = <3>;
 				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
+				qcom,switch-freq = <11>;
 				qcom,ovp-val = <0>;
 				qcom,num-strings = <1>;
 				qcom,id = <0>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 55d8691..10a2dce 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -328,7 +328,7 @@
 				qcom,ctrl-delay-us = <0>;
 				qcom,boost-curr-lim = <3>;
 				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
+				qcom,switch-freq = <11>;
 				qcom,ovp-val = <0>;
 				qcom,num-strings = <1>;
 				qcom,id = <0>;
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
index a2ad682..cb6c1af 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
@@ -13,7 +13,6 @@
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "msm8226-camera-sensor-cdp.dtsi"
 /include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index b836100..a5d511b 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -1072,16 +1072,17 @@
 		interrupts = <0 95 0>, <0 238 0>;
 		spi-max-frequency = <19200000>;
 
-		gpios = <&msmgpio 3 0>, /* CLK  */
-			<&msmgpio 1 0>, /* MISO */
-			<&msmgpio 0 0>; /* MOSI */
-		cs-gpios = <&msmgpio 22 0>;
+		qcom,gpio-mosi = <&msmgpio 0 0>;
+		qcom,gpio-miso = <&msmgpio 1 0>;
+		qcom,gpio-clk  = <&msmgpio 3 0>;
+		qcom,gpio-cs0  = <&msmgpio 22 0>;
 
 		qcom,infinite-mode = <0>;
 		qcom,use-bam;
 		qcom,ver-reg-exists;
 		qcom,bam-consumer-pipe-index = <12>;
 		qcom,bam-producer-pipe-index = <13>;
+		qcom,master-id = <86>;
 	};
 
 	qcom,bam_dmux@fc834000 {
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
index c435038..947a312 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -76,7 +76,7 @@
 			vdd-supply = <&pm8110_l19>;
 			vio-supply = <&pm8110_l14>;
 			fsl,irq-gpio = <&msmgpio 81 0x00>;
-			fsl,sensors-position = <5>;
+			fsl,sensors-position = <1>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 0078861..e6aa347 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -518,16 +518,17 @@
 		interrupts = <0 98 0>, <0 238 0>;
 		spi-max-frequency = <50000000>;
 
-		gpios = <&msmgpio 89 0>, /* CLK  */
-			<&msmgpio 87 0>, /* MISO */
-			<&msmgpio 86 0>; /* MOSI */
-		cs-gpios = <&msmgpio 88 0>;
+		qcom,gpio-mosi = <&msmgpio 86 0>;
+		qcom,gpio-miso = <&msmgpio 87 0>;
+		qcom,gpio-clk  = <&msmgpio 89 0>;
+		qcom,gpio-cs0  = <&msmgpio 88 0>;
 
 		qcom,infinite-mode = <0>;
 		qcom,use-bam;
 		qcom,ver-reg-exists;
 		qcom,bam-consumer-pipe-index = <18>;
 		qcom,bam-producer-pipe-index = <19>;
+		qcom,master-id = <86>;
 	};
 
 	qcom,pronto@fb21b000 {
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-qrd.dts
index 8497ba2..e056b7e 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-qrd.dts
@@ -13,7 +13,6 @@
 /dts-v1/;
 /include/ "msm8926.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926 QRD";
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index e66ea25..a4f512a 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -272,7 +272,7 @@
 			qcom,ctrl-delay-us = <0>;
 			qcom,boost-curr-lim = <3>;
 			qcom,cp-sel = <0>;
-			qcom,switch-freq = <2>;
+			qcom,switch-freq = <11>;
 			qcom,ovp-val = <2>;
 			qcom,num-strings = <1>;
 			qcom,id = <0>;
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 7f714e8..3d20f7c 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -271,7 +271,7 @@
 			qcom,ctrl-delay-us = <0>;
 			qcom,boost-curr-lim = <3>;
 			qcom,cp-sel = <0>;
-			qcom,switch-freq = <2>;
+			qcom,switch-freq = <11>;
 			qcom,ovp-val = <2>;
 			qcom,num-strings = <1>;
 			qcom,id = <0>;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 4ee56ad..c1a8792 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -212,7 +212,7 @@
 			qcom,ctrl-delay-us = <0>;
 			qcom,boost-curr-lim = <3>;
 			qcom,cp-sel = <0>;
-			qcom,switch-freq = <2>;
+			qcom,switch-freq = <11>;
 			qcom,ovp-val = <2>;
 			qcom,num-strings = <1>;
 			qcom,id = <0>;
diff --git a/arch/arm/boot/dts/msm8974-rumi.dtsi b/arch/arm/boot/dts/msm8974-rumi.dtsi
index c01a4e5..152ac4d 100644
--- a/arch/arm/boot/dts/msm8974-rumi.dtsi
+++ b/arch/arm/boot/dts/msm8974-rumi.dtsi
@@ -13,6 +13,12 @@
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor-cdp.dtsi"
 
+/ {
+	aliases {
+		spi0 = &spi_0;
+	};
+};
+
 &soc {
 	timer {
 		clock-frequency = <5000000>;
@@ -42,17 +48,28 @@
 		status = "disable";
 	};
 
-	spi@f9923000 {
+	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
 		compatible = "qcom,spi-qup-v2";
-		reg = <0xf9923000 0x1000>;
-		interrupts = <0 95 0>;
-		spi-max-frequency = <24000000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		gpios = <&msmgpio 3 0>, /* CLK  */
-			<&msmgpio 1 0>, /* MISO */
-			<&msmgpio 0 0>; /* MOSI */
-		cs-gpios = <&msmgpio 9 0>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0xf9923000 0x1000>,
+		      <0xf9904000 0xf000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 95 0>, <0 238 0>;
+		spi-max-frequency = <19200000>;
+
+		qcom,gpio-mosi = <&msmgpio 0 0>;
+		qcom,gpio-miso = <&msmgpio 1 0>;
+		qcom,gpio-clk  = <&msmgpio 3 0>;
+		qcom,gpio-cs0  = <&msmgpio 9 0>;
+
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <12>;
+		qcom,bam-producer-pipe-index = <13>;
+		qcom,master-id = <86>;
 
 		ethernet-switch@2 {
 			compatible = "simtec,ks8851";
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index 7b801da..86a61cd 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -148,3 +148,20 @@
 &usb_otg {
 	qcom,hsusb-otg-pnoc-errata-fix;
 };
+
+&gdsc_venus {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
+
+&gdsc_mdss {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
+
+&gdsc_oxili_gx {
+	qcom,retain-mem;
+	qcom,retain-periph;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-cdp.dts b/arch/arm/boot/dts/msm8974-v2.0-1-cdp.dts
similarity index 90%
rename from arch/arm/boot/dts/msm8974-v2-cdp.dts
rename to arch/arm/boot/dts/msm8974-v2.0-1-cdp.dts
index f4014aa..875b3fc 100644
--- a/arch/arm/boot/dts/msm8974-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v2.0-1-cdp.dts
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "msm8974-v2.dtsi"
+/include/ "msm8974-v2.0-1.dtsi"
 /include/ "msm8974-cdp.dtsi"
 
 / {
-	model = "Qualcomm MSM 8974v2 CDP";
+	model = "Qualcomm MSM 8974v2.0/1 CDP";
 	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
 	qcom,msm-id = <126 1 0x20000>,
 		      <185 1 0x20000>,
diff --git a/arch/arm/boot/dts/msm8974-v2-fluid.dts b/arch/arm/boot/dts/msm8974-v2.0-1-fluid.dts
similarity index 90%
rename from arch/arm/boot/dts/msm8974-v2-fluid.dts
rename to arch/arm/boot/dts/msm8974-v2.0-1-fluid.dts
index 9c9e3c0..236593d 100644
--- a/arch/arm/boot/dts/msm8974-v2-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v2.0-1-fluid.dts
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "msm8974-v2.dtsi"
+/include/ "msm8974-v2.0-1.dtsi"
 /include/ "msm8974-fluid.dtsi"
 
 / {
-	model = "Qualcomm MSM 8974v2 FLUID";
+	model = "Qualcomm MSM 8974v2.0/1 FLUID";
 	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
 	qcom,msm-id = <126 3 0x20000>,
 		      <185 3 0x20000>,
diff --git a/arch/arm/boot/dts/msm8974-v2-liquid.dts b/arch/arm/boot/dts/msm8974-v2.0-1-liquid.dts
similarity index 90%
rename from arch/arm/boot/dts/msm8974-v2-liquid.dts
rename to arch/arm/boot/dts/msm8974-v2.0-1-liquid.dts
index ddae6fe..23292f6 100644
--- a/arch/arm/boot/dts/msm8974-v2-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v2.0-1-liquid.dts
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "msm8974-v2.dtsi"
+/include/ "msm8974-v2.0-1.dtsi"
 /include/ "msm8974-liquid.dtsi"
 
 / {
-	model = "Qualcomm MSM 8974v2 LIQUID";
+	model = "Qualcomm MSM 8974v2.0/1 LIQUID";
 	compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
 	qcom,msm-id = <126 9 0x20000>,
 		      <185 9 0x20000>,
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2.0-1-mtp.dts
similarity index 91%
rename from arch/arm/boot/dts/msm8974-v2-mtp.dts
rename to arch/arm/boot/dts/msm8974-v2.0-1-mtp.dts
index 021b626..de9e6a3 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2.0-1-mtp.dts
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "msm8974-v2.dtsi"
+/include/ "msm8974-v2.0-1.dtsi"
 /include/ "msm8974-mtp.dtsi"
 
 / {
-	model = "Qualcomm MSM 8974v2 MTP";
+	model = "Qualcomm MSM 8974v2.0/1 MTP";
 	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
 	qcom,msm-id = <126 8 0x20000>,
 		      <185 8 0x20000>,
diff --git a/arch/arm/boot/dts/msm8974-v2.0-1.dtsi b/arch/arm/boot/dts/msm8974-v2.0-1.dtsi
new file mode 100644
index 0000000..1fad868
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2.0-1.dtsi
@@ -0,0 +1,36 @@
+/* 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi file.
+ */
+
+/include/ "msm8974-v2.dtsi"
+
+&gdsc_venus {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
+
+&gdsc_mdss {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
+
+&gdsc_oxili_gx {
+	qcom,retain-mem;
+	qcom,retain-periph;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.2.dtsi b/arch/arm/boot/dts/msm8974-v2.2.dtsi
index 09455b1..0ca021b 100644
--- a/arch/arm/boot/dts/msm8974-v2.2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.2.dtsi
@@ -103,3 +103,8 @@
 		};
 	};
 };
+
+&gdsc_mdss {
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 59e8dac..725cfaf 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -580,18 +580,28 @@
 		qcom,bam-dma-res-pipes = <6>;
 	};
 
-	spi_7: spi_epm: spi@f9966000 {
+	spi_7: spi_epm: spi@f9966000 { /* BLSP2 QUP4 */
 		compatible = "qcom,spi-qup-v2";
-		reg = <0xf9966000 0x1000>;
-		interrupts = <0 104 0>;
-		spi-max-frequency = <19200000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		qcom,master-id = <84>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0xf9966000 0x1000>,
+		      <0xf9944000 0x15000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 104 0>, <0 239 0>;
+		spi-max-frequency = <19200000>;
+
 		qcom,gpio-mosi = <&msmgpio 53 0>;
 		qcom,gpio-miso = <&msmgpio 54 0>;
 		qcom,gpio-clk  = <&msmgpio 56 0>;
 		qcom,gpio-cs0  = <&msmgpio 55 0>;
+
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <18>;
+		qcom,bam-producer-pipe-index = <19>;
+		qcom,master-id = <84>;
 	};
 
 	tspp: msm_tspp@f99d8000 {
@@ -816,18 +826,28 @@
 		qcom,master-id = <86>;
 	};
 
-	spi_0: spi@f9923000 {
+	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
 		compatible = "qcom,spi-qup-v2";
-		reg = <0xf9923000 0x1000>;
-		interrupts = <0 95 0>;
-		spi-max-frequency = <19200000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		qcom,master-id = <86>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0xf9923000 0x1000>,
+		      <0xf9904000 0xf000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 95 0>, <0 238 0>;
+		spi-max-frequency = <19200000>;
+
 		qcom,gpio-mosi = <&msmgpio 0 0>;
 		qcom,gpio-miso = <&msmgpio 1 0>;
 		qcom,gpio-clk  = <&msmgpio 3 0>;
-		qcom,gpio-cs2  = <&msmgpio 9 0>;
+		qcom,gpio-cs0  = <&msmgpio 9 0>;
+
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <12>;
+		qcom,bam-producer-pipe-index = <13>;
+		qcom,master-id = <86>;
 	};
 
 	qcom,acpuclk@f9000000 {
@@ -1651,17 +1671,11 @@
 
 &gdsc_venus {
 	qcom,clock-names = "core_clk";
-	qcom,skip-logic-collapse;
-	qcom,retain-periph;
-	qcom,retain-mem;
 	status = "ok";
 };
 
 &gdsc_mdss {
 	qcom,clock-names = "core_clk", "lut_clk";
-	qcom,skip-logic-collapse;
-	qcom,retain-periph;
-	qcom,retain-mem;
 	status = "ok";
 };
 
@@ -1678,8 +1692,6 @@
 
 &gdsc_oxili_gx {
 	qcom,clock-names = "core_clk";
-	qcom,retain-mem;
-	qcom,retain-periph;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 59d7ba0..0e7baf1 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -328,18 +328,26 @@
 		interrupt-names = "bam_irq";
 	};
 
-	spi_0: spi@f9924000 {
+	spi_0: spi@f9924000 { /* BLSP1 QUP2 */
 		compatible = "qcom,spi-qup-v2";
-		reg = <0xf9924000 0x1000>;
-		interrupts = <0 96 0>;
-		spi-max-frequency = <25000000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		gpios = <&msmgpio 7 0>, /* CLK  */
-			<&msmgpio 5 0>, /* MISO */
-			<&msmgpio 4 0>; /* MOSI */
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0xf9924000 0x1000>,
+		      <0xf9904000 0x11000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 96 0>, <0 238 0>;
+		spi-max-frequency = <19200000>;
+		qcom,gpio-mosi = <&msmgpio 4 0>;
+		qcom,gpio-miso = <&msmgpio 5 0>;
+		qcom,gpio-clk  = <&msmgpio 7 0>;
+		qcom,gpio-cs0  = <&msmgpio 6 0>;
 
-		cs-gpios = <&msmgpio 6 0>;
+		qcom,infinite-mode = <0>;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <14>;
+		qcom,bam-producer-pipe-index = <15>;
+		qcom,master-id = <86>;
 
 		ethernet-switch@0 {
 			compatible = "simtec,ks8851";
@@ -736,7 +744,23 @@
 			compatible = "qcom,msm-dai-q6-dev";
 			qcom,msm-dai-q6-dev-id = <240>;
 		};
+
+		qcom,msm-dai-q6-incall-record-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32771>;
+		};
+
+		qcom,msm-dai-q6-incall-record-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32772>;
+		};
+
+		qcom,msm-dai-q6-incall-music-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32773>;
+		};
 	};
+
 	qcom,msm-pcm-dtmf {
 		compatible = "qcom,msm-pcm-dtmf";
 	};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index cdaf964..f3e9dbb 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -17,6 +17,10 @@
 	compatible = "qcom,msmkrypton";
 	interrupt-parent = <&intc>;
 
+	aliases {
+		spi6 = &spi_6;
+	};
+
 	soc: soc { };
 };
 
@@ -140,18 +144,27 @@
 	};
 
 	spi_6: spi@f9928000 { /* BLSP1 QUP6 */
-		cell-index = <0>;
 		compatible = "qcom,spi-qup-v2";
 		#address-cells = <1>;
 		#size-cells = <0>;
-		reg = <0xf9928000 0x1000>;
-		interrupts = <0 100 0>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0xf9928000 0x1000>,
+		      <0xf9904000 0x19000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 100 0>, <0 238 0>;
 		spi-max-frequency = <19200000>;
 
-		gpios = <&msmgpio 23 0>, /* CLK  */
-		<&msmgpio 21 0>, /* MISO */
-		<&msmgpio 20 0>; /* MOSI */
-		cs-gpios = <&msmgpio 22 0>;
+		qcom,gpio-mosi = <&msmgpio 20 0>;
+		qcom,gpio-miso = <&msmgpio 21 0>;
+		qcom,gpio-clk  = <&msmgpio 23 0>;
+		qcom,gpio-cs0  = <&msmgpio 22 0>;
+
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <22>;
+		qcom,bam-producer-pipe-index = <23>;
+		qcom,master-id = <86>;
 	};
 
 	qcom,ipc-spinlock@fd484000 {
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index 251bef2..31ab623 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -89,6 +89,14 @@
 		status = "disabled";
 	};
 
+	qcom,sps@f9980000 {
+		compatible = "qcom,msm_sps";
+		reg = <0xf9984000 0x15000>,
+		      <0xf9999000 0xb000>;
+		reg-names = "bam_mem", "core_mem";
+		interrupts = <0 94 0>;
+	};
+
 	qcom,wdt@f9017000 {
 		compatible = "qcom,msm-watchdog";
 		reg = <0xf9017000 0x1000>;
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index cfd346e..a5f0704 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -71,7 +71,6 @@
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_BOOT_STATS=y
-CONFIG_MSM_XPU_ERR_FATAL=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index b80949c..5c0d2cf 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -284,6 +284,7 @@
 	select MSM_ULTRASOUND_B
 	select MSM_RPM_LOG
 	select ARCH_WANT_KMAP_ATOMIC_FLUSH
+	select KRAIT_REGULATOR
 
 config ARCH_APQ8084
 	bool "APQ8084"
@@ -521,6 +522,7 @@
 	select ARM_GIC
 	select CPU_V7
 	select MSM_SCM
+	select MSM_PIL
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_SPM_V2
@@ -3060,4 +3062,11 @@
 	 Support the wallclk directory in sysfs filesystem to enable the
 	 wall clock simulation and read the current SFN.
 
+config KRAIT_REGULATOR
+	bool "Support Kraits powered via ganged regulators in the pmic"
+	help
+	 Certain MSMs have the Krait CPUs powered via a single supply
+	 line from the PMIC. This supply line is powered by multiple
+	 regulators running in ganged mode inside the PMIC. Enable
+	 this option to support such configurations.
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 8c42b8d..cd71104 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -296,7 +296,7 @@
 obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
 obj-$(CONFIG_ARCH_MPQ8092) += gdsc.o
 obj-$(CONFIG_ARCH_APQ8084) += gdsc.o
-obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
+obj-$(CONFIG_KRAIT_REGULATOR) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSMKRYPTON) += board-krypton.o board-krypton-gpiomux.o
 obj-$(CONFIG_ARCH_MSMSAMARIUM) += board-samarium.o board-samarium-gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 3505afe..72472f9 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -53,13 +53,13 @@
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v1-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v1-rumi.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v1-sim.dtb
-        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-cdp.dtb
-        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-fluid.dtb
-        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-liquid.dtb
-        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-mtp.dtb
-        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-cdp.dtb
-        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-liquid.dtb
-        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-dragonboard.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2.0-1-cdp.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2.0-1-fluid.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2.0-1-liquid.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2.0-1-mtp.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2.0-1-cdp.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2.0-1-liquid.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2.0-1-dragonboard.dtb
 
 # APQ8084
    zreladdr-$(CONFIG_ARCH_APQ8084)	:= 0x00008000
diff --git a/arch/arm/mach-msm/board-fsm9900-gpiomux.c b/arch/arm/mach-msm/board-fsm9900-gpiomux.c
index dede706..990aefc 100644
--- a/arch/arm/mach-msm/board-fsm9900-gpiomux.c
+++ b/arch/arm/mach-msm/board-fsm9900-gpiomux.c
@@ -17,6 +17,370 @@
 #include <mach/board.h>
 #include <mach/gpiomux.h>
 
+static struct gpiomux_setting blsp_uart_no_pull_config = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting blsp_uart_pull_up_config = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting blsp_i2c_config = {
+	.func = GPIOMUX_FUNC_3,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config fsm_blsp_configs[] __initdata = {
+	{
+		.gpio      = 0,	       /* BLSP UART1 TX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_uart_no_pull_config,
+		},
+	},
+	{
+		.gpio      = 1,	       /* BLSP UART1 RX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_uart_pull_up_config,
+		},
+	},
+	{
+		.gpio      = 2,	       /* BLSP I2C SDA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_i2c_config,
+		},
+	},
+	{
+		.gpio      = 3,	       /* BLSP I2C SCL */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_i2c_config,
+		},
+	},
+	{
+		.gpio      = 6,	       /* BLSP I2C SDA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_i2c_config,
+		},
+	},
+	{
+		.gpio      = 7,	       /* BLSP I2C SCL */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_i2c_config,
+		},
+	},
+	{
+		.gpio      = 36,       /* BLSP UART10 TX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_uart_no_pull_config,
+		},
+	},
+	{
+		.gpio      = 37,       /* BLSP UART10 RX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_uart_pull_up_config,
+		},
+	},
+	{
+		.gpio      = 38,       /* BLSP I2C10 SDA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_i2c_config,
+		},
+	},
+	{
+		.gpio      = 39,       /* BLSP I2C10 SCL */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &blsp_i2c_config,
+		},
+	},
+
+};
+
+static struct gpiomux_setting geni_func4_config = {
+	.func = GPIOMUX_FUNC_4,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting geni_func5_config = {
+	.func = GPIOMUX_FUNC_5,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config fsm_geni_configs[] __initdata = {
+	{
+		.gpio      = 8,	       /* GENI7 DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func4_config,
+		},
+	},
+	{
+		.gpio      = 9,	       /* GENI1 DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func4_config,
+		},
+	},
+	{
+		.gpio      = 10,       /* GENI2 DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func4_config,
+		},
+	},
+	{
+		.gpio      = 11,       /* GENI7 CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func4_config,
+		},
+	},
+	{
+		.gpio      = 20,       /* GENI3 DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func5_config,
+		},
+	},
+	{
+		.gpio      = 21,       /* GENI4 DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func5_config,
+		},
+	},
+	{
+		.gpio      = 22,       /* GENI6 DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func5_config,
+		},
+	},
+	{
+		.gpio      = 23,       /* GENI6 CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func5_config,
+		},
+	},
+	{
+		.gpio      = 30,       /* GENI5 DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func4_config,
+		},
+	},
+	{
+		.gpio      = 31,       /* GENI5 CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &geni_func4_config,
+		},
+	},
+
+};
+
+static struct gpiomux_setting dan_spi_func4_config = {
+	.func = GPIOMUX_FUNC_4,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting dan_spi_func1_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config fsm_dan_spi_configs[] __initdata = {
+	{
+		.gpio      = 12,       /* BLSP DAN0 SPI_MOSI */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func4_config,
+		},
+	},
+	{
+		.gpio      = 13,       /* BLSP DAN0 SPI_MISO */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func4_config,
+		},
+	},
+	{
+		.gpio      = 14,       /* BLSP DAN0 SPI_CS */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func4_config,
+		},
+	},
+	{
+		.gpio      = 15,       /* BLSP DAN0 SPI_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func4_config,
+		},
+	},
+	{
+		.gpio      = 16,       /* BLSP DAN1 SPI_MOSI */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func4_config,
+		},
+	},
+	{
+		.gpio      = 17,       /* BLSP DAN1 SPI_MISO */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func4_config,
+		},
+	},
+	{
+		.gpio      = 18,       /* BLSP DAN1 SPI_CS */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func4_config,
+		},
+	},
+	{
+		.gpio      = 19,       /* BLSP DAN1 SPI_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func4_config,
+		},
+	},
+	{
+		.gpio      = 81,       /* BLSP DAN1 SPI_CS0 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func1_config,
+		},
+	},
+	{
+		.gpio      = 82,       /* BLSP DAN1 SPI_CS1 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &dan_spi_func1_config,
+		},
+	},
+};
+
+static struct gpiomux_setting uim_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_4MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config fsm_uim_configs[] __initdata = {
+	{
+		.gpio      = 24,       /* UIM_DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &uim_config,
+		},
+	},
+	{
+		.gpio      = 25,       /* UIM_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &uim_config,
+		},
+	},
+	{
+		.gpio      = 26,       /* UIM_RESET */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &uim_config,
+		},
+	},
+	{
+		.gpio      = 27,       /* UIM_PRESENT */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &uim_config,
+		},
+	},
+};
+
+static struct gpiomux_setting pcie_config = {
+	.func = GPIOMUX_FUNC_4,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config fsm_pcie_configs[] __initdata = {
+	{
+		.gpio      = 28,       /* BLSP PCIE1_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &pcie_config,
+		},
+	},
+	{
+		.gpio      = 32,       /* BLSP PCIE0_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &pcie_config,
+		},
+	},
+};
+
+static struct gpiomux_setting pps_out_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_4MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting pps_in_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting gps_clk_in_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting gps_nav_tlmm_blank_config = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+static struct msm_gpiomux_config fsm_gps_configs[] __initdata = {
+	{
+		.gpio      = 40,       /* GPS_PPS_OUT */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &pps_out_config,
+		},
+	},
+	{
+		.gpio      = 41,       /* GPS_PPS_IN */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &pps_in_config,
+		},
+	},
+	{
+		.gpio      = 43,       /* GPS_CLK_IN */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gps_clk_in_config,
+		},
+	},
+	{
+		.gpio      = 120,      /* GPS_NAV_TLMM_BLANK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gps_nav_tlmm_blank_config,
+		},
+	},
+};
+
+static struct gpiomux_setting sd_detect_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sd_wp_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config fsm_sd_configs[] __initdata = {
+	{
+		.gpio      = 42,       /* SD_CARD_DET */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &sd_detect_config,
+		},
+	},
+	{
+		.gpio      = 122,      /* BLSP SD WRITE PROTECT */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &sd_wp_config,
+		},
+	},
+};
+
 void __init fsm9900_init_gpiomux(void)
 {
 	int rc;
@@ -26,4 +390,13 @@
 		pr_err("%s failed %d\n", __func__, rc);
 		return;
 	}
+
+	msm_gpiomux_install(fsm_blsp_configs, ARRAY_SIZE(fsm_blsp_configs));
+	msm_gpiomux_install(fsm_geni_configs, ARRAY_SIZE(fsm_geni_configs));
+	msm_gpiomux_install(fsm_dan_spi_configs,
+			    ARRAY_SIZE(fsm_dan_spi_configs));
+	msm_gpiomux_install(fsm_uim_configs, ARRAY_SIZE(fsm_uim_configs));
+	msm_gpiomux_install(fsm_pcie_configs, ARRAY_SIZE(fsm_pcie_configs));
+	msm_gpiomux_install(fsm_gps_configs, ARRAY_SIZE(fsm_gps_configs));
+	msm_gpiomux_install(fsm_sd_configs, ARRAY_SIZE(fsm_sd_configs));
 }
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 0cd5d55..cf6c23f 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3616,6 +3616,13 @@
 	 */
 	clk_prepare_enable(&xo_a_clk.c);
 
+	/*
+	 * Handoff will override the prepare enable count as well as the rate
+	 * Set them again.
+	 */
+	clk_set_rate(&mmssnoc_ahb_a_clk.c, 40000000);
+	clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
+
 	/* Set an initial rate (fmax at nominal) on the MMSSNOC AXI clock */
 	clk_set_rate(&axi_clk_src.c, 200000000);
 
@@ -3693,6 +3700,9 @@
 	if (IS_ERR(vdd_sr2_pll.regulator[1]))
 		panic("clock-8226: Unable to get the vdd_sr2_dig regulator!");
 
+
+	enable_rpm_scaling();
+
 	/*
 	 * Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
 	 * source. Sleep set vote is 0.
@@ -3700,8 +3710,7 @@
 	 * access mmss clock controller registers.
 	 */
 	clk_set_rate(&mmssnoc_ahb_a_clk.c, 40000000);
-
-	enable_rpm_scaling();
+	clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
 
 	reg_init();
 
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 527d73d..e3c11c5 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -90,16 +90,17 @@
 			continue;
 
 		rc = regulator_set_optimum_mode(r[i], ua[lvl_base + i]);
-		if (rc < 0)
+		rc = rc > 0 ? 0 : rc;
+		if (rc)
 			goto set_mode_fail;
 	}
 	if (vdd_class->set_vdd && !vdd_class->num_regulators)
 		rc = vdd_class->set_vdd(vdd_class, level);
 
-	if (rc < 0)
+	if (!rc)
 		vdd_class->cur_level = level;
 
-	return 0;
+	return rc;
 
 set_mode_fail:
 	regulator_set_voltage(r[i], uv[vdd_class->cur_level * n_reg + i],
diff --git a/arch/arm/mach-msm/include/mach/msm_smem.h b/arch/arm/mach-msm/include/mach/msm_smem.h
index 64ab6bf..a121791 100644
--- a/arch/arm/mach-msm/include/mach/msm_smem.h
+++ b/arch/arm/mach-msm/include/mach/msm_smem.h
@@ -136,6 +136,7 @@
 	SMEM_BAM_PIPE_MEMORY,     /* 468 */
 	SMEM_IMAGE_VERSION_TABLE, /* 469 */
 	SMEM_LC_DEBUGGER, /* 470 */
+	SMEM_FLASH_NAND_DEV_INFO, /* 471 */
 	SMEM_NUM_ITEMS,
 };
 
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
index 3a996eb..4538c4f 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -524,6 +524,7 @@
 		.mode = NOC_QOS_MODE_FIXED,
 		.qport = qports_ipa,
 		.mas_hw_id = MAS_IPA,
+		.hw_sel = MSM_BUS_NOC,
 	},
 	{
 		.id = MSM_BUS_MASTER_QDSS_ETR,
diff --git a/drivers/bif/qpnp-bsi.c b/drivers/bif/qpnp-bsi.c
index 5068a21..9d0abd2 100644
--- a/drivers/bif/qpnp-bsi.c
+++ b/drivers/bif/qpnp-bsi.c
@@ -56,6 +56,7 @@
 	atomic_t		irq_flag[QPNP_BSI_IRQ_COUNT];
 	int			batt_present_irq;
 	enum qpnp_vadc_channels	batt_id_adc_channel;
+	struct qpnp_vadc_chip	*vadc_dev;
 };
 
 #define QPNP_BSI_DRIVER_NAME	"qcom,qpnp-bsi"
@@ -1343,7 +1344,8 @@
 		return -ENXIO;
 	}
 
-	rc = qpnp_vadc_read(chip->batt_id_adc_channel, &adc_result);
+	rc = qpnp_vadc_read(chip->vadc_dev, chip->batt_id_adc_channel,
+								&adc_result);
 	if (!rc) {
 		vid_uV = adc_result.physical;
 
@@ -1672,8 +1674,11 @@
 
 	/* Ensure that ADC channel is available if it was specified. */
 	if (chip->batt_id_adc_channel < ADC_MAX_NUM) {
-		rc = qpnp_vadc_is_ready();
-		if (rc) {
+		chip->vadc_dev = qpnp_get_vadc(dev, "bsi");
+		if (IS_ERR(chip->vadc_dev)) {
+			rc = PTR_ERR(chip->vadc_dev);
+			if (rc != -EPROBE_DEFER)
+				pr_err("missing vadc property, rc=%d\n", rc);
 			/* Probe retry, do not print an error message */
 			goto cleanup_irqs;
 		}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index cf21b82..7ef1d80 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -308,7 +308,7 @@
 	mempool_t *diag_hdlc_pool;
 	mempool_t *diag_user_pool;
 	mempool_t *diag_write_struct_pool;
-	struct mutex diagmem_mutex;
+	spinlock_t diag_mem_lock;
 	int count;
 	int count_hdlc_pool;
 	int count_user_pool;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 099dc09..24d7fac 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -131,12 +131,8 @@
 	mutex_lock(&driver->diagchar_mutex);
 	if (buf_hdlc) {
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
-		if (err) {
-			/*Free the buffer right away if write failed */
+		if (err)
 			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
-			diagmem_free(driver, (unsigned char *)driver->
-				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
-		}
 		buf_hdlc = NULL;
 #ifdef DIAG_DEBUG
 		pr_debug("diag: Number of bytes written "
@@ -1818,10 +1814,6 @@
 	if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) {
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
 		if (err) {
-			/*Free the buffer right away if write failed */
-			if (driver->logging_mode == USB_MODE)
-				diagmem_free(driver, (unsigned char *)driver->
-					write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
 			ret = -EIO;
 			goto fail_free_hdlc;
 		}
@@ -1846,10 +1838,6 @@
 		 (unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) {
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
 		if (err) {
-			/*Free the buffer right away if write failed */
-			if (driver->logging_mode == USB_MODE)
-				diagmem_free(driver, (unsigned char *)driver->
-					write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
 			ret = -EIO;
 			goto fail_free_hdlc;
 		}
@@ -1871,10 +1859,6 @@
 	if (pkt_type == DATA_TYPE_RESPONSE) {
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
 		if (err) {
-			/*Free the buffer right away if write failed */
-			if (driver->logging_mode == USB_MODE)
-				diagmem_free(driver, (unsigned char *)driver->
-					write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
 			ret = -EIO;
 			goto fail_free_hdlc;
 		}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 609d6cd..a1f6b2c 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -789,8 +789,16 @@
 				driver->write_ptr_svc->buf = buf;
 				err = usb_diag_write(driver->legacy_ch,
 						driver->write_ptr_svc);
-			} else
-				err = -1;
+				/* Free the buffer if write failed */
+				if (err) {
+					diagmem_free(driver,
+						     (unsigned char *)driver->
+						     write_ptr_svc,
+						     POOL_TYPE_WRITE_STRUCT);
+				}
+			} else {
+				err = -ENOMEM;
+			}
 		} else if ((data_type >= MODEM_DATA) &&
 				(data_type <= WCNSS_DATA)) {
 			write_ptr->buf = buf;
@@ -1762,6 +1770,9 @@
 	}
 #endif
 	if (!found_it) {
+		if (driver->logging_mode != USB_MODE)
+			pr_debug("diag: freeing buffer when not in usb mode\n");
+
 		diagmem_free(driver, (unsigned char *)buf,
 						POOL_TYPE_HDLC);
 		diagmem_free(driver, (unsigned char *)diag_write_ptr,
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index a6ef3ca..4ceca4f 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -25,22 +25,24 @@
 void *diagmem_alloc(struct diagchar_dev *driver, int size, int pool_type)
 {
 	void *buf = NULL;
+	unsigned long flags;
 	int index;
 
+	spin_lock_irqsave(&driver->diag_mem_lock, flags);
 	index = 0;
 	if (pool_type == POOL_TYPE_COPY) {
 		if (driver->diagpool) {
-			mutex_lock(&driver->diagmem_mutex);
-			if (driver->count < driver->poolsize) {
+			if ((driver->count < driver->poolsize) &&
+				(size <= driver->itemsize)) {
 				atomic_add(1, (atomic_t *)&driver->count);
 				buf = mempool_alloc(driver->diagpool,
 								 GFP_ATOMIC);
 			}
-			mutex_unlock(&driver->diagmem_mutex);
 		}
 	} else if (pool_type == POOL_TYPE_HDLC) {
 		if (driver->diag_hdlc_pool) {
-			if (driver->count_hdlc_pool < driver->poolsize_hdlc) {
+			if ((driver->count_hdlc_pool < driver->poolsize_hdlc) &&
+				(size <= driver->itemsize_hdlc)) {
 				atomic_add(1,
 					 (atomic_t *)&driver->count_hdlc_pool);
 				buf = mempool_alloc(driver->diag_hdlc_pool,
@@ -49,7 +51,8 @@
 		}
 	} else if (pool_type == POOL_TYPE_USER) {
 		if (driver->diag_user_pool) {
-			if (driver->count_user_pool < driver->poolsize_user) {
+			if ((driver->count_user_pool < driver->poolsize_user) &&
+				(size <= driver->itemsize_user)) {
 				atomic_add(1,
 					(atomic_t *)&driver->count_user_pool);
 				buf = mempool_alloc(driver->diag_user_pool,
@@ -58,8 +61,9 @@
 		}
 	} else if (pool_type == POOL_TYPE_WRITE_STRUCT) {
 		if (driver->diag_write_struct_pool) {
-			if (driver->count_write_struct_pool <
-					 driver->poolsize_write_struct) {
+			if ((driver->count_write_struct_pool <
+			     driver->poolsize_write_struct) &&
+			     (size <= driver->itemsize_write_struct)) {
 				atomic_add(1,
 				 (atomic_t *)&driver->count_write_struct_pool);
 				buf = mempool_alloc(
@@ -71,8 +75,9 @@
 				pool_type == POOL_TYPE_HSIC_2) {
 		index = pool_type - POOL_TYPE_HSIC;
 		if (diag_hsic[index].diag_hsic_pool) {
-			if (diag_hsic[index].count_hsic_pool <
-					diag_hsic[index].poolsize_hsic) {
+			if ((diag_hsic[index].count_hsic_pool <
+			     diag_hsic[index].poolsize_hsic) &&
+			     (size <= diag_hsic[index].itemsize_hsic)) {
 				atomic_add(1, (atomic_t *)
 					&diag_hsic[index].count_hsic_pool);
 				buf = mempool_alloc(
@@ -85,7 +90,8 @@
 		index = pool_type - POOL_TYPE_HSIC_WRITE;
 		if (diag_hsic[index].diag_hsic_write_pool) {
 			if (diag_hsic[index].count_hsic_write_pool <
-				diag_hsic[index].poolsize_hsic_write) {
+			    diag_hsic[index].poolsize_hsic_write &&
+			    (size <= diag_hsic[index].itemsize_hsic_write)) {
 				atomic_add(1, (atomic_t *)
 					&diag_hsic[index].
 					count_hsic_write_pool);
@@ -96,14 +102,17 @@
 		}
 #endif
 	}
+	spin_unlock_irqrestore(&driver->diag_mem_lock, flags);
 	return buf;
 }
 
 void diagmem_exit(struct diagchar_dev *driver, int pool_type)
 {
 	int index;
+	unsigned long flags;
 	index = 0;
 
+	spin_lock_irqsave(&driver->diag_mem_lock, flags);
 	if (driver->diagpool) {
 		if (driver->count == 0 && driver->ref_count == 0) {
 			mempool_destroy(driver->diagpool);
@@ -176,12 +185,18 @@
 		}
 	}
 #endif
+	spin_unlock_irqrestore(&driver->diag_mem_lock, flags);
 }
 
 void diagmem_free(struct diagchar_dev *driver, void *buf, int pool_type)
 {
 	int index;
+	unsigned long flags;
 
+	if (!buf)
+		return;
+
+	spin_lock_irqsave(&driver->diag_mem_lock, flags);
 	index = 0;
 	if (pool_type == POOL_TYPE_COPY) {
 		if (driver->diagpool != NULL && driver->count > 0) {
@@ -246,13 +261,13 @@
 			__func__, pool_type);
 
 	}
-
+	spin_unlock_irqrestore(&driver->diag_mem_lock, flags);
 	diagmem_exit(driver, pool_type);
 }
 
 void diagmem_init(struct diagchar_dev *driver)
 {
-	mutex_init(&driver->diagmem_mutex);
+	spin_lock_init(&driver->diag_mem_lock);
 
 	if (driver->count == 0) {
 		driver->diagpool = mempool_create_kmalloc_pool(
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index 40649d2..8fc1753 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -235,8 +235,10 @@
 	tz_pwrlevels[0] = j;
 	ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID, tz_pwrlevels,
 				sizeof(tz_pwrlevels), NULL, 0);
-	if (ret)
+	if (ret) {
+		KGSL_DRV_ERR(device, "Fall back to idle based GPU DCVS algo");
 		priv->idle_dcvs = 1;
+	}
 	return 0;
 }
 #else
diff --git a/drivers/gud/mobicore_driver/api.c b/drivers/gud/mobicore_driver/api.c
index 871f6cc..b47383a0 100644
--- a/drivers/gud/mobicore_driver/api.c
+++ b/drivers/gud/mobicore_driver/api.c
@@ -98,7 +98,11 @@
  */
 struct mc_instance *mobicore_open(void)
 {
-	return mc_alloc_instance();
+	struct mc_instance *instance = mc_alloc_instance();
+	if(instance) {
+		instance->admin = true;
+	}
+	return instance;
 }
 EXPORT_SYMBOL(mobicore_open);
 
diff --git a/drivers/gud/mobicore_driver/build_tag.h b/drivers/gud/mobicore_driver/build_tag.h
index 2a7772e..4a24275 100644
--- a/drivers/gud/mobicore_driver/build_tag.h
+++ b/drivers/gud/mobicore_driver/build_tag.h
@@ -26,4 +26,4 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #define MOBICORE_COMPONENT_BUILD_TAG \
-		"*** GC_MSM8960_Release_V019 ###"
+		"*** t-base-202_V001 ###"
diff --git a/drivers/gud/mobicore_driver/main.c b/drivers/gud/mobicore_driver/main.c
index 6f91974..0451452 100644
--- a/drivers/gud/mobicore_driver/main.c
+++ b/drivers/gud/mobicore_driver/main.c
@@ -47,7 +47,7 @@
 
 /* Define a MobiCore device structure for use with dev_debug() etc */
 struct device_driver mcd_debug_name = {
-	.name = "mcdrvkmod"
+	.name = "MobiCore"
 };
 
 struct device mcd_debug_subname = {
diff --git a/drivers/gud/mobicore_driver/platforms/msm8960_surf_std/platform.h b/drivers/gud/mobicore_driver/platforms/msm8960_surf_std/platform.h
index 4768f39..7854fc5 100644
--- a/drivers/gud/mobicore_driver/platforms/msm8960_surf_std/platform.h
+++ b/drivers/gud/mobicore_driver/platforms/msm8960_surf_std/platform.h
@@ -41,7 +41,15 @@
 /* Enable the use of vm_unamp instead of the deprecated do_munmap
  * and other 3.7 features
  */
+#ifndef CONFIG_ARCH_MSM8960
 #define MC_VM_UNMAP
+#endif
+
+
+#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8226)
+/* Perform clock enable/disable */
+#define MC_CRYPTO_CLOCK_MANAGEMENT
+#endif
 
 /* Enable Power Management for Crypto Engine */
 #define MC_CRYPTO_CLOCK_MANAGEMENT
diff --git a/drivers/gud/mobicore_driver/pm.c b/drivers/gud/mobicore_driver/pm.c
index 3ad2015..55a1ef7 100644
--- a/drivers/gud/mobicore_driver/pm.c
+++ b/drivers/gud/mobicore_driver/pm.c
@@ -67,8 +67,8 @@
 	MCDRV_DBG(mcd, "MobiCore IDLE=%d!", flags->schedule);
 	MCDRV_DBG(mcd,
 		  "MobiCore Request Sleep=%d!", flags->sleep_mode.SleepReq);
-	MCDRV_DBG(mcd, "MobiCore Sleep Ready=%d!",
-		  flags->sleep_mode.ReadyToSleep);
+	MCDRV_DBG(mcd,
+		  "MobiCore Sleep Ready=%d!", flags->sleep_mode.ReadyToSleep);
 }
 
 static int mc_suspend_notifier(struct notifier_block *nb,
diff --git a/drivers/gud/mobicore_driver/public/mc_linux.h b/drivers/gud/mobicore_driver/public/mc_linux.h
index 9c49aef..af027dc 100644
--- a/drivers/gud/mobicore_driver/public/mc_linux.h
+++ b/drivers/gud/mobicore_driver/public/mc_linux.h
@@ -43,6 +43,10 @@
 
 #include "version.h"
 
+#ifndef __KERNEL__
+#include <stdint.h>
+#endif
+
 #define MC_ADMIN_DEVNODE	"mobicore"
 #define MC_USER_DEVNODE		"mobicore-user"
 
diff --git a/drivers/gud/mobicore_kernelapi/clientlib.c b/drivers/gud/mobicore_kernelapi/clientlib.c
index 7038e02..16b52e5 100644
--- a/drivers/gud/mobicore_kernelapi/clientlib.c
+++ b/drivers/gud/mobicore_kernelapi/clientlib.c
@@ -299,7 +299,8 @@
 			{
 				session->device_id,
 				*uuid,
-				(uint32_t)wsm->phys_addr,
+				(uint32_t)(wsm->phys_addr) & 0xFFF,
+				wsm->handle,
 				len
 			}
 		};
@@ -926,7 +927,8 @@
 				{
 					session->session_id,
 					handle,
-					(uint32_t)(map_info->secure_virt_addr)
+					(uint32_t)(map_info->secure_virt_addr),
+					map_info->secure_virt_len
 				}
 			};
 
@@ -956,11 +958,11 @@
 			break;
 		}
 
-		struct mc_drv_rsp_unmap_bulk_mem_payload_t
+		/*struct mc_drv_rsp_unmap_bulk_mem_payload_t
 						rsp_unmap_bulk_mem_payload;
 		connection_read_datablock(dev_con,
 					  &rsp_unmap_bulk_mem_payload,
-					  sizeof(rsp_unmap_bulk_mem_payload));
+					  sizeof(rsp_unmap_bulk_mem_payload));*/
 
 		/*
 		 * Unregister mapped bulk buffer from Kernel Module and
diff --git a/drivers/gud/mobicore_kernelapi/public/mobicore_driver_cmd.h b/drivers/gud/mobicore_kernelapi/public/mobicore_driver_cmd.h
index 3b8eb4b..eaf7e6c 100644
--- a/drivers/gud/mobicore_kernelapi/public/mobicore_driver_cmd.h
+++ b/drivers/gud/mobicore_kernelapi/public/mobicore_driver_cmd.h
@@ -109,6 +109,7 @@
 	uint32_t device_id;
 	struct mc_uuid_t uuid;
 	uint32_t tci;
+	uint32_t handle;
 	uint32_t len;
 };
 
@@ -119,10 +120,8 @@
 
 
 struct mc_drv_rsp_open_session_payload_t {
-	uint32_t device_id;
 	uint32_t session_id;
 	uint32_t device_session_id;
-	uint32_t mc_result;
 	uint32_t session_magic;
 };
 
@@ -186,7 +185,6 @@
 struct mc_drv_rsp_map_bulk_mem_payload_t {
 	uint32_t session_id;
 	uint32_t secure_virtual_adr;
-	uint32_t mc_result;
 };
 
 struct mc_drv_rsp_map_bulk_mem_t {
@@ -210,7 +208,6 @@
 struct mc_drv_rsp_unmap_bulk_mem_payload_t {
 	uint32_t response_id;
 	uint32_t session_id;
-	uint32_t mc_result;
 };
 
 struct mc_drv_rsp_unmap_bulk_mem_t {
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 4e77ca2..8b0fcf4 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -377,7 +377,8 @@
 	return adc_voltage;
 }
 
-int32_t qpnp_adc_scale_pmic_therm(int32_t adc_code,
+int32_t qpnp_adc_scale_pmic_therm(struct qpnp_vadc_chip *vadc,
+		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
 		const struct qpnp_vadc_chan_properties *chan_properties,
 		struct qpnp_vadc_result *adc_chan_result)
@@ -421,7 +422,7 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_pmic_therm);
 
-int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *chip,
 		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
@@ -429,7 +430,7 @@
 	int64_t low_output = 0, high_output = 0;
 	int rc = 0, sign = 0;
 
-	rc = qpnp_get_vadc_gain_and_offset(&btm_param, CALIB_ABSOLUTE);
+	rc = qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_ABSOLUTE);
 	if (rc < 0) {
 		pr_err("Could not acquire gain and offset\n");
 		return rc;
@@ -476,7 +477,8 @@
 /* Scales the ADC code to degC using the mapping
  * table for the XO thermistor.
  */
-int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
+int32_t qpnp_adc_tdkntcg_therm(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
 		const struct qpnp_vadc_chan_properties *chan_properties,
 		struct qpnp_vadc_result *adc_chan_result)
@@ -499,7 +501,8 @@
 }
 EXPORT_SYMBOL(qpnp_adc_tdkntcg_therm);
 
-int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
+int32_t qpnp_adc_scale_batt_therm(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
 		const struct qpnp_vadc_chan_properties *chan_properties,
 		struct qpnp_vadc_result *adc_chan_result)
@@ -517,7 +520,8 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_batt_therm);
 
-int32_t qpnp_adc_scale_qrd_batt_therm(int32_t adc_code,
+int32_t qpnp_adc_scale_qrd_batt_therm(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
 		const struct qpnp_vadc_chan_properties *chan_properties,
 		struct qpnp_vadc_result *adc_chan_result)
@@ -535,7 +539,8 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_qrd_batt_therm);
 
-int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+int32_t qpnp_adc_scale_therm_pu1(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
 		const struct qpnp_vadc_chan_properties *chan_properties,
 		struct qpnp_vadc_result *adc_chan_result)
@@ -553,7 +558,8 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_therm_pu1);
 
-int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+int32_t qpnp_adc_scale_therm_pu2(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
 		const struct qpnp_vadc_chan_properties *chan_properties,
 		struct qpnp_vadc_result *adc_chan_result)
@@ -571,13 +577,14 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_therm_pu2);
 
-int32_t qpnp_adc_tm_scale_voltage_therm_pu2(uint32_t reg, int64_t *result)
+int32_t qpnp_adc_tm_scale_voltage_therm_pu2(struct qpnp_vadc_chip *chip,
+					uint32_t reg, int64_t *result)
 {
 	int64_t adc_voltage = 0;
 	struct qpnp_vadc_linear_graph param1;
 	int negative_offset;
 
-	qpnp_get_vadc_gain_and_offset(&param1, CALIB_RATIOMETRIC);
+	qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
 
 	adc_voltage = (reg - param1.adc_gnd) * param1.adc_vref;
 	if (adc_voltage < 0) {
@@ -597,12 +604,13 @@
 }
 EXPORT_SYMBOL(qpnp_adc_tm_scale_voltage_therm_pu2);
 
-int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_adc_tm_config *param)
+int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip,
+				struct qpnp_adc_tm_config *param)
 {
 	struct qpnp_vadc_linear_graph param1;
 	int rc;
 
-	qpnp_get_vadc_gain_and_offset(&param1, CALIB_RATIOMETRIC);
+	qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
 
 	rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
 		ARRAY_SIZE(adcmap_100k_104ef_104fb),
@@ -628,7 +636,8 @@
 }
 EXPORT_SYMBOL(qpnp_adc_tm_scale_therm_voltage_pu2);
 
-int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
+int32_t qpnp_adc_scale_batt_id(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
 		const struct qpnp_vadc_chan_properties *chan_properties,
 		struct qpnp_vadc_result *adc_chan_result)
@@ -644,7 +653,8 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_batt_id);
 
-int32_t qpnp_adc_scale_default(int32_t adc_code,
+int32_t qpnp_adc_scale_default(struct qpnp_vadc_chip *vadc,
+		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
 		const struct qpnp_vadc_chan_properties *chan_properties,
 		struct qpnp_vadc_result *adc_chan_result)
@@ -701,12 +711,13 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_default);
 
-int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
+int32_t qpnp_adc_usb_scaler(struct qpnp_vadc_chip *chip,
+		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
 	struct qpnp_vadc_linear_graph usb_param;
 
-	qpnp_get_vadc_gain_and_offset(&usb_param, CALIB_RATIOMETRIC);
+	qpnp_get_vadc_gain_and_offset(chip, &usb_param, CALIB_RATIOMETRIC);
 
 	*low_threshold = param->low_thr * usb_param.dy;
 	do_div(*low_threshold, usb_param.adc_vref);
@@ -722,14 +733,15 @@
 }
 EXPORT_SYMBOL(qpnp_adc_usb_scaler);
 
-int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *chip,
+		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
 	struct qpnp_vadc_linear_graph vbatt_param;
 	int rc = 0, sign = 0;
 	int64_t low_thr = 0, high_thr = 0;
 
-	rc = qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
+	rc = qpnp_get_vadc_gain_and_offset(chip, &vbatt_param, CALIB_ABSOLUTE);
 	if (rc < 0)
 		return rc;
 
@@ -764,14 +776,15 @@
 }
 EXPORT_SYMBOL(qpnp_adc_vbatt_rscaler);
 
-int32_t qpnp_adc_btm_scaler(struct qpnp_adc_tm_btm_param *param,
+int32_t qpnp_adc_btm_scaler(struct qpnp_vadc_chip *chip,
+		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
 	struct qpnp_vadc_linear_graph btm_param;
 	int64_t low_output = 0, high_output = 0;
 	int rc = 0;
 
-	qpnp_get_vadc_gain_and_offset(&btm_param, CALIB_RATIOMETRIC);
+	qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
 
 	pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
 				param->low_temp);
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index a453159..606d8dd 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -145,6 +145,7 @@
 	struct mutex				iadc_vadc_lock;
 	bool					iadc_mode_sel;
 	struct qpnp_iadc_comp			iadc_comp;
+	struct qpnp_vadc_chip			*vadc_dev;
 	struct sensor_device_attribute		sens_attr[0];
 	bool					skip_auto_calibrations;
 };
@@ -723,7 +724,7 @@
 	int64_t die_temp_offset;
 	int rc = 0;
 
-	rc = qpnp_vadc_read(DIE_TEMP, &result_pmic_therm);
+	rc = qpnp_vadc_read(iadc->vadc_dev, DIE_TEMP, &result_pmic_therm);
 	if (rc < 0)
 		return rc;
 
@@ -882,7 +883,7 @@
 
 	iadc->iadc_mode_sel = true;
 
-	rc = qpnp_vadc_iadc_sync_request(v_channel);
+	rc = qpnp_vadc_iadc_sync_request(iadc->vadc_dev, v_channel);
 	if (rc) {
 		pr_err("Configuring VADC failed\n");
 		goto fail;
@@ -893,7 +894,7 @@
 		pr_err("Configuring IADC failed\n");
 	/* Intentional fall through to release VADC */
 
-	rc = qpnp_vadc_iadc_sync_complete_request(v_channel,
+	rc = qpnp_vadc_iadc_sync_complete_request(iadc->vadc_dev, v_channel,
 							v_result);
 	if (rc)
 		pr_err("Releasing VADC failed\n");
@@ -1005,6 +1006,14 @@
 		goto fail;
 	}
 
+	iadc->vadc_dev = qpnp_get_vadc(&spmi->dev, "iadc");
+	if (IS_ERR(iadc->vadc_dev)) {
+		rc = PTR_ERR(iadc->vadc_dev);
+		if (rc != -EPROBE_DEFER)
+			pr_err("vadc property missing, rc=%d\n", rc);
+		goto fail;
+	}
+
 	mutex_init(&iadc->adc->adc_lock);
 
 	rc = of_property_read_u32(node, "qcom,rsense",
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 53e43d1..2fe69fb 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -101,19 +101,21 @@
 #define QPNP_ADC_COMPLETION_TIMEOUT				HZ
 #define QPNP_VADC_ERR_COUNT					5
 
-struct qpnp_vadc_drv {
+struct qpnp_vadc_chip {
+	struct device			*dev;
 	struct qpnp_adc_drv		*adc;
+	struct list_head		list;
 	struct dentry			*dent;
 	struct device			*vadc_hwmon;
 	bool				vadc_init_calib;
-	bool				vadc_initialized;
 	int				max_channels_available;
 	bool				vadc_iadc_sync_lock;
 	u8				id;
+	struct work_struct		trigger_completion_work;
 	struct sensor_device_attribute	sens_attr[0];
 };
 
-struct qpnp_vadc_drv *qpnp_vadc;
+LIST_HEAD(qpnp_vadc_device_list);
 
 static struct qpnp_vadc_scale_fn vadc_scale_fn[] = {
 	[SCALE_DEFAULT] = {qpnp_adc_scale_default},
@@ -125,9 +127,9 @@
 	[SCALE_QRD_BATT_THERM] = {qpnp_adc_scale_qrd_batt_therm},
 };
 
-static int32_t qpnp_vadc_read_reg(int16_t reg, u8 *data)
+static int32_t qpnp_vadc_read_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
+								u8 *data)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	int rc;
 
 	rc = spmi_ext_register_readl(vadc->adc->spmi->ctrl, vadc->adc->slave,
@@ -140,9 +142,9 @@
 	return 0;
 }
 
-static int32_t qpnp_vadc_write_reg(int16_t reg, u8 data)
+static int32_t qpnp_vadc_write_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
+								u8 data)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	int rc;
 	u8 *buf;
 
@@ -158,24 +160,24 @@
 	return 0;
 }
 
-static int32_t qpnp_vadc_warm_rst_configure(void)
+static int32_t qpnp_vadc_warm_rst_configure(struct qpnp_vadc_chip *vadc)
 {
 	int rc = 0;
 	u8 data = 0;
 
-	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
 	if (rc < 0) {
 		pr_err("VADC write access failed\n");
 		return rc;
 	}
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_PERH_RESET_CTL3, &data);
+	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_PERH_RESET_CTL3, &data);
 	if (rc < 0) {
 		pr_err("VADC perh reset ctl3 read failed\n");
 		return rc;
 	}
 
-	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
 	if (rc < 0) {
 		pr_err("VADC write access failed\n");
 		return rc;
@@ -183,7 +185,7 @@
 
 	data |= QPNP_FOLLOW_WARM_RB;
 
-	rc = qpnp_vadc_write_reg(QPNP_VADC_PERH_RESET_CTL3, data);
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_PERH_RESET_CTL3, data);
 	if (rc < 0) {
 		pr_err("VADC perh reset ctl3 write failed\n");
 		return rc;
@@ -192,21 +194,21 @@
 	return 0;
 }
 
-static int32_t qpnp_vadc_enable(bool state)
+static int32_t qpnp_vadc_enable(struct qpnp_vadc_chip *vadc, bool state)
 {
 	int rc = 0;
 	u8 data = 0;
 
 	data = QPNP_VADC_ADC_EN;
 	if (state) {
-		rc = qpnp_vadc_write_reg(QPNP_VADC_EN_CTL1,
+		rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_EN_CTL1,
 					data);
 		if (rc < 0) {
 			pr_err("VADC enable failed\n");
 			return rc;
 		}
 	} else {
-		rc = qpnp_vadc_write_reg(QPNP_VADC_EN_CTL1,
+		rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_EN_CTL1,
 					(~data & QPNP_VADC_ADC_EN));
 		if (rc < 0) {
 			pr_err("VADC disable failed\n");
@@ -217,42 +219,42 @@
 	return 0;
 }
 
-static int32_t qpnp_vadc_status_debug(void)
+static int32_t qpnp_vadc_status_debug(struct qpnp_vadc_chip *vadc)
 {
 	int rc = 0;
 	u8 mode = 0, status1 = 0, chan = 0, dig = 0, en = 0, status2 = 0;
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_MODE_CTL, &mode);
+	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_MODE_CTL, &mode);
 	if (rc < 0) {
 		pr_err("mode ctl register read failed with %d\n", rc);
 		return rc;
 	}
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_DIG_PARAM, &dig);
+	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_ADC_DIG_PARAM, &dig);
 	if (rc < 0) {
 		pr_err("digital param read failed with %d\n", rc);
 		return rc;
 	}
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_CH_SEL_CTL, &chan);
+	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_ADC_CH_SEL_CTL, &chan);
 	if (rc < 0) {
 		pr_err("channel read failed with %d\n", rc);
 		return rc;
 	}
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
 	if (rc < 0) {
 		pr_err("status1 read failed with %d\n", rc);
 		return rc;
 	}
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS2, &status2);
+	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS2, &status2);
 	if (rc < 0) {
 		pr_err("status2 read failed with %d\n", rc);
 		return rc;
 	}
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_EN_CTL1, &en);
+	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_EN_CTL1, &en);
 	if (rc < 0) {
 		pr_err("en read failed with %d\n", rc);
 		return rc;
@@ -261,7 +263,7 @@
 	pr_err("EOC not set - status1/2:%x/%x, dig:%x, ch:%x, mode:%x, en:%x\n",
 			status1, status2, dig, chan, mode, en);
 
-	rc = qpnp_vadc_enable(false);
+	rc = qpnp_vadc_enable(vadc, false);
 	if (rc < 0) {
 		pr_err("VADC disable failed with %d\n", rc);
 		return rc;
@@ -269,10 +271,9 @@
 
 	return 0;
 }
-static int32_t qpnp_vadc_configure(
+static int32_t qpnp_vadc_configure(struct qpnp_vadc_chip *vadc,
 			struct qpnp_adc_amux_properties *chan_prop)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	u8 decimation = 0, conv_sequence = 0, conv_sequence_trig = 0;
 	u8 mode_ctrl = 0;
 	int rc = 0;
@@ -280,7 +281,7 @@
 	/* Mode selection */
 	mode_ctrl |= ((chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT) |
 			(QPNP_VADC_ADC_TRIM_EN | QPNP_VADC_AMUX_TRIM_EN));
-	rc = qpnp_vadc_write_reg(QPNP_VADC_MODE_CTL, mode_ctrl);
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_MODE_CTL, mode_ctrl);
 	if (rc < 0) {
 		pr_err("Mode configure write error\n");
 		return rc;
@@ -288,7 +289,7 @@
 
 
 	/* Channel selection */
-	rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_CH_SEL_CTL,
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ADC_CH_SEL_CTL,
 						chan_prop->amux_channel);
 	if (rc < 0) {
 		pr_err("Channel configure error\n");
@@ -298,14 +299,14 @@
 	/* Digital parameter setup */
 	decimation = chan_prop->decimation <<
 				QPNP_VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT;
-	rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_DIG_PARAM, decimation);
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ADC_DIG_PARAM, decimation);
 	if (rc < 0) {
 		pr_err("Digital parameter configure write error\n");
 		return rc;
 	}
 
 	/* HW settling time delay */
-	rc = qpnp_vadc_write_reg(QPNP_VADC_HW_SETTLE_DELAY,
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HW_SETTLE_DELAY,
 						chan_prop->hw_settle_time);
 	if (rc < 0) {
 		pr_err("HW settling time setup error\n");
@@ -315,7 +316,7 @@
 	if (chan_prop->mode_sel == (ADC_OP_NORMAL_MODE <<
 					QPNP_VADC_OP_MODE_SHIFT)) {
 		/* Normal measurement mode */
-		rc = qpnp_vadc_write_reg(QPNP_VADC_FAST_AVG_CTL,
+		rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_FAST_AVG_CTL,
 						chan_prop->fast_avg_setup);
 		if (rc < 0) {
 			pr_err("Fast averaging configure error\n");
@@ -327,7 +328,7 @@
 		conv_sequence = ((ADC_SEQ_HOLD_100US <<
 				QPNP_VADC_CONV_SEQ_HOLDOFF_SHIFT) |
 				ADC_CONV_SEQ_TIMEOUT_5MS);
-		rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_SEQ_CTL,
+		rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_SEQ_CTL,
 							conv_sequence);
 		if (rc < 0) {
 			pr_err("Conversion sequence error\n");
@@ -337,7 +338,7 @@
 		conv_sequence_trig = ((QPNP_VADC_CONV_SEQ_RISING_EDGE <<
 				QPNP_VADC_CONV_SEQ_EDGE_SHIFT) |
 				chan_prop->trigger_channel);
-		rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_SEQ_TRIG_CTL,
+		rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_SEQ_TRIG_CTL,
 							conv_sequence_trig);
 		if (rc < 0) {
 			pr_err("Conversion trigger error\n");
@@ -347,13 +348,13 @@
 
 	INIT_COMPLETION(vadc->adc->adc_rslt_completion);
 
-	rc = qpnp_vadc_enable(true);
+	rc = qpnp_vadc_enable(vadc, true);
 	if (rc)
 		return rc;
 
 	if (!vadc->vadc_iadc_sync_lock) {
 		/* Request conversion */
-		rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_REQ,
+		rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_REQ,
 					QPNP_VADC_CONV_REQ_SET);
 		if (rc < 0) {
 			pr_err("Request conversion failed\n");
@@ -364,18 +365,19 @@
 	return 0;
 }
 
-static int32_t qpnp_vadc_read_conversion_result(int32_t *data)
+static int32_t qpnp_vadc_read_conversion_result(struct qpnp_vadc_chip *vadc,
+								int32_t *data)
 {
 	uint8_t rslt_lsb, rslt_msb;
 	int rc = 0, status = 0;
 
-	status = qpnp_vadc_read_reg(QPNP_VADC_DATA0, &rslt_lsb);
+	status = qpnp_vadc_read_reg(vadc, QPNP_VADC_DATA0, &rslt_lsb);
 	if (status < 0) {
 		pr_err("qpnp adc result read failed for data0\n");
 		goto fail;
 	}
 
-	status = qpnp_vadc_read_reg(QPNP_VADC_DATA1, &rslt_msb);
+	status = qpnp_vadc_read_reg(vadc, QPNP_VADC_DATA1, &rslt_msb);
 	if (status < 0) {
 		pr_err("qpnp adc result read failed for data1\n");
 		goto fail;
@@ -390,14 +392,14 @@
 	}
 
 fail:
-	rc = qpnp_vadc_enable(false);
+	rc = qpnp_vadc_enable(vadc, false);
 	if (rc)
 		return rc;
 
 	return status;
 }
 
-static int32_t qpnp_vadc_read_status(int mode_sel)
+static int32_t qpnp_vadc_read_status(struct qpnp_vadc_chip *vadc, int mode_sel)
 {
 	u8 status1, status2, status2_conv_seq_state;
 	u8 status_err = QPNP_VADC_CONV_TIMEOUT_ERR;
@@ -405,13 +407,13 @@
 
 	switch (mode_sel) {
 	case (ADC_OP_CONVERSION_SEQUENCER << QPNP_VADC_OP_MODE_SHIFT):
-		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+		rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
 		if (rc) {
 			pr_err("qpnp_vadc read mask interrupt failed\n");
 			return rc;
 		}
 
-		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS2, &status2);
+		rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS2, &status2);
 		if (rc) {
 			pr_err("qpnp_vadc read mask interrupt failed\n");
 			return rc;
@@ -437,32 +439,45 @@
 	return 0;
 }
 
+static int qpnp_vadc_is_valid(struct qpnp_vadc_chip *vadc)
+{
+	struct qpnp_vadc_chip *vadc_chip = NULL;
+
+	list_for_each_entry(vadc_chip, &qpnp_vadc_device_list, list)
+		if (vadc == vadc_chip)
+			return 0;
+
+	return -EINVAL;
+}
+
 static void qpnp_vadc_work(struct work_struct *work)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
+	struct qpnp_vadc_chip *vadc = container_of(work,
+			struct qpnp_vadc_chip, trigger_completion_work);
 
-	if (!vadc || !vadc->vadc_initialized)
+	if (qpnp_vadc_is_valid(vadc) < 0)
 		return;
 
 	complete(&vadc->adc->adc_rslt_completion);
 
 	return;
 }
-DECLARE_WORK(trigger_completion_work, qpnp_vadc_work);
 
 static irqreturn_t qpnp_vadc_isr(int irq, void *dev_id)
 {
-	schedule_work(&trigger_completion_work);
+	struct qpnp_vadc_chip *vadc = dev_id;
+
+	schedule_work(&vadc->trigger_completion_work);
 
 	return IRQ_HANDLED;
 }
 
-static int32_t qpnp_vadc_version_check(void)
+static int32_t qpnp_vadc_version_check(struct qpnp_vadc_chip *dev)
 {
 	uint8_t revision;
 	int rc;
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_REVISION2, &revision);
+	rc = qpnp_vadc_read_reg(dev, QPNP_VADC_REVISION2, &revision);
 	if (rc < 0) {
 		pr_err("qpnp adc result read failed with %d\n", rc);
 		return rc;
@@ -510,13 +525,17 @@
 	return 0;
 }
 
-int32_t qpnp_vbat_sns_comp_result(int64_t *result)
+int32_t qpnp_vbat_sns_comp_result(struct qpnp_vadc_chip *vadc,
+						int64_t *result)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	struct qpnp_vadc_result die_temp_result;
 	int rc = 0;
 
-	rc = qpnp_vadc_conv_seq_request(ADC_SEQ_NONE,
+	rc = qpnp_vadc_is_valid(vadc);
+	if (rc < 0)
+		return rc;
+
+	rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
 			DIE_TEMP, &die_temp_result);
 	if (rc < 0) {
 		pr_err("Error reading die_temp\n");
@@ -532,9 +551,9 @@
 }
 EXPORT_SYMBOL(qpnp_vbat_sns_comp_result);
 
-static void qpnp_vadc_625mv_channel_sel(uint32_t *ref_channel_sel)
+static void qpnp_vadc_625mv_channel_sel(struct qpnp_vadc_chip *vadc,
+				uint32_t *ref_channel_sel)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	uint32_t dt_index = 0;
 
 	/* Check if the buffered 625mV channel exists */
@@ -551,9 +570,8 @@
 	}
 }
 
-static int32_t qpnp_vadc_calib_device(void)
+static int32_t qpnp_vadc_calib_device(struct qpnp_vadc_chip *vadc)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	struct qpnp_adc_amux_properties conv;
 	int rc, calib_read_1, calib_read_2, count = 0;
 	u8 status1 = 0;
@@ -565,14 +583,14 @@
 	conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
 	conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
 
-	rc = qpnp_vadc_configure(&conv);
+	rc = qpnp_vadc_configure(vadc, &conv);
 	if (rc) {
 		pr_err("qpnp_vadc configure failed with %d\n", rc);
 		goto calib_fail;
 	}
 
 	while (status1 != QPNP_VADC_STATUS1_EOC) {
-		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+		rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
 		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
@@ -585,19 +603,19 @@
 		}
 	}
 
-	rc = qpnp_vadc_read_conversion_result(&calib_read_1);
+	rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_1);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
 		goto calib_fail;
 	}
 
-	qpnp_vadc_625mv_channel_sel(&ref_channel_sel);
+	qpnp_vadc_625mv_channel_sel(vadc, &ref_channel_sel);
 	conv.amux_channel = ref_channel_sel;
 	conv.decimation = DECIMATION_TYPE2;
 	conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
 	conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
 	conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
-	rc = qpnp_vadc_configure(&conv);
+	rc = qpnp_vadc_configure(vadc, &conv);
 	if (rc) {
 		pr_err("qpnp adc configure failed with %d\n", rc);
 		goto calib_fail;
@@ -606,7 +624,7 @@
 	status1 = 0;
 	count = 0;
 	while (status1 != QPNP_VADC_STATUS1_EOC) {
-		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+		rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
 		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
@@ -619,7 +637,7 @@
 		}
 	}
 
-	rc = qpnp_vadc_read_conversion_result(&calib_read_2);
+	rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_2);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
 		goto calib_fail;
@@ -643,7 +661,7 @@
 	conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
 	conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
 	conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
-	rc = qpnp_vadc_configure(&conv);
+	rc = qpnp_vadc_configure(vadc, &conv);
 	if (rc) {
 		pr_err("qpnp adc configure failed with %d\n", rc);
 		goto calib_fail;
@@ -652,7 +670,7 @@
 	status1 = 0;
 	count = 0;
 	while (status1 != QPNP_VADC_STATUS1_EOC) {
-		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+		rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
 		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
@@ -665,7 +683,7 @@
 		}
 	}
 
-	rc = qpnp_vadc_read_conversion_result(&calib_read_1);
+	rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_1);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
 		goto calib_fail;
@@ -676,7 +694,7 @@
 	conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
 	conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
 	conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
-	rc = qpnp_vadc_configure(&conv);
+	rc = qpnp_vadc_configure(vadc, &conv);
 	if (rc) {
 		pr_err("qpnp adc configure failed with %d\n", rc);
 		goto calib_fail;
@@ -685,7 +703,7 @@
 	status1 = 0;
 	count = 0;
 	while (status1 != QPNP_VADC_STATUS1_EOC) {
-		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+		rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
 		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
@@ -698,7 +716,7 @@
 		}
 	}
 
-	rc = qpnp_vadc_read_conversion_result(&calib_read_2);
+	rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_2);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
 		goto calib_fail;
@@ -719,11 +737,15 @@
 	return rc;
 }
 
-int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_linear_graph *param,
+int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_chip *vadc,
+				struct qpnp_vadc_linear_graph *param,
 				enum qpnp_adc_calib_type calib_type)
 {
+	int rc = 0;
 
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
+	rc = qpnp_vadc_is_valid(vadc);
+	if (rc < 0)
+		return rc;
 
 	switch (calib_type) {
 	case CALIB_RATIOMETRIC:
@@ -752,36 +774,44 @@
 }
 EXPORT_SYMBOL(qpnp_get_vadc_gain_and_offset);
 
-int32_t qpnp_vadc_is_ready(void)
+struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev, const char *name)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
+	struct qpnp_vadc_chip *vadc;
+	struct device_node *node = NULL;
+	char prop_name[QPNP_MAX_PROP_NAME_LEN];
 
-	if (!vadc || !vadc->vadc_initialized)
-		return -EPROBE_DEFER;
-	else
-		return 0;
+	snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-vadc", name);
+
+	node = of_parse_phandle(dev->of_node, prop_name, 0);
+	if (node == NULL)
+		return ERR_PTR(-ENODEV);
+
+	list_for_each_entry(vadc, &qpnp_vadc_device_list, list)
+		if (vadc->adc->spmi->dev.of_node == node)
+			return vadc;
+	return ERR_PTR(-EPROBE_DEFER);
 }
-EXPORT_SYMBOL(qpnp_vadc_is_ready);
+EXPORT_SYMBOL(qpnp_get_vadc);
 
-int32_t qpnp_vadc_conv_seq_request(enum qpnp_vadc_trigger trigger_channel,
+int32_t qpnp_vadc_conv_seq_request(struct qpnp_vadc_chip *vadc,
+				enum qpnp_vadc_trigger trigger_channel,
 					enum qpnp_vadc_channels channel,
 					struct qpnp_vadc_result *result)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	int rc = 0, scale_type, amux_prescaling, dt_index = 0;
 	uint32_t ref_channel;
 
-	if (!vadc || !vadc->vadc_initialized)
+	if (qpnp_vadc_is_valid(vadc))
 		return -EPROBE_DEFER;
 
 	mutex_lock(&vadc->adc->adc_lock);
 
 	if (!vadc->vadc_init_calib) {
-		rc = qpnp_vadc_version_check();
+		rc = qpnp_vadc_version_check(vadc);
 		if (rc)
 			goto fail_unlock;
 
-		rc = qpnp_vadc_calib_device();
+		rc = qpnp_vadc_calib_device(vadc);
 		if (rc) {
 			pr_err("Calibration failed\n");
 			goto fail_unlock;
@@ -790,7 +820,7 @@
 	}
 
 	if (channel == REF_625MV) {
-		qpnp_vadc_625mv_channel_sel(&ref_channel);
+		qpnp_vadc_625mv_channel_sel(vadc, &ref_channel);
 		channel = ref_channel;
 	}
 
@@ -826,7 +856,7 @@
 
 	vadc->adc->amux_prop->trigger_channel = trigger_channel;
 
-	rc = qpnp_vadc_configure(vadc->adc->amux_prop);
+	rc = qpnp_vadc_configure(vadc, vadc->adc->amux_prop);
 	if (rc) {
 		pr_err("qpnp vadc configure failed with %d\n", rc);
 		goto fail_unlock;
@@ -836,14 +866,14 @@
 					QPNP_ADC_COMPLETION_TIMEOUT);
 	if (!rc) {
 		u8 status1 = 0;
-		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+		rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			goto fail_unlock;
 		status1 &= (QPNP_VADC_STATUS1_REQ_STS | QPNP_VADC_STATUS1_EOC);
 		if (status1 == QPNP_VADC_STATUS1_EOC)
 			pr_debug("End of conversion status set\n");
 		else {
-			rc = qpnp_vadc_status_debug();
+			rc = qpnp_vadc_status_debug(vadc);
 			if (rc < 0)
 				pr_err("VADC disable failed\n");
 			rc = -EINVAL;
@@ -852,12 +882,13 @@
 	}
 
 	if (trigger_channel < ADC_SEQ_NONE) {
-		rc = qpnp_vadc_read_status(vadc->adc->amux_prop->mode_sel);
+		rc = qpnp_vadc_read_status(vadc,
+					vadc->adc->amux_prop->mode_sel);
 		if (rc)
 			pr_debug("Conversion sequence timed out - %d\n", rc);
 	}
 
-	rc = qpnp_vadc_read_conversion_result(&result->adc_code);
+	rc = qpnp_vadc_read_conversion_result(vadc, &result->adc_code);
 	if (rc) {
 		pr_err("qpnp vadc read adc code failed with %d\n", rc);
 		goto fail_unlock;
@@ -882,7 +913,7 @@
 		goto fail_unlock;
 	}
 
-	vadc_scale_fn[scale_type].chan(result->adc_code,
+	vadc_scale_fn[scale_type].chan(vadc, result->adc_code,
 		vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
 
 fail_unlock:
@@ -892,23 +923,22 @@
 }
 EXPORT_SYMBOL(qpnp_vadc_conv_seq_request);
 
-int32_t qpnp_vadc_read(enum qpnp_vadc_channels channel,
+int32_t qpnp_vadc_read(struct qpnp_vadc_chip *vadc,
+				enum qpnp_vadc_channels channel,
 				struct qpnp_vadc_result *result)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
-	enum qpnp_vadc_channels;
 	struct qpnp_vadc_result die_temp_result;
 	int rc = 0;
 
 	if (channel == VBAT_SNS) {
-		rc = qpnp_vadc_conv_seq_request(ADC_SEQ_NONE,
+		rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
 				channel, result);
 		if (rc < 0) {
 			pr_err("Error reading vbatt\n");
 			return rc;
 		}
 
-		rc = qpnp_vadc_conv_seq_request(ADC_SEQ_NONE,
+		rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
 				DIE_TEMP, &die_temp_result);
 		if (rc < 0) {
 			pr_err("Error reading die_temp\n");
@@ -922,41 +952,37 @@
 
 		return 0;
 	} else
-		return qpnp_vadc_conv_seq_request(ADC_SEQ_NONE,
+		return qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
 				channel, result);
 }
 EXPORT_SYMBOL(qpnp_vadc_read);
 
-static void qpnp_vadc_lock(void)
+static void qpnp_vadc_lock(struct qpnp_vadc_chip *vadc)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
-
 	mutex_lock(&vadc->adc->adc_lock);
 }
 
-static void qpnp_vadc_unlock(void)
+static void qpnp_vadc_unlock(struct qpnp_vadc_chip *vadc)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
-
 	mutex_unlock(&vadc->adc->adc_lock);
 }
 
-int32_t qpnp_vadc_iadc_sync_request(enum qpnp_vadc_channels channel)
+int32_t qpnp_vadc_iadc_sync_request(struct qpnp_vadc_chip *vadc,
+				enum qpnp_vadc_channels channel)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	int rc = 0, dt_index = 0;
 
-	if (!vadc || !vadc->vadc_initialized)
+	if (qpnp_vadc_is_valid(vadc))
 		return -EPROBE_DEFER;
 
-	qpnp_vadc_lock();
+	qpnp_vadc_lock(vadc);
 
 	if (!vadc->vadc_init_calib) {
-		rc = qpnp_vadc_version_check();
+		rc = qpnp_vadc_version_check(vadc);
 		if (rc)
 			goto fail;
 
-		rc = qpnp_vadc_calib_device();
+		rc = qpnp_vadc_calib_device(vadc);
 		if (rc) {
 			pr_err("Calibration failed\n");
 			goto fail;
@@ -986,7 +1012,7 @@
 					<< QPNP_VADC_OP_MODE_SHIFT);
 	vadc->vadc_iadc_sync_lock = true;
 
-	rc = qpnp_vadc_configure(vadc->adc->amux_prop);
+	rc = qpnp_vadc_configure(vadc, vadc->adc->amux_prop);
 	if (rc) {
 		pr_err("qpnp vadc configure failed with %d\n", rc);
 		goto fail;
@@ -995,15 +1021,15 @@
 	return rc;
 fail:
 	vadc->vadc_iadc_sync_lock = false;
-	qpnp_vadc_unlock();
+	qpnp_vadc_unlock(vadc);
 	return rc;
 }
 EXPORT_SYMBOL(qpnp_vadc_iadc_sync_request);
 
-int32_t qpnp_vadc_iadc_sync_complete_request(enum qpnp_vadc_channels channel,
+int32_t qpnp_vadc_iadc_sync_complete_request(struct qpnp_vadc_chip *vadc,
+					enum qpnp_vadc_channels channel,
 						struct qpnp_vadc_result *result)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	int rc = 0, scale_type, amux_prescaling, dt_index = 0;
 
 	vadc->adc->amux_prop->amux_channel = channel;
@@ -1012,7 +1038,7 @@
 		!= channel) && (dt_index < vadc->max_channels_available))
 		dt_index++;
 
-	rc = qpnp_vadc_read_conversion_result(&result->adc_code);
+	rc = qpnp_vadc_read_conversion_result(vadc, &result->adc_code);
 	if (rc) {
 		pr_err("qpnp vadc read adc code failed with %d\n", rc);
 		goto fail;
@@ -1037,12 +1063,12 @@
 		goto fail;
 	}
 
-	vadc_scale_fn[scale_type].chan(result->adc_code,
+	vadc_scale_fn[scale_type].chan(vadc, result->adc_code,
 		vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
 
 fail:
 	vadc->vadc_iadc_sync_lock = false;
-	qpnp_vadc_unlock();
+	qpnp_vadc_unlock(vadc);
 	return rc;
 }
 EXPORT_SYMBOL(qpnp_vadc_iadc_sync_complete_request);
@@ -1051,10 +1077,11 @@
 			struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct qpnp_vadc_chip *vadc = dev_get_drvdata(dev);
 	struct qpnp_vadc_result result;
 	int rc = -1;
 
-	rc = qpnp_vadc_read(attr->index, &result);
+	rc = qpnp_vadc_read(vadc, attr->index, &result);
 
 	if (rc) {
 		pr_err("VADC read error with %d\n", rc);
@@ -1068,9 +1095,9 @@
 static struct sensor_device_attribute qpnp_adc_attr =
 	SENSOR_ATTR(NULL, S_IRUGO, qpnp_adc_show, NULL, 0);
 
-static int32_t qpnp_vadc_init_hwmon(struct spmi_device *spmi)
+static int32_t qpnp_vadc_init_hwmon(struct qpnp_vadc_chip *vadc,
+					struct spmi_device *spmi)
 {
-	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	struct device_node *child;
 	struct device_node *node = spmi->dev.of_node;
 	int rc = 0, i = 0, channel;
@@ -1102,21 +1129,13 @@
 
 static int __devinit qpnp_vadc_probe(struct spmi_device *spmi)
 {
-	struct qpnp_vadc_drv *vadc;
+	struct qpnp_vadc_chip *vadc;
 	struct qpnp_adc_drv *adc_qpnp;
 	struct device_node *node = spmi->dev.of_node;
 	struct device_node *child;
-	int rc, count_adc_channel_list = 0;
+	int rc, count_adc_channel_list = 0, i = 0;
 	u8 fab_id = 0;
 
-	if (!node)
-		return -EINVAL;
-
-	if (qpnp_vadc) {
-		pr_err("VADC already in use\n");
-		return -EBUSY;
-	}
-
 	for_each_child_of_node(node, child)
 		count_adc_channel_list++;
 
@@ -1125,7 +1144,7 @@
 		return -EINVAL;
 	}
 
-	vadc = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_vadc_drv) +
+	vadc = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_vadc_chip) +
 		(sizeof(struct sensor_device_attribute) *
 				count_adc_channel_list), GFP_KERNEL);
 	if (!vadc) {
@@ -1133,20 +1152,19 @@
 		return -ENOMEM;
 	}
 
+	vadc->dev = &(spmi->dev);
 	adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
 			GFP_KERNEL);
 	if (!adc_qpnp) {
 		dev_err(&spmi->dev, "Unable to allocate memory\n");
-		rc = -ENOMEM;
-		goto fail;
+		return -ENOMEM;
 	}
 
 	vadc->adc = adc_qpnp;
-
 	rc = qpnp_adc_get_devicetree_data(spmi, vadc->adc);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to read device tree\n");
-		goto fail;
+		return rc;
 	}
 	mutex_init(&vadc->adc->adc_lock);
 
@@ -1156,46 +1174,54 @@
 	if (rc) {
 		dev_err(&spmi->dev,
 			"failed to request adc irq with error %d\n", rc);
-		goto fail;
+		return rc;
 	} else {
 		enable_irq_wake(vadc->adc->adc_irq_eoc);
 	}
 
-	qpnp_vadc = vadc;
-	dev_set_drvdata(&spmi->dev, vadc);
-	rc = qpnp_vadc_init_hwmon(spmi);
+	rc = qpnp_vadc_init_hwmon(vadc, spmi);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
-		goto fail;
+		return rc;
 	}
 	vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
 	vadc->vadc_init_calib = false;
 	vadc->max_channels_available = count_adc_channel_list;
-	rc = qpnp_vadc_read_reg(QPNP_INT_TEST_VAL, &fab_id);
+	rc = qpnp_vadc_read_reg(vadc, QPNP_INT_TEST_VAL, &fab_id);
 	if (rc < 0) {
 		pr_err("qpnp adc comp id failed with %d\n", rc);
-		goto fail;
+		goto err_setup;
 	}
 	vadc->id = fab_id;
 
-	rc = qpnp_vadc_warm_rst_configure();
+	rc = qpnp_vadc_warm_rst_configure(vadc);
 	if (rc < 0) {
 		pr_err("Setting perp reset on warm reset failed %d\n", rc);
-		goto fail;
+		goto err_setup;
 	}
 
-	vadc->vadc_initialized = true;
+	INIT_WORK(&vadc->trigger_completion_work, qpnp_vadc_work);
 	vadc->vadc_iadc_sync_lock = false;
 
+	dev_set_drvdata(&spmi->dev, vadc);
+	list_add(&vadc->list, &qpnp_vadc_device_list);
+
 	return 0;
-fail:
-	qpnp_vadc = NULL;
+
+err_setup:
+	for_each_child_of_node(node, child) {
+		device_remove_file(&spmi->dev,
+			&vadc->sens_attr[i].dev_attr);
+		i++;
+	}
+	hwmon_device_unregister(vadc->vadc_hwmon);
+
 	return rc;
 }
 
 static int __devexit qpnp_vadc_remove(struct spmi_device *spmi)
 {
-	struct qpnp_vadc_drv *vadc = dev_get_drvdata(&spmi->dev);
+	struct qpnp_vadc_chip *vadc = dev_get_drvdata(&spmi->dev);
 	struct device_node *node = spmi->dev.of_node;
 	struct device_node *child;
 	int i = 0;
@@ -1205,7 +1231,8 @@
 			&vadc->sens_attr[i].dev_attr);
 		i++;
 	}
-	vadc->vadc_initialized = false;
+	hwmon_device_unregister(vadc->vadc_hwmon);
+	list_del(&vadc->list);
 	dev_set_drvdata(&spmi->dev, NULL);
 
 	return 0;
diff --git a/drivers/input/misc/cm36283.c b/drivers/input/misc/cm36283.c
new file mode 100644
index 0000000..6280013
--- /dev/null
+++ b/drivers/input/misc/cm36283.c
@@ -0,0 +1,1658 @@
+/* drivers/input/misc/cm36283.c - cm36283 optical sensors driver
+ *
+ * Copyright (C) 2012 Capella Microsystems Inc.
+ * Author: Frank Hsieh <pengyueh@gmail.com>
+ *                                    
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/earlysuspend.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/lightsensor.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <asm/mach-types.h>
+#include <linux/cm36283.h>
+#include <linux/capella_cm3602.h>
+#include <asm/setup.h>
+#include <linux/wakelock.h>
+#include <linux/jiffies.h>
+
+#define D(x...) pr_info(x)
+
+#define I2C_RETRY_COUNT 10
+
+#define NEAR_DELAY_TIME ((100 * HZ) / 1000)
+
+#define CONTROL_INT_ISR_REPORT        0x00
+#define CONTROL_ALS                   0x01
+#define CONTROL_PS                    0x02
+
+static int record_init_fail = 0;
+static void sensor_irq_do_work(struct work_struct *work);
+static DECLARE_WORK(sensor_irq_work, sensor_irq_do_work);
+
+struct cm36283_info {
+	struct class *cm36283_class;
+	struct device *ls_dev;
+	struct device *ps_dev;
+
+	struct input_dev *ls_input_dev;
+	struct input_dev *ps_input_dev;
+
+	struct early_suspend early_suspend;
+	struct i2c_client *i2c_client;
+	struct workqueue_struct *lp_wq;
+
+	int intr_pin;
+	int als_enable;
+	int ps_enable;
+	int ps_irq_flag;
+
+	uint16_t *adc_table;
+	uint16_t cali_table[10];
+	int irq;
+
+	int ls_calibrate;
+	
+	int (*power)(int, uint8_t); /* power to the chip */
+
+	uint32_t als_kadc;
+	uint32_t als_gadc;
+	uint16_t golden_adc;
+
+	struct wake_lock ps_wake_lock;
+	int psensor_opened;
+	int lightsensor_opened;
+	uint8_t slave_addr;
+
+	uint8_t ps_close_thd_set;
+	uint8_t ps_away_thd_set;	
+	int current_level;
+	uint16_t current_adc;
+
+	uint16_t ps_conf1_val;
+	uint16_t ps_conf3_val;
+
+	uint16_t ls_cmd;
+	uint8_t record_clear_int_fail;
+};
+struct cm36283_info *lp_info;
+int fLevel=-1;
+static struct mutex als_enable_mutex, als_disable_mutex, als_get_adc_mutex;
+static struct mutex ps_enable_mutex, ps_disable_mutex, ps_get_adc_mutex;
+static struct mutex CM36283_control_mutex;
+static int lightsensor_enable(struct cm36283_info *lpi);
+static int lightsensor_disable(struct cm36283_info *lpi);
+static int initial_cm36283(struct cm36283_info *lpi);
+static void psensor_initial_cmd(struct cm36283_info *lpi);
+
+int32_t als_kadc;
+
+static int control_and_report(struct cm36283_info *lpi, uint8_t mode, uint16_t param);
+
+static int I2C_RxData(uint16_t slaveAddr, uint8_t cmd, uint8_t *rxData, int length)
+{
+	uint8_t loop_i;
+	int val;
+	struct cm36283_info *lpi = lp_info;
+  uint8_t subaddr[1];
+
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = slaveAddr,
+		 .flags = 0,
+		 .len = 1,
+		 .buf = subaddr,
+		 },
+		{
+		 .addr = slaveAddr,
+		 .flags = I2C_M_RD,
+		 .len = length,
+		 .buf = rxData,
+		 },		 
+	};
+  subaddr[0] = cmd;
+
+	for (loop_i = 0; loop_i < I2C_RETRY_COUNT; loop_i++) {
+
+		if (i2c_transfer(lp_info->i2c_client->adapter, msgs, 2) > 0)
+			break;
+
+		val = gpio_get_value(lpi->intr_pin);
+		/*check intr GPIO when i2c error*/
+		if (loop_i == 0 || loop_i == I2C_RETRY_COUNT -1)
+			D("[PS][CM36283 error] %s, i2c err, slaveAddr 0x%x ISR gpio %d  = %d, record_init_fail %d \n",
+				__func__, slaveAddr, lpi->intr_pin, val, record_init_fail);
+
+		msleep(10);
+	}
+	if (loop_i >= I2C_RETRY_COUNT) {
+		printk(KERN_ERR "[PS_ERR][CM36283 error] %s retry over %d\n",
+			__func__, I2C_RETRY_COUNT);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int I2C_TxData(uint16_t slaveAddr, uint8_t *txData, int length)
+{
+	uint8_t loop_i;
+	int val;
+	struct cm36283_info *lpi = lp_info;
+	struct i2c_msg msg[] = {
+		{
+		 .addr = slaveAddr,
+		 .flags = 0,
+		 .len = length,
+		 .buf = txData,
+		 },
+	};
+
+	for (loop_i = 0; loop_i < I2C_RETRY_COUNT; loop_i++) {
+		if (i2c_transfer(lp_info->i2c_client->adapter, msg, 1) > 0)
+			break;
+
+		val = gpio_get_value(lpi->intr_pin);
+		/*check intr GPIO when i2c error*/
+		if (loop_i == 0 || loop_i == I2C_RETRY_COUNT -1)
+			D("[PS][CM36283 error] %s, i2c err, slaveAddr 0x%x, value 0x%x, ISR gpio%d  = %d, record_init_fail %d\n",
+				__func__, slaveAddr, txData[0], lpi->intr_pin, val, record_init_fail);
+
+		msleep(10);
+	}
+
+	if (loop_i >= I2C_RETRY_COUNT) {
+		printk(KERN_ERR "[PS_ERR][CM36283 error] %s retry over %d\n",
+			__func__, I2C_RETRY_COUNT);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int _cm36283_I2C_Read_Word(uint16_t slaveAddr, uint8_t cmd, uint16_t *pdata)
+{
+	uint8_t buffer[2];
+	int ret = 0;
+
+	if (pdata == NULL)
+		return -EFAULT;
+
+	ret = I2C_RxData(slaveAddr, cmd, buffer, 2);
+	if (ret < 0) {
+		pr_err(
+			"[PS_ERR][CM3218 error]%s: I2C_RxData fail [0x%x, 0x%x]\n",
+			__func__, slaveAddr, cmd);
+		return ret;
+	}
+
+	*pdata = (buffer[1]<<8)|buffer[0];
+#if 0
+	/* Debug use */
+	printk(KERN_DEBUG "[CM3218] %s: I2C_RxData[0x%x, 0x%x] = 0x%x\n",
+		__func__, slaveAddr, cmd, *pdata);
+#endif
+	return ret;
+}
+
+static int _cm36283_I2C_Write_Word(uint16_t SlaveAddress, uint8_t cmd, uint16_t data)
+{
+	char buffer[3];
+	int ret = 0;
+#if 0
+	/* Debug use */
+	printk(KERN_DEBUG
+	"[CM3218] %s: _cm36283_I2C_Write_Word[0x%x, 0x%x, 0x%x]\n",
+		__func__, SlaveAddress, cmd, data);
+#endif
+	buffer[0] = cmd;
+	buffer[1] = (uint8_t)(data&0xff);
+	buffer[2] = (uint8_t)((data&0xff00)>>8);	
+	
+	ret = I2C_TxData(SlaveAddress, buffer, 3);
+	if (ret < 0) {
+		pr_err("[PS_ERR][CM3218 error]%s: I2C_TxData fail\n", __func__);
+		return -EIO;
+	}
+
+	return ret;
+}
+
+static int get_ls_adc_value(uint16_t *als_step, bool resume)
+{
+	struct cm36283_info *lpi = lp_info;
+	uint32_t tmpResult;
+	int ret = 0;
+
+	if (als_step == NULL)
+		return -EFAULT;
+
+	/* Read ALS data: */
+	ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_DATA, als_step);
+	if (ret < 0) {
+		pr_err(
+			"[LS][CM3218 error]%s: _cm36283_I2C_Read_Word fail\n",
+			__func__);
+		return -EIO;
+	}
+
+  if (!lpi->ls_calibrate) {
+		tmpResult = (uint32_t)(*als_step) * lpi->als_gadc / lpi->als_kadc;
+		if (tmpResult > 0xFFFF)
+			*als_step = 0xFFFF;
+		else
+		  *als_step = tmpResult;  			
+	}
+
+	D("[LS][CM3218] %s: raw adc = 0x%X, ls_calibrate = %d\n",
+		__func__, *als_step, lpi->ls_calibrate);
+
+	return ret;
+}
+
+static int set_lsensor_range(uint16_t low_thd, uint16_t high_thd)
+{
+	int ret = 0;
+	struct cm36283_info *lpi = lp_info;
+
+	_cm36283_I2C_Write_Word(lpi->slave_addr, ALS_THDH, high_thd);
+	_cm36283_I2C_Write_Word(lpi->slave_addr, ALS_THDL, low_thd);
+
+	return ret;
+}
+
+static int get_ps_adc_value(uint16_t *data)
+{
+	int ret = 0;
+	struct cm36283_info *lpi = lp_info;
+
+	if (data == NULL)
+		return -EFAULT;	
+
+	ret = _cm36283_I2C_Read_Word(lpi->slave_addr, PS_DATA, data);
+	
+	(*data) &= 0xFF;
+	
+	if (ret < 0) {
+		pr_err(
+			"[PS][CM36283 error]%s: _cm36283_I2C_Read_Word fail\n",
+			__func__);
+		return -EIO;
+	} else {
+		pr_err(
+			"[PS][CM36283 OK]%s: _cm36283_I2C_Read_Word OK 0x%x\n",
+			__func__, *data);
+	}
+
+	return ret;
+}
+
+static uint16_t mid_value(uint16_t value[], uint8_t size)
+{
+	int i = 0, j = 0;
+	uint16_t temp = 0;
+
+	if (size < 3)
+		return 0;
+
+	for (i = 0; i < (size - 1); i++)
+		for (j = (i + 1); j < size; j++)
+			if (value[i] > value[j]) {
+				temp = value[i];
+				value[i] = value[j];
+				value[j] = temp;
+			}
+	return value[((size - 1) / 2)];
+}
+
+static int get_stable_ps_adc_value(uint16_t *ps_adc)
+{
+	uint16_t value[3] = {0, 0, 0}, mid_val = 0;
+	int ret = 0;
+	int i = 0;
+	int wait_count = 0;
+	struct cm36283_info *lpi = lp_info;
+
+	for (i = 0; i < 3; i++) {
+		/*wait interrupt GPIO high*/
+		while (gpio_get_value(lpi->intr_pin) == 0) {
+			msleep(10);
+			wait_count++;
+			if (wait_count > 12) {
+				pr_err("[PS_ERR][CM36283 error]%s: interrupt GPIO low,"
+					" get_ps_adc_value\n", __func__);
+				return -EIO;
+			}
+		}
+
+		ret = get_ps_adc_value(&value[i]);
+		if (ret < 0) {
+			pr_err("[PS_ERR][CM36283 error]%s: get_ps_adc_value\n",
+				__func__);
+			return -EIO;
+		}
+
+		if (wait_count < 60/10) {/*wait gpio less than 60ms*/
+			msleep(60 - (10*wait_count));
+		}
+		wait_count = 0;
+	}
+
+	/*D("Sta_ps: Before sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
+		value[0], value[1], value[2]);*/
+	mid_val = mid_value(value, 3);
+	D("Sta_ps: After sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
+		value[0], value[1], value[2]);
+	*ps_adc = (mid_val & 0xFF);
+
+	return 0;
+}
+
+static void sensor_irq_do_work(struct work_struct *work)
+{
+	struct cm36283_info *lpi = lp_info;
+	uint16_t intFlag;
+  _cm36283_I2C_Read_Word(lpi->slave_addr, INT_FLAG, &intFlag);
+	control_and_report(lpi, CONTROL_INT_ISR_REPORT, intFlag);  
+	  
+	enable_irq(lpi->irq);
+}
+
+static irqreturn_t cm36283_irq_handler(int irq, void *data)
+{
+	struct cm36283_info *lpi = data;
+
+	disable_irq_nosync(lpi->irq);
+	queue_work(lpi->lp_wq, &sensor_irq_work);
+
+	return IRQ_HANDLED;
+}
+
+static int als_power(int enable)
+{
+	struct cm36283_info *lpi = lp_info;
+
+	if (lpi->power)
+		lpi->power(LS_PWR_ON, 1);
+
+	return 0;
+}
+
+static void ls_initial_cmd(struct cm36283_info *lpi)
+{	
+	/*must disable l-sensor interrupt befrore IST create*//*disable ALS func*/
+	lpi->ls_cmd &= CM36283_ALS_INT_MASK;
+  lpi->ls_cmd |= CM36283_ALS_SD;
+  _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);  
+}
+
+static void psensor_initial_cmd(struct cm36283_info *lpi)
+{
+	/*must disable p-sensor interrupt befrore IST create*//*disable ALS func*/		
+  lpi->ps_conf1_val |= CM36283_PS_SD;
+  lpi->ps_conf1_val &= CM36283_PS_INT_MASK;  
+  _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);   
+  _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
+  _cm36283_I2C_Write_Word(lpi->slave_addr, PS_THD, (lpi->ps_close_thd_set <<8)| lpi->ps_away_thd_set);
+
+	D("[PS][CM36283] %s, finish\n", __func__);	
+}
+
+static int psensor_enable(struct cm36283_info *lpi)
+{
+	int ret = -EIO;
+	
+	mutex_lock(&ps_enable_mutex);
+	D("[PS][CM36283] %s\n", __func__);
+
+	if ( lpi->ps_enable ) {
+		D("[PS][CM36283] %s: already enabled\n", __func__);
+		ret = 0;
+	} else
+  	ret = control_and_report(lpi, CONTROL_PS, 1);
+	
+	mutex_unlock(&ps_enable_mutex);
+	return ret;
+}
+
+static int psensor_disable(struct cm36283_info *lpi)
+{
+	int ret = -EIO;
+	
+	mutex_lock(&ps_disable_mutex);
+	D("[PS][CM36283] %s\n", __func__);
+
+	if ( lpi->ps_enable == 0 ) {
+		D("[PS][CM36283] %s: already disabled\n", __func__);
+		ret = 0;
+	} else
+  	ret = control_and_report(lpi, CONTROL_PS,0);
+	
+	mutex_unlock(&ps_disable_mutex);
+	return ret;
+}
+
+static int psensor_open(struct inode *inode, struct file *file)
+{
+	struct cm36283_info *lpi = lp_info;
+
+	D("[PS][CM36283] %s\n", __func__);
+
+	if (lpi->psensor_opened)
+		return -EBUSY;
+
+	lpi->psensor_opened = 1;
+
+	return 0;
+}
+
+static int psensor_release(struct inode *inode, struct file *file)
+{
+	struct cm36283_info *lpi = lp_info;
+
+	D("[PS][CM36283] %s\n", __func__);
+
+	lpi->psensor_opened = 0;
+
+	return psensor_disable(lpi);
+	//return 0;
+}
+
+static long psensor_ioctl(struct file *file, unsigned int cmd,
+			unsigned long arg)
+{
+	int val;
+	struct cm36283_info *lpi = lp_info;
+
+	D("[PS][CM36283] %s cmd %d\n", __func__, _IOC_NR(cmd));
+
+	switch (cmd) {
+	case CAPELLA_CM3602_IOCTL_ENABLE:
+		if (get_user(val, (unsigned long __user *)arg))
+			return -EFAULT;
+		if (val)
+			return psensor_enable(lpi);
+		else
+			return psensor_disable(lpi);
+		break;
+	case CAPELLA_CM3602_IOCTL_GET_ENABLED:
+		return put_user(lpi->ps_enable, (unsigned long __user *)arg);
+		break;
+	default:
+		pr_err("[PS][CM36283 error]%s: invalid cmd %d\n",
+			__func__, _IOC_NR(cmd));
+		return -EINVAL;
+	}
+}
+
+static const struct file_operations psensor_fops = {
+	.owner = THIS_MODULE,
+	.open = psensor_open,
+	.release = psensor_release,
+	.unlocked_ioctl = psensor_ioctl
+};
+
+struct miscdevice psensor_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "proximity",
+	.fops = &psensor_fops
+};
+
+void lightsensor_set_kvalue(struct cm36283_info *lpi)
+{
+	if (!lpi) {
+		pr_err("[LS][CM36283 error]%s: ls_info is empty\n", __func__);
+		return;
+	}
+
+	D("[LS][CM36283] %s: ALS calibrated als_kadc=0x%x\n",
+			__func__, als_kadc);
+
+	if (als_kadc >> 16 == ALS_CALIBRATED)
+		lpi->als_kadc = als_kadc & 0xFFFF;
+	else {
+		lpi->als_kadc = 0;
+		D("[LS][CM36283] %s: no ALS calibrated\n", __func__);
+	}
+
+	if (lpi->als_kadc && lpi->golden_adc > 0) {
+		lpi->als_kadc = (lpi->als_kadc > 0 && lpi->als_kadc < 0x1000) ?
+				lpi->als_kadc : lpi->golden_adc;
+		lpi->als_gadc = lpi->golden_adc;
+	} else {
+		lpi->als_kadc = 1;
+		lpi->als_gadc = 1;
+	}
+	D("[LS][CM36283] %s: als_kadc=0x%x, als_gadc=0x%x\n",
+		__func__, lpi->als_kadc, lpi->als_gadc);
+}
+
+
+static int lightsensor_update_table(struct cm36283_info *lpi)
+{
+	uint32_t tmpData[10];
+	int i;
+	for (i = 0; i < 10; i++) {
+		tmpData[i] = (uint32_t)(*(lpi->adc_table + i))
+				* lpi->als_kadc / lpi->als_gadc ;
+		if( tmpData[i] <= 0xFFFF ){
+      lpi->cali_table[i] = (uint16_t) tmpData[i];		
+    } else {
+      lpi->cali_table[i] = 0xFFFF;    
+    }         
+		D("[LS][CM36283] %s: Calibrated adc_table: data[%d], %x\n",
+			__func__, i, lpi->cali_table[i]);
+	}
+
+	return 0;
+}
+
+
+static int lightsensor_enable(struct cm36283_info *lpi)
+{
+	int ret = -EIO;
+	
+	mutex_lock(&als_enable_mutex);
+	D("[LS][CM36283] %s\n", __func__);
+
+	if (lpi->als_enable) {
+		D("[LS][CM36283] %s: already enabled\n", __func__);
+		ret = 0;
+	} else
+  	ret = control_and_report(lpi, CONTROL_ALS, 1);
+	
+	mutex_unlock(&als_enable_mutex);
+	return ret;
+}
+
+static int lightsensor_disable(struct cm36283_info *lpi)
+{
+	int ret = -EIO;
+	mutex_lock(&als_disable_mutex);
+	D("[LS][CM36283] %s\n", __func__);
+
+	if ( lpi->als_enable == 0 ) {
+		D("[LS][CM36283] %s: already disabled\n", __func__);
+		ret = 0;
+	} else
+    ret = control_and_report(lpi, CONTROL_ALS, 0);
+	
+	mutex_unlock(&als_disable_mutex);
+	return ret;
+}
+
+static int lightsensor_open(struct inode *inode, struct file *file)
+{
+	struct cm36283_info *lpi = lp_info;
+	int rc = 0;
+
+	D("[LS][CM36283] %s\n", __func__);
+	if (lpi->lightsensor_opened) {
+		pr_err("[LS][CM36283 error]%s: already opened\n", __func__);
+		rc = -EBUSY;
+	}
+	lpi->lightsensor_opened = 1;
+	return rc;
+}
+
+static int lightsensor_release(struct inode *inode, struct file *file)
+{
+	struct cm36283_info *lpi = lp_info;
+
+	D("[LS][CM36283] %s\n", __func__);
+	lpi->lightsensor_opened = 0;
+	return 0;
+}
+
+static long lightsensor_ioctl(struct file *file, unsigned int cmd,
+		unsigned long arg)
+{
+	int rc, val;
+	struct cm36283_info *lpi = lp_info;
+
+	/*D("[CM36283] %s cmd %d\n", __func__, _IOC_NR(cmd));*/
+
+	switch (cmd) {
+	case LIGHTSENSOR_IOCTL_ENABLE:
+		if (get_user(val, (unsigned long __user *)arg)) {
+			rc = -EFAULT;
+			break;
+		}
+		D("[LS][CM36283] %s LIGHTSENSOR_IOCTL_ENABLE, value = %d\n",
+			__func__, val);
+		rc = val ? lightsensor_enable(lpi) : lightsensor_disable(lpi);
+		break;
+	case LIGHTSENSOR_IOCTL_GET_ENABLED:
+		val = lpi->als_enable;
+		D("[LS][CM36283] %s LIGHTSENSOR_IOCTL_GET_ENABLED, enabled %d\n",
+			__func__, val);
+		rc = put_user(val, (unsigned long __user *)arg);
+		break;
+	default:
+		pr_err("[LS][CM36283 error]%s: invalid cmd %d\n",
+			__func__, _IOC_NR(cmd));
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static const struct file_operations lightsensor_fops = {
+	.owner = THIS_MODULE,
+	.open = lightsensor_open,
+	.release = lightsensor_release,
+	.unlocked_ioctl = lightsensor_ioctl
+};
+
+static struct miscdevice lightsensor_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "lightsensor",
+	.fops = &lightsensor_fops
+};
+
+
+static ssize_t ps_adc_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+
+	uint16_t value;
+	int ret;
+	struct cm36283_info *lpi = lp_info;
+	int intr_val;
+
+	intr_val = gpio_get_value(lpi->intr_pin);
+
+	get_ps_adc_value(&value);
+
+	ret = sprintf(buf, "ADC[0x%04X], ENABLE = %d, intr_pin = %d\n", value, lpi->ps_enable, intr_val);
+
+	return ret;
+}
+
+static ssize_t ps_enable_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int ps_en;
+	struct cm36283_info *lpi = lp_info;
+
+	ps_en = -1;
+	sscanf(buf, "%d", &ps_en);
+
+	if (ps_en != 0 && ps_en != 1
+		&& ps_en != 10 && ps_en != 13 && ps_en != 16)
+		return -EINVAL;
+
+	if (ps_en) {
+		D("[PS][CM36283] %s: ps_en=%d\n",
+			__func__, ps_en);
+		psensor_enable(lpi);
+	} else
+		psensor_disable(lpi);
+
+	D("[PS][CM36283] %s\n", __func__);
+
+	return count;
+}
+
+static DEVICE_ATTR(ps_adc, 0664, ps_adc_show, ps_enable_store);
+
+unsigned PS_cmd_test_value;
+static ssize_t ps_parameters_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct cm36283_info *lpi = lp_info;
+
+	ret = sprintf(buf, "PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x, PS_cmd_cmd:value = 0x%x\n",
+		lpi->ps_close_thd_set, lpi->ps_away_thd_set, PS_cmd_test_value);
+
+	return ret;
+}
+
+static ssize_t ps_parameters_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+
+	struct cm36283_info *lpi = lp_info;
+	char *token[10];
+	int i;
+
+	printk(KERN_INFO "[PS][CM36283] %s\n", buf);
+	for (i = 0; i < 3; i++)
+		token[i] = strsep((char **)&buf, " ");
+
+	lpi->ps_close_thd_set = simple_strtoul(token[0], NULL, 16);
+	lpi->ps_away_thd_set = simple_strtoul(token[1], NULL, 16);	
+	PS_cmd_test_value = simple_strtoul(token[2], NULL, 16);
+	printk(KERN_INFO
+		"[PS][CM36283]Set PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x, PS_cmd_cmd:value = 0x%x\n",
+		lpi->ps_close_thd_set, lpi->ps_away_thd_set, PS_cmd_test_value);
+
+	D("[PS][CM36283] %s\n", __func__);
+
+	return count;
+}
+
+static DEVICE_ATTR(ps_parameters, 0664,
+	ps_parameters_show, ps_parameters_store);
+
+
+static ssize_t ps_conf_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct cm36283_info *lpi = lp_info;
+	return sprintf(buf, "PS_CONF1 = 0x%x, PS_CONF3 = 0x%x\n", lpi->ps_conf1_val, lpi->ps_conf3_val);
+}
+static ssize_t ps_conf_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int code1, code2;
+	struct cm36283_info *lpi = lp_info;
+
+	sscanf(buf, "0x%x 0x%x", &code1, &code2);
+
+	D("[PS]%s: store value PS conf1 reg = 0x%x PS conf3 reg = 0x%x\n", __func__, code1, code2);
+
+  lpi->ps_conf1_val = code1;
+  lpi->ps_conf3_val = code2;
+
+	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val );  
+	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val );
+
+	return count;
+}
+static DEVICE_ATTR(ps_conf, 0664, ps_conf_show, ps_conf_store);
+
+static ssize_t ps_thd_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct cm36283_info *lpi = lp_info;
+  ret = sprintf(buf, "%s ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n", __func__, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
+  return ret;	
+}
+static ssize_t ps_thd_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int code;
+	struct cm36283_info *lpi = lp_info;
+
+	sscanf(buf, "0x%x", &code);
+
+	D("[PS]%s: store value = 0x%x\n", __func__, code);
+
+	lpi->ps_away_thd_set = code &0xFF;
+	lpi->ps_close_thd_set = (code &0xFF00)>>8;	
+
+	D("[PS]%s: ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n", __func__, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
+
+	return count;
+}
+static DEVICE_ATTR(ps_thd, 0664, ps_thd_show, ps_thd_store);
+
+static ssize_t ps_hw_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	int ret = 0;
+	struct cm36283_info *lpi = lp_info;
+
+	ret = sprintf(buf, "PS1: reg = 0x%x, PS3: reg = 0x%x, ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n",
+		lpi->ps_conf1_val, lpi->ps_conf3_val, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
+
+	return ret;
+}
+static ssize_t ps_hw_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int code;
+//	struct cm36283_info *lpi = lp_info;
+
+	sscanf(buf, "0x%x", &code);
+
+	D("[PS]%s: store value = 0x%x\n", __func__, code);
+
+	return count;
+}
+static DEVICE_ATTR(ps_hw, 0664, ps_hw_show, ps_hw_store);
+
+static ssize_t ls_adc_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct cm36283_info *lpi = lp_info;
+
+	D("[LS][CM36283] %s: ADC = 0x%04X, Level = %d \n",
+		__func__, lpi->current_adc, lpi->current_level);
+	ret = sprintf(buf, "ADC[0x%04X] => level %d\n",
+		lpi->current_adc, lpi->current_level);
+
+	return ret;
+}
+
+static DEVICE_ATTR(ls_adc, 0664, ls_adc_show, NULL);
+
+static ssize_t ls_enable_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+
+	int ret = 0;
+	struct cm36283_info *lpi = lp_info;
+
+	ret = sprintf(buf, "Light sensor Auto Enable = %d\n",
+			lpi->als_enable);
+
+	return ret;
+}
+
+static ssize_t ls_enable_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	int ret = 0;
+	int ls_auto;
+	struct cm36283_info *lpi = lp_info;
+
+	ls_auto = -1;
+	sscanf(buf, "%d", &ls_auto);
+
+	if (ls_auto != 0 && ls_auto != 1 && ls_auto != 147)
+		return -EINVAL;
+
+	if (ls_auto) {
+		lpi->ls_calibrate = (ls_auto == 147) ? 1 : 0;
+		ret = lightsensor_enable(lpi);
+	} else {
+		lpi->ls_calibrate = 0;
+		ret = lightsensor_disable(lpi);
+	}
+
+	D("[LS][CM36283] %s: lpi->als_enable = %d, lpi->ls_calibrate = %d, ls_auto=%d\n",
+		__func__, lpi->als_enable, lpi->ls_calibrate, ls_auto);
+
+	if (ret < 0)
+		pr_err(
+		"[LS][CM36283 error]%s: set auto light sensor fail\n",
+		__func__);
+
+	return count;
+}
+
+static DEVICE_ATTR(ls_auto, 0664,
+	ls_enable_show, ls_enable_store);
+
+static ssize_t ls_kadc_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct cm36283_info *lpi = lp_info;
+	int ret;
+
+	ret = sprintf(buf, "kadc = 0x%x",
+			lpi->als_kadc);
+
+	return ret;
+}
+
+static ssize_t ls_kadc_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct cm36283_info *lpi = lp_info;
+	int kadc_temp = 0;
+
+	sscanf(buf, "%d", &kadc_temp);
+
+	mutex_lock(&als_get_adc_mutex);
+  if(kadc_temp != 0) {
+		lpi->als_kadc = kadc_temp;
+		if(  lpi->als_gadc != 0){
+  		if (lightsensor_update_table(lpi) < 0)
+				printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n", __func__);
+  	} else {
+			printk(KERN_INFO "[LS]%s: als_gadc =0x%x wait to be set\n",
+					__func__, lpi->als_gadc);
+  	}		
+	} else {
+		printk(KERN_INFO "[LS]%s: als_kadc can't be set to zero\n",
+				__func__);
+	}
+				
+	mutex_unlock(&als_get_adc_mutex);
+	return count;
+}
+
+static DEVICE_ATTR(ls_kadc, 0664, ls_kadc_show, ls_kadc_store);
+
+static ssize_t ls_gadc_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct cm36283_info *lpi = lp_info;
+	int ret;
+
+	ret = sprintf(buf, "gadc = 0x%x\n", lpi->als_gadc);
+
+	return ret;
+}
+
+static ssize_t ls_gadc_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct cm36283_info *lpi = lp_info;
+	int gadc_temp = 0;
+
+	sscanf(buf, "%d", &gadc_temp);
+	
+	mutex_lock(&als_get_adc_mutex);
+  if(gadc_temp != 0) {
+		lpi->als_gadc = gadc_temp;
+		if(  lpi->als_kadc != 0){
+  		if (lightsensor_update_table(lpi) < 0)
+				printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n", __func__);
+  	} else {
+			printk(KERN_INFO "[LS]%s: als_kadc =0x%x wait to be set\n",
+					__func__, lpi->als_kadc);
+  	}		
+	} else {
+		printk(KERN_INFO "[LS]%s: als_gadc can't be set to zero\n",
+				__func__);
+	}
+	mutex_unlock(&als_get_adc_mutex);
+	return count;
+}
+
+static DEVICE_ATTR(ls_gadc, 0664, ls_gadc_show, ls_gadc_store);
+
+static ssize_t ls_adc_table_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	unsigned length = 0;
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		length += sprintf(buf + length,
+			"[CM36283]Get adc_table[%d] =  0x%x ; %d, Get cali_table[%d] =  0x%x ; %d, \n",
+			i, *(lp_info->adc_table + i),
+			*(lp_info->adc_table + i),
+			i, *(lp_info->cali_table + i),
+			*(lp_info->cali_table + i));
+	}
+	return length;
+}
+
+static ssize_t ls_adc_table_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+
+	struct cm36283_info *lpi = lp_info;
+	char *token[10];
+	uint16_t tempdata[10];
+	int i;
+
+	printk(KERN_INFO "[LS][CM36283]%s\n", buf);
+	for (i = 0; i < 10; i++) {
+		token[i] = strsep((char **)&buf, " ");
+		tempdata[i] = simple_strtoul(token[i], NULL, 16);
+		if (tempdata[i] < 1 || tempdata[i] > 0xffff) {
+			printk(KERN_ERR
+			"[LS][CM36283 error] adc_table[%d] =  0x%x Err\n",
+			i, tempdata[i]);
+			return count;
+		}
+	}
+	mutex_lock(&als_get_adc_mutex);
+	for (i = 0; i < 10; i++) {
+		lpi->adc_table[i] = tempdata[i];
+		printk(KERN_INFO
+		"[LS][CM36283]Set lpi->adc_table[%d] =  0x%x\n",
+		i, *(lp_info->adc_table + i));
+	}
+	if (lightsensor_update_table(lpi) < 0)
+		printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n",
+		__func__);
+	mutex_unlock(&als_get_adc_mutex);
+	D("[LS][CM36283] %s\n", __func__);
+
+	return count;
+}
+
+static DEVICE_ATTR(ls_adc_table, 0664,
+	ls_adc_table_show, ls_adc_table_store);
+
+static ssize_t ls_conf_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct cm36283_info *lpi = lp_info;
+	return sprintf(buf, "ALS_CONF = %x\n", lpi->ls_cmd);
+}
+static ssize_t ls_conf_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct cm36283_info *lpi = lp_info;
+	int value = 0;
+	sscanf(buf, "0x%x", &value);
+
+	lpi->ls_cmd = value;
+	printk(KERN_INFO "[LS]set ALS_CONF = %x\n", lpi->ls_cmd);
+	
+	_cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
+	return count;
+}
+static DEVICE_ATTR(ls_conf, 0664, ls_conf_show, ls_conf_store);
+
+static ssize_t ls_fLevel_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "fLevel = %d\n", fLevel);
+}
+static ssize_t ls_fLevel_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct cm36283_info *lpi = lp_info;
+	int value=0;
+	sscanf(buf, "%d", &value);
+	(value>=0)?(value=min(value,10)):(value=max(value,-1));
+	fLevel=value;
+	input_report_abs(lpi->ls_input_dev, ABS_MISC, fLevel);
+	input_sync(lpi->ls_input_dev);
+	printk(KERN_INFO "[LS]set fLevel = %d\n", fLevel);
+
+	msleep(1000);
+	fLevel=-1;
+	return count;
+}
+static DEVICE_ATTR(ls_flevel, 0664, ls_fLevel_show, ls_fLevel_store);
+
+static int lightsensor_setup(struct cm36283_info *lpi)
+{
+	int ret;
+
+	lpi->ls_input_dev = input_allocate_device();
+	if (!lpi->ls_input_dev) {
+		pr_err(
+			"[LS][CM36283 error]%s: could not allocate ls input device\n",
+			__func__);
+		return -ENOMEM;
+	}
+	lpi->ls_input_dev->name = "cm36283-ls";
+	set_bit(EV_ABS, lpi->ls_input_dev->evbit);
+	input_set_abs_params(lpi->ls_input_dev, ABS_MISC, 0, 9, 0, 0);
+
+	ret = input_register_device(lpi->ls_input_dev);
+	if (ret < 0) {
+		pr_err("[LS][CM36283 error]%s: can not register ls input device\n",
+				__func__);
+		goto err_free_ls_input_device;
+	}
+
+	ret = misc_register(&lightsensor_misc);
+	if (ret < 0) {
+		pr_err("[LS][CM36283 error]%s: can not register ls misc device\n",
+				__func__);
+		goto err_unregister_ls_input_device;
+	}
+
+	return ret;
+
+err_unregister_ls_input_device:
+	input_unregister_device(lpi->ls_input_dev);
+err_free_ls_input_device:
+	input_free_device(lpi->ls_input_dev);
+	return ret;
+}
+
+static int psensor_setup(struct cm36283_info *lpi)
+{
+	int ret;
+
+	lpi->ps_input_dev = input_allocate_device();
+	if (!lpi->ps_input_dev) {
+		pr_err(
+			"[PS][CM36283 error]%s: could not allocate ps input device\n",
+			__func__);
+		return -ENOMEM;
+	}
+	lpi->ps_input_dev->name = "cm36283-ps";
+	set_bit(EV_ABS, lpi->ps_input_dev->evbit);
+	input_set_abs_params(lpi->ps_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
+
+	ret = input_register_device(lpi->ps_input_dev);
+	if (ret < 0) {
+		pr_err(
+			"[PS][CM36283 error]%s: could not register ps input device\n",
+			__func__);
+		goto err_free_ps_input_device;
+	}
+
+	ret = misc_register(&psensor_misc);
+	if (ret < 0) {
+		pr_err(
+			"[PS][CM36283 error]%s: could not register ps misc device\n",
+			__func__);
+		goto err_unregister_ps_input_device;
+	}
+
+	return ret;
+
+err_unregister_ps_input_device:
+	input_unregister_device(lpi->ps_input_dev);
+err_free_ps_input_device:
+	input_free_device(lpi->ps_input_dev);
+	return ret;
+}
+
+
+static int initial_cm36283(struct cm36283_info *lpi)
+{
+	int val, ret;
+	uint16_t idReg;
+
+	val = gpio_get_value(lpi->intr_pin);
+	D("[PS][CM36283] %s, INTERRUPT GPIO val = %d\n", __func__, val);
+
+	ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ID_REG, &idReg);
+	if ((ret < 0) || (idReg != 0xC082)) {
+  		if (record_init_fail == 0)
+  			record_init_fail = 1;
+  		return -ENOMEM;/*If devices without cm36283 chip and did not probe driver*/	
+  }
+  
+	return 0;
+}
+
+static int cm36283_setup(struct cm36283_info *lpi)
+{
+	int ret = 0;
+
+	als_power(1);
+	msleep(5);
+	ret = gpio_request(lpi->intr_pin, "gpio_cm36283_intr");
+	if (ret < 0) {
+		pr_err("[PS][CM36283 error]%s: gpio %d request failed (%d)\n",
+			__func__, lpi->intr_pin, ret);
+		return ret;
+	}
+
+	ret = gpio_direction_input(lpi->intr_pin);
+	if (ret < 0) {
+		pr_err(
+			"[PS][CM36283 error]%s: fail to set gpio %d as input (%d)\n",
+			__func__, lpi->intr_pin, ret);
+		goto fail_free_intr_pin;
+	}
+
+
+	ret = initial_cm36283(lpi);
+	if (ret < 0) {
+		pr_err(
+			"[PS_ERR][CM36283 error]%s: fail to initial cm36283 (%d)\n",
+			__func__, ret);
+		goto fail_free_intr_pin;
+	}
+	
+	/*Default disable P sensor and L sensor*/
+  ls_initial_cmd(lpi);
+	psensor_initial_cmd(lpi);
+
+	ret = request_any_context_irq(lpi->irq,
+			cm36283_irq_handler,
+			IRQF_TRIGGER_LOW,
+			"cm36283",
+			lpi);
+	if (ret < 0) {
+		pr_err(
+			"[PS][CM36283 error]%s: req_irq(%d) fail for gpio %d (%d)\n",
+			__func__, lpi->irq,
+			lpi->intr_pin, ret);
+		goto fail_free_intr_pin;
+	}
+
+	return ret;
+
+fail_free_intr_pin:
+	gpio_free(lpi->intr_pin);
+	return ret;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cm36283_early_suspend(struct early_suspend *h)
+{
+	struct cm36283_info *lpi = lp_info;
+
+	D("[LS][CM36283] %s\n", __func__);
+
+	if (lpi->als_enable)
+		lightsensor_disable(lpi);
+
+}
+
+static void cm36283_late_resume(struct early_suspend *h)
+{
+	struct cm36283_info *lpi = lp_info;
+
+	D("[LS][CM36283] %s\n", __func__);
+
+	if (!lpi->als_enable)
+		lightsensor_enable(lpi);
+}
+#endif
+
+static int cm36283_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int ret = 0;
+	struct cm36283_info *lpi;
+	struct cm36283_platform_data *pdata;
+
+	D("[PS][CM36283] %s\n", __func__);
+
+
+	lpi = kzalloc(sizeof(struct cm36283_info), GFP_KERNEL);
+	if (!lpi)
+		return -ENOMEM;
+
+	/*D("[CM36283] %s: client->irq = %d\n", __func__, client->irq);*/
+
+	lpi->i2c_client = client;
+	pdata = client->dev.platform_data;
+	if (!pdata) {
+		pr_err("[PS][CM36283 error]%s: Assign platform_data error!!\n",
+			__func__);
+		ret = -EBUSY;
+		goto err_platform_data_null;
+	}
+
+	lpi->irq = client->irq;
+
+	i2c_set_clientdata(client, lpi);
+	
+  lpi->intr_pin = pdata->intr;
+	lpi->adc_table = pdata->levels;
+	lpi->power = pdata->power;
+	
+	lpi->slave_addr = pdata->slave_addr;
+	
+	lpi->ps_away_thd_set = pdata->ps_away_thd_set;
+	lpi->ps_close_thd_set = pdata->ps_close_thd_set;	
+	lpi->ps_conf1_val = pdata->ps_conf1_val;
+	lpi->ps_conf3_val = pdata->ps_conf3_val;
+	
+	lpi->ls_cmd  = pdata->ls_cmd;
+	
+	lpi->record_clear_int_fail=0;
+	
+	D("[PS][CM36283] %s: ls_cmd 0x%x\n",
+		__func__, lpi->ls_cmd);
+	
+	if (pdata->ls_cmd == 0) {
+		lpi->ls_cmd  = CM36283_ALS_IT_160ms | CM36283_ALS_GAIN_2;
+	}
+
+	lp_info = lpi;
+
+	mutex_init(&CM36283_control_mutex);
+
+	mutex_init(&als_enable_mutex);
+	mutex_init(&als_disable_mutex);
+	mutex_init(&als_get_adc_mutex);
+
+	ret = lightsensor_setup(lpi);
+	if (ret < 0) {
+		pr_err("[LS][CM36283 error]%s: lightsensor_setup error!!\n",
+			__func__);
+		goto err_lightsensor_setup;
+	}
+
+	mutex_init(&ps_enable_mutex);
+	mutex_init(&ps_disable_mutex);
+	mutex_init(&ps_get_adc_mutex);
+
+	ret = psensor_setup(lpi);
+	if (ret < 0) {
+		pr_err("[PS][CM36283 error]%s: psensor_setup error!!\n",
+			__func__);
+		goto err_psensor_setup;
+	}
+
+  //SET LUX STEP FACTOR HERE
+  // if adc raw value one step = 5/100 = 1/20 = 0.05 lux
+  // the following will set the factor 0.05 = 1/20
+  // and lpi->golden_adc = 1;  
+  // set als_kadc = (ALS_CALIBRATED <<16) | 20;
+
+  als_kadc = (ALS_CALIBRATED <<16) | 20;
+  lpi->golden_adc = 1;
+
+  //ls calibrate always set to 1 
+  lpi->ls_calibrate = 1;
+
+	lightsensor_set_kvalue(lpi);
+	ret = lightsensor_update_table(lpi);
+	if (ret < 0) {
+		pr_err("[LS][CM36283 error]%s: update ls table fail\n",
+			__func__);
+		goto err_lightsensor_update_table;
+	}
+
+	lpi->lp_wq = create_singlethread_workqueue("cm36283_wq");
+	if (!lpi->lp_wq) {
+		pr_err("[PS][CM36283 error]%s: can't create workqueue\n", __func__);
+		ret = -ENOMEM;
+		goto err_create_singlethread_workqueue;
+	}
+	wake_lock_init(&(lpi->ps_wake_lock), WAKE_LOCK_SUSPEND, "proximity");
+
+	ret = cm36283_setup(lpi);
+	if (ret < 0) {
+		pr_err("[PS_ERR][CM36283 error]%s: cm36283_setup error!\n", __func__);
+		goto err_cm36283_setup;
+	}
+	lpi->cm36283_class = class_create(THIS_MODULE, "optical_sensors");
+	if (IS_ERR(lpi->cm36283_class)) {
+		ret = PTR_ERR(lpi->cm36283_class);
+		lpi->cm36283_class = NULL;
+		goto err_create_class;
+	}
+
+	lpi->ls_dev = device_create(lpi->cm36283_class,
+				NULL, 0, "%s", "lightsensor");
+	if (unlikely(IS_ERR(lpi->ls_dev))) {
+		ret = PTR_ERR(lpi->ls_dev);
+		lpi->ls_dev = NULL;
+		goto err_create_ls_device;
+	}
+
+	/* register the attributes */
+	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_adc);
+	if (ret)
+		goto err_create_ls_device_file;
+
+	/* register the attributes */
+	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_auto);
+	if (ret)
+		goto err_create_ls_device_file;
+
+	/* register the attributes */
+	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_kadc);
+	if (ret)
+		goto err_create_ls_device_file;
+
+	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_gadc);
+	if (ret)
+		goto err_create_ls_device_file;
+
+	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_adc_table);
+	if (ret)
+		goto err_create_ls_device_file;
+
+	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_conf);
+	if (ret)
+		goto err_create_ls_device_file;
+
+	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_flevel);
+	if (ret)
+		goto err_create_ls_device_file;
+
+	lpi->ps_dev = device_create(lpi->cm36283_class,
+				NULL, 0, "%s", "proximity");
+	if (unlikely(IS_ERR(lpi->ps_dev))) {
+		ret = PTR_ERR(lpi->ps_dev);
+		lpi->ps_dev = NULL;
+		goto err_create_ls_device_file;
+	}
+
+	/* register the attributes */
+	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_adc);
+	if (ret)
+		goto err_create_ps_device;
+
+	ret = device_create_file(lpi->ps_dev,
+		&dev_attr_ps_parameters);
+	if (ret)
+		goto err_create_ps_device;
+
+	/* register the attributes */
+	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_conf);
+	if (ret)
+		goto err_create_ps_device;
+
+	/* register the attributes */
+	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_thd);
+	if (ret)
+		goto err_create_ps_device;
+
+	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_hw);
+	if (ret)
+		goto err_create_ps_device;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	lpi->early_suspend.level =
+			EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	lpi->early_suspend.suspend = cm36283_early_suspend;
+	lpi->early_suspend.resume = cm36283_late_resume;
+	register_early_suspend(&lpi->early_suspend);
+#endif
+
+	D("[PS][CM36283] %s: Probe success!\n", __func__);
+
+	return ret;
+
+err_create_ps_device:
+	device_unregister(lpi->ps_dev);
+err_create_ls_device_file:
+	device_unregister(lpi->ls_dev);
+err_create_ls_device:
+	class_destroy(lpi->cm36283_class);
+err_create_class:
+err_cm36283_setup:
+	destroy_workqueue(lpi->lp_wq);
+	wake_lock_destroy(&(lpi->ps_wake_lock));
+
+	input_unregister_device(lpi->ls_input_dev);
+	input_free_device(lpi->ls_input_dev);
+	input_unregister_device(lpi->ps_input_dev);
+	input_free_device(lpi->ps_input_dev);
+err_create_singlethread_workqueue:
+err_lightsensor_update_table:
+	misc_deregister(&psensor_misc);
+err_psensor_setup:
+	mutex_destroy(&CM36283_control_mutex);
+	mutex_destroy(&ps_enable_mutex);
+	mutex_destroy(&ps_disable_mutex);
+	mutex_destroy(&ps_get_adc_mutex);
+	misc_deregister(&lightsensor_misc);
+err_lightsensor_setup:
+	mutex_destroy(&als_enable_mutex);
+	mutex_destroy(&als_disable_mutex);
+	mutex_destroy(&als_get_adc_mutex);
+err_platform_data_null:
+	kfree(lpi);
+	return ret;
+}
+   
+static int control_and_report( struct cm36283_info *lpi, uint8_t mode, uint16_t param ) {
+  int ret=0;
+	uint16_t adc_value = 0;
+	uint16_t ps_data = 0;	
+	int level = 0, i, val;
+	
+  mutex_lock(&CM36283_control_mutex);
+
+  if( mode == CONTROL_ALS ){
+    if(param){
+      lpi->ls_cmd &= CM36283_ALS_SD_MASK;      
+    } else {
+      lpi->ls_cmd |= CM36283_ALS_SD;
+    }
+    _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
+    lpi->als_enable=param;
+  } else if( mode == CONTROL_PS ){
+    if(param){ 
+      lpi->ps_conf1_val &= CM36283_PS_SD_MASK;
+      lpi->ps_conf1_val |= CM36283_PS_INT_IN_AND_OUT;      
+    } else {
+      lpi->ps_conf1_val |= CM36283_PS_SD;
+      lpi->ps_conf1_val &= CM36283_PS_INT_MASK;
+    }
+    _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);    
+    lpi->ps_enable=param;  
+  }
+  if((mode == CONTROL_ALS)||(mode == CONTROL_PS)){  
+    if( param==1 ){
+		  msleep(100);  
+    }
+  }
+     	
+  if(lpi->als_enable){
+    if( mode == CONTROL_ALS ||
+      ( mode == CONTROL_INT_ISR_REPORT && 
+      ((param&INT_FLAG_ALS_IF_L)||(param&INT_FLAG_ALS_IF_H)))){
+    
+    	  lpi->ls_cmd &= CM36283_ALS_INT_MASK;
+    	  ret = _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);  
+      
+        get_ls_adc_value(&adc_value, 0);
+          
+        if( lpi->ls_calibrate ) {
+        	for (i = 0; i < 10; i++) {
+      	  	if (adc_value <= (*(lpi->cali_table + i))) {
+      		  	level = i;
+      			  if (*(lpi->cali_table + i))
+      				  break;
+      		  }
+      		  if ( i == 9) {/*avoid  i = 10, because 'cali_table' of size is 10 */
+      			  level = i;
+      			  break;
+      		  }
+      	  }
+        } else {
+      	  for (i = 0; i < 10; i++) {
+      		  if (adc_value <= (*(lpi->adc_table + i))) {
+      			  level = i;
+      			  if (*(lpi->adc_table + i))
+      				  break;
+      		  }
+      		  if ( i == 9) {/*avoid  i = 10, because 'cali_table' of size is 10 */
+      			  level = i;
+      			  break;
+      		  }
+      	  }
+    	  }
+    
+    	  ret = set_lsensor_range(((i == 0) || (adc_value == 0)) ? 0 :
+    		   	*(lpi->cali_table + (i - 1)) + 1,
+    		    *(lpi->cali_table + i));
+    	  
+        lpi->ls_cmd |= CM36283_ALS_INT_EN;
+    	  
+        ret = _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);  
+    	  
+    		if ((i == 0) || (adc_value == 0))
+    			D("[LS][CM3628] %s: ADC=0x%03X, Level=%d, l_thd equal 0, h_thd = 0x%x \n",
+    				__func__, adc_value, level, *(lpi->cali_table + i));
+    		else
+    			D("[LS][CM3628] %s: ADC=0x%03X, Level=%d, l_thd = 0x%x, h_thd = 0x%x \n",
+    				__func__, adc_value, level, *(lpi->cali_table + (i - 1)) + 1, *(lpi->cali_table + i));
+    		lpi->current_level = level;
+    		lpi->current_adc = adc_value;    
+        input_report_abs(lpi->ls_input_dev, ABS_MISC, level);
+        input_sync(lpi->ls_input_dev);
+    }
+  }
+
+#define PS_CLOSE 1
+#define PS_AWAY  (1<<1)
+#define PS_CLOSE_AND_AWAY PS_CLOSE+PS_AWAY
+
+  if(lpi->ps_enable){
+    int ps_status = 0;
+    if( mode == CONTROL_PS )
+      ps_status = PS_CLOSE_AND_AWAY;   
+    else if(mode == CONTROL_INT_ISR_REPORT ){  
+      if ( param & INT_FLAG_PS_IF_CLOSE )
+        ps_status |= PS_CLOSE;      
+      if ( param & INT_FLAG_PS_IF_AWAY )
+        ps_status |= PS_AWAY;
+    }
+      
+    if (ps_status!=0){
+      switch(ps_status){
+        case PS_CLOSE_AND_AWAY:
+          get_stable_ps_adc_value(&ps_data);
+          val = (ps_data >= lpi->ps_close_thd_set) ? 0 : 1;
+          break;
+        case PS_AWAY:
+          val = 1;
+          break;
+        case PS_CLOSE:
+          val = 0;
+          break;
+        };
+      input_report_abs(lpi->ps_input_dev, ABS_DISTANCE, val);      
+      input_sync(lpi->ps_input_dev);        
+    }
+  }
+
+  mutex_unlock(&CM36283_control_mutex);
+  return ret;
+}
+
+
+static const struct i2c_device_id cm36283_i2c_id[] = {
+	{CM36283_I2C_NAME, 0},
+	{}
+};
+
+static struct i2c_driver cm36283_driver = {
+	.id_table = cm36283_i2c_id,
+	.probe = cm36283_probe,
+	.driver = {
+		.name = CM36283_I2C_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init cm36283_init(void)
+{
+	return i2c_add_driver(&cm36283_driver);
+}
+
+static void __exit cm36283_exit(void)
+{
+	i2c_del_driver(&cm36283_driver);
+}
+
+module_init(cm36283_init);
+module_exit(cm36283_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CM36283 Driver");
+MODULE_AUTHOR("Frank Hsieh <pengyueh@gmail.com>");
diff --git a/drivers/input/misc/stk3x1x.c b/drivers/input/misc/stk3x1x.c
new file mode 100644
index 0000000..eee9a28
--- /dev/null
+++ b/drivers/input/misc/stk3x1x.c
@@ -0,0 +1,2020 @@
+/*
+ *  stk3x1x.c - Linux kernel modules for sensortek stk301x, stk321x and stk331x
+ *  proximity/ambient light sensor
+ *
+ *  Copyright (C) 2012 Lex Hsieh / sensortek <lex_hsieh@sitronix.com.tw> or
+ *   <lex_hsieh@sensortek.com.tw>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/kdev_t.h>
+#include <linux/fs.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/errno.h>
+#include <linux/wakelock.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include "linux/stk3x1x.h"
+
+#define DRIVER_VERSION  "3.4.4ts"
+
+/* Driver Settings */
+#define CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
+#ifdef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
+#define STK_ALS_CHANGE_THD	20	/* The threshold to trigger ALS interrupt, unit: lux */
+#endif	/* #ifdef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD */
+#define STK_INT_PS_MODE			1	/* 1, 2, or 3	*/
+#define STK_POLL_PS
+#define STK_POLL_ALS		/* ALS interrupt is valid only when STK_PS_INT_MODE = 1	or 4*/
+
+#define STK_DEBUG_PRINTF
+
+/* Define Register Map */
+#define STK_STATE_REG 			0x00
+#define STK_PSCTRL_REG 			0x01
+#define STK_ALSCTRL_REG 		0x02
+#define STK_LEDCTRL_REG 		0x03
+#define STK_INT_REG 			0x04
+#define STK_WAIT_REG 			0x05
+#define STK_THDH1_PS_REG 		0x06
+#define STK_THDH2_PS_REG 		0x07
+#define STK_THDL1_PS_REG 		0x08
+#define STK_THDL2_PS_REG 		0x09
+#define STK_THDH1_ALS_REG 		0x0A
+#define STK_THDH2_ALS_REG 		0x0B
+#define STK_THDL1_ALS_REG 		0x0C
+#define STK_THDL2_ALS_REG 		0x0D
+#define STK_FLAG_REG 			0x10
+#define STK_DATA1_PS_REG	 	0x11
+#define STK_DATA2_PS_REG 		0x12
+#define STK_DATA1_ALS_REG 		0x13
+#define STK_DATA2_ALS_REG 		0x14
+#define STK_DATA1_OFFSET_REG 	0x15
+#define STK_DATA2_OFFSET_REG 	0x16
+#define STK_DATA1_IR_REG 		0x17
+#define STK_DATA2_IR_REG 		0x18
+#define STK_PDT_ID_REG 			0x3E
+#define STK_RSRVD_REG 			0x3F
+#define STK_SW_RESET_REG		0x80
+
+
+/* Define state reg */
+#define STK_STATE_EN_IRS_SHIFT  	7
+#define STK_STATE_EN_AK_SHIFT  		6
+#define STK_STATE_EN_ASO_SHIFT  	5
+#define STK_STATE_EN_IRO_SHIFT  	4
+#define STK_STATE_EN_WAIT_SHIFT  	2
+#define STK_STATE_EN_ALS_SHIFT  	1
+#define STK_STATE_EN_PS_SHIFT  		0
+
+#define STK_STATE_EN_IRS_MASK	0x80
+#define STK_STATE_EN_AK_MASK	0x40
+#define STK_STATE_EN_ASO_MASK	0x20
+#define STK_STATE_EN_IRO_MASK	0x10
+#define STK_STATE_EN_WAIT_MASK	0x04
+#define STK_STATE_EN_ALS_MASK	0x02
+#define STK_STATE_EN_PS_MASK	0x01
+
+/* Define PS ctrl reg */
+#define STK_PS_PRS_SHIFT  		6
+#define STK_PS_GAIN_SHIFT  		4
+#define STK_PS_IT_SHIFT  		0
+
+#define STK_PS_PRS_MASK			0xC0
+#define STK_PS_GAIN_MASK		0x30
+#define STK_PS_IT_MASK			0x0F
+
+/* Define ALS ctrl reg */
+#define STK_ALS_PRS_SHIFT  		6
+#define STK_ALS_GAIN_SHIFT  	4
+#define STK_ALS_IT_SHIFT  		0
+
+#define STK_ALS_PRS_MASK		0xC0
+#define STK_ALS_GAIN_MASK		0x30
+#define STK_ALS_IT_MASK			0x0F
+
+/* Define LED ctrl reg */
+#define STK_LED_IRDR_SHIFT  	6
+#define STK_LED_DT_SHIFT  		0
+
+#define STK_LED_IRDR_MASK		0xC0
+#define STK_LED_DT_MASK			0x3F
+
+/* Define interrupt reg */
+#define STK_INT_CTRL_SHIFT  	7
+#define STK_INT_OUI_SHIFT  		4
+#define STK_INT_ALS_SHIFT  		3
+#define STK_INT_PS_SHIFT  		0
+
+#define STK_INT_CTRL_MASK		0x80
+#define STK_INT_OUI_MASK		0x10
+#define STK_INT_ALS_MASK		0x08
+#define STK_INT_PS_MASK			0x07
+
+#define STK_INT_ALS				0x08
+
+/* Define flag reg */
+#define STK_FLG_ALSDR_SHIFT  		7
+#define STK_FLG_PSDR_SHIFT  		6
+#define STK_FLG_ALSINT_SHIFT  		5
+#define STK_FLG_PSINT_SHIFT  		4
+#define STK_FLG_OUI_SHIFT  			2
+#define STK_FLG_IR_RDY_SHIFT  		1
+#define STK_FLG_NF_SHIFT  			0
+
+#define STK_FLG_ALSDR_MASK		0x80
+#define STK_FLG_PSDR_MASK		0x40
+#define STK_FLG_ALSINT_MASK		0x20
+#define STK_FLG_PSINT_MASK		0x10
+#define STK_FLG_OUI_MASK		0x04
+#define STK_FLG_IR_RDY_MASK		0x02
+#define STK_FLG_NF_MASK			0x01
+
+/* misc define */
+#define MIN_ALS_POLL_DELAY_NS	110000000
+
+#define DEVICE_NAME		"stk_ps"
+#define ALS_NAME "lightsensor-level"
+#define PS_NAME "proximity"
+
+struct stk3x1x_data {
+	struct i2c_client *client;
+#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
+    int32_t irq;
+    struct work_struct stk_work;
+	struct workqueue_struct *stk_wq;
+#endif
+	int		int_pin;
+	uint8_t wait_reg;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	struct early_suspend stk_early_suspend;
+#endif
+	uint16_t ps_thd_h;
+	uint16_t ps_thd_l;
+	struct mutex io_lock;
+	struct input_dev *ps_input_dev;
+	int32_t ps_distance_last;
+	bool ps_enabled;
+	struct wake_lock ps_wakelock;
+    struct work_struct stk_ps_work;
+	struct workqueue_struct *stk_ps_wq;
+#ifdef STK_POLL_PS
+	struct wake_lock ps_nosuspend_wl;
+#endif
+	struct input_dev *als_input_dev;
+	int32_t als_lux_last;
+	uint32_t als_transmittance;
+	bool als_enabled;
+	struct hrtimer als_timer;
+	struct hrtimer ps_timer;
+	ktime_t als_poll_delay;
+	ktime_t ps_poll_delay;
+#ifdef STK_POLL_ALS
+    struct work_struct stk_als_work;
+	struct workqueue_struct *stk_als_wq;
+#endif
+};
+
+#if( !defined(CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD))
+static uint32_t lux_threshold_table[] =
+{
+	3,
+	10,
+	40,
+	65,
+	145,
+	300,
+	550,
+	930,
+	1250,
+	1700,
+};
+
+#define LUX_THD_TABLE_SIZE (sizeof(lux_threshold_table)/sizeof(uint32_t)+1)
+static uint16_t code_threshold_table[LUX_THD_TABLE_SIZE+1];
+#endif
+
+static int32_t stk3x1x_enable_ps(struct stk3x1x_data *ps_data, uint8_t enable);
+static int32_t stk3x1x_enable_als(struct stk3x1x_data *ps_data, uint8_t enable);
+static int32_t stk3x1x_set_ps_thd_l(struct stk3x1x_data *ps_data, uint16_t thd_l);
+static int32_t stk3x1x_set_ps_thd_h(struct stk3x1x_data *ps_data, uint16_t thd_h);
+static int32_t stk3x1x_set_als_thd_l(struct stk3x1x_data *ps_data, uint16_t thd_l);
+static int32_t stk3x1x_set_als_thd_h(struct stk3x1x_data *ps_data, uint16_t thd_h);
+//static int32_t stk3x1x_set_ps_aoffset(struct stk3x1x_data *ps_data, uint16_t offset);
+
+inline uint32_t stk_alscode2lux(struct stk3x1x_data *ps_data, uint32_t alscode)
+{
+	alscode += ((alscode<<7)+(alscode<<3)+(alscode>>1));
+    alscode<<=3;
+    alscode/=ps_data->als_transmittance;
+	return alscode;
+}
+
+inline uint32_t stk_lux2alscode(struct stk3x1x_data *ps_data, uint32_t lux)
+{
+    lux*=ps_data->als_transmittance;
+    lux/=1100;
+    if (unlikely(lux>=(1<<16)))
+        lux = (1<<16) -1;
+    return lux;
+}
+
+#ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
+static void stk_init_code_threshold_table(struct stk3x1x_data *ps_data)
+{
+    uint32_t i,j;
+    uint32_t alscode;
+
+    code_threshold_table[0] = 0;
+#ifdef STK_DEBUG_PRINTF
+    printk(KERN_INFO "alscode[0]=%d\n",0);
+#endif
+    for (i=1,j=0;i<LUX_THD_TABLE_SIZE;i++,j++)
+    {
+        alscode = stk_lux2alscode(ps_data, lux_threshold_table[j]);
+        printk(KERN_INFO "alscode[%d]=%d\n",i,alscode);
+        code_threshold_table[i] = (uint16_t)(alscode);
+    }
+    code_threshold_table[i] = 0xffff;
+    printk(KERN_INFO "alscode[%d]=%d\n",i,alscode);
+}
+
+static uint32_t stk_get_lux_interval_index(uint16_t alscode)
+{
+    uint32_t i;
+    for (i=1;i<=LUX_THD_TABLE_SIZE;i++)
+    {
+        if ((alscode>=code_threshold_table[i-1])&&(alscode<code_threshold_table[i]))
+        {
+            return i;
+        }
+    }
+    return LUX_THD_TABLE_SIZE;
+}
+#else
+inline void stk_als_set_new_thd(struct stk3x1x_data *ps_data, uint16_t alscode)
+{
+    int32_t high_thd,low_thd;
+    high_thd = alscode + stk_lux2alscode(ps_data, STK_ALS_CHANGE_THD);
+    low_thd = alscode - stk_lux2alscode(ps_data, STK_ALS_CHANGE_THD);
+    if (high_thd >= (1<<16))
+        high_thd = (1<<16) -1;
+    if (low_thd <0)
+        low_thd = 0;
+    stk3x1x_set_als_thd_h(ps_data, (uint16_t)high_thd);
+    stk3x1x_set_als_thd_l(ps_data, (uint16_t)low_thd);
+}
+#endif // CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
+
+
+static int32_t stk3x1x_init_all_reg(struct stk3x1x_data *ps_data, struct stk3x1x_platform_data *plat_data)
+{
+	int32_t ret;
+	uint8_t w_reg;
+
+	w_reg = plat_data->state_reg;
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, w_reg);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+        return ret;
+    }
+
+	ps_data->ps_thd_h = plat_data->ps_thd_h;
+	ps_data->ps_thd_l = plat_data->ps_thd_l;
+
+	w_reg = plat_data->psctrl_reg;
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_PSCTRL_REG, w_reg);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+        return ret;
+    }
+	w_reg = plat_data->alsctrl_reg;
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_ALSCTRL_REG, w_reg);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+        return ret;
+    }
+	w_reg = plat_data->ledctrl_reg;
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_LEDCTRL_REG, w_reg);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+        return ret;
+    }
+	ps_data->wait_reg = plat_data->wait_reg;
+
+	if(ps_data->wait_reg < 2)
+	{
+		printk(KERN_WARNING "%s: wait_reg should be larger than 2, force to write 2\n", __func__);
+		ps_data->wait_reg = 2;
+	}
+	else if (ps_data->wait_reg > 0xFF)
+	{
+		printk(KERN_WARNING "%s: wait_reg should be less than 0xFF, force to write 0xFF\n", __func__);
+		ps_data->wait_reg = 0xFF;
+	}
+	w_reg = plat_data->wait_reg;
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_WAIT_REG, w_reg);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+        return ret;
+    }
+	stk3x1x_set_ps_thd_h(ps_data, ps_data->ps_thd_h);
+	stk3x1x_set_ps_thd_l(ps_data, ps_data->ps_thd_l);
+
+	w_reg = 0;
+#ifndef STK_POLL_PS
+	w_reg |= STK_INT_PS_MODE;
+#else
+	w_reg |= 0x01;
+#endif
+
+#if (!defined(STK_POLL_ALS) && (STK_INT_PS_MODE != 0x02) && (STK_INT_PS_MODE != 0x03))
+	w_reg |= STK_INT_ALS;
+#endif
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_INT_REG, w_reg);
+    if (ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+	}
+	return 0;
+}
+
+static int32_t stk3x1x_check_pid(struct stk3x1x_data *ps_data)
+{
+	int32_t err1, err2;
+
+	err1 = i2c_smbus_read_byte_data(ps_data->client,STK_PDT_ID_REG);
+	if (err1 < 0)
+	{
+		printk(KERN_ERR "%s: read i2c error, err=%d\n", __func__, err1);
+		return err1;
+	}
+
+    err2 = i2c_smbus_read_byte_data(ps_data->client,STK_RSRVD_REG);
+    if (err2 < 0)
+    {
+        printk(KERN_ERR "%s: read i2c error, err=%d\n", __func__, err2);
+        return -1;
+    }
+	printk(KERN_INFO "%s: PID=0x%x, RID=0x%x\n", __func__, err1, err2);
+	if(err2 == 0xC0)
+		printk(KERN_INFO "%s: RID=0xC0!!!!!!!!!!!!!\n", __func__);
+
+	return 0;
+}
+
+
+static int32_t stk3x1x_software_reset(struct stk3x1x_data *ps_data)
+{
+    int32_t r;
+    uint8_t w_reg;
+
+    w_reg = 0x7F;
+    r = i2c_smbus_write_byte_data(ps_data->client,STK_WAIT_REG,w_reg);
+    if (r<0)
+    {
+        printk(KERN_ERR "%s: software reset: write i2c error, ret=%d\n", __func__, r);
+        return r;
+    }
+    r = i2c_smbus_read_byte_data(ps_data->client,STK_WAIT_REG);
+    if (w_reg != r)
+    {
+        printk(KERN_ERR "%s: software reset: read-back value is not the same\n", __func__);
+        return -1;
+    }
+
+    r = i2c_smbus_write_byte_data(ps_data->client,STK_SW_RESET_REG,0);
+    if (r<0)
+    {
+        printk(KERN_ERR "%s: software reset: read error after reset\n", __func__);
+        return r;
+    }
+    msleep(1);
+    return 0;
+}
+
+
+static int32_t stk3x1x_set_als_thd_l(struct stk3x1x_data *ps_data, uint16_t thd_l)
+{
+    uint8_t temp;
+    uint8_t* pSrc = (uint8_t*)&thd_l;
+    temp = *pSrc;
+    *pSrc = *(pSrc+1);
+    *(pSrc+1) = temp;
+    return i2c_smbus_write_word_data(ps_data->client,STK_THDL1_ALS_REG,thd_l);
+}
+static int32_t stk3x1x_set_als_thd_h(struct stk3x1x_data *ps_data, uint16_t thd_h)
+{
+	uint8_t temp;
+    uint8_t* pSrc = (uint8_t*)&thd_h;
+    temp = *pSrc;
+    *pSrc = *(pSrc+1);
+    *(pSrc+1) = temp;
+    return i2c_smbus_write_word_data(ps_data->client,STK_THDH1_ALS_REG,thd_h);
+}
+
+static int32_t stk3x1x_set_ps_thd_l(struct stk3x1x_data *ps_data, uint16_t thd_l)
+{
+    uint8_t temp;
+    uint8_t* pSrc = (uint8_t*)&thd_l;
+
+    temp = *pSrc;
+    *pSrc = *(pSrc+1);
+    *(pSrc+1) = temp;
+    ps_data->ps_thd_l = thd_l;
+	return i2c_smbus_write_word_data(ps_data->client,STK_THDL1_PS_REG,thd_l);
+}
+
+static int32_t stk3x1x_set_ps_thd_h(struct stk3x1x_data *ps_data, uint16_t thd_h)
+{
+    uint8_t temp;
+    uint8_t* pSrc = (uint8_t*)&thd_h;
+
+    temp = *pSrc;
+    *pSrc = *(pSrc+1);
+    *(pSrc+1) = temp;
+    ps_data->ps_thd_h = thd_h;
+	return i2c_smbus_write_word_data(ps_data->client,STK_THDH1_PS_REG,thd_h);
+}
+
+/*
+static int32_t stk3x1x_set_ps_foffset(struct stk3x1x_data *ps_data, uint16_t offset)
+{
+	uint8_t temp;
+    uint8_t* pSrc = (uint8_t*)&offset;
+    temp = *pSrc;
+    *pSrc = *(pSrc+1);
+    *(pSrc+1) = temp;
+    return i2c_smbus_write_word_data(ps_data->client,STK_DATA1_OFFSET_REG,offset);
+}
+
+static int32_t stk3x1x_set_ps_aoffset(struct stk3x1x_data *ps_data, uint16_t offset)
+{
+	uint8_t temp;
+    uint8_t* pSrc = (uint8_t*)&offset;
+	int ret;
+	uint8_t w_state_reg;
+	uint8_t re_en;
+
+	ret = i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG);
+	if (ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+	}
+	re_en = (ret & STK_STATE_EN_AK_MASK) ? 1: 0;
+	if(re_en)
+	{
+		w_state_reg = (uint8_t)(ret & (~STK_STATE_EN_AK_MASK));
+		ret = i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, w_state_reg);
+		if (ret < 0)
+		{
+			printk(KERN_ERR "%s: write i2c error\n", __func__);
+			return ret;
+		}
+		msleep(1);
+	}
+    temp = *pSrc;
+    *pSrc = *(pSrc+1);
+    *(pSrc+1) = temp;
+	ret = i2c_smbus_write_word_data(ps_data->client,0x0E,offset);
+	if(!re_en)
+		return ret;
+
+	w_state_reg |= STK_STATE_EN_AK_MASK;
+	ret = i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, w_state_reg);
+	if (ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+*/
+
+static inline uint32_t stk3x1x_get_ps_reading(struct stk3x1x_data *ps_data)
+{
+	int32_t word_data, tmp_word_data;
+
+	tmp_word_data = i2c_smbus_read_word_data(ps_data->client,STK_DATA1_PS_REG);
+	if(tmp_word_data < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, tmp_word_data);
+		return tmp_word_data;
+	}
+	word_data = ((tmp_word_data & 0xFF00) >> 8) | ((tmp_word_data & 0x00FF) << 8) ;
+	return word_data;
+}
+
+static int32_t stk3x1x_set_flag(struct stk3x1x_data *ps_data, uint8_t org_flag_reg, uint8_t clr)
+{
+	uint8_t w_flag;
+	w_flag = org_flag_reg | (STK_FLG_ALSINT_MASK | STK_FLG_PSINT_MASK | STK_FLG_OUI_MASK | STK_FLG_IR_RDY_MASK);
+	w_flag &= (~clr);
+	//printk(KERN_INFO "%s: org_flag_reg=0x%x, w_flag = 0x%x\n", __func__, org_flag_reg, w_flag);
+    return i2c_smbus_write_byte_data(ps_data->client,STK_FLAG_REG, w_flag);
+}
+
+static int32_t stk3x1x_get_flag(struct stk3x1x_data *ps_data)
+{
+    return i2c_smbus_read_byte_data(ps_data->client,STK_FLAG_REG);
+}
+
+static int32_t stk3x1x_enable_ps(struct stk3x1x_data *ps_data, uint8_t enable)
+{
+    int32_t ret;
+	uint8_t w_state_reg;
+	uint8_t curr_ps_enable;
+	curr_ps_enable = ps_data->ps_enabled?1:0;
+	if(curr_ps_enable == enable)
+		return 0;
+
+    ret = i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG);
+    if (ret < 0)
+    {
+			printk(KERN_ERR "%s: write i2c error, ret=%d\n", __func__, ret);
+		return ret;
+    }
+	w_state_reg = ret;
+	w_state_reg &= ~(STK_STATE_EN_PS_MASK | STK_STATE_EN_WAIT_MASK | 0x60);
+	if(enable)
+	{
+		w_state_reg |= STK_STATE_EN_PS_MASK;
+		if(!(ps_data->als_enabled))
+			w_state_reg |= STK_STATE_EN_WAIT_MASK;
+	}
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, w_state_reg);
+    if (ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error, ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+    if(enable)
+	{
+#ifdef STK_POLL_PS
+		hrtimer_start(&ps_data->ps_timer, ps_data->ps_poll_delay, HRTIMER_MODE_REL);
+		ps_data->ps_distance_last = -1;
+#endif
+		ps_data->ps_enabled = true;
+#ifndef STK_POLL_PS
+#ifndef STK_POLL_ALS
+		if(!(ps_data->als_enabled))
+#endif	/* #ifndef STK_POLL_ALS	*/
+			enable_irq(ps_data->irq);
+		msleep(1);
+		ret = stk3x1x_get_flag(ps_data);
+		if (ret < 0)
+		{
+			printk(KERN_ERR "%s: read i2c error, ret=%d\n", __func__, ret);
+			return ret;
+		}
+
+		near_far_state = ret & STK_FLG_NF_MASK;
+		ps_data->ps_distance_last = near_far_state;
+		input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, near_far_state);
+		input_sync(ps_data->ps_input_dev);
+		wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
+		reading = stk3x1x_get_ps_reading(ps_data);
+		printk(KERN_INFO "%s: ps input event=%d, ps code = %d\n",__func__, near_far_state, reading);
+#endif	/* #ifndef STK_POLL_PS */
+	}
+	else
+	{
+#ifdef STK_POLL_PS
+		hrtimer_cancel(&ps_data->ps_timer);
+#else
+#ifndef STK_POLL_ALS
+		if(!(ps_data->als_enabled))
+#endif
+			disable_irq(ps_data->irq);
+#endif
+		ps_data->ps_enabled = false;
+	}
+	return ret;
+}
+
+static int32_t stk3x1x_enable_als(struct stk3x1x_data *ps_data, uint8_t enable)
+{
+    int32_t ret;
+	uint8_t w_state_reg;
+	uint8_t curr_als_enable = (ps_data->als_enabled)?1:0;
+
+	if(curr_als_enable == enable)
+		return 0;
+
+#ifndef STK_POLL_ALS
+    if (enable)
+	{
+        stk3x1x_set_als_thd_h(ps_data, 0x0000);
+        stk3x1x_set_als_thd_l(ps_data, 0xFFFF);
+	}
+#endif
+    ret = i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+    }
+	w_state_reg = (uint8_t)(ret & (~(STK_STATE_EN_ALS_MASK | STK_STATE_EN_WAIT_MASK)));
+	if(enable)
+		w_state_reg |= STK_STATE_EN_ALS_MASK;
+	else if (ps_data->ps_enabled)
+		w_state_reg |= STK_STATE_EN_WAIT_MASK;
+
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, w_state_reg);
+    if (ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+	}
+
+    if (enable)
+    {
+		ps_data->als_enabled = true;
+#ifdef STK_POLL_ALS
+		hrtimer_start(&ps_data->als_timer, ps_data->als_poll_delay, HRTIMER_MODE_REL);
+#else
+#ifndef STK_POLL_PS
+		if(!(ps_data->ps_enabled))
+#endif
+			enable_irq(ps_data->irq);
+#endif
+    }
+	else
+	{
+		ps_data->als_enabled = false;
+#ifdef STK_POLL_ALS
+		hrtimer_cancel(&ps_data->als_timer);
+#else
+#ifndef STK_POLL_PS
+		if(!(ps_data->ps_enabled))
+#endif
+			disable_irq(ps_data->irq);
+#endif
+	}
+    return ret;
+}
+
+static inline int32_t stk3x1x_get_als_reading(struct stk3x1x_data *ps_data)
+{
+    int32_t word_data, tmp_word_data;
+	tmp_word_data = i2c_smbus_read_word_data(ps_data->client, STK_DATA1_ALS_REG);
+	if(tmp_word_data < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, tmp_word_data);
+		return tmp_word_data;
+	}
+	word_data = ((tmp_word_data & 0xFF00) >> 8) | ((tmp_word_data & 0x00FF) << 8) ;
+	return word_data;
+}
+
+static int32_t stk3x1x_get_ir_reading(struct stk3x1x_data *ps_data)
+{
+    int32_t word_data, tmp_word_data;
+	int32_t ret;
+	uint8_t w_reg, retry = 0;
+
+	if(ps_data->ps_enabled)
+	{
+		stk3x1x_enable_ps(ps_data, 0);
+		ps_data->ps_enabled = true;
+	}
+    ret = i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+    }
+	w_reg = (uint8_t)(ret & (~STK_STATE_EN_IRS_MASK));
+	w_reg |= STK_STATE_EN_IRS_MASK;
+
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, w_reg);
+    if (ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+	}
+	msleep(100);
+
+	do
+	{
+		msleep(50);
+		ret = stk3x1x_get_flag(ps_data);
+		if (ret < 0)
+		{
+			printk(KERN_ERR "%s: write i2c error\n", __func__);
+			return ret;
+		}
+		retry++;
+	}while(retry < 5 && ((ret&STK_FLG_IR_RDY_MASK) == 0));
+
+	if(retry == 5)
+	{
+		printk(KERN_ERR "%s: ir data is not ready for 300ms\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = stk3x1x_get_flag(ps_data);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+    }
+
+	ret = stk3x1x_set_flag(ps_data, ret, STK_FLG_IR_RDY_MASK);
+    if (ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+	}
+
+	tmp_word_data = i2c_smbus_read_word_data(ps_data->client, STK_DATA1_IR_REG);
+	if(tmp_word_data < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, tmp_word_data);
+		return tmp_word_data;
+	}
+	word_data = ((tmp_word_data & 0xFF00) >> 8) | ((tmp_word_data & 0x00FF) << 8) ;
+
+	if(ps_data->ps_enabled)
+		stk3x1x_enable_ps(ps_data, 1);
+	return word_data;
+}
+
+
+static ssize_t stk_als_code_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    int32_t reading;
+
+    reading = stk3x1x_get_als_reading(ps_data);
+    return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
+}
+
+
+static ssize_t stk_als_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    int32_t enable, ret;
+
+    mutex_lock(&ps_data->io_lock);
+	enable = (ps_data->als_enabled)?1:0;
+    mutex_unlock(&ps_data->io_lock);
+    ret = i2c_smbus_read_byte_data(ps_data->client,STK_STATE_REG);
+    ret = (ret & STK_STATE_EN_ALS_MASK)?1:0;
+
+	if(enable != ret)
+		printk(KERN_ERR "%s: driver and sensor mismatch! driver_enable=0x%x, sensor_enable=%x\n", __func__, enable, ret);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+
+static ssize_t stk_als_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data = dev_get_drvdata(dev);
+	uint8_t en;
+	if (sysfs_streq(buf, "1"))
+		en = 1;
+	else if (sysfs_streq(buf, "0"))
+		en = 0;
+	else
+	{
+		printk(KERN_ERR "%s, invalid value %d\n", __func__, *buf);
+		return -EINVAL;
+	}
+    printk(KERN_INFO "%s: Enable ALS : %d\n", __func__, en);
+    mutex_lock(&ps_data->io_lock);
+    stk3x1x_enable_als(ps_data, en);
+    mutex_unlock(&ps_data->io_lock);
+    return size;
+}
+
+static ssize_t stk_als_lux_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data = dev_get_drvdata(dev);
+    int32_t als_reading;
+	uint32_t als_lux;
+    als_reading = stk3x1x_get_als_reading(ps_data);
+	mutex_lock(&ps_data->io_lock);
+	als_lux = stk_alscode2lux(ps_data, als_reading);
+	mutex_unlock(&ps_data->io_lock);
+    return scnprintf(buf, PAGE_SIZE, "%d lux\n", als_lux);
+}
+
+static ssize_t stk_als_lux_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+	ret = strict_strtoul(buf, 16, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+    mutex_lock(&ps_data->io_lock);
+    ps_data->als_lux_last = value;
+	input_report_abs(ps_data->als_input_dev, ABS_MISC, value);
+	input_sync(ps_data->als_input_dev);
+	mutex_unlock(&ps_data->io_lock);
+	printk(KERN_INFO "%s: als input event %ld lux\n",__func__, value);
+
+    return size;
+}
+
+
+static ssize_t stk_als_transmittance_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    int32_t transmittance;
+    mutex_lock(&ps_data->io_lock);
+    transmittance = ps_data->als_transmittance;
+    mutex_unlock(&ps_data->io_lock);
+    return scnprintf(buf, PAGE_SIZE, "%d\n", transmittance);
+}
+
+
+static ssize_t stk_als_transmittance_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+	ret = strict_strtoul(buf, 10, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+	mutex_lock(&ps_data->io_lock);
+    ps_data->als_transmittance = value;
+    mutex_unlock(&ps_data->io_lock);
+    return size;
+}
+
+static ssize_t stk_als_delay_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%lld\n", ktime_to_ns(ps_data->als_poll_delay));
+}
+
+
+static ssize_t stk_als_delay_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+    uint64_t value = 0;
+	int ret;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	ret = strict_strtoull(buf, 10, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoull failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+#ifdef STK_DEBUG_PRINTF
+	printk(KERN_INFO "%s: set als poll delay=%lld\n", __func__, value);
+#endif
+	if(value < MIN_ALS_POLL_DELAY_NS)
+	{
+		printk(KERN_ERR "%s: delay is too small\n", __func__);
+		value = MIN_ALS_POLL_DELAY_NS;
+	}
+	mutex_lock(&ps_data->io_lock);
+	if(value != ktime_to_ns(ps_data->als_poll_delay))
+		ps_data->als_poll_delay = ns_to_ktime(value);
+	mutex_unlock(&ps_data->io_lock);
+	return size;
+}
+
+static ssize_t stk_als_ir_code_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    int32_t reading;
+    reading = stk3x1x_get_ir_reading(ps_data);
+    return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
+}
+
+static ssize_t stk_ps_code_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    uint32_t reading;
+    reading = stk3x1x_get_ps_reading(ps_data);
+    return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
+}
+
+static ssize_t stk_ps_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    int32_t enable, ret;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+
+    mutex_lock(&ps_data->io_lock);
+	enable = (ps_data->ps_enabled)?1:0;
+    mutex_unlock(&ps_data->io_lock);
+    ret = i2c_smbus_read_byte_data(ps_data->client,STK_STATE_REG);
+    ret = (ret & STK_STATE_EN_PS_MASK)?1:0;
+
+	if(enable != ret)
+		printk(KERN_ERR "%s: driver and sensor mismatch! driver_enable=0x%x, sensor_enable=%x\n", __func__, enable, ret);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+
+static ssize_t stk_ps_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	uint8_t en;
+	if (sysfs_streq(buf, "1"))
+		en = 1;
+	else if (sysfs_streq(buf, "0"))
+		en = 0;
+	else
+	{
+		printk(KERN_ERR "%s, invalid value %d\n", __func__, *buf);
+		return -EINVAL;
+	}
+    printk(KERN_INFO "%s: Enable PS : %d\n", __func__, en);
+    mutex_lock(&ps_data->io_lock);
+    stk3x1x_enable_ps(ps_data, en);
+    mutex_unlock(&ps_data->io_lock);
+    return size;
+}
+
+static ssize_t stk_ps_enable_aso_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    int32_t ret;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+
+    ret = i2c_smbus_read_byte_data(ps_data->client,STK_STATE_REG);
+    ret = (ret & STK_STATE_EN_ASO_MASK)?1:0;
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+
+static ssize_t stk_ps_enable_aso_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	uint8_t en;
+    int32_t ret;
+	uint8_t w_state_reg;
+
+	if (sysfs_streq(buf, "1"))
+		en = 1;
+	else if (sysfs_streq(buf, "0"))
+		en = 0;
+	else
+	{
+		printk(KERN_ERR "%s, invalid value %d\n", __func__, *buf);
+		return -EINVAL;
+	}
+    printk(KERN_INFO "%s: Enable PS ASO : %d\n", __func__, en);
+
+    ret = i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG);
+    if (ret < 0)
+    {
+        printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+    }
+	w_state_reg = (uint8_t)(ret & (~STK_STATE_EN_ASO_MASK));
+	if(en)
+		w_state_reg |= STK_STATE_EN_ASO_MASK;
+
+    ret = i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, w_state_reg);
+    if (ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+	}
+
+	return size;
+}
+
+
+static ssize_t stk_ps_offset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    int32_t word_data, tmp_word_data;
+
+	tmp_word_data = i2c_smbus_read_word_data(ps_data->client, STK_DATA1_OFFSET_REG);
+	if(tmp_word_data < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, tmp_word_data);
+		return tmp_word_data;
+	}
+		word_data = ((tmp_word_data & 0xFF00) >> 8) | ((tmp_word_data & 0x00FF) << 8) ;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", word_data);
+}
+
+static ssize_t stk_ps_offset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+	uint16_t offset;
+
+	ret = strict_strtoul(buf, 10, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+	if(value > 65535)
+	{
+		printk(KERN_ERR "%s: invalid value, offset=%ld\n", __func__, value);
+		return -EINVAL;
+	}
+
+	offset = (uint16_t) ((value&0x00FF) << 8) | ((value&0xFF00) >>8);
+	ret = i2c_smbus_write_word_data(ps_data->client,STK_DATA1_OFFSET_REG,offset);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s: write i2c error\n", __func__);
+		return ret;
+	}
+	return size;
+}
+
+
+static ssize_t stk_ps_distance_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    int32_t dist=1, ret;
+
+    mutex_lock(&ps_data->io_lock);
+    ret = stk3x1x_get_flag(ps_data);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s: stk3x1x_get_flag failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+    dist = (ret & STK_FLG_NF_MASK)?1:0;
+
+    ps_data->ps_distance_last = dist;
+	input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, dist);
+	input_sync(ps_data->ps_input_dev);
+    mutex_unlock(&ps_data->io_lock);
+	wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
+	printk(KERN_INFO "%s: ps input event %d cm\n",__func__, dist);
+    return scnprintf(buf, PAGE_SIZE, "%d\n", dist);
+}
+
+
+static ssize_t stk_ps_distance_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+	ret = strict_strtoul(buf, 10, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+    mutex_lock(&ps_data->io_lock);
+    ps_data->ps_distance_last = value;
+	input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, value);
+	input_sync(ps_data->ps_input_dev);
+    mutex_unlock(&ps_data->io_lock);
+	wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
+	printk(KERN_INFO "%s: ps input event %ld cm\n",__func__, value);
+    return size;
+}
+
+
+static ssize_t stk_ps_code_thd_l_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    int32_t ps_thd_l1_reg, ps_thd_l2_reg;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    mutex_lock(&ps_data->io_lock);
+    ps_thd_l1_reg = i2c_smbus_read_byte_data(ps_data->client,STK_THDL1_PS_REG);
+    if(ps_thd_l1_reg < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, ps_thd_l1_reg);
+		return -EINVAL;
+	}
+    ps_thd_l2_reg = i2c_smbus_read_byte_data(ps_data->client,STK_THDL2_PS_REG);
+    if(ps_thd_l2_reg < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, ps_thd_l2_reg);
+		return -EINVAL;
+	}
+    mutex_unlock(&ps_data->io_lock);
+	ps_thd_l1_reg = ps_thd_l1_reg<<8 | ps_thd_l2_reg;
+    return scnprintf(buf, PAGE_SIZE, "%d\n", ps_thd_l1_reg);
+}
+
+
+static ssize_t stk_ps_code_thd_l_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+	ret = strict_strtoul(buf, 10, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+    mutex_lock(&ps_data->io_lock);
+    stk3x1x_set_ps_thd_l(ps_data, value);
+    mutex_unlock(&ps_data->io_lock);
+    return size;
+}
+
+static ssize_t stk_ps_code_thd_h_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    int32_t ps_thd_h1_reg, ps_thd_h2_reg;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    mutex_lock(&ps_data->io_lock);
+    ps_thd_h1_reg = i2c_smbus_read_byte_data(ps_data->client,STK_THDH1_PS_REG);
+    if(ps_thd_h1_reg < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, ps_thd_h1_reg);
+		return -EINVAL;
+	}
+    ps_thd_h2_reg = i2c_smbus_read_byte_data(ps_data->client,STK_THDH2_PS_REG);
+    if(ps_thd_h2_reg < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, ps_thd_h2_reg);
+		return -EINVAL;
+	}
+    mutex_unlock(&ps_data->io_lock);
+	ps_thd_h1_reg = ps_thd_h1_reg<<8 | ps_thd_h2_reg;
+    return scnprintf(buf, PAGE_SIZE, "%d\n", ps_thd_h1_reg);
+}
+
+
+static ssize_t stk_ps_code_thd_h_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+	ret = strict_strtoul(buf, 10, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+    mutex_lock(&ps_data->io_lock);
+    stk3x1x_set_ps_thd_h(ps_data, value);
+    mutex_unlock(&ps_data->io_lock);
+    return size;
+}
+
+#if 0
+static ssize_t stk_als_lux_thd_l_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    int32_t als_thd_l0_reg,als_thd_l1_reg;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	uint32_t als_lux;
+
+    mutex_lock(&ps_data->io_lock);
+    als_thd_l0_reg = i2c_smbus_read_byte_data(ps_data->client,STK_THDL1_ALS_REG);
+    als_thd_l1_reg = i2c_smbus_read_byte_data(ps_data->client,STK_THDL2_ALS_REG);
+    if(als_thd_l0_reg < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, als_thd_l0_reg);
+		return -EINVAL;
+	}
+	if(als_thd_l1_reg < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, als_thd_l1_reg);
+		return -EINVAL;
+	}
+    als_thd_l0_reg|=(als_thd_l1_reg<<8);
+	als_lux = stk_alscode2lux(ps_data, als_thd_l0_reg);
+	mutex_unlock(&ps_data->io_lock);
+    return scnprintf(buf, PAGE_SIZE, "%d\n", als_lux);
+}
+
+
+static ssize_t stk_als_lux_thd_l_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+	ret = strict_strtoul(buf, 10, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+    mutex_lock(&ps_data->io_lock);
+	value = stk_lux2alscode(ps_data, value);
+    stk3x1x_set_als_thd_l(ps_data, value);
+    mutex_unlock(&ps_data->io_lock);
+    return size;
+}
+
+static ssize_t stk_als_lux_thd_h_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    int32_t als_thd_h0_reg,als_thd_h1_reg;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	uint32_t als_lux;
+
+    mutex_lock(&ps_data->io_lock);
+    als_thd_h0_reg = i2c_smbus_read_byte_data(ps_data->client,STK_THDH1_ALS_REG);
+    als_thd_h1_reg = i2c_smbus_read_byte_data(ps_data->client,STK_THDH2_ALS_REG);
+    if(als_thd_h0_reg < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, als_thd_h0_reg);
+		return -EINVAL;
+	}
+	if(als_thd_h1_reg < 0)
+	{
+		printk(KERN_ERR "%s fail, err=0x%x", __func__, als_thd_h1_reg);
+		return -EINVAL;
+	}
+    als_thd_h0_reg|=(als_thd_h1_reg<<8);
+	als_lux = stk_alscode2lux(ps_data, als_thd_h0_reg);
+	mutex_unlock(&ps_data->io_lock);
+    return scnprintf(buf, PAGE_SIZE, "%d\n", als_lux);
+}
+
+
+static ssize_t stk_als_lux_thd_h_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+	ret = strict_strtoul(buf, 10, &value);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+	mutex_lock(&ps_data->io_lock);
+    value = stk_lux2alscode(ps_data, value);
+    stk3x1x_set_als_thd_h(ps_data, value);
+    mutex_unlock(&ps_data->io_lock);
+    return size;
+}
+#endif
+
+
+static ssize_t stk_all_reg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    int32_t ps_reg[27];
+	uint8_t cnt;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+    mutex_lock(&ps_data->io_lock);
+	for(cnt=0;cnt<25;cnt++)
+	{
+		ps_reg[cnt] = i2c_smbus_read_byte_data(ps_data->client, (cnt));
+		if(ps_reg[cnt] < 0)
+		{
+			mutex_unlock(&ps_data->io_lock);
+			printk(KERN_ERR "stk_all_reg_show:i2c_smbus_read_byte_data fail, ret=%d", ps_reg[cnt]);
+			return -EINVAL;
+		}
+		else
+		{
+			printk(KERN_INFO "reg[0x%2X]=0x%2X\n", cnt, ps_reg[cnt]);
+		}
+	}
+	ps_reg[cnt] = i2c_smbus_read_byte_data(ps_data->client, STK_PDT_ID_REG);
+	if(ps_reg[cnt] < 0)
+	{
+		mutex_unlock(&ps_data->io_lock);
+		printk( KERN_ERR "all_reg_show:i2c_smbus_read_byte_data fail, ret=%d", ps_reg[cnt]);
+		return -EINVAL;
+	}
+	printk( KERN_INFO "reg[0x%x]=0x%2X\n", STK_PDT_ID_REG, ps_reg[cnt]);
+	cnt++;
+	ps_reg[cnt] = i2c_smbus_read_byte_data(ps_data->client, STK_RSRVD_REG);
+	if(ps_reg[cnt] < 0)
+	{
+		mutex_unlock(&ps_data->io_lock);
+		printk( KERN_ERR "all_reg_show:i2c_smbus_read_byte_data fail, ret=%d", ps_reg[cnt]);
+		return -EINVAL;
+	}
+	printk( KERN_INFO "reg[0x%x]=0x%2X\n", STK_RSRVD_REG, ps_reg[cnt]);
+    mutex_unlock(&ps_data->io_lock);
+
+    return scnprintf(buf, PAGE_SIZE, "%2X %2X %2X %2X %2X,%2X %2X %2X %2X %2X,%2X %2X %2X %2X %2X,%2X %2X %2X %2X %2X,%2X %2X %2X %2X %2X,%2X %2X\n",
+		ps_reg[0], ps_reg[1], ps_reg[2], ps_reg[3], ps_reg[4], ps_reg[5], ps_reg[6], ps_reg[7], ps_reg[8],
+		ps_reg[9], ps_reg[10], ps_reg[11], ps_reg[12], ps_reg[13], ps_reg[14], ps_reg[15], ps_reg[16], ps_reg[17],
+		ps_reg[18], ps_reg[19], ps_reg[20], ps_reg[21], ps_reg[22], ps_reg[23], ps_reg[24], ps_reg[25], ps_reg[26]);
+}
+
+static ssize_t stk_recv_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return 0;
+}
+
+
+static ssize_t stk_recv_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+    unsigned long value = 0;
+	int ret;
+	int32_t recv_data;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+
+	if((ret = strict_strtoul(buf, 16, &value)) < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+	recv_data = i2c_smbus_read_byte_data(ps_data->client,value);
+	printk("%s: reg 0x%x=0x%x\n", __func__, (int)value, recv_data);
+	return size;
+}
+
+
+static ssize_t stk_send_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return 0;
+}
+
+
+static ssize_t stk_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+	int addr, cmd;
+	u8 addr_u8, cmd_u8;
+	int32_t ret, i;
+	char *token[10];
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+
+	for (i = 0; i < 2; i++)
+		token[i] = strsep((char **)&buf, " ");
+	if((ret = strict_strtoul(token[0], 16, (unsigned long *)&(addr))) < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+	if((ret = strict_strtoul(token[1], 16, (unsigned long *)&(cmd))) < 0)
+	{
+		printk(KERN_ERR "%s:strict_strtoul failed, ret=0x%x\n", __func__, ret);
+		return ret;
+	}
+	printk(KERN_INFO "%s: write reg 0x%x=0x%x\n", __func__, addr, cmd);
+
+	addr_u8 = (u8) addr;
+	cmd_u8 = (u8) cmd;
+	//mutex_lock(&ps_data->io_lock);
+	ret = i2c_smbus_write_byte_data(ps_data->client,addr_u8,cmd_u8);
+	//mutex_unlock(&ps_data->io_lock);
+	if (0 != ret)
+	{
+		printk(KERN_ERR "%s: i2c_smbus_write_byte_data fail\n", __func__);
+		return ret;
+	}
+
+	return size;
+}
+
+
+static struct device_attribute als_enable_attribute = __ATTR(enable,0664,stk_als_enable_show,stk_als_enable_store);
+static struct device_attribute als_lux_attribute = __ATTR(lux,0664,stk_als_lux_show,stk_als_lux_store);
+static struct device_attribute als_code_attribute = __ATTR(code, 0444, stk_als_code_show, NULL);
+static struct device_attribute als_transmittance_attribute = __ATTR(transmittance,0664,stk_als_transmittance_show,stk_als_transmittance_store);
+static struct device_attribute als_poll_delay_attribute = __ATTR(delay,0664,stk_als_delay_show,stk_als_delay_store);
+static struct device_attribute als_ir_code_attribute = __ATTR(ircode,0444,stk_als_ir_code_show,NULL);
+
+
+static struct attribute *stk_als_attrs [] =
+{
+	&als_enable_attribute.attr,
+    &als_lux_attribute.attr,
+    &als_code_attribute.attr,
+    &als_transmittance_attribute.attr,
+	&als_poll_delay_attribute.attr,
+	&als_ir_code_attribute.attr,
+    NULL
+};
+
+static struct attribute_group stk_als_attribute_group = {
+	.name = "driver",
+	.attrs = stk_als_attrs,
+};
+
+
+static struct device_attribute ps_enable_attribute = __ATTR(enable,0664,stk_ps_enable_show,stk_ps_enable_store);
+static struct device_attribute ps_enable_aso_attribute = __ATTR(enableaso,0664,stk_ps_enable_aso_show,stk_ps_enable_aso_store);
+static struct device_attribute ps_distance_attribute = __ATTR(distance,0664,stk_ps_distance_show, stk_ps_distance_store);
+static struct device_attribute ps_offset_attribute = __ATTR(offset,0664,stk_ps_offset_show, stk_ps_offset_store);
+static struct device_attribute ps_code_attribute = __ATTR(code, 0444, stk_ps_code_show, NULL);
+static struct device_attribute ps_code_thd_l_attribute = __ATTR(codethdl,0664,stk_ps_code_thd_l_show,stk_ps_code_thd_l_store);
+static struct device_attribute ps_code_thd_h_attribute = __ATTR(codethdh,0664,stk_ps_code_thd_h_show,stk_ps_code_thd_h_store);
+static struct device_attribute recv_attribute = __ATTR(recv,0664,stk_recv_show,stk_recv_store);
+static struct device_attribute send_attribute = __ATTR(send,0664,stk_send_show, stk_send_store);
+static struct device_attribute all_reg_attribute = __ATTR(allreg, 0444, stk_all_reg_show, NULL);
+
+static struct attribute *stk_ps_attrs [] =
+{
+    &ps_enable_attribute.attr,
+    &ps_enable_aso_attribute.attr,
+    &ps_distance_attribute.attr,
+	&ps_offset_attribute.attr,
+    &ps_code_attribute.attr,
+	&ps_code_thd_l_attribute.attr,
+	&ps_code_thd_h_attribute.attr,
+	&recv_attribute.attr,
+	&send_attribute.attr,
+	&all_reg_attribute.attr,
+    NULL
+};
+
+static struct attribute_group stk_ps_attribute_group = {
+	.name = "driver",
+	.attrs = stk_ps_attrs,
+};
+
+#ifdef STK_POLL_ALS
+static enum hrtimer_restart stk_als_timer_func(struct hrtimer *timer)
+{
+	struct stk3x1x_data *ps_data = container_of(timer, struct stk3x1x_data, als_timer);
+	queue_work(ps_data->stk_als_wq, &ps_data->stk_als_work);
+	hrtimer_forward_now(&ps_data->als_timer, ps_data->als_poll_delay);
+	return HRTIMER_RESTART;
+}
+
+static void stk_als_work_func(struct work_struct *work)
+{
+	struct stk3x1x_data *ps_data = container_of(work, struct stk3x1x_data, stk_als_work);
+	int32_t reading;
+
+    mutex_lock(&ps_data->io_lock);
+	reading = stk3x1x_get_als_reading(ps_data);
+	if(reading < 0)
+		return;
+	ps_data->als_lux_last = stk_alscode2lux(ps_data, reading);
+	input_report_abs(ps_data->als_input_dev, ABS_MISC, ps_data->als_lux_last);
+	input_sync(ps_data->als_input_dev);
+	mutex_unlock(&ps_data->io_lock);
+	//printk(KERN_INFO "%s: als input event %d lux\n",__func__, ps_data->als_lux_last);
+}
+#endif
+
+static enum hrtimer_restart stk_ps_timer_func(struct hrtimer *timer)
+{
+	struct stk3x1x_data *ps_data = container_of(timer, struct stk3x1x_data, ps_timer);
+	queue_work(ps_data->stk_ps_wq, &ps_data->stk_ps_work);
+#ifdef STK_POLL_PS
+	hrtimer_forward_now(&ps_data->ps_timer, ps_data->ps_poll_delay);
+	return HRTIMER_RESTART;
+#else
+	hrtimer_cancel(&ps_data->ps_timer);
+	return HRTIMER_NORESTART;
+#endif
+}
+
+static void stk_ps_work_func(struct work_struct *work)
+{
+	struct stk3x1x_data *ps_data = container_of(work, struct stk3x1x_data, stk_ps_work);
+	uint32_t reading;
+	int32_t near_far_state;
+    uint8_t org_flag_reg;
+	int32_t ret;
+    uint8_t disable_flag = 0;
+    mutex_lock(&ps_data->io_lock);
+
+	org_flag_reg = stk3x1x_get_flag(ps_data);
+	if(org_flag_reg < 0)
+	{
+		printk(KERN_ERR "%s: get_status_reg fail, ret=%d", __func__, org_flag_reg);
+		goto err_i2c_rw;
+	}
+	near_far_state = (org_flag_reg & STK_FLG_NF_MASK)?1:0;
+	reading = stk3x1x_get_ps_reading(ps_data);
+	if(ps_data->ps_distance_last != near_far_state)
+	{
+		ps_data->ps_distance_last = near_far_state;
+		input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, near_far_state);
+		input_sync(ps_data->ps_input_dev);
+		wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
+#ifdef STK_DEBUG_PRINTF
+		printk(KERN_INFO "%s: ps input event %d cm, ps code = %d\n",__func__, near_far_state, reading);
+#endif
+	}
+	ret = stk3x1x_set_flag(ps_data, org_flag_reg, disable_flag);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:stk3x1x_set_flag fail, ret=%d\n", __func__, ret);
+		goto err_i2c_rw;
+	}
+
+	mutex_unlock(&ps_data->io_lock);
+	return;
+
+err_i2c_rw:
+	mutex_unlock(&ps_data->io_lock);
+	msleep(30);
+	return;
+}
+
+
+#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
+static void stk_work_func(struct work_struct *work)
+{
+	uint32_t reading;
+#if ((STK_INT_PS_MODE != 0x03) && (STK_INT_PS_MODE != 0x02))
+    int32_t ret;
+    uint8_t disable_flag = 0;
+    uint8_t org_flag_reg;
+#endif	/* #if ((STK_INT_PS_MODE != 0x03) && (STK_INT_PS_MODE != 0x02)) */
+
+#ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
+	uint32_t nLuxIndex;
+#endif
+	struct stk3x1x_data *ps_data = container_of(work, struct stk3x1x_data, stk_work);
+	int32_t near_far_state;
+
+    mutex_lock(&ps_data->io_lock);
+
+#if (STK_INT_PS_MODE	== 0x03)
+	near_far_state = gpio_get_value(ps_data->int_pin);
+#elif	(STK_INT_PS_MODE	== 0x02)
+	near_far_state = !(gpio_get_value(ps_data->int_pin));
+#endif
+
+#if ((STK_INT_PS_MODE == 0x03) || (STK_INT_PS_MODE	== 0x02))
+	ps_data->ps_distance_last = near_far_state;
+	input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, near_far_state);
+	input_sync(ps_data->ps_input_dev);
+	wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
+	reading = stk3x1x_get_ps_reading(ps_data);
+#ifdef STK_DEBUG_PRINTF
+	printk(KERN_INFO "%s: ps input event %d cm, ps code = %d\n",__func__, near_far_state, reading);
+#endif
+#else
+	/* mode 0x01 or 0x04 */
+	org_flag_reg = stk3x1x_get_flag(ps_data);
+	if(org_flag_reg < 0)
+	{
+		printk(KERN_ERR "%s: get_status_reg fail, org_flag_reg=%d", __func__, org_flag_reg);
+		goto err_i2c_rw;
+	}
+
+    if (org_flag_reg & STK_FLG_ALSINT_MASK)
+    {
+		disable_flag |= STK_FLG_ALSINT_MASK;
+        reading = stk3x1x_get_als_reading(ps_data);
+		if(reading < 0)
+		{
+			printk(KERN_ERR "%s: stk3x1x_get_als_reading fail, ret=%d", __func__, reading);
+			goto err_i2c_rw;
+		}
+#ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
+        nLuxIndex = stk_get_lux_interval_index(reading);
+        stk3x1x_set_als_thd_h(ps_data, code_threshold_table[nLuxIndex]);
+        stk3x1x_set_als_thd_l(ps_data, code_threshold_table[nLuxIndex-1]);
+#else
+        stk_als_set_new_thd(ps_data, reading);
+#endif //CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
+		ps_data->als_lux_last = stk_alscode2lux(ps_data, reading);
+		input_report_abs(ps_data->als_input_dev, ABS_MISC, ps_data->als_lux_last);
+		input_sync(ps_data->als_input_dev);
+#ifdef STK_DEBUG_PRINTF
+		printk(KERN_INFO "%s: als input event %d lux\n",__func__, ps_data->als_lux_last);
+#endif
+    }
+    if (org_flag_reg & STK_FLG_PSINT_MASK)
+    {
+		disable_flag |= STK_FLG_PSINT_MASK;
+		near_far_state = (org_flag_reg & STK_FLG_NF_MASK)?1:0;
+
+		ps_data->ps_distance_last = near_far_state;
+		input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, near_far_state);
+		input_sync(ps_data->ps_input_dev);
+		wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
+        reading = stk3x1x_get_ps_reading(ps_data);
+#ifdef STK_DEBUG_PRINTF
+		printk(KERN_INFO "%s: ps input event=%d, ps code = %d\n",__func__, near_far_state, reading);
+#endif
+    }
+
+    ret = stk3x1x_set_flag(ps_data, org_flag_reg, disable_flag);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "%s:reset_int_flag fail, ret=%d\n", __func__, ret);
+		goto err_i2c_rw;
+	}
+#endif
+
+	msleep(1);
+    enable_irq(ps_data->irq);
+    mutex_unlock(&ps_data->io_lock);
+	return;
+
+err_i2c_rw:
+	mutex_unlock(&ps_data->io_lock);
+	msleep(30);
+	enable_irq(ps_data->irq);
+	return;
+}
+#endif
+
+#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
+static irqreturn_t stk_oss_irq_handler(int irq, void *data)
+{
+	struct stk3x1x_data *pData = data;
+	disable_irq_nosync(irq);
+	queue_work(pData->stk_wq,&pData->stk_work);
+	return IRQ_HANDLED;
+}
+#endif	/*	#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))	*/
+static int32_t stk3x1x_init_all_setting(struct i2c_client *client, struct stk3x1x_platform_data *plat_data)
+{
+	int32_t ret;
+	struct stk3x1x_data *ps_data = i2c_get_clientdata(client);
+
+	mutex_lock(&ps_data->io_lock);
+	ps_data->als_enabled = false;
+	ps_data->ps_enabled = false;
+	mutex_unlock(&ps_data->io_lock);
+
+	ret = stk3x1x_software_reset(ps_data);
+	if(ret < 0)
+		return ret;
+
+	stk3x1x_check_pid(ps_data);
+	if(ret < 0)
+		return ret;
+
+	ret = stk3x1x_init_all_reg(ps_data, plat_data);
+	if(ret < 0)
+		return ret;
+#ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
+	stk_init_code_threshold_table(ps_data);
+#endif
+    return 0;
+}
+
+#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
+static int stk3x1x_setup_irq(struct i2c_client *client)
+{
+	int irq, err = -EIO;
+	struct stk3x1x_data *ps_data = i2c_get_clientdata(client);
+
+	irq = gpio_to_irq(ps_data->int_pin);
+#ifdef STK_DEBUG_PRINTF
+	printk(KERN_INFO "%s: int pin #=%d, irq=%d\n",__func__, ps_data->int_pin, irq);
+#endif
+	if (irq <= 0)
+	{
+		printk(KERN_ERR "irq number is not specified, irq # = %d, int pin=%d\n",irq, ps_data->int_pin);
+		return irq;
+	}
+	ps_data->irq = irq;
+	err = gpio_request(ps_data->int_pin,"stk-int");
+	if(err < 0)
+	{
+		printk(KERN_ERR "%s: gpio_request, err=%d", __func__, err);
+		return err;
+	}
+	err = gpio_direction_input(ps_data->int_pin);
+	if(err < 0)
+	{
+		printk(KERN_ERR "%s: gpio_direction_input, err=%d", __func__, err);
+		return err;
+	}
+#if ((STK_INT_PS_MODE == 0x03) || (STK_INT_PS_MODE	== 0x02))
+	err = request_any_context_irq(irq, stk_oss_irq_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, DEVICE_NAME, ps_data);
+#else
+	err = request_any_context_irq(irq, stk_oss_irq_handler, IRQF_TRIGGER_LOW, DEVICE_NAME, ps_data);
+#endif
+	if (err < 0)
+	{
+		printk(KERN_WARNING "%s: request_any_context_irq(%d) failed for (%d)\n", __func__, irq, err);
+		goto err_request_any_context_irq;
+	}
+	disable_irq(irq);
+
+	return 0;
+err_request_any_context_irq:
+	gpio_free(ps_data->int_pin);
+	return err;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void stk3x1x_early_suspend(struct early_suspend *h)
+{
+	struct stk3x1x_data *ps_data = container_of(h, struct stk3x1x_data, stk_early_suspend);
+#ifndef STK_POLL_PS
+	int err;
+#endif
+
+	printk(KERN_INFO "%s", __func__);
+    mutex_lock(&ps_data->io_lock);
+	if(ps_data->als_enabled)
+	{
+		stk3x1x_enable_als(ps_data, 0);
+		ps_data->als_enabled = true;
+	}
+	if(ps_data->ps_enabled)
+	{
+#ifdef STK_POLL_PS
+		wake_lock(&ps_data->ps_nosuspend_wl);
+#else
+		err = enable_irq_wake(ps_data->irq);
+		if (err)
+			printk(KERN_WARNING "%s: set_irq_wake(%d) failed, err=(%d)\n", __func__, ps_data->irq, err);
+#endif
+	}
+	mutex_unlock(&ps_data->io_lock);
+	return;
+}
+
+static void stk3x1x_late_resume(struct early_suspend *h)
+{
+	struct stk3x1x_data *ps_data = container_of(h, struct stk3x1x_data, stk_early_suspend);
+#ifndef STK_POLL_PS
+	int err;
+#endif
+
+	printk(KERN_INFO "%s", __func__);
+    mutex_lock(&ps_data->io_lock);
+	if(ps_data->als_enabled)
+		stk3x1x_enable_als(ps_data, 1);
+
+	if(ps_data->ps_enabled)
+	{
+#ifdef STK_POLL_PS
+		wake_lock(&ps_data->ps_nosuspend_wl);
+#else
+		err = disable_irq_wake(ps_data->irq);
+		if (err)
+			printk(KERN_WARNING "%s: disable_irq_wake(%d) failed, err=(%d)\n", __func__, ps_data->irq, err);
+#endif
+	}
+	mutex_unlock(&ps_data->io_lock);
+	return;
+}
+#endif	//#ifdef CONFIG_HAS_EARLYSUSPEND
+
+
+static int stk3x1x_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+    int err = -ENODEV;
+    struct stk3x1x_data *ps_data;
+	struct stk3x1x_platform_data *plat_data;
+    printk(KERN_INFO "%s: driver version = %s\n", __func__, DRIVER_VERSION);
+
+    if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+    {
+        printk(KERN_ERR "%s: No Support for I2C_FUNC_SMBUS_BYTE_DATA\n", __func__);
+        return -ENODEV;
+    }
+    if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
+    {
+        printk(KERN_ERR "%s: No Support for I2C_FUNC_SMBUS_WORD_DATA\n", __func__);
+        return -ENODEV;
+    }
+
+	ps_data = kzalloc(sizeof(struct stk3x1x_data),GFP_KERNEL);
+	if(!ps_data)
+	{
+		printk(KERN_ERR "%s: failed to allocate stk3x1x_data\n", __func__);
+		return -ENOMEM;
+	}
+	ps_data->client = client;
+	i2c_set_clientdata(client,ps_data);
+	mutex_init(&ps_data->io_lock);
+	wake_lock_init(&ps_data->ps_wakelock,WAKE_LOCK_SUSPEND, "stk_input_wakelock");
+
+#ifdef STK_POLL_PS
+	wake_lock_init(&ps_data->ps_nosuspend_wl,WAKE_LOCK_SUSPEND, "stk_nosuspend_wakelock");
+#endif
+	if(client->dev.platform_data != NULL)
+	{
+		plat_data = client->dev.platform_data;
+		ps_data->als_transmittance = plat_data->transmittance;
+		ps_data->int_pin = plat_data->int_pin;
+		if(ps_data->als_transmittance == 0)
+		{
+			printk(KERN_ERR "%s: Please set als_transmittance in platform data\n", __func__);
+			goto err_als_input_allocate;
+		}
+	}
+	else
+	{
+		printk(KERN_ERR "%s: no stk3x1x platform data!\n", __func__);
+		goto err_als_input_allocate;
+	}
+
+	ps_data->als_input_dev = input_allocate_device();
+	if (ps_data->als_input_dev==NULL)
+	{
+		printk(KERN_ERR "%s: could not allocate als device\n", __func__);
+		err = -ENOMEM;
+		goto err_als_input_allocate;
+	}
+	ps_data->ps_input_dev = input_allocate_device();
+	if (ps_data->ps_input_dev==NULL)
+	{
+		printk(KERN_ERR "%s: could not allocate ps device\n", __func__);
+		err = -ENOMEM;
+		goto err_ps_input_allocate;
+	}
+	ps_data->als_input_dev->name = ALS_NAME;
+	ps_data->ps_input_dev->name = PS_NAME;
+	set_bit(EV_ABS, ps_data->als_input_dev->evbit);
+	set_bit(EV_ABS, ps_data->ps_input_dev->evbit);
+	input_set_abs_params(ps_data->als_input_dev, ABS_MISC, 0, stk_alscode2lux(ps_data, (1<<16)-1), 0, 0);
+	input_set_abs_params(ps_data->ps_input_dev, ABS_DISTANCE, 0,1, 0, 0);
+	err = input_register_device(ps_data->als_input_dev);
+	if (err<0)
+	{
+		printk(KERN_ERR "%s: can not register als input device\n", __func__);
+		goto err_als_input_register;
+	}
+	err = input_register_device(ps_data->ps_input_dev);
+	if (err<0)
+	{
+		printk(KERN_ERR "%s: can not register ps input device\n", __func__);
+		goto err_ps_input_register;
+	}
+
+	err = sysfs_create_group(&ps_data->als_input_dev->dev.kobj, &stk_als_attribute_group);
+	if (err < 0)
+	{
+		printk(KERN_ERR "%s:could not create sysfs group for als\n", __func__);
+		goto err_als_sysfs_create_group;
+	}
+	err = sysfs_create_group(&ps_data->ps_input_dev->dev.kobj, &stk_ps_attribute_group);
+	if (err < 0)
+	{
+		printk(KERN_ERR "%s:could not create sysfs group for ps\n", __func__);
+		goto err_ps_sysfs_create_group;
+	}
+	input_set_drvdata(ps_data->als_input_dev, ps_data);
+	input_set_drvdata(ps_data->ps_input_dev, ps_data);
+
+#ifdef STK_POLL_ALS
+	ps_data->stk_als_wq = create_singlethread_workqueue("stk_als_wq");
+	INIT_WORK(&ps_data->stk_als_work, stk_als_work_func);
+	hrtimer_init(&ps_data->als_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	ps_data->als_poll_delay = ns_to_ktime(110 * NSEC_PER_MSEC);
+	ps_data->als_timer.function = stk_als_timer_func;
+#endif
+
+	ps_data->stk_ps_wq = create_singlethread_workqueue("stk_ps_wq");
+	INIT_WORK(&ps_data->stk_ps_work, stk_ps_work_func);
+	hrtimer_init(&ps_data->ps_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	ps_data->ps_poll_delay = ns_to_ktime(110 * NSEC_PER_MSEC);
+	ps_data->ps_timer.function = stk_ps_timer_func;
+#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
+	ps_data->stk_wq = create_singlethread_workqueue("stk_wq");
+	INIT_WORK(&ps_data->stk_work, stk_work_func);
+	err = stk3x1x_setup_irq(client);
+	if(err < 0)
+		goto err_stk3x1x_setup_irq;
+#endif
+
+	err = stk3x1x_init_all_setting(client, plat_data);
+	if(err < 0)
+		goto err_init_all_setting;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	ps_data->stk_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	ps_data->stk_early_suspend.suspend = stk3x1x_early_suspend;
+	ps_data->stk_early_suspend.resume = stk3x1x_late_resume;
+	register_early_suspend(&ps_data->stk_early_suspend);
+#endif
+	printk(KERN_INFO "%s: probe successfully", __func__);
+	return 0;
+
+err_init_all_setting:
+#ifndef STK_POLL_PS
+	free_irq(ps_data->irq, ps_data);
+	gpio_free(plat_data->int_pin);
+#endif
+#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
+err_stk3x1x_setup_irq:
+#endif
+#ifdef STK_POLL_ALS
+	hrtimer_try_to_cancel(&ps_data->als_timer);
+	destroy_workqueue(ps_data->stk_als_wq);
+#endif
+	destroy_workqueue(ps_data->stk_ps_wq);
+#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
+	destroy_workqueue(ps_data->stk_wq);
+#endif
+	sysfs_remove_group(&ps_data->ps_input_dev->dev.kobj, &stk_ps_attribute_group);
+err_ps_sysfs_create_group:
+	sysfs_remove_group(&ps_data->als_input_dev->dev.kobj, &stk_als_attribute_group);
+err_als_sysfs_create_group:
+	input_unregister_device(ps_data->ps_input_dev);
+err_ps_input_register:
+	input_unregister_device(ps_data->als_input_dev);
+err_als_input_register:
+	input_free_device(ps_data->ps_input_dev);
+err_ps_input_allocate:
+	input_free_device(ps_data->als_input_dev);
+err_als_input_allocate:
+#ifdef STK_POLL_PS
+    wake_lock_destroy(&ps_data->ps_nosuspend_wl);
+#endif
+    wake_lock_destroy(&ps_data->ps_wakelock);
+    mutex_destroy(&ps_data->io_lock);
+	kfree(ps_data);
+    return err;
+}
+
+
+static int stk3x1x_remove(struct i2c_client *client)
+{
+	struct stk3x1x_data *ps_data = i2c_get_clientdata(client);
+#ifndef STK_POLL_PS
+	free_irq(ps_data->irq, ps_data);
+	gpio_free(ps_data->int_pin);
+#endif
+#ifdef STK_POLL_ALS
+	hrtimer_try_to_cancel(&ps_data->als_timer);
+	destroy_workqueue(ps_data->stk_als_wq);
+#endif
+	destroy_workqueue(ps_data->stk_ps_wq);
+#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
+	destroy_workqueue(ps_data->stk_wq);
+#endif
+	sysfs_remove_group(&ps_data->ps_input_dev->dev.kobj, &stk_ps_attribute_group);
+	sysfs_remove_group(&ps_data->als_input_dev->dev.kobj, &stk_als_attribute_group);
+	input_unregister_device(ps_data->ps_input_dev);
+	input_unregister_device(ps_data->als_input_dev);
+	input_free_device(ps_data->ps_input_dev);
+	input_free_device(ps_data->als_input_dev);
+#ifdef STK_POLL_PS
+	wake_lock_destroy(&ps_data->ps_nosuspend_wl);
+#endif
+	wake_lock_destroy(&ps_data->ps_wakelock);
+    mutex_destroy(&ps_data->io_lock);
+	kfree(ps_data);
+
+    return 0;
+}
+
+static const struct i2c_device_id stk_ps_id[] =
+{
+    { "stk_ps", 0},
+    {}
+};
+MODULE_DEVICE_TABLE(i2c, stk_ps_id);
+
+static struct i2c_driver stk_ps_driver =
+{
+    .driver = {
+        .name = DEVICE_NAME,
+		.owner = THIS_MODULE,
+    },
+    .probe = stk3x1x_probe,
+    .remove = stk3x1x_remove,
+    .id_table = stk_ps_id,
+};
+
+
+static int __init stk3x1x_init(void)
+{
+	int ret;
+    ret = i2c_add_driver(&stk_ps_driver);
+    if (ret)
+        return ret;
+
+    return 0;
+}
+
+static void __exit stk3x1x_exit(void)
+{
+    i2c_del_driver(&stk_ps_driver);
+}
+
+module_init(stk3x1x_init);
+module_exit(stk3x1x_exit);
+MODULE_AUTHOR("Lex Hsieh <lex_hsieh@sitronix.com.tw>");
+MODULE_DESCRIPTION("Sensortek stk3x1x Proximity Sensor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index b9c4cae..53c7c30 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -692,7 +692,6 @@
 	if (ret)
 		goto fail;
 
-	ret = __flush_iotlb_va(domain, va);
 fail:
 	mutex_unlock(&msm_iommu_lock);
 	return ret;
@@ -742,7 +741,6 @@
 	if (ret)
 		goto fail;
 
-	__flush_iotlb(domain);
 fail:
 	mutex_unlock(&msm_iommu_lock);
 	return ret;
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 474efdf..78fffb2 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -371,7 +371,7 @@
 	map.info.ctx_id = ctx_drvdata->num;
 	map.info.va = va;
 	map.info.size = len;
-	map.flags = IOMMU_TLBINVAL_FLAG;
+	map.flags = 0;
 	flush_va = &pa;
 	flush_pa = virt_to_phys(&pa);
 
@@ -421,7 +421,7 @@
 	map.info.ctx_id = ctx_drvdata->num;
 	map.info.va = va;
 	map.info.size = len;
-	map.flags = IOMMU_TLBINVAL_FLAG;
+	map.flags = 0;
 
 	if (sg->length == len) {
 		pa = get_phys_addr(sg);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index bdc476e..b896f65 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -43,7 +43,7 @@
 #define WLED_HIGH_POLE_CAP_REG(base)		(base + 0x58)
 #define WLED_CURR_SINK_MASK		0xE0
 #define WLED_CURR_SINK_SHFT		0x05
-#define WLED_SWITCH_FREQ_MASK		0x02
+#define WLED_SWITCH_FREQ_MASK		0x0F
 #define WLED_OVP_VAL_MASK		0x03
 #define WLED_OVP_VAL_BIT_SHFT		0x00
 #define WLED_BOOST_LIMIT_MASK		0x07
@@ -78,7 +78,7 @@
 #define WLED_BOOST_LIM_DEFAULT		0x03
 #define WLED_CP_SEL_DEFAULT		0x00
 #define WLED_CTRL_DLY_DEFAULT		0x00
-#define WLED_SWITCH_FREQ_DEFAULT	0x02
+#define WLED_SWITCH_FREQ_DEFAULT	0x0B
 
 #define FLASH_SAFETY_TIMER(base)	(base + 0x40)
 #define FLASH_MAX_CURR(base)		(base + 0x41)
@@ -239,14 +239,6 @@
 	WLED_OVP_37V,
 };
 
-/* switch frquency */
-enum wled_switch_freq {
-	WLED_800kHz = 0,
-	WLED_960kHz,
-	WLED_1600kHz,
-	WLED_3200kHz,
-};
-
 enum flash_headroom {
 	HEADROOM_250mV = 0,
 	HEADROOM_300mV,
@@ -1312,11 +1304,12 @@
 	}
 
 	/* program switch frequency */
-	rc = qpnp_led_masked_write(led, WLED_SWITCHING_FREQ_REG(led->base),
+	rc = qpnp_led_masked_write(led,
+		WLED_SWITCHING_FREQ_REG(led->base),
 		WLED_SWITCH_FREQ_MASK, led->wled_cfg->switch_freq);
 	if (rc) {
 		dev_err(&led->spmi_dev->dev,
-				"WLED switch freq reg write failed(%d)\n", rc);
+			"WLED switch freq reg write failed(%d)\n", rc);
 		return rc;
 	}
 
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 692a04e..9d606a1 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -128,6 +128,20 @@
 	DMX_IDX_H264_NON_IDR_START
 };
 
+static const struct dvb_dmx_video_patterns h264_non_access_unit_del = {
+	{0x00, 0x00, 0x01, 0x09},
+	{0xFF, 0xFF, 0xFF, 0x1F},
+	4,
+	DMX_IDX_H264_ACCESS_UNIT_DEL
+};
+
+static const struct dvb_dmx_video_patterns h264_non_sei = {
+	{0x00, 0x00, 0x01, 0x06},
+	{0xFF, 0xFF, 0xFF, 0x1F},
+	4,
+	DMX_IDX_H264_SEI
+};
+
 static const struct dvb_dmx_video_patterns vc1_seq_hdr = {
 	{0x00, 0x00, 0x01, 0x0F},
 	{0xFF, 0xFF, 0xFF, 0xFF},
@@ -1791,6 +1805,12 @@
 	case DMX_IDX_H264_NON_IDR_START:
 		return &h264_non_idr;
 
+	case DMX_IDX_H264_ACCESS_UNIT_DEL:
+		return &h264_non_access_unit_del;
+
+	case DMX_IDX_H264_SEI:
+		return &h264_non_sei;
+
 	case DMX_IDX_VC1_SEQ_HEADER:
 		return &vc1_seq_hdr;
 
@@ -1913,6 +1933,20 @@
 	}
 
 	if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+		(feed->idx_params.types & DMX_IDX_H264_ACCESS_UNIT_DEL)) {
+		feed->patterns[feed->pattern_num] =
+			dvb_dmx_get_pattern(DMX_IDX_H264_ACCESS_UNIT_DEL);
+		feed->pattern_num++;
+	}
+
+	if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+		(feed->idx_params.types & DMX_IDX_H264_SEI)) {
+		feed->patterns[feed->pattern_num] =
+			dvb_dmx_get_pattern(DMX_IDX_H264_SEI);
+		feed->pattern_num++;
+	}
+
+	if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
 		(feed->idx_params.types &
 		 (DMX_IDX_VC1_SEQ_HEADER |
 		  DMX_IDX_VC1_FIRST_SEQ_FRAME_START |
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index d3618c0..c70e151 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -328,6 +328,10 @@
 
 		pr_debug("%s: num planes :%c\n", __func__,
 					user_fmt->num_planes);
+		/*num_planes need to bound checked, otherwise for loop
+		can execute forever */
+		if (WARN_ON(user_fmt->num_planes > VIDEO_MAX_PLANES))
+			return -EINVAL;
 		for (i = 0; i < user_fmt->num_planes; i++)
 			pr_debug("%s: plane size[%d]\n", __func__,
 					user_fmt->plane_sizes[i]);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index f1f4c17..8c42ed2 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -90,7 +90,8 @@
 	void (*enable_wm) (struct vfe_device *vfe_dev,
 		uint8_t wm_idx, uint8_t enable);
 	void (*cfg_io_format) (struct vfe_device *vfe_dev,
-		struct msm_vfe_axi_stream *stream_info);
+		enum msm_vfe_axi_stream_src stream_src,
+		uint32_t io_format);
 	void (*cfg_framedrop) (struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info);
 	void (*clear_framedrop) (struct vfe_device *vfe_dev,
@@ -289,6 +290,7 @@
 	enum msm_vfe_inputmux input_mux;
 	uint32_t width;
 	long pixel_clock;
+	uint32_t input_format;
 };
 
 enum msm_wm_ub_cfg_type {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 07a66e6..aac973e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -144,7 +144,7 @@
 	/* CGC_OVERRIDE */
 	msm_camera_io_w(0x07FFFFFF, vfe_dev->vfe_base + 0xC);
 	/* BUS_CFG */
-	msm_camera_io_w(0x00000001, vfe_dev->vfe_base + 0x3C);
+	msm_camera_io_w(0x00000009, vfe_dev->vfe_base + 0x3C);
 	msm_camera_io_w(0x01000025, vfe_dev->vfe_base + 0x1C);
 	msm_camera_io_w_mb(0x1CFFFFFF, vfe_dev->vfe_base + 0x20);
 	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24);
@@ -481,11 +481,11 @@
 }
 
 static void msm_vfe32_cfg_io_format(struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream *stream_info)
+	enum msm_vfe_axi_stream_src stream_src, uint32_t io_format)
 {
 	int bpp, bpp_reg = 0;
 	uint32_t io_format_reg;
-	bpp = msm_isp_get_bit_per_pixel(stream_info->output_format);
+	bpp = msm_isp_get_bit_per_pixel(io_format);
 
 	switch (bpp) {
 	case 8:
@@ -499,7 +499,9 @@
 		break;
 	}
 	io_format_reg = msm_camera_io_r(vfe_dev->vfe_base + 0x6F8);
-	switch (stream_info->stream_src) {
+	switch (stream_src) {
+	case PIX_ENCODER:
+	case PIX_VIEWFINDER:
 	case CAMIF_RAW:
 		io_format_reg &= 0xFFFFCFFF;
 		io_format_reg |= bpp_reg << 12;
@@ -508,8 +510,6 @@
 		io_format_reg &= 0xFFFFFFC8;
 		io_format_reg |= bpp_reg << 4;
 		break;
-	case PIX_ENCODER:
-	case PIX_VIEWFINDER:
 	case RDI_INTF_0:
 	case RDI_INTF_1:
 	case RDI_INTF_2:
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 2db25a6..84b95f1 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -688,11 +688,11 @@
 }
 
 static void msm_vfe40_cfg_io_format(struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream *stream_info)
+	enum msm_vfe_axi_stream_src stream_src, uint32_t io_format)
 {
 	int bpp, bpp_reg = 0;
 	uint32_t io_format_reg;
-	bpp = msm_isp_get_bit_per_pixel(stream_info->output_format);
+	bpp = msm_isp_get_bit_per_pixel(io_format);
 
 	switch (bpp) {
 	case 8:
@@ -706,7 +706,9 @@
 		break;
 	}
 	io_format_reg = msm_camera_io_r(vfe_dev->vfe_base + 0x54);
-	switch (stream_info->stream_src) {
+	switch (stream_src) {
+	case PIX_ENCODER:
+	case PIX_VIEWFINDER:
 	case CAMIF_RAW:
 		io_format_reg &= 0xFFFFCFFF;
 		io_format_reg |= bpp_reg << 12;
@@ -715,8 +717,6 @@
 		io_format_reg &= 0xFFFFFFC8;
 		io_format_reg |= bpp_reg << 4;
 		break;
-	case PIX_ENCODER:
-	case PIX_VIEWFINDER:
 	case RDI_INTF_0:
 	case RDI_INTF_1:
 	case RDI_INTF_2:
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index d3138ed..5b7658d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -474,6 +474,7 @@
 int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
 {
 	int rc = 0, i;
+	uint32_t io_format = 0;
 	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd = arg;
 	struct msm_vfe_axi_stream *stream_info;
 
@@ -497,10 +498,20 @@
 		stream_info[HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
 	msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_info);
 
-	if (stream_cfg_cmd->stream_src == CAMIF_RAW ||
-		stream_cfg_cmd->stream_src == IDEAL_RAW)
-			vfe_dev->hw_info->vfe_ops.axi_ops.
-				cfg_io_format(vfe_dev, stream_info);
+	if (stream_info->stream_src < RDI_INTF_0) {
+		io_format = vfe_dev->axi_data.src_info[VFE_PIX_0].input_format;
+		if (stream_info->stream_src == CAMIF_RAW ||
+			stream_info->stream_src == IDEAL_RAW) {
+			if (stream_info->stream_src == CAMIF_RAW &&
+				io_format != stream_info->output_format)
+				pr_warn("%s: Overriding input format\n",
+					__func__);
+
+			io_format = stream_info->output_format;
+		}
+		vfe_dev->hw_info->vfe_ops.axi_ops.cfg_io_format(
+			vfe_dev, stream_info->stream_src, io_format);
+	}
 
 	msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);
 
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index d857a14..33f63b3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -150,6 +150,12 @@
 	stats_idx = vfe_dev->hw_info->vfe_ops.stats_ops.
 		get_stats_idx(stream_req_cmd->stats_type);
 
+	if ((stats_idx > MSM_ISP_STATS_MAX) ||
+		(stats_idx == -EINVAL)) {
+		pr_err("%s: Stats idx Error\n", __func__);
+		return rc;
+	}
+
 	stream_info = &stats_data->stream_info[stats_idx];
 	if (stream_info->state != STATS_AVALIABLE) {
 		pr_err("%s: Stats already requested\n", __func__);
@@ -188,7 +194,7 @@
 
 int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg)
 {
-	int rc = 0;
+	int rc = -1;
 	struct msm_vfe_stats_stream_request_cmd *stream_req_cmd = arg;
 	struct msm_vfe_stats_stream *stream_info = NULL;
 	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
@@ -202,6 +208,11 @@
 	}
 
 	stats_idx = STATS_IDX(stream_req_cmd->stream_handle);
+	if (stats_idx > MSM_ISP_STATS_MAX) {
+		pr_err("%s: Stats idx Error\n", __func__);
+		return rc;
+	}
+
 	stream_info = &stats_data->stream_info[stats_idx];
 
 	framedrop_period = msm_isp_get_framedrop_period(
@@ -228,9 +239,14 @@
 	struct msm_vfe_stats_stream_release_cmd *stream_release_cmd = arg;
 	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
 	int stats_idx = STATS_IDX(stream_release_cmd->stream_handle);
-	struct msm_vfe_stats_stream *stream_info =
-		&stats_data->stream_info[stats_idx];
+	struct msm_vfe_stats_stream *stream_info = NULL;
 
+	if (stats_idx > MSM_ISP_STATS_MAX) {
+		pr_err("%s: Stats idx Error\n", __func__);
+		return rc;
+	}
+
+	stream_info = &stats_data->stream_info[stats_idx];
 	if (stream_info->state == STATS_AVALIABLE) {
 		pr_err("%s: stream already release\n", __func__);
 		return rc;
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 3806213..590b636 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
@@ -273,6 +273,9 @@
 		return rc;
 	}
 
+	vfe_dev->axi_data.src_info[VFE_PIX_0].input_format =
+		input_cfg->d.pix_cfg.input_format;
+
 	vfe_dev->hw_info->vfe_ops.core_ops.cfg_camif(
 		vfe_dev, &input_cfg->d.pix_cfg);
 	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 a4eb274..822c0c8 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
@@ -1219,6 +1219,14 @@
 		goto ERROR1;
 	}
 
+	if ((new_frame->msg_len == 0) ||
+		(new_frame->msg_len > MSM_CPP_MAX_FRAME_LENGTH)) {
+		pr_err("%s:%d: Invalid frame len:%d\n", __func__,
+			__LINE__, new_frame->msg_len);
+		rc = -EINVAL;
+		goto ERROR1;
+	}
+
 	cpp_frame_msg = kzalloc(sizeof(uint32_t)*new_frame->msg_len,
 		GFP_KERNEL);
 	if (!cpp_frame_msg) {
@@ -1380,7 +1388,10 @@
 		pr_err("ioctl_ptr is null\n");
 		return -EINVAL;
 	}
-
+	if (cpp_dev == NULL) {
+		pr_err("cpp_dev is null\n");
+		return -EINVAL;
+	}
 	mutex_lock(&cpp_dev->mutex);
 	CPP_DBG("E cmd: %d\n", cmd);
 	switch (cmd) {
@@ -1396,8 +1407,16 @@
 
 	case VIDIOC_MSM_CPP_LOAD_FIRMWARE: {
 		if (cpp_dev->is_firmware_loaded == 0) {
-			kfree(cpp_dev->fw_name_bin);
-			cpp_dev->fw_name_bin = NULL;
+			if (cpp_dev->fw_name_bin != NULL) {
+				kfree(cpp_dev->fw_name_bin);
+				cpp_dev->fw_name_bin = NULL;
+			}
+			if ((ioctl_ptr->len == 0) ||
+				(ioctl_ptr->len > MSM_CPP_MAX_FW_NAME_LEN)) {
+				pr_err("ioctl_ptr->len is 0\n");
+				mutex_unlock(&cpp_dev->mutex);
+				return -EINVAL;
+			}
 			cpp_dev->fw_name_bin = kzalloc(ioctl_ptr->len+1,
 				GFP_KERNEL);
 			if (!cpp_dev->fw_name_bin) {
@@ -1406,13 +1425,9 @@
 				mutex_unlock(&cpp_dev->mutex);
 				return -EINVAL;
 			}
-
 			if (ioctl_ptr->ioctl_ptr == NULL) {
 				pr_err("ioctl_ptr->ioctl_ptr=NULL\n");
-				return -EINVAL;
-			}
-			if (ioctl_ptr->len == 0) {
-				pr_err("ioctl_ptr->len is 0\n");
+				mutex_unlock(&cpp_dev->mutex);
 				return -EINVAL;
 			}
 			rc = (copy_from_user(cpp_dev->fw_name_bin,
@@ -1426,11 +1441,6 @@
 				return -EINVAL;
 			}
 			*(cpp_dev->fw_name_bin+ioctl_ptr->len) = '\0';
-			if (cpp_dev == NULL) {
-				pr_err("cpp_dev is null\n");
-				return -EINVAL;
-			}
-
 			disable_irq(cpp_dev->irq->start);
 			cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin);
 			enable_irq(cpp_dev->irq->start);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 8de8997..2bc460b 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -198,7 +198,8 @@
 		patterns[1] = dvb_dmx_get_pattern(DMX_IDX_H264_PPS);
 		patterns[2] = dvb_dmx_get_pattern(DMX_IDX_H264_IDR_START);
 		patterns[3] = dvb_dmx_get_pattern(DMX_IDX_H264_NON_IDR_START);
-		*patterns_num = 4;
+		patterns[4] = dvb_dmx_get_pattern(DMX_IDX_H264_SEI);
+		*patterns_num = 5;
 		break;
 
 	case DMX_VIDEO_CODEC_VC1:
diff --git a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
index 0908a6e..9ddb9b7 100644
--- a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
+++ b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
@@ -134,6 +134,8 @@
 			case DMX_IDX_H264_SPS:
 			case DMX_IDX_MPEG_SEQ_HEADER:
 			case DMX_IDX_VC1_SEQ_HEADER:
+			case DMX_IDX_H264_ACCESS_UNIT_DEL:
+			case DMX_IDX_H264_SEI:
 				DBG("SPS FOUND\n");
 				frame_found = false;
 				break;
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index a63ee61..653ba46 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -45,6 +45,7 @@
 	case HFI_ERR_SESSION_UNSUPPORTED_PROPERTY:
 	case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
 	case HFI_ERR_SESSION_INSUFFICIENT_RESOURCES:
+	case HFI_ERR_SESSION_UNSUPPORTED_STREAM:
 		vidc_err = VIDC_ERR_NOT_SUPPORTED;
 		break;
 	case HFI_ERR_SYS_MAX_SESSIONS_REACHED:
@@ -786,6 +787,8 @@
 	data_done.input_done.offset = pkt->offset;
 	data_done.input_done.filled_len = pkt->filled_len;
 	data_done.input_done.packet_buffer = pkt->packet_buffer;
+	data_done.input_done.status =
+		hfi_map_err_status((u32) pkt->error_type);
 	callback(SESSION_ETB_DONE, &data_done);
 }
 
@@ -1003,7 +1006,6 @@
 		struct hfi_msg_sys_session_end_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
-	struct hal_session *sess_close;
 
 	dprintk(VIDC_DBG, "RECEIVED:SESSION_END_DONE");
 
@@ -1021,12 +1023,6 @@
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	sess_close = (struct hal_session *)pkt->session_id;
-	dprintk(VIDC_INFO, "deleted the session: 0x%x",
-		sess_close->session_id);
-	list_del(&sess_close->list);
-	kfree(sess_close);
-	sess_close = NULL;
 	callback(SESSION_END_DONE, &cmd_done);
 }
 
@@ -1035,7 +1031,6 @@
 	struct hfi_msg_sys_session_abort_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
-	struct hal_session *sess_close;
 
 	dprintk(VIDC_DBG, "RECEIVED:SESSION_ABORT_DONE");
 
@@ -1053,16 +1048,6 @@
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
 
-	sess_close = (struct hal_session *)pkt->session_id;
-	if (!sess_close) {
-		dprintk(VIDC_ERR, "%s: invalid session pointer\n", __func__);
-		return;
-	}
-	dprintk(VIDC_ERR, "deleted the session: 0x%x",
-		sess_close->session_id);
-	list_del(&sess_close->list);
-	kfree(sess_close);
-	sess_close = NULL;
 	callback(SESSION_ABORT_DONE, &cmd_done);
 }
 
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 57b98dc..f94b6f1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -627,6 +627,8 @@
 				if (inst->core)
 					hdev = inst->core->device;
 				if (hdev && inst->session) {
+					dprintk(VIDC_DBG,
+					"cleaning up inst: 0x%p", inst);
 					rc = call_hfi_op(hdev, session_clean,
 						(void *) inst->session);
 					if (rc)
@@ -693,10 +695,24 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
+	struct hfi_device *hdev = NULL;
+
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
-		signal_session_msg_receipt(cmd, inst);
+		if (!inst || !inst->core || !inst->core->device) {
+			dprintk(VIDC_ERR, "%s invalid params\n", __func__);
+			return;
+		}
+		hdev = inst->core->device;
+		mutex_lock(&inst->lock);
+		if (inst->session) {
+			dprintk(VIDC_DBG, "cleaning up inst: 0x%p", inst);
+			call_hfi_op(hdev, session_clean,
+				(void *) inst->session);
+		}
 		inst->session = NULL;
+		mutex_unlock(&inst->lock);
+		signal_session_msg_receipt(cmd, inst);
 		show_stats(inst);
 	} else {
 		dprintk(VIDC_ERR,
@@ -737,22 +753,45 @@
 	struct msm_vidc_cb_data_done *response = data;
 	struct vb2_buffer *vb;
 	struct msm_vidc_inst *inst;
+	struct vidc_hal_ebd *empty_buf_done;
+
 	if (!response) {
 		dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
 		return;
 	}
 	vb = response->clnt_data;
 	inst = (struct msm_vidc_inst *)response->session_id;
+	if (!inst) {
+		dprintk(VIDC_ERR, "%s Invalid response from vidc_hal\n",
+			__func__);
+		return;
+	}
 	if (vb) {
 		vb->v4l2_planes[0].bytesused = response->input_done.filled_len;
 		vb->v4l2_planes[0].data_offset = response->input_done.offset;
 		if (vb->v4l2_planes[0].data_offset > vb->v4l2_planes[0].length)
-			dprintk(VIDC_ERR, "Error: data_offset overflow\n");
+			dprintk(VIDC_INFO, "data_offset overflow length\n");
 		if (vb->v4l2_planes[0].bytesused > vb->v4l2_planes[0].length)
-			dprintk(VIDC_ERR, "Error: buffer overflow\n");
+			dprintk(VIDC_INFO, "bytesused overflow length\n");
 		if ((u8 *)vb->v4l2_planes[0].m.userptr !=
 			response->input_done.packet_buffer)
-			dprintk(VIDC_ERR, "Error: unexpected buffer address\n");
+			dprintk(VIDC_INFO, "Unexpected buffer address\n");
+		vb->v4l2_buf.flags = 0;
+		empty_buf_done = (struct vidc_hal_ebd *)&response->input_done;
+		if (empty_buf_done) {
+			if (empty_buf_done->status == VIDC_ERR_NOT_SUPPORTED) {
+				dprintk(VIDC_INFO,
+					"Failed : Unsupported input stream\n");
+				vb->v4l2_buf.flags |=
+					V4L2_QCOM_BUF_INPUT_UNSUPPORTED;
+			}
+			if (empty_buf_done->status == VIDC_ERR_BITSTREAM_ERR) {
+				dprintk(VIDC_INFO,
+					"Failed : Corrupted input stream\n");
+				vb->v4l2_buf.flags |=
+					V4L2_QCOM_BUF_DATA_CORRUPT;
+			}
+		}
 		mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 		mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 5c22552..010f15d 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -936,6 +936,7 @@
 	u32 timestamp_hi;
 	u32 timestamp_lo;
 	u32 flags;
+	u32 status;
 	u32 mark_target;
 	u32 mark_data;
 	u32 stats;
diff --git a/drivers/misc/qpnp-misc.c b/drivers/misc/qpnp-misc.c
index 608be81..6ad4816 100644
--- a/drivers/misc/qpnp-misc.c
+++ b/drivers/misc/qpnp-misc.c
@@ -21,7 +21,8 @@
 
 #define QPNP_MISC_DEV_NAME "qcom,qpnp-misc"
 
-#define REVID_REVISION2	0x1
+#define REG_DIG_MAJOR_REV	0x01
+#define REG_SUBTYPE		0x05
 
 static DEFINE_MUTEX(qpnp_misc_dev_list_mutex);
 static LIST_HEAD(qpnp_misc_dev_list);
@@ -45,6 +46,11 @@
 	struct spmi_device		*spmi;
 };
 
+struct qpnp_misc_version {
+	u8				subtype;
+	u8				dig_major_rev;
+};
+
 static struct of_device_id qpnp_misc_match_table[] = {
 	{ .compatible = QPNP_MISC_DEV_NAME },
 	{}
@@ -63,17 +69,28 @@
 	return val;
 }
 
-#define REV2_IRQ_AVAILABLE_VERSION	2
+static struct qpnp_misc_version irq_support_version[] = {
+	{0x01, 0x02}, /* PM8941 */
+	{0x07, 0x00}, /* PM8226 */
+	{0x09, 0x00}, /* PMA8084 */
+};
+
 static bool __misc_irqs_available(struct qpnp_misc_dev *dev)
 {
-	u8 rev2;
+	int i;
+	u8 subtype, dig_major_rev;
 
-	rev2 = qpnp_read_byte(dev->spmi,
-		dev->resource->start + REVID_REVISION2);
-	pr_debug("rev2 0x%x\n", rev2);
+	subtype = qpnp_read_byte(dev->spmi, dev->resource->start + REG_SUBTYPE);
+	pr_debug("subtype = 0x%02X\n", subtype);
 
-	if (rev2 >= REV2_IRQ_AVAILABLE_VERSION)
-		return 1;
+	dig_major_rev = qpnp_read_byte(dev->spmi,
+		dev->resource->start + REG_DIG_MAJOR_REV);
+	pr_debug("dig_major rev = 0x%02X\n", dig_major_rev);
+
+	for (i = 0; i < ARRAY_SIZE(irq_support_version); i++)
+		if (subtype == irq_support_version[i].subtype
+		    && dig_major_rev >= irq_support_version[i].dig_major_rev)
+			return 1;
 
 	return 0;
 }
@@ -84,6 +101,11 @@
 	struct qpnp_misc_dev *mdev = NULL;
 	struct qpnp_misc_dev *mdev_found = NULL;
 
+	if (IS_ERR_OR_NULL(consumer_dev)) {
+		pr_err("Invalid consumer device pointer\n");
+		return -EINVAL;
+	}
+
 	misc_node = of_parse_phandle(consumer_dev->of_node, "qcom,misc-ref", 0);
 	if (!misc_node) {
 		pr_debug("Could not find qcom,misc-ref property in %s\n",
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index bd838fc..b750602 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -2647,6 +2647,11 @@
 	struct qseecom_dev_handle *data = file->private_data;
 	void __user *argp = (void __user *) arg;
 
+	if (!data) {
+		pr_err("Invalid/uninitialized device handle\n");
+		return -EINVAL;
+	}
+
 	if (data->abort) {
 		pr_err("Aborting qseecom driver\n");
 		return -ENODEV;
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index 83f486c..3f3d76a 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -55,7 +55,7 @@
 #define DBG2(x...) DBG(DEBUG_MASK_LVL2, x)
 
 /* Configure device instances */
-#define RMNET_DEVICE_COUNT (8)
+#define RMNET_DEVICE_COUNT  9
 
 /* allow larger frames */
 #define RMNET_DATA_LEN 2000
@@ -85,6 +85,7 @@
 	u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
 	uint8_t device_up;
 	uint8_t in_reset;
+	struct platform_driver *bam_pdev;
 };
 
 #ifdef CONFIG_MSM_RMNET_DEBUG
@@ -401,6 +402,14 @@
 					__func__, p->ch_id, r);
 			return -ENODEV;
 		}
+
+		r = platform_driver_register(p->bam_pdev);
+		if (r) {
+			pr_err("%s: bam pdev registration failed n=%d rc=%d\n",
+					__func__, p->ch_id, r);
+			msm_bam_dmux_close(p->ch_id);
+			return r;
+		}
 	}
 
 	p->device_up = DEVICE_ACTIVE;
@@ -711,6 +720,11 @@
 			break;
 	}
 
+	if (i >= RMNET_DEVICE_COUNT) {
+		pr_err("%s: wrong netdev %s\n", __func__, pdev->name);
+		return -ENODEV;
+	}
+
 	p = netdev_priv(netdevs[i]);
 	if (p->in_reset) {
 		p->in_reset = 0;
@@ -766,7 +780,7 @@
 
 	if (i >= RMNET_REV_DEVICE_COUNT) {
 		pr_err("%s: wrong netdev %s\n", __func__, pdev->name);
-		return 0;
+		return -ENODEV;
 	}
 
 	p = netdev_priv(netdevs_rev[i]);
@@ -871,8 +885,13 @@
 #endif
 
 	for (n = 0; n < RMNET_DEVICE_COUNT; n++) {
+		const char *dev_name = "rmnet%d";
+
+		if (n == BAM_DMUX_USB_RMNET_0)
+			dev_name = "rmnet_usb%d";
+
 		dev = alloc_netdev(sizeof(struct rmnet_private),
-				   "rmnet%d", rmnet_setup);
+				   dev_name, rmnet_setup);
 
 		if (!dev) {
 			pr_err("%s: no memory for netdev %d\n", __func__, n);
@@ -898,6 +917,7 @@
 		if (ret) {
 			pr_err("%s: unable to register netdev"
 				   " %d rc=%d\n", __func__, n, ret);
+			netdevs[n] = NULL;
 			free_netdev(dev);
 			return ret;
 		}
@@ -921,18 +941,16 @@
 		bam_rmnet_drivers[n].probe = bam_rmnet_probe;
 		bam_rmnet_drivers[n].remove = bam_rmnet_remove;
 		tempname = kmalloc(BAM_DMUX_CH_NAME_MAX_LEN, GFP_KERNEL);
-		if (tempname == NULL)
-			return -ENOMEM;
+		if (tempname == NULL) {
+			netdevs[n] = NULL;
+			ret = -ENOMEM;
+			goto error;
+		}
 		scnprintf(tempname, BAM_DMUX_CH_NAME_MAX_LEN, "bam_dmux_ch_%d",
 									n);
 		bam_rmnet_drivers[n].driver.name = tempname;
 		bam_rmnet_drivers[n].driver.owner = THIS_MODULE;
-		ret = platform_driver_register(&bam_rmnet_drivers[n]);
-		if (ret) {
-			pr_err("%s: registration failed n=%d rc=%d\n",
-					__func__, n, ret);
-			return ret;
-		}
+		p->bam_pdev = &bam_rmnet_drivers[n];
 	}
 	/*Support for new rmnet ports */
 	for (n = 0; n < RMNET_REV_DEVICE_COUNT; n++) {
@@ -960,6 +978,7 @@
 		if (ret) {
 			pr_err("%s: unable to register rev netdev %d rc=%d\n",
 							__func__, n, ret);
+			netdevs_rev[n] = NULL;
 			free_netdev(dev);
 			return ret;
 		}
@@ -968,20 +987,23 @@
 		bam_rmnet_rev_drivers[n].probe = bam_rmnet_rev_probe;
 		bam_rmnet_rev_drivers[n].remove = bam_rmnet_rev_remove;
 		tempname = kmalloc(BAM_DMUX_CH_NAME_MAX_LEN, GFP_KERNEL);
-		if (tempname == NULL)
-			return -ENOMEM;
+		if (tempname == NULL) {
+			netdevs_rev[n] = NULL;
+			ret = -ENOMEM;
+			goto error;
+		}
 		scnprintf(tempname, BAM_DMUX_CH_NAME_MAX_LEN, "bam_dmux_ch_%d",
 					(n+BAM_DMUX_DATA_REV_RMNET_0));
 		bam_rmnet_rev_drivers[n].driver.name = tempname;
 		bam_rmnet_rev_drivers[n].driver.owner = THIS_MODULE;
-		ret = platform_driver_register(&bam_rmnet_rev_drivers[n]);
-		if (ret) {
-			pr_err("%s: new rev driver registration failed n=%d rc=%d\n",
-					__func__, n, ret);
-			return ret;
-		}
+		p->bam_pdev = &bam_rmnet_rev_drivers[n];
 	}
 	return 0;
+
+error:
+	unregister_netdev(dev);
+	free_netdev(dev);
+	return ret;
 }
 
 module_init(rmnet_init);
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index d972e7b..bd4328a 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -445,6 +445,10 @@
 	if ((dev->props.manage & SPS_BAM_MGR_DEVICE_REMOTE)) {
 		/* No, so just mark it disabled */
 		dev->state &= ~BAM_STATE_ENABLED;
+		if ((dev->state & BAM_STATE_IRQ) && (dev->props.irq > 0)) {
+			free_irq(dev->props.irq, dev);
+			dev->state &= ~BAM_STATE_IRQ;
+		}
 		return 0;
 	}
 
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index b518f1f..c246036 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1970,6 +1970,11 @@
 		pr_debug("new delta ocv = %d\n", delta_ocv_uv);
 	}
 
+	if (wake_lock_active(&chip->low_voltage_wake_lock)) {
+		pr_debug("Low Voltage, apply only ibat limited corrections\n");
+		goto skip_limiting_corrections;
+	}
+
 	if (chip->last_ocv_uv > 3800000)
 		correction_limit_uv = the_chip->high_ocv_correction_limit_uv;
 	else
@@ -1986,6 +1991,7 @@
 		pr_debug("new delta ocv = %d\n", delta_ocv_uv);
 	}
 
+skip_limiting_corrections:
 	chip->last_ocv_uv -= delta_ocv_uv;
 
 	if (chip->last_ocv_uv >= chip->max_voltage_uv)
@@ -2278,7 +2284,6 @@
 	int new_calculated_soc;
 	static int firsttime = 1;
 
-	calib_hkadc_check(chip, batt_temp);
 	calculate_soc_params(chip, raw, batt_temp, chargecycles,
 						&fcc_uah,
 						&unusable_charge_uah,
@@ -2426,6 +2431,7 @@
 	get_batt_temp(chip, &batt_temp);
 
 	mutex_lock(&chip->last_ocv_uv_mutex);
+	calib_hkadc_check(chip, batt_temp);
 	read_soc_params_raw(chip, &raw, batt_temp);
 
 	soc = calculate_state_of_charge(chip, &raw,
@@ -2762,6 +2768,7 @@
 	get_batt_temp(the_chip, &batt_temp);
 
 	mutex_lock(&the_chip->last_ocv_uv_mutex);
+	calib_hkadc_check(the_chip, batt_temp);
 	read_soc_params_raw(the_chip, &raw, batt_temp);
 	mutex_unlock(&the_chip->last_ocv_uv_mutex);
 
@@ -2907,6 +2914,7 @@
 
 	mutex_lock(&the_chip->last_ocv_uv_mutex);
 
+	calib_hkadc_check(the_chip, batt_temp);
 	read_soc_params_raw(the_chip, &raw, batt_temp);
 
 	calculate_cc_uah(the_chip, raw.cc, &bms_end_cc_uah);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index d5b2cc6..f3f59e6 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -298,6 +298,7 @@
 	bool				disable_aicl;
 	int				usb_type;
 	bool				disable_chg_rmvl_wrkarnd;
+	struct msm_xo_voter		*voter;
 };
 
 /* user space parameter to limit usb current */
@@ -4034,6 +4035,7 @@
 	int err;
 	u8 temp;
 
+	msm_xo_mode_vote(chip->voter, MSM_XO_MODE_ON);
 	temp  = 0xD1;
 	err = pm_chg_write(chip, CHG_TEST, temp);
 	if (err) {
@@ -4092,6 +4094,8 @@
 		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
 		return;
 	}
+
+	msm_xo_mode_vote(chip->voter, MSM_XO_MODE_OFF);
 }
 
 static void pm8921_chg_set_hw_clk_switching(struct pm8921_chg_chip *chip)
@@ -4099,6 +4103,7 @@
 	int err;
 	u8 temp;
 
+	msm_xo_mode_vote(chip->voter, MSM_XO_MODE_ON);
 	temp  = 0xD1;
 	err = pm_chg_write(chip, CHG_TEST, temp);
 	if (err) {
@@ -4112,6 +4117,7 @@
 		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
 		return;
 	}
+	msm_xo_mode_vote(chip->voter, MSM_XO_MODE_OFF);
 }
 
 #define VREF_BATT_THERM_FORCE_ON	BIT(7)
@@ -4800,6 +4806,7 @@
 	chip->ibatmax_max_adj_ma = find_ibat_max_adj_ma(
 					chip->max_bat_chg_current);
 
+	chip->voter = msm_xo_get(MSM_XO_TCXO_D0, "pm8921_charger");
 	rc = pm8921_chg_hw_init(chip);
 	if (rc) {
 		pr_err("couldn't init hardware rc=%d\n", rc);
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index cf20a81..c43a777 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -275,6 +275,7 @@
 	bool				battery_removed;
 	struct bms_irq			sw_cc_thr_irq;
 	struct bms_irq			ocv_thr_irq;
+	struct qpnp_vadc_chip		*vadc_dev;
 };
 
 static struct of_device_id qpnp_bms_match_table[] = {
@@ -480,7 +481,7 @@
 	pr_debug("%u raw converted into %lld uv\n", reading, uv);
 	uv = adjust_vbatt_reading(chip, uv);
 	pr_debug("adjusted into %lld uv\n", uv);
-	rc = qpnp_vbat_sns_comp_result(&uv);
+	rc = qpnp_vbat_sns_comp_result(chip->vadc_dev, &uv);
 	if (rc)
 		pr_debug("could not compensate vbatt\n");
 	pr_debug("compensated into %lld uv\n", uv);
@@ -595,12 +596,12 @@
 	return 0;
 }
 
-static int get_battery_voltage(int *result_uv)
+static int get_battery_voltage(struct qpnp_bms_chip *chip, int *result_uv)
 {
 	int rc;
 	struct qpnp_vadc_result adc_result;
 
-	rc = qpnp_vadc_read(VBAT_SNS, &adc_result);
+	rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &adc_result);
 	if (rc) {
 		pr_err("error reading adc channel = %d, rc = %d\n",
 					VBAT_SNS, rc);
@@ -654,14 +655,14 @@
 	int rc, raw_0625, raw_1250;
 	struct qpnp_vadc_result result;
 
-	rc = qpnp_vadc_read(REF_625MV, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, REF_625MV, &result);
 	if (rc) {
 		pr_debug("vadc read failed with rc = %d\n", rc);
 		return rc;
 	}
 	raw_0625 = result.adc_code;
 
-	rc = qpnp_vadc_read(REF_125V, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, REF_125V, &result);
 	if (rc) {
 		pr_debug("vadc read failed with rc = %d\n", rc);
 		return rc;
@@ -806,7 +807,7 @@
 			pr_err("bms current read failed with rc: %d\n", rc);
 			return rc;
 		}
-		rc = qpnp_vadc_read(VBAT_SNS, &v_result);
+		rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &v_result);
 		if (rc) {
 			pr_err("vadc read failed with rc: %d\n", rc);
 			return rc;
@@ -1048,7 +1049,7 @@
 
 	software_counter = cc_type == SHDW_CC ?
 			&chip->software_shdw_cc_uah : &chip->software_cc_uah;
-	rc = qpnp_vadc_read(DIE_TEMP, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, DIE_TEMP, &result);
 	if (rc) {
 		pr_err("could not read pmic die temperature: %d\n", rc);
 		return *software_counter;
@@ -1429,7 +1430,7 @@
 	int rc;
 	struct qpnp_vadc_result result;
 
-	rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &result);
 	if (rc) {
 		pr_err("Unable to read battery temperature\n");
 		return rc;
@@ -1689,7 +1690,7 @@
 	int rc;
 	bool charging, charging_since_last_report;
 
-	rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &result);
 
 	if (rc) {
 		pr_err("error reading adc channel = %d, rc = %d\n",
@@ -2060,7 +2061,7 @@
 {
 	int rc, vbat_uv;
 
-	rc = get_battery_voltage(&vbat_uv);
+	rc = get_battery_voltage(chip, &vbat_uv);
 	if (rc < 0) {
 		pr_err("adc vbat failed err = %d\n", rc);
 		return soc;
@@ -2319,7 +2320,7 @@
 	int voltage_range_uv, voltage_remaining_uv, voltage_based_soc;
 	int rc, vbat_uv;
 
-	rc = get_battery_voltage(&vbat_uv);
+	rc = get_battery_voltage(chip, &vbat_uv);
 	if (rc < 0) {
 		pr_err("adc vbat failed err = %d\n", rc);
 		return rc;
@@ -2359,7 +2360,8 @@
 	} else {
 		if (!chip->batfet_closed)
 			qpnp_iadc_calibrate_for_trim(true);
-		rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
+		rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM,
+								&result);
 		if (rc) {
 			pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
 						LR_MUX1_BATT_THERM, rc);
@@ -2512,10 +2514,10 @@
 	struct qpnp_vadc_result result;
 	int rc;
 
-	rc = qpnp_vadc_read(VBAT_SNS, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &result);
 	pr_debug("vbat = %lld, raw = 0x%x\n", result.physical, result.adc_code);
 
-	get_battery_voltage(&vbat_uv);
+	get_battery_voltage(chip, &vbat_uv);
 	pr_debug("vbat is at %d, state is at %d\n", vbat_uv, state);
 
 	if (state == ADC_TM_LOW_STATE) {
@@ -2893,7 +2895,7 @@
 	struct qpnp_vadc_result result;
 	int fcc_uah, new_fcc_uah, delta_cc_uah, delta_soc;
 
-	rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &result);
 	if (rc) {
 		pr_err("Unable to read batt_temp\n");
 		return;
@@ -3292,7 +3294,7 @@
 	int rc;
 	struct qpnp_vadc_result result;
 
-	rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
 	if (rc) {
 		pr_err("error reading batt id channel = %d, rc = %d\n",
 					LR_MUX2_BAT_ID, rc);
@@ -3727,7 +3729,7 @@
 	struct qpnp_vadc_result result;
 	int rc;
 
-	rc = qpnp_vadc_read(DIE_TEMP, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, DIE_TEMP, &result);
 
 	pr_debug("low = %lld, high = %lld\n",
 			result.physical - chip->temperature_margin,
@@ -3747,7 +3749,7 @@
 	struct qpnp_vadc_result result;
 	int rc;
 
-	rc = qpnp_vadc_read(DIE_TEMP, &result);
+	rc = qpnp_vadc_read(chip->vadc_dev, DIE_TEMP, &result);
 
 	if (state == ADC_TM_LOW_STATE)
 		pr_debug("low state triggered\n");
@@ -3793,10 +3795,11 @@
 		return -ENOMEM;
 	}
 
-	rc = qpnp_vadc_is_ready();
-	if (rc) {
-		pr_info("vadc not ready: %d, deferring probe\n", rc);
-		rc = -EPROBE_DEFER;
+	chip->vadc_dev = qpnp_get_vadc(&(spmi->dev), "bms");
+	if (IS_ERR(chip->vadc_dev)) {
+		rc = PTR_ERR(chip->vadc_dev);
+		if (rc != -EPROBE_DEFER)
+			pr_err("vadc property missing, rc=%d\n", rc);
 		goto error_read;
 	}
 
@@ -3957,7 +3960,7 @@
 
 	chip->bms_psy_registered = true;
 	vbatt = 0;
-	rc = get_battery_voltage(&vbatt);
+	rc = get_battery_voltage(chip, &vbatt);
 	if (rc) {
 		pr_err("error reading vbat_sns adc channel = %d, rc = %d\n",
 						VBAT_SNS, rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index e93d085..c023a6d 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -306,8 +306,8 @@
 	unsigned int			maxinput_dc_ma;
 	unsigned int			hot_batt_p;
 	unsigned int			cold_batt_p;
-	unsigned int			warm_bat_decidegc;
-	unsigned int			cool_bat_decidegc;
+	int				warm_bat_decidegc;
+	int				cool_bat_decidegc;
 	unsigned int			safe_current;
 	unsigned int			revision;
 	unsigned int			type;
@@ -327,6 +327,7 @@
 	struct wake_lock		eoc_wake_lock;
 	struct qpnp_chg_regulator	otg_vreg;
 	struct qpnp_chg_regulator	boost_vreg;
+	struct qpnp_vadc_chip		*vadc_dev;
 };
 
 
@@ -1330,7 +1331,7 @@
 		pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
 		return 0;
 	} else {
-		rc = qpnp_vadc_read(VBAT_SNS, &results);
+		rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
 		if (rc) {
 			pr_err("Unable to read vbat rc=%d\n", rc);
 			return 0;
@@ -1523,7 +1524,7 @@
 	if (chip->use_default_batt_values || !get_prop_batt_present(chip))
 		return DEFAULT_TEMP;
 
-	rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &results);
+	rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
 	if (rc) {
 		pr_debug("Unable to read batt temperature rc=%d\n", rc);
 		return 0;
@@ -1733,8 +1734,7 @@
 		return -EINVAL;
 	}
 
-	temp = (safe_current - QPNP_CHG_IBATSAFE_MIN_MA)
-				/ QPNP_CHG_I_STEP_MA;
+	temp = safe_current / QPNP_CHG_I_STEP_MA;
 	return qpnp_chg_masked_write(chip,
 			chip->chgr_base + CHGR_IBAT_SAFE,
 			QPNP_CHG_I_MASK, temp, 1);
@@ -2671,7 +2671,7 @@
 			"qcom,battery-data");
 	if (node) {
 		memset(&batt_data, 0, sizeof(struct bms_battery_data));
-		rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
+		rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
 		if (rc) {
 			pr_err("error reading batt id channel = %d, rc = %d\n",
 						LR_MUX2_BAT_ID, rc);
@@ -3131,14 +3131,18 @@
 
 		if (subtype == SMBB_BAT_IF_SUBTYPE ||
 			subtype == SMBBP_BAT_IF_SUBTYPE ||
-			subtype == SMBCL_BAT_IF_SUBTYPE){
-			rc = qpnp_vadc_is_ready();
-			if (rc)
+			subtype == SMBCL_BAT_IF_SUBTYPE) {
+			chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
+			if (IS_ERR(chip->vadc_dev)) {
+				rc = PTR_ERR(chip->vadc_dev);
+				if (rc != -EPROBE_DEFER)
+					pr_err("vadc property missing\n");
 				goto fail_chg_enable;
 
 			rc = qpnp_chg_load_battery_data(chip);
 			if (rc)
 				goto fail_chg_enable;
+			}
 		}
 	}
 
@@ -3462,66 +3466,6 @@
 	return rc;
 }
 
-static int
-qpnp_chg_ops_set(const char *val, const struct kernel_param *kp)
-{
-	return -EINVAL;
-}
-
-#define MAX_LEN_VADC	10
-static int
-qpnp_chg_usb_in_get(char *val, const struct kernel_param *kp)
-{
-	int rc;
-	struct qpnp_vadc_result results;
-
-	rc = qpnp_vadc_is_ready();
-	if (rc)
-		return rc;
-
-	rc = qpnp_vadc_read(USBIN, &results);
-	if (rc) {
-		pr_err("Unable to read vchg rc=%d\n", rc);
-		return 0;
-	}
-	rc = snprintf(val, MAX_LEN_VADC, "%lld\n", results.physical);
-
-	return rc;
-}
-
-static int
-qpnp_chg_vchg_get(char *val, const struct kernel_param *kp)
-{
-	int rc;
-	struct qpnp_vadc_result results;
-
-	rc = qpnp_vadc_is_ready();
-	if (rc)
-		return rc;
-
-	rc = qpnp_vadc_read(VCHG_SNS, &results);
-	if (rc) {
-		pr_err("Unable to read vchg rc=%d\n", rc);
-		return 0;
-	}
-	rc = snprintf(val, MAX_LEN_VADC, "%lld\n", results.physical);
-
-	return rc;
-}
-
-static struct kernel_param_ops usb_in_uv_param_ops = {
-	.set = qpnp_chg_ops_set,
-	.get = qpnp_chg_usb_in_get,
-};
-
-static struct kernel_param_ops vchg_uv_param_ops = {
-	.set = qpnp_chg_ops_set,
-	.get = qpnp_chg_vchg_get,
-};
-
-module_param_cb(usb_in_uv, &usb_in_uv_param_ops, NULL, 0644);
-module_param_cb(vchg_uv, &vchg_uv_param_ops, NULL, 0644);
-
 static const struct dev_pm_ops qpnp_chg_pm_ops = {
 	.resume		= qpnp_chg_resume,
 	.suspend	= qpnp_chg_suspend,
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 9a4ea63..e3998a5 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -34,7 +34,7 @@
 
 config SCSI_UFSHCD
 	tristate "Universal Flash Storage Controller Driver Core"
-	depends on SCSI
+	depends on SCSI && SCSI_DMA
 	---help---
 	This selects the support for UFS devices in Linux, say Y and make
 	  sure that you know the name of your UFS host adapter (the card
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 03319ac..5634caf 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -132,12 +132,6 @@
 		goto out_iounmap;
 	}
 
-	err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
-	if (err) {
-		dev_err(&pdev->dev, "set dma mask failed\n");
-		goto out_iounmap;
-	}
-
 	err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
 	if (err) {
 		dev_err(&pdev->dev, "Intialization failed\n");
@@ -184,12 +178,12 @@
 		mem_size = resource_size(mem_res);
 		release_mem_region(mem_res->start, mem_size);
 	}
-	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
 
 static const struct of_device_id ufs_of_match[] = {
 	{ .compatible = "jedec,ufs-1.1"},
+	{},
 };
 
 static const struct dev_pm_ops ufshcd_dev_pm_ops = {
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2230f14..df02ff1 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1349,7 +1349,7 @@
 		goto fatal_eh;
 
 	if (hba->errors & UIC_ERROR) {
-		reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
+		reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER);
 		if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
 			goto fatal_eh;
 	}
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index c9b2476..25b4b5e 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -2919,15 +2919,6 @@
 		goto err_probe_reqmem;
 	}
 
-	if (pdata && pdata->ver_reg_exists) {
-		enum msm_spi_qup_version ver =
-					msm_spi_get_qup_hw_ver(&pdev->dev, dd);
-		if (dd->qup_ver != ver)
-			dev_warn(&pdev->dev,
-			"%s: HW version different then initially assumed by probe",
-			__func__);
-	}
-
 	if (pdata && pdata->rsl_id) {
 		struct remote_mutex_id rmid;
 		rmid.r_spinlock_id = pdata->rsl_id;
@@ -2986,6 +2977,16 @@
 	}
 
 	pclk_enabled = 1;
+
+	if (pdata && pdata->ver_reg_exists) {
+		enum msm_spi_qup_version ver =
+					msm_spi_get_qup_hw_ver(&pdev->dev, dd);
+		if (dd->qup_ver != ver)
+			dev_warn(&pdev->dev,
+			"%s: HW version different then initially assumed by probe",
+			__func__);
+	}
+
 	/* GSBI dose not exists on B-family MSM-chips */
 	if (dd->qup_ver != SPI_QUP_VERSION_BFAM) {
 		rc = msm_spi_configure_gsbi(dd, pdev);
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 3b0ef8c..eae5cc8 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -191,6 +191,7 @@
 	struct qpnp_adc_drv		*adc;
 	bool				adc_tm_initialized;
 	int				max_channels_available;
+	struct qpnp_vadc_chip		*vadc_dev;
 	struct qpnp_adc_tm_sensor	sensor[0];
 };
 
@@ -873,7 +874,8 @@
 		return -EINVAL;
 	}
 
-	rc = qpnp_adc_tm_scale_voltage_therm_pu2(reg, &result);
+	rc = qpnp_adc_tm_scale_voltage_therm_pu2(adc_tm->vadc_dev, reg,
+								&result);
 	if (rc < 0) {
 		pr_err("Failed to lookup the therm thresholds\n");
 		return rc;
@@ -913,7 +915,7 @@
 
 	pr_debug("requested a high - %d and low - %d with trip - %d\n",
 			tm_config.high_thr_temp, tm_config.low_thr_temp, trip);
-	rc = qpnp_adc_tm_scale_therm_voltage_pu2(&tm_config);
+	rc = qpnp_adc_tm_scale_therm_voltage_pu2(adc_tm->vadc_dev, &tm_config);
 	if (rc < 0) {
 		pr_err("Failed to lookup the adc-tm thresholds\n");
 		return rc;
@@ -1282,10 +1284,12 @@
 			     unsigned long *temp)
 {
 	struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
+	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
 	struct qpnp_vadc_result result;
 	int rc = 0;
 
-	rc = qpnp_vadc_read(adc_tm_sensor->vadc_channel_num, &result);
+	rc = qpnp_vadc_read(adc_tm->vadc_dev,
+				adc_tm_sensor->vadc_channel_num, &result);
 	if (rc)
 		return rc;
 
@@ -1362,7 +1366,7 @@
 		ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
 	adc_tm->adc->amux_prop->chan_prop->meas_interval1 =
 						ADC_MEAS1_INTERVAL_1S;
-	adc_tm_rscale_fn[scale_type].chan(param,
+	adc_tm_rscale_fn[scale_type].chan(adc_tm->vadc_dev, param,
 			&adc_tm->adc->amux_prop->chan_prop->low_thr,
 			&adc_tm->adc->amux_prop->chan_prop->high_thr);
 	adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
@@ -1553,6 +1557,14 @@
 		goto fail;
 	}
 
+	adc_tm->vadc_dev = qpnp_get_vadc(&spmi->dev, "adc_tm");
+	if (IS_ERR(adc_tm->vadc_dev)) {
+		rc = PTR_ERR(adc_tm->vadc_dev);
+		if (rc != -EPROBE_DEFER)
+			pr_err("vadc property missing, rc=%d\n", rc);
+		goto fail;
+	}
+
 	rc = devm_request_irq(&spmi->dev, adc_tm->adc->adc_irq_eoc,
 				qpnp_adc_tm_isr, IRQF_TRIGGER_RISING,
 				"qpnp_adc_tm_interrupt", adc_tm);
diff --git a/drivers/thermal/qpnp-temp-alarm.c b/drivers/thermal/qpnp-temp-alarm.c
index 499d67e..36b84c8 100644
--- a/drivers/thermal/qpnp-temp-alarm.c
+++ b/drivers/thermal/qpnp-temp-alarm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -93,6 +93,7 @@
 	enum qpnp_vadc_channels		adc_channel;
 	u16				base_addr;
 	bool				allow_software_override;
+	struct qpnp_vadc_chip		*vadc_dev;
 };
 
 /* Delay between TEMP_STAT IRQ going high and status value changing in ms. */
@@ -160,7 +161,7 @@
 	struct qpnp_vadc_result adc_result;
 	int rc;
 
-	rc = qpnp_vadc_read(chip->adc_channel, &adc_result);
+	rc = qpnp_vadc_read(chip->vadc_dev, chip->adc_channel, &adc_result);
 	if (!rc)
 		chip->temperature = adc_result.physical;
 	else
@@ -543,9 +544,12 @@
 				__func__, chip->adc_channel);
 		} else {
 			chip->adc_type = QPNP_TM_ADC_QPNP_ADC;
-			rc = qpnp_vadc_is_ready();
-			if (rc) {
-				/* Probe retry, do not print an error message */
+			chip->vadc_dev = qpnp_get_vadc(&spmi->dev,
+							"temp_alarm");
+			if (IS_ERR(chip->vadc_dev)) {
+				rc = PTR_ERR(chip->vadc_dev);
+				if (rc != -EPROBE_DEFER)
+					pr_err("vadc property missing\n");
 				goto err_cancel_work;
 			}
 		}
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index a775459..b0b2f56 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -127,6 +127,8 @@
 
 	struct work_struct	connect_w;
 	struct work_struct	disconnect_w;
+	struct work_struct	suspend_w;
+	struct work_struct	resume_w;
 };
 
 static struct bam_portmaster {
@@ -542,7 +544,9 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
+	spin_lock(&port->port_lock_ul);
 	if (!port->port_usb) {
+		spin_unlock(&port->port_lock_ul);
 		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
 	}
@@ -551,6 +555,7 @@
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
+	spin_unlock(&port->port_lock_ul);
 }
 
 static void gbam_start_endless_tx(struct gbam_port *port)
@@ -558,7 +563,9 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
+	spin_lock(&port->port_lock_dl);
 	if (!port->port_usb) {
+		spin_unlock(&port->port_lock_dl);
 		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
 	}
@@ -567,6 +574,8 @@
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
+	spin_unlock(&port->port_lock_dl);
+
 }
 
 static void gbam_stop_endless_rx(struct gbam_port *port)
@@ -574,7 +583,9 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
+	spin_lock(&port->port_lock_ul);
 	if (!port->port_usb) {
+		spin_unlock(&port->port_lock_ul);
 		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
 	}
@@ -583,14 +594,17 @@
 	status = usb_ep_dequeue(port->port_usb->out, d->rx_req);
 	if (status)
 		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
-
+	spin_unlock(&port->port_lock_ul);
 }
+
 static void gbam_stop_endless_tx(struct gbam_port *port)
 {
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
+	spin_lock(&port->port_lock_dl);
 	if (!port->port_usb) {
+		spin_unlock(&port->port_lock_dl);
 		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
 	}
@@ -599,6 +613,7 @@
 	status = usb_ep_dequeue(port->port_usb->in, d->tx_req);
 	if (status)
 		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+	spin_unlock(&port->port_lock_dl);
 }
 
 static void gbam_start(void *param, enum usb_bam_pipe_dir dir)
@@ -893,6 +908,46 @@
 	pr_debug("%s: done\n", __func__);
 }
 
+static int gbam_wake_cb(void *param)
+{
+	struct gbam_port	*port = (struct gbam_port *)param;
+	struct bam_ch_info *d;
+	struct f_rmnet		*dev;
+
+	dev = port_to_rmnet(port->gr);
+	d = &port->data_ch;
+
+	pr_debug("%s: woken up by peer\n", __func__);
+
+	return usb_gadget_wakeup(dev->cdev->gadget);
+}
+
+static void gbam2bam_suspend_work(struct work_struct *w)
+{
+	struct gbam_port *port = container_of(w, struct gbam_port, suspend_w);
+	struct bam_ch_info *d = &port->data_ch;
+
+	pr_debug("%s: suspend work started\n", __func__);
+
+	usb_bam_register_wake_cb(d->dst_connection_idx, gbam_wake_cb, port);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		usb_bam_register_start_stop_cbs(gbam_start, gbam_stop, port);
+		usb_bam_suspend(&d->ipa_params);
+	}
+}
+
+static void gbam2bam_resume_work(struct work_struct *w)
+{
+	struct gbam_port *port = container_of(w, struct gbam_port, resume_w);
+	struct bam_ch_info *d = &port->data_ch;
+
+	pr_debug("%s: resume work started\n", __func__);
+
+	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+		usb_bam_resume(&d->ipa_params);
+}
+
 static int gbam_peer_reset_cb(void *param)
 {
 	struct gbam_port	*port = (struct gbam_port *)param;
@@ -1122,6 +1177,8 @@
 
 	INIT_WORK(&port->connect_w, gbam2bam_connect_work);
 	INIT_WORK(&port->disconnect_w, gbam2bam_disconnect_work);
+	INIT_WORK(&port->suspend_w, gbam2bam_suspend_work);
+	INIT_WORK(&port->resume_w, gbam2bam_resume_work);
 
 	/* data ch */
 	d = &port->data_ch;
@@ -1446,20 +1503,6 @@
 	return ret;
 }
 
-static int gbam_wake_cb(void *param)
-{
-	struct gbam_port	*port = (struct gbam_port *)param;
-	struct bam_ch_info *d;
-	struct f_rmnet		*dev;
-
-	dev = port_to_rmnet(port->gr);
-	d = &port->data_ch;
-
-	pr_debug("%s: woken up by peer\n", __func__);
-
-	return usb_gadget_wakeup(dev->cdev->gadget);
-}
-
 void gbam_suspend(struct grmnet *gr, u8 port_num, enum transport_type trans)
 {
 	struct gbam_port	*port;
@@ -1474,11 +1517,7 @@
 
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
 
-	usb_bam_register_wake_cb(d->dst_connection_idx, gbam_wake_cb, port);
-	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		usb_bam_register_start_stop_cbs(gbam_start, gbam_stop, port);
-		usb_bam_suspend(&d->ipa_params);
-	}
+	queue_work(gbam_wq, &port->suspend_w);
 }
 
 void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans)
@@ -1495,7 +1534,5 @@
 
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
 
-	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
-	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA)
-		usb_bam_resume(&d->ipa_params);
+	queue_work(gbam_wq, &port->resume_w);
 }
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 577a4fe..b315605 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -62,10 +62,15 @@
 
 	struct work_struct		connect_w;
 	struct work_struct		disconnect_w;
+	struct work_struct		suspend_w;
+	struct work_struct		resume_w;
 };
 
 struct bam_data_port *bam2bam_data_ports[BAM2BAM_DATA_N_PORTS];
 
+static void bam2bam_data_suspend_work(struct work_struct *w);
+static void bam2bam_data_resume_work(struct work_struct *w);
+
 /*------------data_path----------------------------*/
 
 static void bam_data_endless_rx_complete(struct usb_ep *ep,
@@ -351,6 +356,8 @@
 
 	INIT_WORK(&port->connect_w, bam2bam_data_connect_work);
 	INIT_WORK(&port->disconnect_w, bam2bam_data_disconnect_work);
+	INIT_WORK(&port->suspend_w, bam2bam_data_suspend_work);
+	INIT_WORK(&port->resume_w, bam2bam_data_resume_work);
 
 	/* data ch */
 	d = &port->data_ch;
@@ -578,12 +585,8 @@
 	d = &port->data_ch;
 
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
-	usb_bam_register_wake_cb(d->dst_connection_idx, bam_data_wake_cb, port);
-	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		usb_bam_register_start_stop_cbs(bam_data_start, bam_data_stop,
-									port);
-		usb_bam_suspend(&d->ipa_params);
-	}
+
+	queue_work(bam_data_wq, &port->suspend_w);
 }
 
 void bam_data_resume(u8 port_num)
@@ -596,6 +599,34 @@
 	d = &port->data_ch;
 
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
+
+	queue_work(bam_data_wq, &port->resume_w);
+}
+
+static void bam2bam_data_suspend_work(struct work_struct *w)
+{
+	struct bam_data_port *port =
+			container_of(w, struct bam_data_port, suspend_w);
+	struct bam_data_ch_info *d = &port->data_ch;
+
+	pr_debug("%s: suspend work started\n", __func__);
+
+	usb_bam_register_wake_cb(d->dst_connection_idx, bam_data_wake_cb, port);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		usb_bam_register_start_stop_cbs(bam_data_start, bam_data_stop,
+									port);
+		usb_bam_suspend(&d->ipa_params);
+	}
+}
+
+static void bam2bam_data_resume_work(struct work_struct *w)
+{
+	struct bam_data_port *port =
+			container_of(w, struct bam_data_port, resume_w);
+	struct bam_data_ch_info *d = &port->data_ch;
+
+	pr_debug("%s: resume work started\n", __func__);
+
 	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA)
 		usb_bam_resume(&d->ipa_params);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 253658e..cfc5961 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1122,10 +1122,16 @@
 	u32 cmd;
 	unsigned long flags;
 	int retries = 0, ret, cnt = RESET_SIGNAL_TIME_USEC;
+	s32 next_latency = 0;
 
-	if (pdata && pdata->swfi_latency)
-		pm_qos_update_request(&mehci->pm_qos_req_dma,
-			pdata->swfi_latency + 1);
+	if (pdata && pdata->swfi_latency) {
+		next_latency = pdata->swfi_latency + 1;
+		pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
+		if (pdata->standalone_latency)
+			next_latency = pdata->standalone_latency + 1;
+		else
+			next_latency = PM_QOS_DEFAULT_VALUE;
+	}
 
 	mehci->bus_reset = 1;
 
@@ -1196,9 +1202,8 @@
 	pr_debug("reset completed\n");
 fail:
 	mehci->bus_reset = 0;
-	if (pdata && pdata->swfi_latency)
-		pm_qos_update_request(&mehci->pm_qos_req_dma,
-			PM_QOS_DEFAULT_VALUE);
+	if (next_latency)
+		pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
 }
 
 static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
@@ -1229,19 +1234,27 @@
 	int			retry_cnt = 0;
 	int			tight_resume = 0;
 	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
+	s32 next_latency = 0;
 
 	dbg_log_event(NULL, "Resume RH", 0);
 
+	if (pdata && pdata->swfi_latency) {
+		next_latency = pdata->swfi_latency + 1;
+		pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
+		if (pdata->standalone_latency)
+			next_latency = pdata->standalone_latency + 1;
+		else
+			next_latency = PM_QOS_DEFAULT_VALUE;
+	}
+
 	/* keep delay between bus states */
 	if (time_before(jiffies, ehci->next_statechange))
 		usleep_range(5000, 5000);
 
 	spin_lock_irq(&ehci->lock);
 	if (!HCD_HW_ACCESSIBLE(hcd)) {
-		spin_unlock_irq(&ehci->lock);
 		mehci->resume_status = -ESHUTDOWN;
-		complete(&mehci->rt_completion);
-		return 0;
+		goto exit;
 	}
 
 	if (unlikely(ehci->debug)) {
@@ -1313,13 +1326,7 @@
 				&mehci->timer->gptimer1_ctrl);
 
 			spin_unlock_irq(&ehci->lock);
-			if (pdata && pdata->swfi_latency)
-				pm_qos_update_request(&mehci->pm_qos_req_dma,
-					pdata->swfi_latency + 1);
 			wait_for_completion(&mehci->gpt0_completion);
-			if (pdata && pdata->standalone_latency)
-				pm_qos_update_request(&mehci->pm_qos_req_dma,
-					pdata->standalone_latency + 1);
 			spin_lock_irq(&ehci->lock);
 		} else {
 			dbg_log_event(NULL, "FPR: Tightloop", 0);
@@ -1357,9 +1364,11 @@
 
 	dbg_log_event(NULL, "FPR: RT-Done", 0);
 	mehci->resume_status = 1;
+exit:
 	spin_unlock_irq(&ehci->lock);
-
 	complete(&mehci->rt_completion);
+	if (next_latency)
+		pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
 
 	return 0;
 }
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 3b0cd20..a575d6d 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -477,7 +477,6 @@
 		}
 		ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT;
 	}
-	mdss_dsi_op_mode_config(mipi->mode, pdata);
 
 	if (pdata->panel_info.type == MIPI_CMD_PANEL) {
 		if (mipi->vsync_enable && mipi->hw_vsync_mode
@@ -555,9 +554,9 @@
 
 	mdss_dsi_sw_reset(pdata);
 	mdss_dsi_host_init(mipi, pdata);
+	mdss_dsi_op_mode_config(mipi->mode, pdata);
 
 	if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE) {
-		mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
 		ret = mdss_dsi_unblank(pdata);
 		if (ret) {
 			pr_err("%s: unblank failed\n", __func__);
@@ -586,6 +585,8 @@
 	switch (event) {
 	case MDSS_EVENT_UNBLANK:
 		rc = mdss_dsi_on(pdata);
+		mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode,
+							pdata);
 		if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE)
 			rc = mdss_dsi_unblank(pdata);
 		break;
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 055f233..e48d0d2 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -1157,11 +1157,21 @@
 		dchdr = &cm->dchdr;
 		mdss_dsi_buf_reserve(tp, len);
 		len = mdss_dsi_cmd_dma_add(tp, cm);
+		if (!len) {
+			pr_err("%s: failed to call cmd_dma_add\n", __func__);
+			return -EINVAL;
+		}
 		tot += len;
 		if (dchdr->last) {
 			tp->data = tp->start; /* begin of buf */
 			mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
-			mdss_dsi_cmd_dma_tx(ctrl, tp);
+			len = mdss_dsi_cmd_dma_tx(ctrl, tp);
+			if (IS_ERR_VALUE(len)) {
+				mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
+				pr_err("%s: failed to call cmd_dma_tx for cmd = 0x%x\n",
+					__func__,  cmds->payload[0]);
+				return -EINVAL;
+			}
 			if (dchdr->wait)
 				usleep(dchdr->wait * 1000);
 
@@ -1181,7 +1191,7 @@
 		struct dsi_cmd_desc *cmds, int cnt)
 {
 	u32 dsi_ctrl, data;
-	int video_mode;
+	int video_mode, ret = 0;
 	u32 left_dsi_ctrl = 0;
 	bool left_ctrl_restore = false;
 
@@ -1221,7 +1231,12 @@
 		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
 	}
 
-	mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt);
+	ret = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt);
+	if (IS_ERR_VALUE(ret)) {
+		pr_err("%s: failed to call\n",
+			__func__);
+		cnt = -EINVAL;
+	}
 
 	if (left_ctrl_restore)
 		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
@@ -1257,7 +1272,7 @@
 int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
 			struct dsi_cmd_desc *cmds, int rlen, u32 rx_flags)
 {
-	int cnt, len, diff, pkt_size;
+	int cnt, len, diff, pkt_size, ret = 0;
 	struct dsi_buf *tp, *rp;
 	int no_max_pkt_size;
 	char cmd;
@@ -1334,19 +1349,44 @@
 		/* packet size need to be set at every read */
 		pkt_size = len;
 		max_pktsize[0] = pkt_size;
-		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
 		mdss_dsi_buf_init(tp);
-		mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
-		mdss_dsi_cmd_dma_tx(ctrl, tp);
+		ret = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
+		if (!ret) {
+			pr_err("%s: failed to call\n",
+				__func__);
+			rp->len = 0;
+			goto end;
+		}
+		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
+		ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
+		if (IS_ERR_VALUE(ret)) {
+			mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
+			pr_err("%s: failed to call\n",
+				__func__);
+			rp->len = 0;
+			goto end;
+		}
 		pr_debug("%s: Max packet size sent\n", __func__);
 	}
+	mdss_dsi_buf_init(tp);
+	ret = mdss_dsi_cmd_dma_add(tp, cmds);
+	if (!ret) {
+		pr_err("%s: failed to call cmd_dma_add for cmd = 0x%x\n",
+			__func__,  cmds->payload[0]);
+		rp->len = 0;
+		goto end;
+	}
 
 	mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
-	mdss_dsi_buf_init(tp);
-	mdss_dsi_cmd_dma_add(tp, cmds);
-
 	/* transmit read comamnd to client */
-	mdss_dsi_cmd_dma_tx(ctrl, tp);
+	ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
+	if (IS_ERR_VALUE(ret)) {
+		mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
+		pr_err("%s: failed to call\n",
+			__func__);
+		rp->len = 0;
+		goto end;
+	}
 	/*
 	 * once cmd_dma_done interrupt received,
 	 * return data from client is ready and stored
@@ -1378,7 +1418,7 @@
 	switch (cmd) {
 	case DTYPE_ACK_ERR_RESP:
 		pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
-		break;
+		rp->len = 0;
 	case DTYPE_GEN_READ1_RESP:
 	case DTYPE_DCS_READ1_RESP:
 		mdss_dsi_short_read1_resp(rp);
@@ -1394,10 +1434,10 @@
 		rp->len -= diff; /* align bytes */
 		break;
 	default:
-		pr_debug("%s: Unknown cmd received\n", __func__);
-		break;
+		pr_warning("%s:Invalid response cmd\n", __func__);
+		rp->len = 0;
 	}
-
+end:
 	if (left_ctrl_restore)
 		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
 					left_dsi_ctrl); /*restore */
@@ -1413,7 +1453,7 @@
 static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
 					struct dsi_buf *tp)
 {
-	int len;
+	int len, ret = 0;
 	int domain = MDSS_IOMMU_DOMAIN_UNSECURE;
 	char *bp;
 	unsigned long size, addr;
@@ -1458,16 +1498,18 @@
 	MIPI_OUTP((ctrl->ctrl_base) + 0x090, 0x01);	/* trigger */
 	wmb();
 
-	if (!wait_for_completion_timeout(&ctrl->dma_comp,
-				msecs_to_jiffies(DMA_TX_TIMEOUT))) {
-		pr_err("%s: dma timeout error\n", __func__);
-	}
+	ret = wait_for_completion_timeout(&ctrl->dma_comp,
+				msecs_to_jiffies(DMA_TX_TIMEOUT));
+	if (ret == 0)
+		ret = -ETIMEDOUT;
+	else
+		ret = tp->len;
 
 	if (is_mdss_iommu_attached())
 		msm_iommu_unmap_contig_buffer(addr,
 			mdss_get_iommu_domain(domain), 0, size);
 
-	return tp->len;
+	return ret;
 }
 
 static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index bcd5f28..367c918 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 
 #include "mdss_hdmi_hdcp.h"
 
@@ -1171,6 +1172,38 @@
 	return rc;
 } /* hdmi_hdcp_isr */
 
+static ssize_t hdmi_hdcp_sysfs_rda_status(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct hdmi_hdcp_ctrl *hdcp_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP);
+
+	if (!hdcp_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(hdcp_ctrl->init_data.mutex);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", hdcp_ctrl->hdcp_state);
+	DEV_DBG("%s: '%d'\n", __func__, hdcp_ctrl->hdcp_state);
+	mutex_unlock(hdcp_ctrl->init_data.mutex);
+
+	return ret;
+} /* hdmi_hdcp_sysfs_rda_hdcp*/
+
+static DEVICE_ATTR(status, S_IRUGO, hdmi_hdcp_sysfs_rda_status, NULL);
+
+static struct attribute *hdmi_hdcp_fs_attrs[] = {
+	&dev_attr_status.attr,
+	NULL,
+};
+
+static struct attribute_group hdmi_hdcp_fs_attr_group = {
+	.name = "hdcp",
+	.attrs = hdmi_hdcp_fs_attrs,
+};
+
 void hdmi_hdcp_deinit(void *input)
 {
 	struct hdmi_hdcp_ctrl *hdcp_ctrl = (struct hdmi_hdcp_ctrl *)input;
@@ -1180,6 +1213,9 @@
 		return;
 	}
 
+	sysfs_remove_group(hdcp_ctrl->init_data.sysfs_kobj,
+				&hdmi_hdcp_fs_attr_group);
+
 	kfree(hdcp_ctrl);
 } /* hdmi_hdcp_deinit */
 
@@ -1203,6 +1239,12 @@
 
 	hdcp_ctrl->init_data = *init_data;
 
+	if (sysfs_create_group(init_data->sysfs_kobj,
+				&hdmi_hdcp_fs_attr_group)) {
+		DEV_ERR("%s: hdcp sysfs group creation failed\n", __func__);
+		goto error;
+	}
+
 	INIT_DELAYED_WORK(&hdcp_ctrl->hdcp_auth_work, hdmi_hdcp_auth_work);
 	INIT_WORK(&hdcp_ctrl->hdcp_int_work, hdmi_hdcp_int_work);
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.h b/drivers/video/msm/mdss/mdss_hdmi_hdcp.h
index d35b2a9..2f0c3b9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.h
@@ -26,6 +26,7 @@
 	struct dss_io_data *core_io;
 	struct dss_io_data *qfprom_io;
 	struct mutex *mutex;
+	struct kobject *sysfs_kobj;
 	struct workqueue_struct *workq;
 	void *cb_data;
 	void (*notify_status)(void *cb_data, enum hdmi_hdcp_state status);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 1fef395..7609cdc 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -740,6 +740,7 @@
 		hdcp_init_data.qfprom_io =
 			&hdmi_ctrl->pdata.io[HDMI_TX_QFPROM_IO];
 		hdcp_init_data.mutex = &hdmi_ctrl->mutex;
+		hdcp_init_data.sysfs_kobj = hdmi_ctrl->kobj;
 		hdcp_init_data.ddc_ctrl = &hdmi_ctrl->ddc_ctrl;
 		hdcp_init_data.workq = hdmi_ctrl->workq;
 		hdcp_init_data.notify_status = hdmi_tx_hdcp_cb;
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index b5a5383..d1595b3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -24,7 +24,10 @@
 #define MDSS_MDP_BUS_FACTOR_SHIFT 10
 /* 1.5 bus fudge factor */
 #define MDSS_MDP_BUS_FUDGE_FACTOR_IB(val) (((val) / 2) * 3)
+#define MDSS_MDP_BUS_FUDGE_FACTOR_HIGH_IB(val) (val << 1)
 #define MDSS_MDP_BUS_FUDGE_FACTOR_AB(val) (val << 1)
+#define MDSS_MDP_BUS_FLOOR_BW (3200000000ULL >> MDSS_MDP_BUS_FACTOR_SHIFT)
+
 /* 1.25 clock fudge factor */
 #define MDSS_MDP_CLK_FUDGE_FACTOR(val) (((val) * 5) / 4)
 
@@ -58,6 +61,74 @@
 		pinfo->clk_rate;
 }
 
+static u32 __mdss_mdp_ctrl_perf_ovrd_helper(struct mdss_mdp_mixer *mixer,
+		u32 *npipe)
+{
+	struct mdss_panel_info *pinfo;
+	struct mdss_mdp_pipe *pipe;
+	u32 mnum, ovrd = 0;
+
+	if (!mixer || !mixer->ctl->panel_data)
+		return 0;
+
+	pinfo = &mixer->ctl->panel_data->panel_info;
+	for (mnum = 0; mnum < MDSS_MDP_MAX_STAGE; mnum++) {
+		pipe = mixer->stage_pipe[mnum];
+		if (pipe && pinfo) {
+			*npipe = *npipe + 1;
+			if ((pipe->src.w >= pipe->src.h) &&
+					(pipe->src.w >= pinfo->xres))
+				ovrd = 1;
+		}
+	}
+
+	return ovrd;
+}
+
+/**
+ * mdss_mdp_ctrl_perf_ovrd() - Determines if performance override is needed
+ * @mdata:	Struct containing references to all MDP5 hardware structures
+ *		and status info such as interupts, target caps etc.
+ * @ab_quota:	Arbitrated bandwidth quota
+ * @ib_quota:	Instantaneous bandwidth quota
+ *
+ * Function calculates the minimum required MDP and BIMC clocks to avoid MDP
+ * underflow during portrait video playback. The calculations are based on the
+ * way MDP fetches (bandwidth requirement) and processes data through
+ * MDP pipeline (MDP clock requirement) based on frame size and scaling
+ * requirements.
+ */
+static void __mdss_mdp_ctrl_perf_ovrd(struct mdss_data_type *mdata,
+	u64 *ab_quota, u64 *ib_quota)
+{
+	struct mdss_mdp_ctl *ctl;
+	u32 i, npipe = 0, ovrd = 0;
+
+	for (i = 0; i < mdata->nctl; i++) {
+		ctl = mdata->ctl_off + i;
+		if (!ctl->power_on)
+			continue;
+		ovrd |= __mdss_mdp_ctrl_perf_ovrd_helper(
+				ctl->mixer_left, &npipe);
+		ovrd |= __mdss_mdp_ctrl_perf_ovrd_helper(
+				ctl->mixer_right, &npipe);
+	}
+
+	*ab_quota = MDSS_MDP_BUS_FUDGE_FACTOR_AB(*ab_quota);
+	if (npipe > 1)
+		*ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_HIGH_IB(*ib_quota);
+	else
+		*ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_IB(*ib_quota);
+
+	if (ovrd && (*ib_quota < MDSS_MDP_BUS_FLOOR_BW)) {
+		*ib_quota = MDSS_MDP_BUS_FLOOR_BW;
+		pr_debug("forcing the BIMC clock to 200 MHz : %llu bytes",
+			*ib_quota);
+	} else {
+		pr_debug("ib quota : %llu bytes", *ib_quota);
+	}
+}
+
 static int mdss_mdp_ctl_perf_commit(struct mdss_data_type *mdata, u32 flags)
 {
 	struct mdss_mdp_ctl *ctl;
@@ -82,16 +153,15 @@
 		}
 	}
 	if (flags & MDSS_MDP_PERF_UPDATE_BUS) {
-		bus_ab_quota = bus_ib_quota << MDSS_MDP_BUS_FACTOR_SHIFT;
-		bus_ab_quota = MDSS_MDP_BUS_FUDGE_FACTOR_AB(bus_ab_quota);
-		bus_ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_IB(bus_ib_quota);
+		bus_ab_quota = bus_ib_quota;
+		__mdss_mdp_ctrl_perf_ovrd(mdata, &bus_ab_quota, &bus_ib_quota);
 		bus_ib_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT;
-
+		bus_ab_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT;
 		mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
 	}
 	if (flags & MDSS_MDP_PERF_UPDATE_CLK) {
 		clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(clk_rate);
-		pr_debug("update clk rate = %lu\n", clk_rate);
+		pr_debug("update clk rate = %lu HZ\n", clk_rate);
 		mdss_mdp_set_clk_rate(clk_rate);
 	}
 	mutex_unlock(&mdss_mdp_ctl_lock);
@@ -1337,7 +1407,7 @@
 		 * writeback block
 		*/
 		head[len] = head[len - 1];
-		head[len].num = -1;
+		head[len].num = head[len - 1].num;
 	}
 	mdata->ctl_off = head;
 
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index d0f93cf..e7cd1be 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -74,6 +74,22 @@
 	}
 }
 
+static bool mhl_qualify_path_enable(struct mhl_tx_ctrl *mhl_ctrl)
+{
+	int rc = false;
+
+	if (!mhl_ctrl)
+		return rc;
+
+	if (mhl_ctrl->tmds_en_state ||
+	    /* Identify sink with non-standard INT STAT SIZE */
+	    (mhl_ctrl->devcap[DEVCAP_OFFSET_MHL_VERSION] == 0x10 &&
+	     mhl_ctrl->devcap[DEVCAP_OFFSET_INT_STAT_SIZE] == 0x44))
+		rc = true;
+
+	return rc;
+}
+
 void mhl_register_msc(struct mhl_tx_ctrl *ctrl)
 {
 	if (ctrl)
@@ -253,6 +269,11 @@
 			mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
 			mhl_drive_hpd(mhl_ctrl, HPD_UP);
 			break;
+		case DEVCAP_OFFSET_MHL_VERSION:
+		case DEVCAP_OFFSET_INT_STAT_SIZE:
+			if (mhl_qualify_path_enable(mhl_ctrl))
+				mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
+			break;
 		}
 		break;
 	case MHL_WRITE_BURST:
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index add15a4..c66d50d 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -794,10 +794,14 @@
 void mhl_tmds_ctrl(struct mhl_tx_ctrl *mhl_ctrl, uint8_t on)
 {
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
-	if (on)
+
+	if (on) {
 		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, BIT4);
-	else
+		mhl_ctrl->tmds_en_state = true;
+	} else {
 		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, 0x00);
+		mhl_ctrl->tmds_en_state = false;
+	}
 }
 
 void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state)
diff --git a/include/linux/cm36283.h b/include/linux/cm36283.h
new file mode 100644
index 0000000..cccd5ee
--- /dev/null
+++ b/include/linux/cm36283.h
@@ -0,0 +1,121 @@
+/* include/linux/cm36283.h
+ *
+ * Copyright (C) 2012 Capella Microsystems Inc.
+ * Author: Frank Hsieh <pengyueh@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LINUX_CM36283_H
+#define __LINUX_CM36283_H
+
+#define CM36283_I2C_NAME "cm36283"
+
+/* Define Slave Address*/
+#define	CM36283_slave_add	0xC0>>1
+
+#define ALS_CALIBRATED		0x6E9F
+#define PS_CALIBRATED		  0x509F
+
+/*Define Command Code*/
+#define		ALS_CONF		  0x00
+#define		ALS_THDH  	  0x01
+#define		ALS_THDL	    0x02
+#define		PS_CONF1      0x03
+#define		PS_CONF3      0x04
+#define		PS_CANC       0x05
+#define		PS_THD        0x06
+#define		RESERVED      0x07
+
+#define		PS_DATA       0x08
+#define		ALS_DATA      0x09
+#define		RESERVED2     0x0A
+#define		INT_FLAG      0x0B
+#define		ID_REG        0x0C
+
+/*cm36283*/
+/*for ALS CONF command*/
+#define CM36283_ALS_IT_80ms 	(0 << 6)
+#define CM36283_ALS_IT_160ms 	(1 << 6)
+#define CM36283_ALS_IT_320ms 	(2 << 6)
+#define CM36283_ALS_IT_640ms 	(3 << 6)
+#define CM36283_ALS_GAIN_1 		(0 << 2)
+#define CM36283_ALS_GAIN_2 		(1 << 2)
+#define CM36283_ALS_GAIN_4 		(2 << 2)
+#define CM36283_ALS_GAIN_8 		(3 << 2)
+#define CM36283_ALS_INT_EN	 	(1 << 1) /*enable/disable Interrupt*/
+#define CM36283_ALS_INT_MASK	0xFFFD
+#define CM36283_ALS_SD			  (1 << 0) /*enable/disable ALS func, 1:disable , 0: enable*/
+#define CM36283_ALS_SD_MASK		0xFFFE
+
+/*for PS CONF1 command*/
+#define CM36283_PS_ITB_1_2	 (0 << 14)
+#define CM36283_PS_ITB_1     (1 << 14)
+#define CM36283_PS_ITB_2     (2 << 14)
+#define CM36283_PS_ITB_4     (3 << 14)
+#define CM36283_PS_INT_OFF	       (0 << 8) /*enable/disable Interrupt*/
+#define CM36283_PS_INT_IN          (1 << 8)
+#define CM36283_PS_INT_OUT         (2 << 8)
+#define CM36283_PS_INT_IN_AND_OUT  (3 << 8)
+
+#define CM36283_PS_INT_MASK   0xFCFF
+
+#define CM36283_PS_DR_1_40   (0 << 6)
+#define CM36283_PS_DR_1_80   (1 << 6)
+#define CM36283_PS_DR_1_160  (2 << 6)
+#define CM36283_PS_DR_1_320  (3 << 6)
+#define CM36283_PS_IT_1T 	   (0 << 4)
+#define CM36283_PS_IT_1_3T   (1 << 4)
+#define CM36283_PS_IT_1_6T 	 (2 << 4)
+#define CM36283_PS_IT_2T 		 (3 << 4)
+#define CM36283_PS_PERS_1 	 (0 << 2)
+#define CM36283_PS_PERS_2 	 (1 << 2)
+#define CM36283_PS_PERS_3 	 (2 << 2)
+#define CM36283_PS_PERS_4 	 (3 << 2)
+#define CM36283_PS_RES_1     (1 << 1)
+#define CM36283_PS_SD	       (1 << 0)/*enable/disable PS func, 1:disable , 0: enable*/
+#define CM36283_PS_SD_MASK	 0xFFFE
+
+/*for PS CONF3 command*/
+#define CM36283_PS_MS_NORMAL        (0 << 14)
+#define CM36283_PS_MS_LOGIC_ENABLE  (1 << 14)
+#define CM36283_PS_PROL_63 	     (0 << 12)
+#define CM36283_PS_PROL_127      (1 << 12)
+#define CM36283_PS_PROL_191 	   (2 << 12)
+#define CM36283_PS_PROL_255 		 (3 << 12)
+#define CM36283_PS_SMART_PERS_ENABLE  (1 << 4)
+#define CM36283_PS_ACTIVE_FORCE_MODE  (1 << 3)
+#define CM36283_PS_ACTIVE_FORCE_TRIG  (1 << 2)
+
+/*for INT FLAG*/
+#define INT_FLAG_PS_SPFLAG           (1<<14)
+#define INT_FLAG_ALS_IF_L            (1<<13)
+#define INT_FLAG_ALS_IF_H            (1<<12)
+#define INT_FLAG_PS_IF_CLOSE         (1<<9)
+#define INT_FLAG_PS_IF_AWAY          (1<<8)  
+
+extern unsigned int ps_kparam1;
+extern unsigned int ps_kparam2;
+
+struct cm36283_platform_data {
+	int intr;
+	uint16_t levels[10];
+	uint16_t golden_adc;
+	int (*power)(int, uint8_t); /* power to the chip */
+	uint8_t slave_addr;
+	uint8_t ps_close_thd_set;
+	uint8_t ps_away_thd_set;	
+	uint16_t ls_cmd;
+	uint16_t ps_conf1_val;
+	uint16_t ps_conf3_val;	
+};
+
+#endif
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index dd675f3..02ecb0c 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -152,6 +152,8 @@
 #define DMX_IDX_VC1_FIRST_SEQ_FRAME_END     0x00800000
 #define DMX_IDX_VC1_FRAME_START             0x01000000
 #define DMX_IDX_VC1_FRAME_END               0x02000000
+#define DMX_IDX_H264_ACCESS_UNIT_DEL        0x04000000
+#define DMX_IDX_H264_SEI                    0x08000000
 
 struct dmx_pes_filter_params
 {
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index f0a54eb..d1ee11c 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -149,6 +149,7 @@
 	uint16_t devcap_state;
 	uint8_t status[2];
 	uint8_t path_en_state;
+	uint8_t tmds_en_state;
 	void *hdmi_mhl_ops;
 	struct work_struct mhl_msc_send_work;
 	struct list_head list_cmd;
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 041aae7..a9e13d5 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -138,6 +138,10 @@
 
 #define QPNP_ADC_625_UV	625000
 #define QPNP_ADC_HWMON_NAME_LENGTH				64
+#define QPNP_MAX_PROP_NAME_LEN					32
+
+/* Structure device for qpnp vadc */
+struct qpnp_vadc_chip;
 
 /**
  * enum qpnp_adc_decimation_type - Sampling rate supported.
@@ -893,7 +897,7 @@
  *	and returns the physical result
  */
 struct qpnp_vadc_scale_fn {
-	int32_t (*chan) (int32_t,
+	int32_t (*chan) (struct qpnp_vadc_chip *, int32_t,
 		const struct qpnp_adc_properties *,
 		const struct qpnp_vadc_chan_properties *,
 		struct qpnp_vadc_result *);
@@ -906,7 +910,8 @@
  *	and returns the physical result
  */
 struct qpnp_adc_tm_reverse_scale_fn {
-	int32_t (*chan) (struct qpnp_adc_tm_btm_param *,
+	int32_t (*chan) (struct qpnp_vadc_chip *,
+		struct qpnp_adc_tm_btm_param *,
 		uint32_t *, uint32_t *);
 };
 
@@ -1004,21 +1009,24 @@
 			|| defined(CONFIG_SENSORS_QPNP_ADC_VOLTAGE_MODULE)
 /**
  * qpnp_vadc_read() - Performs ADC read on the channel.
+ * @dev:	Structure device for qpnp vadc
  * @channel:	Input channel to perform the ADC read.
  * @result:	Structure pointer of type adc_chan_result
  *		in which the ADC read results are stored.
  */
-int32_t qpnp_vadc_read(enum qpnp_vadc_channels channel,
+int32_t qpnp_vadc_read(struct qpnp_vadc_chip *dev,
+				enum qpnp_vadc_channels channel,
 				struct qpnp_vadc_result *result);
 
 /**
  * qpnp_vadc_conv_seq_request() - Performs ADC read on the conversion
  *				sequencer channel.
+ * @dev:	Structure device for qpnp vadc
  * @channel:	Input channel to perform the ADC read.
  * @result:	Structure pointer of type adc_chan_result
  *		in which the ADC read results are stored.
  */
-int32_t qpnp_vadc_conv_seq_request(
+int32_t qpnp_vadc_conv_seq_request(struct qpnp_vadc_chip *dev,
 			enum qpnp_vadc_trigger trigger_channel,
 			enum qpnp_vadc_channels channel,
 			struct qpnp_vadc_result *result);
@@ -1041,6 +1049,7 @@
  * qpnp_adc_scale_default() - Scales the pre-calibrated digital output
  *		of an ADC to the ADC reference and compensates for the
  *		gain and offset.
+ * @dev:	Structure device for qpnp vadc
  * @adc_code:	pre-calibrated digital ouput of the ADC.
  * @adc_prop:	adc properties of the qpnp adc such as bit resolution,
  *		reference voltage.
@@ -1048,7 +1057,8 @@
  *		slope and offset.
  * @chan_rslt:	Physical result to be stored.
  */
-int32_t qpnp_adc_scale_default(int32_t adc_code,
+int32_t qpnp_adc_scale_default(struct qpnp_vadc_chip *dev,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
@@ -1057,6 +1067,7 @@
  *		of an ADC to the ADC reference and compensates for the
  *		gain and offset. Performs the AMUX out as 2mV/K and returns
  *		the temperature in milli degC.
+ * @dev:	Structure device for qpnp vadc
  * @adc_code:	pre-calibrated digital ouput of the ADC.
  * @adc_prop:	adc properties of the qpnp adc such as bit resolution,
  *		reference voltage.
@@ -1064,7 +1075,8 @@
  *		slope and offset.
  * @chan_rslt:	Physical result to be stored.
  */
-int32_t qpnp_adc_scale_pmic_therm(int32_t adc_code,
+int32_t qpnp_adc_scale_pmic_therm(struct qpnp_vadc_chip *dev,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
@@ -1072,6 +1084,7 @@
  * qpnp_adc_scale_batt_therm() - Scales the pre-calibrated digital output
  *		of an ADC to the ADC reference and compensates for the
  *		gain and offset. Returns the temperature in decidegC.
+ * @dev:	Structure device for qpnp vadc
  * @adc_code:	pre-calibrated digital ouput of the ADC.
  * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
  *		reference voltage.
@@ -1079,7 +1092,8 @@
  *		slope and offset.
  * @chan_rslt:	physical result to be stored.
  */
-int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
+int32_t qpnp_adc_scale_batt_therm(struct qpnp_vadc_chip *dev,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
@@ -1087,6 +1101,7 @@
  * qpnp_adc_scale_qrd_batt_therm() - Scales the pre-calibrated digital output
  *		of an ADC to the ADC reference and compensates for the
  *		gain and offset. Returns the temperature in decidegC.
+ * @dev:	Structure device for qpnp vadc
  * @adc_code:	pre-calibrated digital ouput of the ADC.
  * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
  *		reference voltage.
@@ -1094,7 +1109,8 @@
  *		slope and offset.
  * @chan_rslt:	physical result to be stored.
  */
-int32_t qpnp_adc_scale_qrd_batt_therm(int32_t adc_code,
+int32_t qpnp_adc_scale_qrd_batt_therm(struct qpnp_vadc_chip *dev,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
@@ -1102,6 +1118,7 @@
  * qpnp_adc_scale_batt_id() - Scales the pre-calibrated digital output
  *		of an ADC to the ADC reference and compensates for the
  *		gain and offset.
+ * @dev:	Structure device for qpnp vadc
  * @adc_code:	pre-calibrated digital ouput of the ADC.
  * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
  *		reference voltage.
@@ -1109,7 +1126,7 @@
  *		slope and offset.
  * @chan_rslt:	physical result to be stored.
  */
-int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
+int32_t qpnp_adc_scale_batt_id(struct qpnp_vadc_chip *dev, int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
@@ -1118,6 +1135,7 @@
  *		of an ADC to the ADC reference and compensates for the
  *		gain and offset. Returns the temperature of the xo therm in mili
 		degC.
+ * @dev:	Structure device for qpnp vadc
  * @adc_code:	pre-calibrated digital ouput of the ADC.
  * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
  *		reference voltage.
@@ -1125,7 +1143,7 @@
  *		slope and offset.
  * @chan_rslt:	physical result to be stored.
  */
-int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
+int32_t qpnp_adc_tdkntcg_therm(struct qpnp_vadc_chip *dev, int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
@@ -1135,6 +1153,7 @@
  *		gain and offset. Returns the temperature of the therm in degC.
  *		It uses a mapping table computed for a 150K pull-up.
  *		Pull-up1 is an internal pull-up on the AMUX of 150K.
+ * @dev:	Structure device for qpnp vadc
  * @adc_code:	pre-calibrated digital ouput of the ADC.
  * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
  *		reference voltage.
@@ -1142,7 +1161,7 @@
  *		slope and offset.
  * @chan_rslt:	physical result to be stored.
  */
-int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+int32_t qpnp_adc_scale_therm_pu1(struct qpnp_vadc_chip *dev, int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
@@ -1152,6 +1171,7 @@
  *		gain and offset. Returns the temperature of the therm in degC.
  *		It uses a mapping table computed for a 100K pull-up.
  *		Pull-up2 is an internal pull-up on the AMUX of 100K.
+ * @dev:	Structure device for qpnp vadc
  * @adc_code:	pre-calibrated digital ouput of the ADC.
  * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
  *		reference voltage.
@@ -1159,17 +1179,22 @@
  *		slope and offset.
  * @chan_rslt:	physical result to be stored.
  */
-int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+int32_t qpnp_adc_scale_therm_pu2(struct qpnp_vadc_chip *dev, int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
 /**
- * qpnp_vadc_is_ready() - Clients can use this API to check if the
- *			  device is ready to use.
- * @result:	0 on success and -EPROBE_DEFER when probe for the device
- *		has not occured.
+ * qpnp_get_vadc() - Clients need to register with the vadc using the
+ *		corresponding device instance it wants to read the channels
+ *		from. Read the bindings document on how to pass the phandle
+ *		for the corresponding vadc driver to register with.
+ * @dev:	Clients device structure
+ * @name:	Corresponding client's DT parser name. Read the DT bindings
+ *		document on how to register with the vadc
+ * @struct qpnp_vadc_chip * - On success returns the vadc device structure
+ *		pointer that needs to be used during an ADC request.
  */
-int32_t qpnp_vadc_is_ready(void);
+struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev, const char *name);
 /**
  * qpnp_adc_tm_scaler() - Performs reverse calibration.
  * @config:	Thermal monitoring configuration.
@@ -1185,17 +1210,20 @@
 /**
  * qpnp_get_vadc_gain_and_offset() - Obtains the VADC gain and offset
  *		for absolute and ratiometric calibration.
+ * @dev:	Structure device for qpnp vadc
  * @param:	The result in which the ADC offset and gain values are stored.
  * @type:	The calibration type whether client needs the absolute or
  *		ratiometric gain and offset values.
  */
-int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_linear_graph *param,
+int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_chip *dev,
+			struct qpnp_vadc_linear_graph *param,
 			enum qpnp_adc_calib_type calib_type);
 /**
  * qpnp_adc_scale_millidegc_pmic_voltage_thr() - Performs reverse calibration
  *		on the low/high temperature threshold values passed by the
  *		client. The function coverts milldegC to voltage threshold
  *		and accounts for the corresponding channels scaling as (2mV/K).
+ * @dev:	Structure device for qpnp vadc
  * @param:	The input parameters that contain the low/high temperature
  *		values.
  * @low_threshold: The low threshold value that needs to be updated with
@@ -1203,7 +1231,7 @@
  * @high_threshold: The low threshold value that needs to be updated with
  *		the above calibrated voltage value.
  */
-int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *dev,
 		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold);
 /**
@@ -1211,6 +1239,7 @@
  *		temperature threshold values passed by the client.
  *		The function maps the temperature to voltage and applies
  *		ratiometric calibration on the voltage values.
+ * @dev:	Structure device for qpnp vadc
  * @param:	The input parameters that contain the low/high temperature
  *		values.
  * @low_threshold: The low threshold value that needs to be updated with
@@ -1218,28 +1247,34 @@
  * @high_threshold: The low threshold value that needs to be updated with
  *		the above calibrated voltage value.
  */
-int32_t qpnp_adc_btm_scaler(struct qpnp_adc_tm_btm_param *param,
+int32_t qpnp_adc_btm_scaler(struct qpnp_vadc_chip *dev,
+		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold);
 /**
  * qpnp_adc_tm_scale_therm_voltage_pu2() - Performs reverse calibration
  *		and convert given temperature to voltage on supported
  *		thermistor channels using 100k pull-up.
+ * @dev:	Structure device for qpnp vadc
  * @param:	The input temperature values.
  */
-int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_adc_tm_config *param);
+int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *dev,
+				struct qpnp_adc_tm_config *param);
 /**
  * qpnp_adc_tm_scale_therm_voltage_pu2() - Performs reverse calibration
  *		and converts the given ADC code to temperature for
  *		thermistor channels using 100k pull-up.
+ * @dev:	Structure device for qpnp vadc
  * @reg:	The input ADC code.
  * @result:	The physical measurement temperature on the thermistor.
  */
-int32_t qpnp_adc_tm_scale_voltage_therm_pu2(uint32_t reg, int64_t *result);
+int32_t qpnp_adc_tm_scale_voltage_therm_pu2(struct qpnp_vadc_chip *dev,
+				uint32_t reg, int64_t *result);
 /**
  * qpnp_adc_usb_scaler() - Performs reverse calibration on the low/high
  *		voltage threshold values passed by the client.
  *		The function applies ratiometric calibration on the
  *		voltage values.
+ * @dev:	Structure device for qpnp vadc
  * @param:	The input parameters that contain the low/high voltage
  *		threshold values.
  * @low_threshold: The low threshold value that needs to be updated with
@@ -1247,13 +1282,15 @@
  * @high_threshold: The low threshold value that needs to be updated with
  *		the above calibrated voltage value.
  */
-int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
+int32_t qpnp_adc_usb_scaler(struct qpnp_vadc_chip *dev,
+		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold);
 /**
  * qpnp_adc_vbatt_rscaler() - Performs reverse calibration on the low/high
  *		voltage threshold values passed by the client.
  *		The function applies ratiometric calibration on the
  *		voltage values.
+ * @dev:	Structure device for qpnp vadc
  * @param:	The input parameters that contain the low/high voltage
  *		threshold values.
  * @low_threshold: The low threshold value that needs to be updated with
@@ -1261,7 +1298,8 @@
  * @high_threshold: The low threshold value that needs to be updated with
  *		the above calibrated voltage value.
  */
-int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *dev,
+		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold);
 /**
  * qpnp_vadc_iadc_sync_request() - Performs Voltage ADC read and
@@ -1269,107 +1307,127 @@
  *		voltage and current request the VADC peripheral is
  *		prepared for conversion and the IADC sync conversion
  *		is done from the IADC peripheral.
+ * @dev:	Structure device for qpnp vadc
  * @channel:	Input channel to perform the voltage ADC read.
  */
-int32_t qpnp_vadc_iadc_sync_request(enum qpnp_vadc_channels channel);
+int32_t qpnp_vadc_iadc_sync_request(struct qpnp_vadc_chip *dev,
+				enum qpnp_vadc_channels channel);
 /**
  * qpnp_vadc_iadc_sync_complete_request() - Reads the ADC result and
  *		unlocks the peripheral.
+ * @dev:	Structure device for qpnp vadc
  * @result:	Structure pointer of type adc_chan_result
  *		in which the ADC read results are stored.
  */
-int32_t qpnp_vadc_iadc_sync_complete_request(
+int32_t qpnp_vadc_iadc_sync_complete_request(struct qpnp_vadc_chip *dev,
 	enum qpnp_vadc_channels channel, struct qpnp_vadc_result *result);
 /**
  * qpnp_vadc_sns_comp_result() - Compensate vbatt readings based on temperature
+ * @dev:	Structure device for qpnp vadc
  * @result:	Voltage in uV that needs compensation.
  */
-int32_t qpnp_vbat_sns_comp_result(int64_t *result);
+int32_t qpnp_vbat_sns_comp_result(struct qpnp_vadc_chip *dev,
+						int64_t *result);
 #else
-static inline int32_t qpnp_vadc_read(uint32_t channel,
+static inline int32_t qpnp_vadc_read(struct qpnp_vadc_chip *dev,
+				uint32_t channel,
 				struct qpnp_vadc_result *result)
 { return -ENXIO; }
-static inline int32_t qpnp_vadc_conv_seq_request(
+static inline int32_t qpnp_vadc_conv_seq_request(struct qpnp_vadc_chip *dev,
 			enum qpnp_vadc_trigger trigger_channel,
 			enum qpnp_vadc_channels channel,
 			struct qpnp_vadc_result *result)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_scale_default(int32_t adc_code,
+static inline int32_t qpnp_adc_scale_default(struct qpnp_vadc_chip *vadc,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_scale_pmic_therm(int32_t adc_code,
+static inline int32_t qpnp_adc_scale_pmic_therm(struct qpnp_vadc_chip *vadc,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
+static inline int32_t qpnp_adc_scale_batt_therm(struct qpnp_vadc_chip *vadc,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_scale_qrd_batt_therm(int32_t adc_code,
+static inline int32_t qpnp_adc_scale_qrd_batt_therm(
+			struct qpnp_vadc_chip *vadc, int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
 { return -ENXIO; }
-static inline int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
+static inline int32_t qpnp_adc_scale_batt_id(struct qpnp_vadc_chip *vadc,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
+static inline int32_t qpnp_adc_tdkntcg_therm(struct qpnp_vadc_chip *vadc,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+static inline int32_t qpnp_adc_scale_therm_pu1(struct qpnp_vadc_chip *vadc,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+static inline int32_t qpnp_adc_scale_therm_pu2(struct qpnp_vadc_chip *vadc,
+			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
-static inline int32_t qpnp_vadc_is_ready(void)
-{ return -ENXIO; }
-static inline int32_t qpnp_get_vadc_gain_and_offset(
+static inline struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev,
+							const char *name)
+{ return ERR_PTR(-ENXIO); }
+static inline int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_chip *dev,
 			struct qpnp_vadc_linear_graph *param,
 			enum qpnp_adc_calib_type calib_type)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_usb_scaler(
+static inline int32_t qpnp_adc_usb_scaler(struct qpnp_vadc_chip *dev,
 		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_vbatt_rscaler(
+static inline int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *dev,
 		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_btm_scaler(
+static inline int32_t qpnp_adc_btm_scaler(struct qpnp_vadc_chip *dev,
 		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+		struct qpnp_vadc_chip *dev,
 		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_tm_scale_therm_voltage_pu2(
+				struct qpnp_vadc_chip *dev,
 				struct qpnp_adc_tm_config *param)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_tm_scale_voltage_therm_pu2(
+				struct qpnp_vadc_chip *dev,
 				uint32_t reg, int64_t *result)
 { return -ENXIO; }
-static inline int32_t qpnp_vadc_iadc_sync_request(
+static inline int32_t qpnp_vadc_iadc_sync_request(struct qpnp_vadc_chip *dev,
 				enum qpnp_vadc_channels channel)
 { return -ENXIO; }
 static inline int32_t qpnp_vadc_iadc_sync_complete_request(
+				struct qpnp_vadc_chip *dev,
 				enum qpnp_vadc_channels channel,
 				struct qpnp_vadc_result *result)
 { return -ENXIO; }
-static inline int32_t qpnp_vbat_sns_comp_result(int64_t *result)
+static inline int32_t qpnp_vbat_sns_comp_result(struct qpnp_vadc_chip *dev,
+						int64_t *result)
 { return -ENXIO; }
 #endif
 
diff --git a/include/linux/stk3x1x.h b/include/linux/stk3x1x.h
new file mode 100644
index 0000000..c34116a
--- /dev/null
+++ b/include/linux/stk3x1x.h
@@ -0,0 +1,29 @@
+/*

+ *

+ * $Id: stk3x1x.h

+ *

+ * Copyright (C) 2012 Lex Hsieh     <lex_hsieh@sitronix.com.tw>

+ *

+ * This file is subject to the terms and conditions of the GNU General Public

+ * License.  See the file COPYING in the main directory of this archive for

+ * more details.

+ *

+ */

+#ifndef __STK3X1X_H__

+#define __STK3X1X_H__

+

+/* platform data */

+struct stk3x1x_platform_data

+{

+	uint8_t state_reg;

+	uint8_t psctrl_reg;

+	uint8_t alsctrl_reg;

+	uint8_t ledctrl_reg;

+	uint8_t	wait_reg;

+	uint16_t ps_thd_h;

+	uint16_t ps_thd_l;

+	int int_pin;

+	uint32_t transmittance;

+};

+

+#endif // __STK3X1X_H__

diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 2424518..101325e 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -704,6 +704,7 @@
 #define V4L2_QCOM_BUF_FLAG_DECODEONLY 0x40000
 #define V4L2_QCOM_BUF_DATA_CORRUPT 0x80000
 #define V4L2_QCOM_BUF_DROP_FRAME 0x100000
+#define V4L2_QCOM_BUF_INPUT_UNSUPPORTED 0x200000
 
 /*
  *	O V E R L A Y   P R E V I E W
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 5ae852a..ec8ec9a 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -98,6 +98,7 @@
 	struct msm_vfe_camif_cfg camif_cfg;
 	enum msm_vfe_inputmux input_mux;
 	enum ISP_START_PIXEL_PATTERN pixel_pattern;
+	uint32_t input_format;
 };
 
 struct msm_vfe_rdi_cfg {
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 162729a..de42c38 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -13,6 +13,8 @@
 
 #define MAX_NUM_CPP_STRIPS 8
 #define MSM_CPP_MAX_NUM_PLANES 3
+#define MSM_CPP_MAX_FRAME_LENGTH 1024
+#define MSM_CPP_MAX_FW_NAME_LEN 32
 
 enum msm_cpp_frame_type {
 	MSM_CPP_OFFLINE_FRAME,
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index a6390dd..ff190cd 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -38,6 +38,9 @@
 #include "wcd9xxx-resmgr.h"
 #include "wcd9xxx-common.h"
 
+#define TAPAN_HPH_PA_SETTLE_COMP_ON 3000
+#define TAPAN_HPH_PA_SETTLE_COMP_OFF 13000
+
 static atomic_t kp_tapan_priv;
 static int spkr_drv_wrnd_param_set(const char *val,
 				   const struct kernel_param *kp);
@@ -224,8 +227,8 @@
 };
 
 static const u32 comp_shift[] = {
-	4, /* Compander 0's clock source is on interpolator 7 */
 	0,
+	1,
 	2,
 };
 
@@ -234,47 +237,44 @@
 	COMPANDER_1,
 	COMPANDER_2,
 	COMPANDER_2,
-	COMPANDER_2,
-	COMPANDER_2,
-	COMPANDER_0,
 	COMPANDER_MAX,
 };
 
 static const struct comp_sample_dependent_params comp_samp_params[] = {
 	{
 		/* 8 Khz */
-		.peak_det_timeout = 0x02,
+		.peak_det_timeout = 0x06,
 		.rms_meter_div_fact = 0x09,
 		.rms_meter_resamp_fact = 0x06,
 	},
 	{
 		/* 16 Khz */
-		.peak_det_timeout = 0x03,
+		.peak_det_timeout = 0x07,
 		.rms_meter_div_fact = 0x0A,
 		.rms_meter_resamp_fact = 0x0C,
 	},
 	{
 		/* 32 Khz */
-		.peak_det_timeout = 0x05,
+		.peak_det_timeout = 0x08,
 		.rms_meter_div_fact = 0x0B,
 		.rms_meter_resamp_fact = 0x1E,
 	},
 	{
 		/* 48 Khz */
-		.peak_det_timeout = 0x05,
+		.peak_det_timeout = 0x09,
 		.rms_meter_div_fact = 0x0B,
 		.rms_meter_resamp_fact = 0x28,
 	},
 	{
 		/* 96 Khz */
-		.peak_det_timeout = 0x06,
+		.peak_det_timeout = 0x0A,
 		.rms_meter_div_fact = 0x0C,
 		.rms_meter_resamp_fact = 0x50,
 	},
 	{
 		/* 192 Khz */
-		.peak_det_timeout = 0x07,
-		.rms_meter_div_fact = 0xD,
+		.peak_det_timeout = 0x0B,
+		.rms_meter_div_fact = 0xC,
 		.rms_meter_resamp_fact = 0xA0,
 	},
 };
@@ -673,6 +673,37 @@
 	dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
 		 __func__, comp, tapan->comp_enabled[comp], value);
 	tapan->comp_enabled[comp] = value;
+
+	if (comp == COMPANDER_1 &&
+			tapan->comp_enabled[comp] == 1) {
+		/* Wavegen to 5 msec */
+		snd_soc_write(codec, TAPAN_A_RX_HPH_CNP_WG_CTL, 0xDA);
+		snd_soc_write(codec, TAPAN_A_RX_HPH_CNP_WG_TIME, 0x15);
+		snd_soc_write(codec, TAPAN_A_RX_HPH_BIAS_WG_OCP, 0x2A);
+
+		/* Enable Chopper */
+		snd_soc_update_bits(codec,
+			TAPAN_A_RX_HPH_CHOP_CTL, 0x80, 0x80);
+
+		snd_soc_write(codec, TAPAN_A_NCP_DTEST, 0x20);
+		pr_debug("%s: Enabled Chopper and set wavegen to 5 msec\n",
+				__func__);
+	} else if (comp == COMPANDER_1 &&
+			tapan->comp_enabled[comp] == 0) {
+		/* Wavegen to 20 msec */
+		snd_soc_write(codec, TAPAN_A_RX_HPH_CNP_WG_CTL, 0xDB);
+		snd_soc_write(codec, TAPAN_A_RX_HPH_CNP_WG_TIME, 0x58);
+		snd_soc_write(codec, TAPAN_A_RX_HPH_BIAS_WG_OCP, 0x1A);
+
+		/* Disable CHOPPER block */
+		snd_soc_update_bits(codec,
+			TAPAN_A_RX_HPH_CHOP_CTL, 0x80, 0x00);
+
+		snd_soc_write(codec, TAPAN_A_NCP_DTEST, 0x10);
+		pr_debug("%s: Disabled Chopper and set wavegen to 20 msec\n",
+				__func__);
+	}
+
 	return 0;
 }
 
@@ -708,26 +739,52 @@
 
 static void tapan_discharge_comp(struct snd_soc_codec *codec, int comp)
 {
-	/* Update RSM to 1, DIVF to 5 */
-	snd_soc_write(codec, TAPAN_A_CDC_COMP0_B3_CTL + (comp * 8), 1);
+	/* Level meter DIV Factor to 5*/
 	snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8), 0xF0,
-			    1 << 5);
-	/* Wait for 1ms */
-	usleep_range(1000, 1000);
+			    0x05 << 4);
+	/* RMS meter Sampling to 0x01 */
+	snd_soc_write(codec, TAPAN_A_CDC_COMP0_B3_CTL + (comp * 8), 0x01);
+
+	/* Worst case timeout for compander CnP sleep timeout */
+	usleep_range(3000, 3000);
+}
+
+static enum wcd9xxx_buck_volt tapan_codec_get_buck_mv(
+	struct snd_soc_codec *codec)
+{
+	int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	struct wcd9xxx_pdata *pdata = tapan->resmgr.pdata;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+		if (!strncmp(pdata->regulator[i].name,
+					 WCD9XXX_SUPPLY_BUCK_NAME,
+					 sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
+			if ((pdata->regulator[i].min_uV ==
+					WCD9XXX_CDC_BUCK_MV_1P8) ||
+				(pdata->regulator[i].min_uV ==
+					WCD9XXX_CDC_BUCK_MV_2P15))
+				buck_volt = pdata->regulator[i].min_uV;
+			break;
+		}
+	}
+	pr_debug("%s: S4 voltage requested is %d\n", __func__, buck_volt);
+	return buck_volt;
 }
 
 static int tapan_config_compander(struct snd_soc_dapm_widget *w,
 				  struct snd_kcontrol *kcontrol, int event)
 {
-	int mask, emask;
-	bool timedout;
-	unsigned long timeout;
+	int mask, enable_mask;
+	u8 rdac5_mux;
 	struct snd_soc_codec *codec = w->codec;
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
 	const int comp = w->shift;
 	const u32 rate = tapan->comp_fs[comp];
 	const struct comp_sample_dependent_params *comp_params =
 	    &comp_samp_params[rate];
+	enum wcd9xxx_buck_volt buck_mv;
 
 	dev_dbg(codec->dev, "%s: %s event %d compander %d, enabled %d",
 		__func__, w->name, event, comp, tapan->comp_enabled[comp]);
@@ -737,72 +794,105 @@
 
 	/* Compander 0 has single channel */
 	mask = (comp == COMPANDER_0 ? 0x01 : 0x03);
-	emask = (comp == COMPANDER_0 ? 0x02 : 0x03);
+	buck_mv = tapan_codec_get_buck_mv(codec);
+
+	rdac5_mux = snd_soc_read(codec, TAPAN_A_CDC_CONN_MISC);
+	rdac5_mux = (rdac5_mux & 0x04) >> 2;
+
+	if (comp == COMPANDER_0) {  /* SPK compander */
+		enable_mask = 0x02;
+	} else if (comp == COMPANDER_1) { /* HPH compander */
+		enable_mask = 0x03;
+	} else if (comp == COMPANDER_2) { /* LO compander */
+
+		if (rdac5_mux == 0) { /* DEM4 */
+
+			/* for LO Stereo SE, enable Compander 2 left
+			 * channel on RX3 interpolator Path and Compander 2
+			 * rigt channel on RX4 interpolator Path.
+			 */
+			enable_mask = 0x03;
+		} else if (rdac5_mux == 1) { /* DEM3_INV */
+
+			/* for LO mono differential only enable Compander 2
+			 * left channel on RX3 interpolator Path.
+			 */
+			enable_mask = 0x02;
+		} else {
+			dev_err(codec->dev, "%s: invalid rdac5_mux val %d",
+					__func__, rdac5_mux);
+			return -EINVAL;
+		}
+	} else {
+		dev_err(codec->dev, "%s: invalid compander %d", __func__, comp);
+		return -EINVAL;
+	}
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
+		/* Set compander Sample rate */
+		snd_soc_update_bits(codec,
+				    TAPAN_A_CDC_COMP0_FS_CFG + (comp * 8),
+				    0x07, rate);
+		/* Set the static gain offset for HPH Path */
+		if (comp == COMPANDER_1) {
+			if (buck_mv == WCD9XXX_CDC_BUCK_MV_2P15)
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_COMP0_B4_CTL + (comp * 8),
+					0x80, 0x00);
+			else
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_COMP0_B4_CTL + (comp * 8),
+					0x80, 0x80);
+		}
+		/* Enable RX interpolation path compander clocks */
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_B2_CTL,
+				    0x01 << comp_shift[comp],
+				    0x01 << comp_shift[comp]);
+
+		/* Toggle compander reset bits */
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL,
+				    0x01 << comp_shift[comp],
+				    0x01 << comp_shift[comp]);
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL,
+				    0x01 << comp_shift[comp], 0);
+
 		/* Set gain source to compander */
 		tapan_config_gain_compander(codec, comp, true);
-		/* Enable RX interpolation path clocks */
-		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_B2_CTL,
-				    mask << comp_shift[comp],
-				    mask << comp_shift[comp]);
+
+		/* Compander enable */
+		snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B1_CTL +
+				    (comp * 8), enable_mask, enable_mask);
 
 		tapan_discharge_comp(codec, comp);
 
-		/* Clear compander halt */
-		snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B1_CTL +
-					   (comp * 8),
-				    1 << 2, 0);
+		/* Set sample rate dependent paramater */
+		snd_soc_write(codec, TAPAN_A_CDC_COMP0_B3_CTL + (comp * 8),
+			      comp_params->rms_meter_resamp_fact);
+		snd_soc_update_bits(codec,
+				    TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8),
+				    0xF0, comp_params->rms_meter_div_fact << 4);
+		snd_soc_update_bits(codec,
+					TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8),
+					0x0F, comp_params->peak_det_timeout);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		/* Disable compander */
+		snd_soc_update_bits(codec,
+				    TAPAN_A_CDC_COMP0_B1_CTL + (comp * 8),
+				    enable_mask, 0x00);
+
 		/* Toggle compander reset bits */
 		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL,
 				    mask << comp_shift[comp],
 				    mask << comp_shift[comp]);
 		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL,
 				    mask << comp_shift[comp], 0);
-		break;
-	case SND_SOC_DAPM_POST_PMU:
-		/* Set sample rate dependent paramater */
-		snd_soc_update_bits(codec,
-				    TAPAN_A_CDC_COMP0_FS_CFG + (comp * 8),
-				    0x07, rate);
-		snd_soc_write(codec, TAPAN_A_CDC_COMP0_B3_CTL + (comp * 8),
-			      comp_params->rms_meter_resamp_fact);
-		snd_soc_update_bits(codec,
-				    TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8),
-				    0x0F, comp_params->peak_det_timeout);
-		snd_soc_update_bits(codec,
-				    TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8),
-				    0xF0, comp_params->rms_meter_div_fact << 4);
-		/* Compander enable */
-		snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B1_CTL +
-				    (comp * 8), emask, emask);
-		break;
-	case SND_SOC_DAPM_PRE_PMD:
-		/* Halt compander */
-		snd_soc_update_bits(codec,
-				    TAPAN_A_CDC_COMP0_B1_CTL + (comp * 8),
-				    1 << 2, 1 << 2);
-		/* Wait up to a second for shutdown complete */
-		timeout = jiffies + HZ;
-		do {
-			if ((snd_soc_read(codec,
-					  TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS +
-					  (comp * 8)) & mask) == mask)
-				break;
-		} while (!(timedout = time_after(jiffies, timeout)));
-		dev_dbg(codec->dev, "%s: Compander %d shutdown %s in %dms\n",
-			 __func__, comp, timedout ? "timedout" : "completed",
-			 jiffies_to_msecs(timeout - HZ - jiffies));
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		/* Disable compander */
-		snd_soc_update_bits(codec,
-				    TAPAN_A_CDC_COMP0_B1_CTL + (comp * 8),
-				    emask, 0x00);
+
 		/* Turn off the clock for compander in pair */
 		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_B2_CTL,
 				    mask << comp_shift[comp], 0);
+
 		/* Set gain source to register */
 		tapan_config_gain_compander(codec, comp, false);
 		break;
@@ -2267,6 +2357,7 @@
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
 	enum wcd9xxx_notify_event e_pre_on, e_post_off;
 	u8 req_clsh_state;
+	u32 pa_settle_time = TAPAN_HPH_PA_SETTLE_COMP_OFF;
 
 	dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
 	if (w->shift == 5) {
@@ -2282,23 +2373,32 @@
 		return -EINVAL;
 	}
 
+	if (tapan->comp_enabled[COMPANDER_1])
+		pa_settle_time = TAPAN_HPH_PA_SETTLE_COMP_ON;
+
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		/* Let MBHC module know PA is turning on */
 		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_pre_on);
 		break;
-
 	case SND_SOC_DAPM_POST_PMU:
+		dev_dbg(codec->dev, "%s: sleep %d ms after %s PA enable.\n",
+			__func__, pa_settle_time / 1000, w->name);
+		/* Time needed for PA to settle */
+		usleep_range(pa_settle_time, pa_settle_time + 1000);
+
 		wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
 						 req_clsh_state,
 						 WCD9XXX_CLSH_REQ_ENABLE,
 						 WCD9XXX_CLSH_EVENT_POST_PA);
 
-
-		usleep_range(5000, 5010);
 		break;
-
 	case SND_SOC_DAPM_POST_PMD:
+		dev_dbg(codec->dev, "%s: sleep %d ms after %s PA disable.\n",
+			__func__, pa_settle_time / 1000, w->name);
+		/* Time needed for PA to settle */
+		usleep_range(pa_settle_time, pa_settle_time + 1000);
+
 		/* Let MBHC module know PA turned off */
 		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off);
 
@@ -2306,10 +2406,6 @@
 						 req_clsh_state,
 						 WCD9XXX_CLSH_REQ_DISABLE,
 						 WCD9XXX_CLSH_EVENT_POST_PA);
-
-		dev_dbg(codec->dev, "%s: sleep 10 ms after %s PA disable.\n",
-			 __func__, w->name);
-		usleep_range(5000, 5010);
 		break;
 	}
 	return 0;
@@ -2549,6 +2645,7 @@
 	{"RX1 MIX1", NULL, "COMP1_CLK"},
 	{"RX2 MIX1", NULL, "COMP1_CLK"},
 	{"RX3 MIX1", NULL, "COMP2_CLK"},
+	{"RX4 MIX1", NULL, "COMP0_CLK"},
 
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
@@ -3019,6 +3116,7 @@
 	u16 rx_mix_1_reg_1, rx_mix_1_reg_2;
 	u16 rx_fs_reg;
 	u8 rx_mix_1_reg_1_val, rx_mix_1_reg_2_val;
+	u8 rdac5_mux;
 	struct snd_soc_codec *codec = dai->codec;
 	struct wcd9xxx_ch *ch;
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
@@ -3036,6 +3134,9 @@
 
 		rx_mix_1_reg_1 = TAPAN_A_CDC_CONN_RX1_B1_CTL;
 
+		rdac5_mux = snd_soc_read(codec, TAPAN_A_CDC_CONN_MISC);
+		rdac5_mux = (rdac5_mux & 0x04) >> 2;
+
 		for (j = 0; j < NUM_INTERPOLATORS; j++) {
 			rx_mix_1_reg_2 = rx_mix_1_reg_1 + 1;
 
@@ -3060,9 +3161,14 @@
 				snd_soc_update_bits(codec, rx_fs_reg,
 						0xE0, rx_fs_rate_reg_val);
 
-				if (comp_rx_path[j] < COMPANDER_MAX)
-					tapan->comp_fs[comp_rx_path[j]]
-					= compander_fs;
+				if (comp_rx_path[j] < COMPANDER_MAX) {
+					if ((j == 3) && (rdac5_mux == 1))
+						tapan->comp_fs[COMPANDER_0] =
+							compander_fs;
+					else
+						tapan->comp_fs[comp_rx_path[j]]
+							= compander_fs;
+				}
 			}
 			if (j <= 1)
 				rx_mix_1_reg_1 += 3;
@@ -3893,13 +3999,13 @@
 
 	SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
 		tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+		SND_SOC_DAPM_PRE_PMD),
 	SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
 		tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+		SND_SOC_DAPM_PRE_PMD),
 	SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
 		tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+		SND_SOC_DAPM_PRE_PMD),
 
 	SND_SOC_DAPM_INPUT("AMIC1"),
 	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
@@ -4239,12 +4345,11 @@
 	TAPAN_REG_VAL(TAPAN_A_RX_HPH_CHOP_CTL, 0xF4),
 	TAPAN_REG_VAL(TAPAN_A_BIAS_CURR_CTL_2, 0x08),
 	TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
-	TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
+	TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x6F),
 
 	/* TODO: Check below reg writes conflict with above */
 	/* PROGRAM_THE_0P85V_VBG_REFERENCE = V_0P858V */
 	TAPAN_REG_VAL(TAPAN_A_BIAS_CURR_CTL_2, 0x04),
-	TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x54),
 	TAPAN_REG_VAL(TAPAN_A_RX_HPH_CHOP_CTL, 0x74),
 	TAPAN_REG_VAL(TAPAN_A_RX_BUCK_BIAS1, 0x62),
 
@@ -4414,6 +4519,15 @@
 	{TAPAN_A_CDC_COMP0_B5_CTL, 0x7F, 0x7F},
 	{TAPAN_A_CDC_COMP1_B5_CTL, 0x7F, 0x7F},
 	{TAPAN_A_CDC_COMP2_B5_CTL, 0x7F, 0x7F},
+
+	/*
+	 * Setup wavegen timer to 20msec and disable chopper
+	 * as default. This corresponds to Compander OFF
+	 */
+	{TAPAN_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDB},
+	{TAPAN_A_RX_HPH_CNP_WG_TIME, 0xFF, 0x58},
+	{TAPAN_A_RX_HPH_BIAS_WG_OCP, 0xFF, 0x1A},
+	{TAPAN_A_RX_HPH_CHOP_CTL, 0xFF, 0x24},
 };
 
 static void tapan_codec_init_reg(struct snd_soc_codec *codec)
@@ -4596,30 +4710,6 @@
 	return 0;
 }
 
-static enum wcd9xxx_buck_volt tapan_codec_get_buck_mv(
-	struct snd_soc_codec *codec)
-{
-	int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
-	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
-	struct wcd9xxx_pdata *pdata = tapan->resmgr.pdata;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
-		if (!strncmp(pdata->regulator[i].name,
-					 WCD9XXX_SUPPLY_BUCK_NAME,
-					 sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
-			if ((pdata->regulator[i].min_uV ==
-					WCD9XXX_CDC_BUCK_MV_1P8) ||
-				(pdata->regulator[i].min_uV ==
-					WCD9XXX_CDC_BUCK_MV_2P15))
-				buck_volt = pdata->regulator[i].min_uV;
-			break;
-		}
-	}
-	pr_debug("%s: S4 voltage requested is %d\n", __func__, buck_volt);
-	return buck_volt;
-}
-
 static int tapan_codec_probe(struct snd_soc_codec *codec)
 {
 	struct wcd9xxx *control;
diff --git a/sound/soc/msm/mdm9625.c b/sound/soc/msm/mdm9625.c
index ad8d85a..60e2c37 100644
--- a/sound/soc/msm/mdm9625.c
+++ b/sound/soc/msm/mdm9625.c
@@ -349,6 +349,14 @@
 	return 0;
 }
 
+static int mdm9625_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				      struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+						      SNDRV_PCM_HW_PARAM_RATE);
+	rate->min = rate->max = 48000;
+	return 0;
+}
 
 static int mdm9625_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
@@ -951,6 +959,45 @@
 		.be_hw_params_fixup = mdm9625_auxpcm_be_params_fixup,
 		.ops = &mdm9625_auxpcm_be_ops,
 	},
+	/* Incall Record Uplink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_TX,
+		.stream_name = "Voice Uplink Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.32772",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+		.be_hw_params_fixup = mdm9625_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Record Downlink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_RX,
+		.stream_name = "Voice Downlink Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.32771",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+		.be_hw_params_fixup = mdm9625_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Music BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE_PLAYBACK_TX,
+		.stream_name = "Voice Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32773",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+		.be_hw_params_fixup = mdm9625_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
 };
 
 static struct snd_soc_card snd_soc_card_mdm9625 = {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index edb24fc..de60430 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -63,6 +63,7 @@
 static int lsm_mux_slim_port;
 static int slim0_rx_aanc_fb_port;
 static int msm_route_ec_ref_rx = 3; /* NONE */
+static uint32_t voc_session_id = ALL_SESSION_VSID;
 
 enum {
 	MADNONE,
@@ -572,7 +573,7 @@
 	}
 	if ((msm_bedais[reg].port_id == VOICE_RECORD_RX)
 			|| (msm_bedais[reg].port_id == VOICE_RECORD_TX))
-		voc_start_record(msm_bedais[reg].port_id, set);
+		voc_start_record(msm_bedais[reg].port_id, set, voc_session_id);
 
 	mutex_unlock(&routing_lock);
 }
@@ -2632,6 +2633,30 @@
 	msm_routing_put_rms_value_control),
 };
 
+static int msm_voc_session_id_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	voc_session_id = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: voc_session_id=%u\n", __func__, voc_session_id);
+
+	return 0;
+}
+
+static int msm_voc_session_id_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = voc_session_id;
+
+	return 0;
+}
+
+static struct snd_kcontrol_new msm_voc_session_controls[] = {
+	SOC_SINGLE_MULTI_EXT("Voc VSID", SND_SOC_NOPM, 0,
+			     0xFFFFFFFF, 0, 1, msm_voc_session_id_get,
+			     msm_voc_session_id_put),
+};
+
 static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
@@ -3910,6 +3935,10 @@
 	snd_soc_add_platform_controls(platform,
 				get_rms_controls,
 			ARRAY_SIZE(get_rms_controls));
+
+	snd_soc_add_platform_controls(platform, msm_voc_session_controls,
+				      ARRAY_SIZE(msm_voc_session_controls));
+
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 7243f19..056e2dc 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -130,6 +130,28 @@
 	return ret;
 }
 
+static bool voice_is_valid_session_id(uint32_t session_id)
+{
+	bool ret = false;
+
+	switch (session_id) {
+	case VOICE_SESSION_VSID:
+	case VOICE2_SESSION_VSID:
+	case VOLTE_SESSION_VSID:
+	case VOIP_SESSION_VSID:
+	case QCHAT_SESSION_VSID:
+	case ALL_SESSION_VSID:
+		ret = true;
+		break;
+	default:
+		pr_err("%s: Invalid session_id : %x\n", __func__, session_id);
+
+		break;
+	}
+
+	return ret;
+}
+
 static u16 voice_get_mvm_handle(struct voice_data *v)
 {
 	if (v == NULL) {
@@ -2989,6 +3011,22 @@
 	v->music_info.force = 1;
 	voice_cvs_stop_playback(v);
 	voice_cvs_stop_record(v);
+	/* If voice call is active during VoLTE, SRVCC happens.
+	   Start recording on voice session if recording started during VoLTE.
+	 */
+	if (is_volte_session(v->session_id) &&
+	    ((common.voice[VOC_PATH_PASSIVE].voc_state == VOC_RUN) ||
+	     (common.voice[VOC_PATH_PASSIVE].voc_state == VOC_CHANGE))) {
+		if (v->rec_info.rec_enable) {
+			voice_cvs_start_record(
+				&common.voice[VOC_PATH_PASSIVE],
+				v->rec_info.rec_mode);
+			common.srvcc_rec_flag = true;
+
+			pr_debug("%s: switch recording, srvcc_rec_flag %d\n",
+				 __func__, common.srvcc_rec_flag);
+		}
+	}
 	/* send stop voice cmd */
 	voice_send_stop_voice_cmd(v);
 
@@ -3561,17 +3599,35 @@
 	return ret;
 }
 
-int voc_start_record(uint32_t port_id, uint32_t set)
+int voc_start_record(uint32_t port_id, uint32_t set, uint32_t session_id)
 {
 	int ret = 0;
 	int rec_mode = 0;
 	u16 cvs_handle;
-	int i, rec_set = 0;
+	int rec_set = 0;
+	struct voice_session_itr itr;
+	struct voice_data *v = NULL;
 
-	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
-		struct voice_data *v = &common.voice[i];
-		pr_debug("%s: i:%d port_id: %d, set: %d\n",
-			__func__, i, port_id, set);
+	/* check if session_id is valid */
+	if (!voice_is_valid_session_id(session_id)) {
+		pr_err("%s: Invalid session id:%u\n", __func__,
+		       session_id);
+
+		return -EINVAL;
+	}
+
+	voice_itr_init(&itr, session_id);
+	pr_debug("%s: session_id:%u\n", __func__, session_id);
+
+	while (voice_itr_get_next_session(&itr, &v)) {
+		if (v == NULL) {
+			pr_err("%s: v is NULL, sessionid:%u\n", __func__,
+				session_id);
+
+			break;
+		}
+		pr_debug("%s: port_id: %d, set: %d, v: %p\n",
+			 __func__, port_id, set, v);
 
 		mutex_lock(&v->lock);
 		rec_mode = v->rec_info.rec_mode;
@@ -3579,13 +3635,11 @@
 		if (set) {
 			if ((v->rec_route_state.ul_flag != 0) &&
 				(v->rec_route_state.dl_flag != 0)) {
-				pr_debug("%s: i=%d, rec mode already set.\n",
-					__func__, i);
+				pr_debug("%s: rec mode already set.\n",
+					__func__);
+
 				mutex_unlock(&v->lock);
-				if (i < MAX_VOC_SESSIONS)
-					continue;
-				else
-					return 0;
+				continue;
 			}
 
 			if (port_id == VOICE_RECORD_TX) {
@@ -3615,13 +3669,10 @@
 		} else {
 			if ((v->rec_route_state.ul_flag == 0) &&
 				(v->rec_route_state.dl_flag == 0)) {
-				pr_debug("%s: i=%d, rec already stops.\n",
-					__func__, i);
+				pr_debug("%s: rec already stops.\n",
+					__func__);
 				mutex_unlock(&v->lock);
-				if (i < MAX_VOC_SESSIONS)
-					continue;
-				else
-					return 0;
+				continue;
 			}
 
 			if (port_id == VOICE_RECORD_TX) {
@@ -3650,8 +3701,8 @@
 				}
 			}
 		}
-		pr_debug("%s: i=%d, mode =%d, set =%d\n", __func__,
-			i, rec_mode, rec_set);
+		pr_debug("%s: mode =%d, set =%d\n", __func__,
+			 rec_mode, rec_set);
 		cvs_handle = voice_get_cvs_handle(v);
 
 		if (cvs_handle != 0) {
@@ -3661,6 +3712,18 @@
 				ret = voice_cvs_stop_record(v);
 		}
 
+		/* During SRVCC, recording will switch from VoLTE session to
+		   voice session.
+		   Then stop recording, need to stop recording on voice session.
+		 */
+		if ((!rec_set) && common.srvcc_rec_flag) {
+			pr_debug("%s, srvcc_rec_flag:%d\n",  __func__,
+				 common.srvcc_rec_flag);
+
+			voice_cvs_stop_record(&common.voice[VOC_PATH_PASSIVE]);
+			common.srvcc_rec_flag = false;
+		}
+
 		/* Cache the value */
 		v->rec_info.rec_enable = rec_set;
 		v->rec_info.rec_mode = rec_mode;
@@ -4590,6 +4653,9 @@
 				c->voice[i].shmem_info.mem_handle = 0;
 			}
 		}
+		/* clean up srvcc rec flag */
+		c->srvcc_rec_flag = false;
+
 		return 0;
 	}
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 1e9c813..20f2857 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1338,6 +1338,8 @@
 	struct dtmf_driver_info dtmf_info;
 
 	struct voice_data voice[MAX_VOC_SESSIONS];
+
+	bool srvcc_rec_flag;
 };
 
 struct voice_session_itr {
@@ -1438,7 +1440,7 @@
 uint32_t voc_get_session_id(char *name);
 
 int voc_start_playback(uint32_t set, uint16_t port_id);
-int voc_start_record(uint32_t port_id, uint32_t set);
+int voc_start_record(uint32_t port_id, uint32_t set, uint32_t session_id);
 int voice_get_idx_for_session(u32 session_id);
 
 #endif